Merge tag 'v4.0.0rc1'

This commit is contained in:
bgme 2022-11-06 11:59:14 +08:00
commit 7ef0a46ebb
1463 changed files with 51604 additions and 34943 deletions

View file

@ -1,10 +1,29 @@
# frozen_string_literal: true
class ActivityPub::AddSerializer < ActivityPub::Serializer
class UriSerializer < ActiveModel::Serializer
include RoutingHelper
def serializable_hash(*_args)
ActivityPub::TagManager.instance.uri_for(object)
end
end
def self.serializer_for(model, options)
case model.class.name
when 'Status'
UriSerializer
when 'FeaturedTag'
ActivityPub::HashtagSerializer
else
super
end
end
include RoutingHelper
attributes :type, :actor, :target
attribute :proper_object, key: :object
has_one :proper_object, key: :object
def type
'Add'
@ -15,7 +34,7 @@ class ActivityPub::AddSerializer < ActivityPub::Serializer
end
def proper_object
ActivityPub::TagManager.instance.uri_for(object)
object
end
def target

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class ActivityPub::HashtagSerializer < ActivityPub::Serializer
context_extensions :hashtag
include RoutingHelper
attributes :type, :href, :name
@ -10,11 +12,11 @@ class ActivityPub::HashtagSerializer < ActivityPub::Serializer
end
def name
"##{object.name}"
"##{object.display_name}"
end
def href
if object.class.name == 'FeaturedTag'
if object.instance_of?(FeaturedTag)
short_account_tag_url(object.account, object.tag)
else
tag_url(object)

View file

@ -6,7 +6,7 @@ class ActivityPub::PublicKeySerializer < ActivityPub::Serializer
attributes :id, :owner, :public_key_pem
def id
[ActivityPub::TagManager.instance.uri_for(object), '#main-key'].join
ActivityPub::TagManager.instance.key_uri_for(object)
end
def owner

View file

@ -1,10 +1,29 @@
# frozen_string_literal: true
class ActivityPub::RemoveSerializer < ActivityPub::Serializer
class UriSerializer < ActiveModel::Serializer
include RoutingHelper
def serializable_hash(*_args)
ActivityPub::TagManager.instance.uri_for(object)
end
end
def self.serializer_for(model, options)
case model.class.name
when 'Status'
UriSerializer
when 'FeaturedTag'
ActivityPub::HashtagSerializer
else
super
end
end
include RoutingHelper
attributes :type, :actor, :target
attribute :proper_object, key: :object
has_one :proper_object, key: :object
def type
'Remove'
@ -15,7 +34,7 @@ class ActivityPub::RemoveSerializer < ActivityPub::Serializer
end
def proper_object
ActivityPub::TagManager.instance.uri_for(object)
object
end
def target

View file

