diff options
Diffstat (limited to 'app/lib')
-rw-r--r-- | app/lib/activitypub/activity/announce.rb | 4 | ||||
-rw-r--r-- | app/lib/activitypub/activity/create.rb | 10 | ||||
-rw-r--r-- | app/lib/activitypub/activity/update.rb | 4 | ||||
-rw-r--r-- | app/lib/activitypub/adapter.rb | 76 | ||||
-rw-r--r-- | app/lib/activitypub/serializer.rb | 30 | ||||
-rw-r--r-- | app/lib/formatter.rb | 4 | ||||
-rw-r--r-- | app/lib/language_detector.rb | 4 | ||||
-rw-r--r-- | app/lib/proof_provider/keybase.rb | 6 | ||||
-rw-r--r-- | app/lib/proof_provider/keybase/config_serializer.rb | 9 | ||||
-rw-r--r-- | app/lib/proof_provider/keybase/verifier.rb | 6 |
10 files changed, 104 insertions, 49 deletions
diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 9f8ffd9fb..1aa6ee9ec 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -47,6 +47,10 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity followed_by_local_accounts? || requested_through_relay? || reblog_of_local_status? end + def requested_through_relay? + super || Relay.find_by(inbox_url: @account.inbox_url)&.enabled? + end + def reblog_of_local_status? status_from_uri(object_uri)&.account&.local? end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 8fe7b9138..dabdcbcf7 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -68,7 +68,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity thread: replied_to_status, conversation: conversation_from_uri(@object['conversation']), media_attachment_ids: process_attachments.take(4).map(&:id), - owned_poll: process_poll, + poll: process_poll, } end end @@ -240,11 +240,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def poll_vote? - return false if replied_to_status.nil? || replied_to_status.poll.nil? || !replied_to_status.local? || !replied_to_status.poll.options.include?(@object['name']) + return false if replied_to_status.nil? || replied_to_status.preloadable_poll.nil? || !replied_to_status.local? || !replied_to_status.preloadable_poll.options.include?(@object['name']) - unless replied_to_status.poll.expired? - replied_to_status.poll.votes.create!(account: @account, choice: replied_to_status.poll.options.index(@object['name']), uri: @object['id']) - ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.poll.hide_totals? + unless replied_to_status.preloadable_poll.expired? + replied_to_status.preloadable_poll.votes.create!(account: @account, choice: replied_to_status.preloadable_poll.options.index(@object['name']), uri: @object['id']) + ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals? end true diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb index bc9a63f98..70035325b 100644 --- a/app/lib/activitypub/activity/update.rb +++ b/app/lib/activitypub/activity/update.rb @@ -23,8 +23,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity return reject_payload! if invalid_origin?(@object['id']) status = Status.find_by(uri: object_uri, account_id: @account.id) - return if status.nil? || status.poll.nil? + return if status.nil? || status.preloadable_poll.nil? - ActivityPub::ProcessPollService.new.call(status.poll, @object) + ActivityPub::ProcessPollService.new.call(status.preloadable_poll, @object) end end diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 99f4d9305..94eb2899c 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -1,30 +1,24 @@ # frozen_string_literal: true class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base - CONTEXT = { - '@context': [ - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - - { - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', - 'sensitive' => 'as:sensitive', - 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' }, - 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' }, - 'Hashtag' => 'as:Hashtag', - 'ostatus' => 'http://ostatus.org#', - 'atomUri' => 'ostatus:atomUri', - 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', - 'conversation' => 'ostatus:conversation', - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' }, - 'featured' => { '@id' => 'toot:featured', '@type' => '@id' }, - 'schema' => 'http://schema.org#', - 'PropertyValue' => 'schema:PropertyValue', - 'value' => 'schema:value', - }, - ], + NAMED_CONTEXT_MAP = { + activitystreams: 'https://www.w3.org/ns/activitystreams', + security: 'https://w3id.org/security/v1', + }.freeze + + CONTEXT_EXTENSION_MAP = { + manually_approves_followers: { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers' }, + sensitive: { 'sensitive' => 'as:sensitive' }, + hashtag: { 'Hashtag' => 'as:Hashtag' }, + moved_to: { 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' } }, + also_known_as: { 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' } }, + emoji: { 'toot' => 'http://joinmastodon.org/ns#', 'Emoji' => 'toot:Emoji' }, + featured: { 'toot' => 'http://joinmastodon.org/ns#', 'featured' => { '@id' => 'toot:featured', '@type' => '@id' } }, + property_value: { 'schema' => 'http://schema.org#', 'PropertyValue' => 'schema:PropertyValue', 'value' => 'schema:value' }, + atom_uri: { 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri' }, + conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' }, + focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } }, + identity_proof: { 'toot' => 'http://joinmastodon.org/ns#', 'IdentityProof' => 'toot:IdentityProof' }, }.freeze def self.default_key_transform @@ -36,8 +30,36 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base end def serializable_hash(options = nil) - options = serialization_options(options) - serialized_hash = ActiveModelSerializers::Adapter::Attributes.new(serializer, instance_options).serializable_hash(options) - CONTEXT.merge(self.class.transform_key_casing!(serialized_hash, instance_options)) + options = serialization_options(options) + serialized_hash = serializer.serializable_hash(options) + serialized_hash = self.class.transform_key_casing!(serialized_hash, instance_options) + + { '@context' => serialized_context }.merge(serialized_hash) + end + + private + + def serialized_context + context_array = [] + + serializer_options = serializer.send(:instance_options) || {} + named_contexts = [:activitystreams] + serializer._named_contexts.keys + serializer_options.fetch(:named_contexts, {}).keys + context_extensions = serializer._context_extensions.keys + serializer_options.fetch(:context_extensions, {}).keys + + named_contexts.each do |key| + context_array << NAMED_CONTEXT_MAP[key] + end + + extensions = context_extensions.each_with_object({}) do |key, h| + h.merge!(CONTEXT_EXTENSION_MAP[key]) + end + + context_array << extensions unless extensions.empty? + + if context_array.size == 1 + context_array.first + else + context_array + end end end diff --git a/app/lib/activitypub/serializer.rb b/app/lib/activitypub/serializer.rb new file mode 100644 index 000000000..07bd8c494 --- /dev/null +++ b/app/lib/activitypub/serializer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class ActivityPub::Serializer < ActiveModel::Serializer + with_options instance_writer: false, instance_reader: true do |serializer| + serializer.class_attribute :_named_contexts + serializer.class_attribute :_context_extensions + + self._named_contexts ||= {} + self._context_extensions ||= {} + end + + def self.inherited(base) + super + + base._named_contexts = _named_contexts.dup + base._context_extensions = _context_extensions.dup + end + + def self.context(*named_contexts) + named_contexts.each do |context| + _named_contexts[context] = true + end + end + + def self.context_extensions(*extension_names) + extension_names.each do |extension_name| + _context_extensions[extension_name] = true + end + end +end diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index aadf03b2a..59dfc9004 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -19,8 +19,8 @@ class Formatter raw_content = status.text - if options[:inline_poll_options] && status.poll - raw_content = raw_content + "\n\n" + status.poll.options.map { |title| "[ ] #{title}" }.join("\n") + if options[:inline_poll_options] && status.preloadable_poll + raw_content = raw_content + "\n\n" + status.preloadable_poll.options.map { |title| "[ ] #{title}" }.join("\n") end return '' if raw_content.blank? diff --git a/app/lib/language_detector.rb b/app/lib/language_detector.rb index 70a9084d1..1e90af42d 100644 --- a/app/lib/language_detector.rb +++ b/app/lib/language_detector.rb @@ -3,7 +3,7 @@ class LanguageDetector include Singleton - CHARACTER_THRESHOLD = 140 + WORDS_THRESHOLD = 4 RELIABLE_CHARACTERS_RE = /[\p{Hebrew}\p{Arabic}\p{Syriac}\p{Thaana}\p{Nko}\p{Han}\p{Katakana}\p{Hiragana}\p{Hangul}]+/m def initialize @@ -37,7 +37,7 @@ class LanguageDetector end def sufficient_text_length?(text) - text.size >= CHARACTER_THRESHOLD + text.split(/\s+/).size >= WORDS_THRESHOLD end def language_specific_character_set?(text) diff --git a/app/lib/proof_provider/keybase.rb b/app/lib/proof_provider/keybase.rb index 96322a265..628972e9d 100644 --- a/app/lib/proof_provider/keybase.rb +++ b/app/lib/proof_provider/keybase.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true class ProofProvider::Keybase - BASE_URL = 'https://keybase.io' + BASE_URL = ENV.fetch('KEYBASE_BASE_URL', 'https://keybase.io') + DOMAIN = ENV.fetch('KEYBASE_DOMAIN', Rails.configuration.x.local_domain) class Error < StandardError; end @@ -27,7 +28,8 @@ class ProofProvider::Keybase return end - return if @proof.provider_username.blank? + # Do not perform synchronous validation for remote accounts + return if @proof.provider_username.blank? || !@proof.account.local? if verifier.valid? @proof.verified = true diff --git a/app/lib/proof_provider/keybase/config_serializer.rb b/app/lib/proof_provider/keybase/config_serializer.rb index 474ea74e2..5241d201f 100644 --- a/app/lib/proof_provider/keybase/config_serializer.rb +++ b/app/lib/proof_provider/keybase/config_serializer.rb @@ -2,6 +2,7 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer include RoutingHelper + include ActionView::Helpers::TextHelper attributes :version, :domain, :display_name, :username, :brand_color, :logo, :description, :prefill_url, @@ -13,7 +14,7 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer end def domain - Rails.configuration.x.local_domain + ProofProvider::Keybase::DOMAIN end def display_name @@ -29,11 +30,11 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer end def description - Setting.site_short_description.presence || Setting.site_description.presence || I18n.t('about.about_mastodon_html') + strip_tags(Setting.site_short_description.presence || I18n.t('about.about_mastodon_html')) end def username - { min: 1, max: 30, re: Account::USERNAME_RE.inspect } + { min: 1, max: 30, re: '[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?' } end def prefill_url @@ -65,6 +66,6 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer end def contact - [Setting.site_contact_email.presence].compact + [Setting.site_contact_email.presence || 'unknown'].compact end end diff --git a/app/lib/proof_provider/keybase/verifier.rb b/app/lib/proof_provider/keybase/verifier.rb index 86f249dd7..ab1422323 100644 --- a/app/lib/proof_provider/keybase/verifier.rb +++ b/app/lib/proof_provider/keybase/verifier.rb @@ -49,14 +49,10 @@ class ProofProvider::Keybase::Verifier def query_params { - domain: domain, + domain: ProofProvider::Keybase::DOMAIN, kb_username: @provider_username, username: @local_username, sig_hash: @token, } end - - def domain - Rails.configuration.x.local_domain - end end |