From bf3cb42da78a3f31a9e07167a764aa942ec73731 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 5 Oct 2022 03:47:56 +0200 Subject: Add server banner to web app, add `GET /api/v2/instance` to REST API (#19294) Cherry-picked d2528b26b6da34f34b5d7a392e263428d3c09d69 Conflicts: - `app/serializers/initial_state_serializer.rb`: Upstream changed stuff, we had extra attributes. Applied upstream changes while keeping our extra attributes. - `app/serializers/rest/instance_serializer.rb`: Upstream actually moved that to `app/serializers/rest/v1/instance_serializer.rb`, so updated that file by keeping our extra attributes, and took upstream's version of `app/serializers/rest/instance_serializer.rb`. - `spec/views/about/show.html.haml_spec.rb`: Took upstream's version. --- app/serializers/initial_state_serializer.rb | 19 ++-- app/serializers/manifest_serializer.rb | 4 +- app/serializers/rest/instance_serializer.rb | 94 +++++--------------- app/serializers/rest/v1/instance_serializer.rb | 115 +++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 86 deletions(-) create mode 100644 app/serializers/rest/v1/instance_serializer.rb (limited to 'app/serializers') diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 45a5cda6f..aa36f82a1 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -6,7 +6,7 @@ class InitialStateSerializer < ActiveModel::Serializer attributes :meta, :compose, :accounts, :media_attachments, :settings, :max_toot_chars, :poll_limits, - :languages, :server + :languages has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer has_one :role, serializer: REST::RoleSerializer @@ -24,18 +24,19 @@ class InitialStateSerializer < ActiveModel::Serializer } end + # rubocop:disable Metrics/AbcSize def meta store = { streaming_api_base_url: Rails.configuration.x.streaming_api_base_url, access_token: object.token, locale: I18n.locale, - domain: Rails.configuration.x.local_domain, - title: instance_presenter.site_title, + domain: instance_presenter.domain, + title: instance_presenter.title, admin: object.admin&.id&.to_s, search_enabled: Chewy.enabled?, repository: Mastodon::Version.repository, - source_url: Mastodon::Version.source_url, - version: Mastodon::Version.to_s, + source_url: instance_presenter.source_url, + version: instance_presenter.version, limited_federation_mode: Rails.configuration.x.whitelist_mode, mascot: instance_presenter.mascot&.file&.url, profile_directory: Setting.profile_directory, @@ -71,6 +72,7 @@ class InitialStateSerializer < ActiveModel::Serializer store end + # rubocop:enable Metrics/AbcSize def compose store = {} @@ -102,13 +104,6 @@ class InitialStateSerializer < ActiveModel::Serializer LanguagesHelper::SUPPORTED_LOCALES.map { |(key, value)| [key, value[0], value[1]] } end - def server - { - hero: instance_presenter.hero&.file&.url || instance_presenter.thumbnail&.file&.url || asset_pack_path('media/images/preview.png'), - description: instance_presenter.site_short_description.presence || I18n.t('about.about_mastodon_html'), - } - end - private def instance_presenter diff --git a/app/serializers/manifest_serializer.rb b/app/serializers/manifest_serializer.rb index 9827323a8..6b5296480 100644 --- a/app/serializers/manifest_serializer.rb +++ b/app/serializers/manifest_serializer.rb @@ -22,11 +22,11 @@ class ManifestSerializer < ActiveModel::Serializer :share_target, :shortcuts def name - object.site_title + object.title end def short_name - object.site_title + object.title end def icons diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 575c6214e..f4ea49427 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -1,74 +1,39 @@ # frozen_string_literal: true class REST::InstanceSerializer < ActiveModel::Serializer - include RoutingHelper - - attributes :uri, :title, :short_description, :description, :email, - :version, :urls, :stats, :thumbnail, :max_toot_chars, :poll_limits, - :languages, :registrations, :approval_required, :invites_enabled, - :configuration - - has_one :contact_account, serializer: REST::AccountSerializer - - has_many :rules, serializer: REST::RuleSerializer - - delegate :contact_account, :rules, to: :instance_presenter - - def uri - Rails.configuration.x.local_domain - end - - def title - Setting.site_title - end + class ContactSerializer < ActiveModel::Serializer + attributes :email - def short_description - Setting.site_short_description + has_one :account, serializer: REST::AccountSerializer end - def description - Setting.site_description - end + include RoutingHelper - def email - Setting.site_contact_email - end + attributes :domain, :title, :version, :source_url, :description, + :usage, :thumbnail, :languages, :configuration, + :registrations - def version - Mastodon::Version.to_s - end + has_one :contact, serializer: ContactSerializer + has_many :rules, serializer: REST::RuleSerializer def thumbnail - instance_presenter.thumbnail ? full_asset_url(instance_presenter.thumbnail.file.url) : full_pack_url('media/images/preview.png') + object.thumbnail ? full_asset_url(object.thumbnail.file.url) : full_pack_url('media/images/preview.png') end - def max_toot_chars - StatusLengthValidator::MAX_CHARS - end - - def poll_limits + def usage { - max_options: PollValidator::MAX_OPTIONS, - max_option_chars: PollValidator::MAX_OPTION_CHARS, - min_expiration: PollValidator::MIN_EXPIRATION, - max_expiration: PollValidator::MAX_EXPIRATION, - } - end - - def stats - { - user_count: instance_presenter.user_count, - status_count: instance_presenter.status_count, - domain_count: instance_presenter.domain_count, + users: { + active_month: object.active_user_count(4), + }, } end - def urls - { streaming_api: Rails.configuration.x.streaming_api_base_url } - end - def configuration { + urls: { + streaming: Rails.configuration.x.streaming_api_base_url, + }, + statuses: { max_characters: StatusLengthValidator::MAX_CHARS, max_media_attachments: 4, @@ -93,25 +58,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer } end - def languages - [I18n.default_locale] - end - def registrations - Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode - end - - def approval_required - Setting.registrations_mode == 'approved' - end - - def invites_enabled - UserRole.everyone.can?(:invite_users) - end - - private - - def instance_presenter - @instance_presenter ||= InstancePresenter.new + { + enabled: Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode, + approval_required: Setting.registrations_mode == 'approved', + } end end diff --git a/app/serializers/rest/v1/instance_serializer.rb b/app/serializers/rest/v1/instance_serializer.rb new file mode 100644 index 000000000..fefbed8ee --- /dev/null +++ b/app/serializers/rest/v1/instance_serializer.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +class REST::V1::InstanceSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :uri, :title, :short_description, :description, :email, + :version, :urls, :stats, :thumbnail, :max_toot_chars, :poll_limits, + :languages, :registrations, :approval_required, :invites_enabled, + :configuration + + has_one :contact_account, serializer: REST::AccountSerializer + + has_many :rules, serializer: REST::RuleSerializer + + def uri + object.domain + end + + def short_description + object.description + end + + def description + Setting.site_description # Legacy + end + + def email + object.contact.email + end + + def contact_account + object.contact.account + end + + def thumbnail + instance_presenter.thumbnail ? full_asset_url(instance_presenter.thumbnail.file.url) : full_pack_url('media/images/preview.png') + end + + def max_toot_chars + StatusLengthValidator::MAX_CHARS + end + + def poll_limits + { + max_options: PollValidator::MAX_OPTIONS, + max_option_chars: PollValidator::MAX_OPTION_CHARS, + min_expiration: PollValidator::MIN_EXPIRATION, + max_expiration: PollValidator::MAX_EXPIRATION, + } + end + + def stats + { + user_count: instance_presenter.user_count, + status_count: instance_presenter.status_count, + domain_count: instance_presenter.domain_count, + } + end + + def urls + { streaming_api: Rails.configuration.x.streaming_api_base_url } + end + + def usage + { + users: { + active_month: instance_presenter.active_user_count(4), + }, + } + end + + def configuration + { + statuses: { + max_characters: StatusLengthValidator::MAX_CHARS, + max_media_attachments: 4, + characters_reserved_per_url: StatusLengthValidator::URL_PLACEHOLDER_CHARS, + }, + + media_attachments: { + supported_mime_types: MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES + MediaAttachment::AUDIO_MIME_TYPES, + image_size_limit: MediaAttachment::IMAGE_LIMIT, + image_matrix_limit: Attachmentable::MAX_MATRIX_LIMIT, + video_size_limit: MediaAttachment::VIDEO_LIMIT, + video_frame_rate_limit: MediaAttachment::MAX_VIDEO_FRAME_RATE, + video_matrix_limit: MediaAttachment::MAX_VIDEO_MATRIX_LIMIT, + }, + + polls: { + max_options: PollValidator::MAX_OPTIONS, + max_characters_per_option: PollValidator::MAX_OPTION_CHARS, + min_expiration: PollValidator::MIN_EXPIRATION, + max_expiration: PollValidator::MAX_EXPIRATION, + }, + } + end + + def registrations + Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode + end + + def approval_required + Setting.registrations_mode == 'approved' + end + + def invites_enabled + UserRole.everyone.can?(:invite_users) + end + + private + + def instance_presenter + @instance_presenter ||= InstancePresenter.new + end +end -- cgit