@ -1,33 +1,37 @@
# frozen_string_literal: true
class InitialStateSerializer < ActiveModel::Serializer
include RoutingHelper
attributes :meta, :compose, :accounts,
:media_attachments, :settings,
:languages, :max_toot_chars
has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer
has_one :role, serializer: REST::RoleSerializer
def max_toot_chars
StatusLengthValidator::MAX_CHARS
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,
invites_enabled: Setting.min_invite_role == 'user',
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,
trends: Setting.trends,
registrations_open: Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode,
timeline_preview: Setting.timeline_preview,
activity_api_enabled: Setting.activity_api_enabled,
single_user_mode: Rails.configuration.x.single_user_mode,
translation_enabled: TranslationService.configured?,
}
if object.current_account
@ -43,7 +47,6 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:advanced_layout] = object.current_account.user.setting_advanced_layout
store[:use_blurhash] = object.current_account.user.setting_use_blurhash
store[:use_pending_items] = object.current_account.user.setting_use_pending_items
store[:is_staff] = object.current_account.user.staff?
store[:trends] = Setting.trends && object.current_account.user.setting_trends
store[:crop_images] = object.current_account.user.setting_crop_images
else
@ -54,8 +57,16 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:crop_images] = Setting.crop_images
end
store[:disabled_account_id] = object.disabled_account.id.to_s if object.disabled_account
store[:moved_to_account_id] = object.moved_to_account.id.to_s if object.moved_to_account
if Rails.configuration.x.single_user_mode
store[:owner] = object.owner&.id&.to_s
end
store
end
# rubocop:enable Metrics/AbcSize
def compose
store = {}
@ -74,8 +85,15 @@ class InitialStateSerializer < ActiveModel::Serializer
def accounts
store = {}
store[object.current_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.current_account, serializer: REST::AccountSerializer) if object.current_account
store[object.admin.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.admin, serializer: REST::AccountSerializer) if object.admin
ActiveRecord::Associations::Preloader.new.preload([object.current_account, object.admin, object.owner, object.disabled_account, object.moved_to_account].compact, [:account_stat, :user, { moved_to_account: [:account_stat, :user] }])
store[object.current_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.current_account, serializer: REST::AccountSerializer) if object.current_account
store[object.admin.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.admin, serializer: REST::AccountSerializer) if object.admin
store[object.owner.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.owner, serializer: REST::AccountSerializer) if object.owner
store[object.disabled_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.disabled_account, serializer: REST::AccountSerializer) if object.disabled_account
store[object.moved_to_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.moved_to_account, serializer: REST::AccountSerializer) if object.moved_to_account
store
end

View file

@ -4,35 +4,43 @@ class ManifestSerializer < ActiveModel::Serializer
include RoutingHelper
include ActionView::Helpers::TextHelper
attributes :name, :short_name, :description,
ICON_SIZES = %w(
36
48
72
96
144
192
256
384
512
).freeze
attributes :name, :short_name,
:icons, :theme_color, :background_color,
:display, :start_url, :scope,
:share_target, :shortcuts
def name
object.site_title
object.title
end
def short_name
object.site_title
end
def description
strip_tags(object.site_short_description.presence || I18n.t('about.about_mastodon_html'))
object.title
end
def icons
[
ICON_SIZES.map do |size|
{
src: '/android-chrome-192x192.png',
sizes: '192x192',
src: full_pack_url("media/icons/android-chrome-#{size}x#{size}.png"),
sizes: "#{size}x#{size}",
type: 'image/png',
},
]
}
end
end
def theme_color
'#282c37'
'#191b22'
end
def background_color
@ -44,7 +52,7 @@ class ManifestSerializer < ActiveModel::Serializer
end
def start_url
'/web/home'
'/home'
end
def scope
@ -68,37 +76,12 @@ class ManifestSerializer < ActiveModel::Serializer
def shortcuts
[
{
name: 'New toot',
url: '/web/publish',
icons: [
{
src: '/shortcuts/new-status.png',
type: 'image/png',
sizes: '192x192',
},
],
name: 'Compose new post',
url: '/publish',
},
{
name: 'Notifications',
url: '/web/notifications',
icons: [
{
src: '/shortcuts/notifications.png',
type: 'image/png',
sizes: '192x192',
},
],
},
{
name: 'Direct messages',
url: '/web/conversations',
icons: [
{
src: '/shortcuts/direct.png',
type: 'image/png',
sizes: '192x192',
},
],
url: '/notifications',
},
]
end

View file

@ -3,7 +3,7 @@
class NodeInfo::Serializer < ActiveModel::Serializer
include RoutingHelper
attributes :version, :software, :protocols, :usage, :open_registrations
attributes :version, :software, :protocols, :services, :usage, :open_registrations, :metadata
def version
'2.0'
@ -37,6 +37,10 @@ class NodeInfo::Serializer < ActiveModel::Serializer
Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode
end
def metadata
[]
end
private
def instance_presenter

View file

