about summary refs log tree commit diff
path: root/app/lib
diff options
context:
space:
mode:
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/feed_manager.rb11
-rw-r--r--app/lib/inline_renderer.rb2
4 files changed, 59 insertions, 5 deletions
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 572b8087e..3509a6c40 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 78138fb73..634ed29fa 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/feed_manager.rb b/app/lib/feed_manager.rb
index 3ce182809..8b3198df7 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -287,9 +287,14 @@ class FeedManager
     combined_regex = active_filters.reduce { |memo, obj| Regexp.union(memo, obj) }
     status         = status.reblog if status.reblog?
 
-    !combined_regex.match(Formatter.instance.plaintext(status)).nil? ||
-      (status.spoiler_text.present? && !combined_regex.match(status.spoiler_text).nil?) ||
-      (status.preloadable_poll && !combined_regex.match(status.preloadable_poll.options.join("\n\n")).nil?)
+    combined_text = [
+      Formatter.instance.plaintext(status),
+      status.spoiler_text,
+      status.preloadable_poll ? status.preloadable_poll.options.join("\n\n") : nil,
+      status.media_attachments.map(&:description).join("\n\n"),
+    ].compact.join("\n\n")
+
+    !combined_regex.match(combined_text).nil?
   end
 
   # Adds a status to an account's feed, returning true if a status was
diff --git a/app/lib/inline_renderer.rb b/app/lib/inline_renderer.rb
index 27e334a4d..b70814748 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