summaryrefslogtreecommitdiffstats
path: root/app/lib
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2020-06-02 19:24:53 +0200
committerGitHub <noreply@github.com>2020-06-02 19:24:53 +0200
commit5d8398c8b8b51ee7363e7d45acc560f489783e34 (patch)
tree1e0b663049feafdc003ad3c01b25bf5d5d793402 /app/lib
parent9b7e3b4774d47c184aa759364d41f40e0cdfa210 (diff)
Add E2EE API (#13820)
Diffstat (limited to 'app/lib')
-rw-r--r--app/lib/activitypub/activity/create.rb50
-rw-r--r--app/lib/activitypub/adapter.rb1
-rw-r--r--app/lib/inline_renderer.rb2
3 files changed, 51 insertions, 2 deletions
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 572b8087e6e..3509a6c4045 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -2,6 +2,45 @@
class ActivityPub::Activity::Create < ActivityPub::Activity
def perform
+ case @object['type']
+ when 'EncryptedMessage'
+ create_encrypted_message
+ else
+ create_status
+ end
+ end
+
+ private
+
+ def create_encrypted_message
+ return reject_payload! if invalid_origin?(@object['id']) || @options[:delivered_to_account_id].blank?
+
+ target_account = Account.find(@options[:delivered_to_account_id])
+ target_device = target_account.devices.find_by(device_id: @object.dig('to', 'deviceId'))
+
+ return if target_device.nil?
+
+ target_device.encrypted_messages.create!(
+ from_account: @account,
+ from_device_id: @object.dig('attributedTo', 'deviceId'),
+ type: @object['messageType'],
+ body: @object['cipherText'],
+ digest: @object.dig('digest', 'digestValue'),
+ message_franking: message_franking.to_token
+ )
+ end
+
+ def message_franking
+ MessageFranking.new(
+ hmac: @object.dig('digest', 'digestValue'),
+ original_franking: @object['messageFranking'],
+ source_account_id: @account.id,
+ target_account_id: @options[:delivered_to_account_id],
+ timestamp: Time.now.utc
+ )
+ end
+
+ def create_status
return reject_payload! if unsupported_object_type? || invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity?
RedisLock.acquire(lock_options) do |lock|
@@ -23,8 +62,6 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
@status
end
- private
-
def audience_to
@object['to'] || @json['to']
end
@@ -262,6 +299,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def poll_vote!
poll = replied_to_status.preloadable_poll
already_voted = true
+
RedisLock.acquire(poll_lock_options) do |lock|
if lock.acquired?
already_voted = poll.votes.where(account: @account).exists?
@@ -270,20 +308,24 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
raise Mastodon::RaceConditionError
end
end
+
increment_voters_count! unless already_voted
ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals?
end
def resolve_thread(status)
return unless status.reply? && status.thread.nil? && Request.valid_url?(in_reply_to_uri)
+
ThreadResolveWorker.perform_async(status.id, in_reply_to_uri)
end
def fetch_replies(status)
collection = @object['replies']
return if collection.nil?
+
replies = ActivityPub::FetchRepliesService.new.call(status, collection, false)
return unless replies.nil?
+
uri = value_or_id(collection)
ActivityPub::FetchRepliesWorker.perform_async(status.id, uri) unless uri.nil?
end
@@ -291,6 +333,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def conversation_from_uri(uri)
return nil if uri.nil?
return Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) if OStatus::TagManager.instance.local_id?(uri)
+
begin
Conversation.find_or_create_by!(uri: uri)
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
@@ -404,6 +447,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def skip_download?
return @skip_download if defined?(@skip_download)
+
@skip_download ||= DomainBlock.reject_media?(@account.domain)
end
@@ -436,11 +480,13 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def forward_for_reply
return unless @json['signature'].present? && reply_to_local?
+
ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url])
end
def increment_voters_count!
poll = replied_to_status.preloadable_poll
+
unless poll.voters_count.nil?
poll.voters_count = poll.voters_count + 1
poll.save
diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb
index 78138fb73f8..634ed29fa3d 100644
--- a/app/lib/activitypub/adapter.rb
+++ b/app/lib/activitypub/adapter.rb
@@ -22,6 +22,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
blurhash: { 'toot' => 'http://joinmastodon.org/ns#', 'blurhash' => 'toot:blurhash' },
discoverable: { 'toot' => 'http://joinmastodon.org/ns#', 'discoverable' => 'toot:discoverable' },
voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' },
+ olm: { 'toot' => 'http://joinmastodon.org/ns#', 'Device' => 'toot:Device', 'Ed25519Signature' => 'toot:Ed25519Signature', 'Ed25519Key' => 'toot:Ed25519Key', 'Curve25519Key' => 'toot:Curve25519Key', 'EncryptedMessage' => 'toot:EncryptedMessage', 'publicKeyBase64' => 'toot:publicKeyBase64', 'deviceId' => 'toot:deviceId', 'claim' => { '@type' => '@id', '@id' => 'toot:claim' }, 'fingerprintKey' => { '@type' => '@id', '@id' => 'toot:fingerprintKey' }, 'identityKey' => { '@type' => '@id', '@id' => 'toot:identityKey' }, 'devices' => { '@type' => '@id', '@id' => 'toot:devices' }, 'messageFranking' => 'toot:messageFranking', 'messageType' => 'toot:messageType', 'cipherText' => 'toot:cipherText' },
}.freeze
def self.default_key_transform
diff --git a/app/lib/inline_renderer.rb b/app/lib/inline_renderer.rb
index 27e334a4de6..b70814748d7 100644
--- a/app/lib/inline_renderer.rb
+++ b/app/lib/inline_renderer.rb
@@ -19,6 +19,8 @@ class InlineRenderer
serializer = REST::AnnouncementSerializer
when :reaction
serializer = REST::ReactionSerializer
+ when :encrypted_message
+ serializer = REST::EncryptedMessageSerializer
else
return
end