@ -14,6 +14,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
attribute :suspended, if: :suspended?
attribute :silenced, key: :limited, if: :silenced?
attribute :noindex, if: :local?
class FieldSerializer < ActiveModel::Serializer
include FormattingHelper
@ -103,7 +104,11 @@ class REST::AccountSerializer < ActiveModel::Serializer
object.silenced?
end
delegate :suspended?, :silenced?, to: :object
def noindex
object.user_prefers_noindex?
end
delegate :suspended?, :silenced?, :local?, to: :object
def moved_and_not_nested?
object.moved? && object.moved_to_account.moved_to_account_id.nil?

View file

@ -77,6 +77,6 @@ class REST::Admin::AccountSerializer < ActiveModel::Serializer
end
def ip
ips&.first
ips&.first&.ip
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class REST::Admin::CanonicalEmailBlockSerializer < ActiveModel::Serializer
attributes :id, :canonical_email_hash
def id
object.id.to_s
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class REST::Admin::DomainAllowSerializer < ActiveModel::Serializer
attributes :id, :domain, :created_at
def id
object.id.to_s
end
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
class REST::Admin::DomainBlockSerializer < ActiveModel::Serializer
attributes :id, :domain, :created_at, :severity,
:reject_media, :reject_reports,
:private_comment, :public_comment, :obfuscate
def id
object.id.to_s
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class REST::Admin::EmailDomainBlockSerializer < ActiveModel::Serializer
attributes :id, :domain, :created_at, :history
def id
object.id.to_s
end
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
class REST::Admin::ExistingDomainBlockErrorSerializer < ActiveModel::Serializer
attributes :error
has_one :existing_domain_block, serializer: REST::Admin::DomainBlockSerializer
def error
I18n.t('admin.domain_blocks.existing_domain_block', name: existing_domain_block.domain)
end
def existing_domain_block
object
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
class REST::Admin::IpBlockSerializer < ActiveModel::Serializer
attributes :id, :ip, :severity, :comment,
:created_at, :expires_at
def id
object.id.to_s
end
def ip
"#{object.ip}/#{object.ip.prefix}"
end
end

View file

@ -1,7 +1,8 @@
# frozen_string_literal: true
class REST::Admin::ReportSerializer < ActiveModel::Serializer
attributes :id, :action_taken, :category, :comment, :created_at, :updated_at
attributes :id, :action_taken, :action_taken_at, :category, :comment,
:forwarded, :created_at, :updated_at
has_one :account, serializer: REST::Admin::AccountSerializer
has_one :target_account, serializer: REST::Admin::AccountSerializer

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
class REST::Admin::WebhookEventSerializer < ActiveModel::Serializer
def self.serializer_for(model, options)
case model.class.name
when 'Account'
REST::Admin::AccountSerializer
when 'Report'
REST::Admin::ReportSerializer
else
super
end
end
attributes :event, :created_at
has_one :virtual_object, key: :object
def virtual_object
object.object
end
def event
object.type
end
end

View file

@ -3,6 +3,8 @@
class REST::CredentialAccountSerializer < REST::AccountSerializer
attributes :source
has_one :role, serializer: REST::RoleSerializer
def source
user = object.user
@ -15,4 +17,8 @@ class REST::CredentialAccountSerializer < REST::AccountSerializer
follow_requests_count: FollowRequest.where(target_account: object).limit(40).count,
}
end
def role
object.user_role
end
end

View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
class REST::DomainBlockSerializer < ActiveModel::Serializer
attributes :domain, :digest, :severity, :comment
def domain
object.public_domain
end
def digest
object.domain_digest
end
def comment
object.public_comment if instance_options[:with_comment]
end
end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
class REST::ExtendedDescriptionSerializer < ActiveModel::Serializer
attributes :updated_at, :content
def updated_at
object.updated_at&.iso8601
end
def content
if object.text.present?
markdown.render(object.text)
else
''
end
end
private
def markdown
@markdown ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML)
end
end

View file

@ -12,4 +12,16 @@ class REST::FeaturedTagSerializer < ActiveModel::Serializer
def url
short_account_tag_url(object.account, object.tag)
end
def name
object.display_name
end
def statuses_count
object.statuses_count.to_s
end
def last_status_at
object.last_status_at&.to_date&.iso8601
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class REST::FilterKeywordSerializer < ActiveModel::Serializer
attributes :id, :keyword, :whole_word
def id
object.id.to_s
end
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
class REST::FilterResultSerializer < ActiveModel::Serializer
belongs_to :filter, serializer: REST::FilterSerializer
has_many :keyword_matches
has_many :status_matches
def status_matches
object.status_matches&.map(&:to_s)
end
end

View file

@ -1,10 +1,15 @@
# frozen_string_literal: true
class REST::FilterSerializer < ActiveModel::Serializer
attributes :id, :phrase, :context, :whole_word, :expires_at,
:irreversible
attributes :id, :title, :context, :expires_at, :filter_action
has_many :keywords, serializer: REST::FilterKeywordSerializer, if: :rules_requested?
has_many :statuses, serializer: REST::FilterStatusSerializer, if: :rules_requested?
def id
object.id.to_s
end
def rules_requested?
instance_options[:rules_requested]
end
end

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
class REST::FilterStatusSerializer < ActiveModel::Serializer
attributes :id, :status_id
def id
object.id.to_s
end
def status_id
object.status_id.to_s
end
end

View file

@ -1,65 +1,56 @@
# frozen_string_literal: true
class REST::InstanceSerializer < ActiveModel::Serializer
class ContactSerializer < ActiveModel::Serializer
attributes :email
has_one :account, serializer: REST::AccountSerializer
end
include RoutingHelper
attributes :uri, :title, :short_description, :description, :email,
:version, :urls, :stats, :thumbnail, :max_toot_chars,
:languages, :registrations, :approval_required, :invites_enabled,
:configuration
has_one :contact_account, serializer: REST::AccountSerializer
attributes :domain, :title, :version, :source_url, :description,
:usage, :thumbnail, :languages, :configuration,
:registrations
has_one :contact, serializer: ContactSerializer
has_many :rules, serializer: REST::RuleSerializer
delegate :contact_account, :rules, to: :instance_presenter
def max_toot_chars
StatusLengthValidator::MAX_CHARS
end
def uri
Rails.configuration.x.local_domain
end
def title
Setting.site_title
end
def short_description
Setting.site_short_description
end
def description
Setting.site_description
end
def email
Setting.site_contact_email
end
def version
Mastodon::Version.to_s
end
def thumbnail
instance_presenter.thumbnail ? full_asset_url(instance_presenter.thumbnail.file.url) : full_pack_url('media/images/preview.jpg')
if object.thumbnail
{
url: full_asset_url(object.thumbnail.file.url(:'@1x')),
blurhash: object.thumbnail.blurhash,
versions: {
'@1x': full_asset_url(object.thumbnail.file.url(:'@1x')),
'@2x': full_asset_url(object.thumbnail.file.url(:'@2x')),
},
}
else
{
url: full_pack_url('media/images/preview.png'),
}
end
end
def stats
def usage
{
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,
},
accounts: {
max_featured_tags: FeaturedTag::LIMIT,
},
statuses: {
max_characters: StatusLengthValidator::MAX_CHARS,
max_media_attachments: 4,
@ -81,28 +72,36 @@ class REST::InstanceSerializer < ActiveModel::Serializer
min_expiration: PollValidator::MIN_EXPIRATION,
max_expiration: PollValidator::MAX_EXPIRATION,
},
translation: {
enabled: TranslationService.configured?,
},
}
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
Setting.min_invite_role == 'user'
{
enabled: registrations_enabled?,
approval_required: Setting.registrations_mode == 'approved',
message: registrations_enabled? ? nil : registrations_message,
}
end
private
def instance_presenter
@instance_presenter ||= InstancePresenter.new
def registrations_enabled?
Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode
end
def registrations_message
if Setting.closed_registrations_message.present?
markdown.render(Setting.closed_registrations_message)
else
nil
end
end
def markdown
@markdown ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, no_images: true)
end
end

View file

@ -5,6 +5,7 @@ class REST::NotificationSerializer < ActiveModel::Serializer
belongs_to :from_account, key: :account, serializer: REST::AccountSerializer
belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer
belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer
def id
object.id.to_s
@ -13,4 +14,8 @@ class REST::NotificationSerializer < ActiveModel::Serializer
def status_type?
[:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type)
end
def report_type?
object.type == :'admin.report'
end
end

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
class REST::PrivacyPolicySerializer < ActiveModel::Serializer
attributes :updated_at, :content
def updated_at
object.updated_at.iso8601
end
def content
markdown.render(object.text % { domain: Rails.configuration.x.local_domain })
end
private
def markdown
@markdown ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, escape_html: true, no_images: true)
end
end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
class REST::RelationshipSerializer < ActiveModel::Serializer
attributes :id, :following, :showing_reblogs, :notifying, :followed_by,
attributes :id, :following, :showing_reblogs, :notifying, :languages, :followed_by,
:blocking, :blocked_by, :muting, :muting_notifications, :requested,
:domain_blocking, :endorsed, :note
@ -25,6 +25,11 @@ class REST::RelationshipSerializer < ActiveModel::Serializer
false
end
def languages
(instance_options[:relationships].following[object.id] || {})[:languages] ||
(instance_options[:relationships].requested[object.id] || {})[:languages]
end
def followed_by
instance_options[:relationships].followed_by[object.id] || false
end

View file

@ -1,7 +1,10 @@
# frozen_string_literal: true
class REST::ReportSerializer < ActiveModel::Serializer
attributes :id, :action_taken
attributes :id, :action_taken, :action_taken_at, :category, :comment,
:forwarded, :created_at, :status_ids, :rule_ids
has_one :target_account, serializer: REST::AccountSerializer
def id
object.id.to_s

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
class REST::RoleSerializer < ActiveModel::Serializer
attributes :id, :name, :permissions, :color, :highlighted
def id
object.id.to_s
end
def permissions
object.computed_permissions.to_s
end
end

View file

@ -13,6 +13,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
attribute :muted, if: :current_user?
attribute :bookmarked, if: :current_user?
attribute :pinned, if: :pinnable?
has_many :filtered, serializer: REST::FilterResultSerializer, if: :current_user?
attribute :content, unless: :source_requested?
attribute :text, if: :source_requested?
@ -120,6 +121,14 @@ class REST::StatusSerializer < ActiveModel::Serializer
end
end
def filtered
if instance_options && instance_options[:relationships]
instance_options[:relationships].filters_map[object.id] || []
else
current_user.account.status_matches_filters(object)
end
end
def pinnable?
current_user? &&
current_user.account_id == object.account_id &&

View file

@ -5,7 +5,25 @@ class REST::TagSerializer < ActiveModel::Serializer
attributes :name, :url, :history
attribute :following, if: :current_user?
def url
tag_url(object)
end
def name
object.display_name
end
def following
if instance_options && instance_options[:relationships]
instance_options[:relationships].following_map[object.id] || false
else
TagFollow.where(tag_id: object.id, account_id: current_user.account_id).exists?
end
end
def current_user?
!current_user.nil?
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class REST::TranslationSerializer < ActiveModel::Serializer
attributes :content, :detected_source_language, :provider
def content
object.text
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
class REST::V1::FilterSerializer < ActiveModel::Serializer
attributes :id, :phrase, :context, :whole_word, :expires_at,
:irreversible
delegate :context, :expires_at, to: :custom_filter
def id
object.id.to_s
end
def phrase
object.keyword
end
def irreversible
custom_filter.irreversible?
end
private
def custom_filter
object.custom_filter
end
end

View file

@ -0,0 +1,106 @@
# frozen_string_literal: true
class REST::V1::InstanceSerializer < ActiveModel::Serializer
include RoutingHelper
attributes :uri, :title, :short_description, :description, :email,
:version, :urls, :stats, :thumbnail,
: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(:'@1x')) : full_pack_url('media/images/preview.png')
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
{
accounts: {
max_featured_tags: FeaturedTag::LIMIT,
},
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