diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/admin/custom_emojis_controller.rb | 78 | ||||
-rw-r--r-- | app/controllers/custom_emojis_controller.rb | 97 | ||||
-rw-r--r-- | app/models/concerns/account_associations.rb | 3 | ||||
-rw-r--r-- | app/models/custom_emoji.rb | 8 | ||||
-rw-r--r-- | app/models/custom_emoji_filter.rb | 9 | ||||
-rw-r--r-- | app/models/form/custom_emoji_batch.rb | 39 | ||||
-rw-r--r-- | app/policies/custom_emoji_policy.rb | 36 | ||||
-rw-r--r-- | app/views/custom_emojis/_custom_emoji.html.haml (renamed from app/views/admin/custom_emojis/_custom_emoji.html.haml) | 1 | ||||
-rw-r--r-- | app/views/custom_emojis/index.html.haml (renamed from app/views/admin/custom_emojis/index.html.haml) | 41 | ||||
-rw-r--r-- | app/views/custom_emojis/new.html.haml (renamed from app/views/admin/custom_emojis/new.html.haml) | 2 |
10 files changed, 208 insertions, 106 deletions
diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb deleted file mode 100644 index 71efb543e..000000000 --- a/app/controllers/admin/custom_emojis_controller.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: true - -module Admin - class CustomEmojisController < BaseController - def index - authorize :custom_emoji, :index? - - @custom_emojis = filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page]) - @form = Form::CustomEmojiBatch.new - end - - def new - authorize :custom_emoji, :create? - - @custom_emoji = CustomEmoji.new - end - - def create - authorize :custom_emoji, :create? - - @custom_emoji = CustomEmoji.new(resource_params) - - if @custom_emoji.save - log_action :create, @custom_emoji - redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.created_msg') - else - render :new - end - end - - def batch - @form = Form::CustomEmojiBatch.new(form_custom_emoji_batch_params.merge(current_account: current_account, action: action_from_button)) - @form.save - rescue ActionController::ParameterMissing - flash[:alert] = I18n.t('admin.accounts.no_account_selected') - rescue Mastodon::NotPermittedError - flash[:alert] = I18n.t('admin.custom_emojis.not_permitted') - ensure - redirect_to admin_custom_emojis_path(filter_params) - end - - private - - def resource_params - params.require(:custom_emoji).permit(:shortcode, :image, :visible_in_picker) - end - - def filtered_custom_emojis - CustomEmojiFilter.new(filter_params).results - end - - def filter_params - params.slice(:page, *CustomEmojiFilter::KEYS).permit(:page, *CustomEmojiFilter::KEYS) - end - - def action_from_button - if params[:update] - 'update' - elsif params[:list] - 'list' - elsif params[:unlist] - 'unlist' - elsif params[:enable] - 'enable' - elsif params[:disable] - 'disable' - elsif params[:copy] - 'copy' - elsif params[:delete] - 'delete' - end - end - - def form_custom_emoji_batch_params - params.require(:form_custom_emoji_batch).permit(:action, :category_id, :category_name, custom_emoji_ids: []) - end - end -end diff --git a/app/controllers/custom_emojis_controller.rb b/app/controllers/custom_emojis_controller.rb new file mode 100644 index 000000000..0ef8d0a50 --- /dev/null +++ b/app/controllers/custom_emojis_controller.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +class CustomEmojisController < ApplicationController + include Authorization + include AccountableConcern + + layout 'admin' + + before_action :authenticate_user! + before_action :set_pack + before_action :set_body_classes + + def index + authorize :custom_emoji, :index? + + @custom_emojis = filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page]) + @form = Form::CustomEmojiBatch.new + end + + def new + authorize :custom_emoji, :create? + + @custom_emoji = CustomEmoji.new(account: current_account) + end + + def create + authorize :custom_emoji, :create? + + @custom_emoji = CustomEmoji.new(resource_params.merge(account: current_account)) + + if @custom_emoji.save + log_action :create, @custom_emoji + redirect_to custom_emojis_path, notice: I18n.t('admin.custom_emojis.created_msg') + else + render :new + end + end + + def batch + @form = Form::CustomEmojiBatch.new(form_custom_emoji_batch_params.merge(current_account: current_account, action: action_from_button)) + @form.save + rescue ActionController::ParameterMissing + flash[:alert] = I18n.t('admin.accounts.no_account_selected') + rescue Mastodon::NotPermittedError + flash[:alert] = I18n.t('admin.custom_emojis.not_permitted') + ensure + redirect_to custom_emojis_path(filter_params) + end + + private + + def resource_params + params.require(:custom_emoji).permit(:shortcode, :image, :visible_in_picker) + end + + def filtered_custom_emojis + CustomEmojiFilter.new(filter_params, current_account).results + end + + def filter_params + params.slice(:page, *CustomEmojiFilter::KEYS).permit(:page, *CustomEmojiFilter::KEYS) + end + + def action_from_button + if params[:update] + 'update' + elsif params[:list] + 'list' + elsif params[:unlist] + 'unlist' + elsif params[:enable] + 'enable' + elsif params[:disable] + 'disable' + elsif params[:copy] + 'copy' + elsif params[:delete] + 'delete' + elsif params[:claim] + 'claim' + elsif params[:unclaim] + 'unclaim' + end + end + + def form_custom_emoji_batch_params + params.require(:form_custom_emoji_batch).permit(:action, :category_id, :category_name, custom_emoji_ids: []) + end + + def set_pack + use_pack 'settings' + end + + def set_body_classes + @body_classes = 'admin' + end +end diff --git a/app/models/concerns/account_associations.rb b/app/models/concerns/account_associations.rb index a8b024346..71947fc22 100644 --- a/app/models/concerns/account_associations.rb +++ b/app/models/concerns/account_associations.rb @@ -78,5 +78,8 @@ module AccountAssociations # Collection items has_many :collection_items, inverse_of: :account, dependent: :destroy + + # Custom emojis + has_many :custom_emojis, inverse_of: :account, dependent: :nullify end end diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb index 7cb03b819..c819288ba 100644 --- a/app/models/custom_emoji.rb +++ b/app/models/custom_emoji.rb @@ -18,6 +18,7 @@ # visible_in_picker :boolean default(TRUE), not null # category_id :bigint(8) # image_storage_schema_version :integer +# account_id :bigint(8) # class CustomEmoji < ApplicationRecord @@ -32,6 +33,7 @@ class CustomEmoji < ApplicationRecord IMAGE_MIME_TYPES = %w(image/png image/gif).freeze belongs_to :category, class_name: 'CustomEmojiCategory', optional: true + belongs_to :account, inverse_of: :custom_emojis, optional: true has_one :local_counterpart, -> { where(domain: nil) }, class_name: 'CustomEmoji', primary_key: :shortcode, foreign_key: :shortcode has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce -strip' } } @@ -46,6 +48,7 @@ class CustomEmoji < ApplicationRecord scope :alphabetic, -> { order(domain: :asc, shortcode: :asc) } scope :by_domain_and_subdomains, ->(domain) { where(domain: domain).or(where(arel_table[:domain].matches('%.' + domain))) } scope :listed, -> { local.where(disabled: false).where(visible_in_picker: true) } + scope :owned_by, ->(account) { where(account: account) } remotable_attachment :image, LIMIT @@ -61,8 +64,11 @@ class CustomEmoji < ApplicationRecord :emoji end - def copy! + def copy!(current_account = nil) copy = self.class.find_or_initialize_by(domain: nil, shortcode: shortcode) + return copy if copy.account_id.present? && copy.account_id != current_account&.id + + copy.account = current_account copy.image = image copy.tap(&:save!) end diff --git a/app/models/custom_emoji_filter.rb b/app/models/custom_emoji_filter.rb index 414e1fcdd..58c888518 100644 --- a/app/models/custom_emoji_filter.rb +++ b/app/models/custom_emoji_filter.rb @@ -5,13 +5,16 @@ class CustomEmojiFilter local remote by_domain + claimed + unclaimed shortcode ).freeze attr_reader :params - def initialize(params) + def initialize(params, account) @params = params + @account = account end def results @@ -36,6 +39,10 @@ class CustomEmojiFilter CustomEmoji.remote when 'by_domain' CustomEmoji.where(domain: value.strip.downcase) + when 'claimed' + CustomEmoji.where(account: @account) + when 'unclaimed' + CustomEmoji.where(account: nil) when 'shortcode' CustomEmoji.search(value.strip) else diff --git a/app/models/form/custom_emoji_batch.rb b/app/models/form/custom_emoji_batch.rb index f4fa84c10..54a15dc18 100644 --- a/app/models/form/custom_emoji_batch.rb +++ b/app/models/form/custom_emoji_batch.rb @@ -24,13 +24,17 @@ class Form::CustomEmojiBatch copy! when 'delete' delete! + when 'claim' + claim! + when 'unclaim' + unclaim! end end private - def custom_emojis - @custom_emojis ||= CustomEmoji.where(id: custom_emoji_ids) + def custom_emojis(include_all = false) + @custom_emojis ||= (include_all || current_account&.user&.staff? ? CustomEmoji.where(id: custom_emoji_ids) : CustomEmoji.local.where(id: custom_emoji_ids, account: current_account)) end def update! @@ -40,10 +44,12 @@ class Form::CustomEmojiBatch if category_id.present? CustomEmojiCategory.find(category_id) elsif category_name.present? - CustomEmojiCategory.find_or_create_by!(name: category_name) + CustomEmojiCategory.find_or_create_by!(name: current_account&.user&.staff? ? category_name.strip : "(@#{current_account.username}) #{category_name}".rstrip) end end + return if category.name.start_with?('(@') && !category.name.start_with?("(@#{current_account.username}) ") + custom_emojis.each do |custom_emoji| custom_emoji.update(category_id: category&.id) log_action :update, custom_emoji @@ -87,10 +93,10 @@ class Form::CustomEmojiBatch end def copy! - custom_emojis.each { |custom_emoji| authorize(custom_emoji, :copy?) } + custom_emojis(true).each { |custom_emoji| authorize(custom_emoji, :copy?) } custom_emojis.each do |custom_emoji| - copied_custom_emoji = custom_emoji.copy! + copied_custom_emoji = custom_emoji.copy!(current_account) log_action :create, copied_custom_emoji end end @@ -103,4 +109,27 @@ class Form::CustomEmojiBatch log_action :destroy, custom_emoji end end + + def claim! + custom_emojis(true).each { |custom_emoji| authorize(custom_emoji, :claim?) } + + custom_emojis.each do |custom_emoji| + if custom_emoji.local? + custom_emoji.update(account: current_account) + log_action :update, custom_emoji + else + copied_custom_emoji = custom_emoji.copy!(current_account) + log_action :create, copied_custom_emoji + end + end + end + + def unclaim! + custom_emojis.each { |custom_emoji| authorize(custom_emoji, :unclaim?) } + + custom_emojis.each do |custom_emoji| + custom_emoji.update(account: nil) + log_action :update, custom_emoji + end + end end diff --git a/app/policies/custom_emoji_policy.rb b/app/policies/custom_emoji_policy.rb index a8c3cbc73..7e585a3d6 100644 --- a/app/policies/custom_emoji_policy.rb +++ b/app/policies/custom_emoji_policy.rb @@ -2,30 +2,52 @@ class CustomEmojiPolicy < ApplicationPolicy def index? - staff? + user_signed_in? end def create? - admin? + user_signed_in? end def update? - admin? + user_signed_in? && owned? end def copy? - admin? + staff? || (user_signed_in? && new_or_owned?) end def enable? - staff? + user_signed_in? && owned? end def disable? - staff? + user_signed_in? && owned? end def destroy? - admin? + user_signed_in? && owned? + end + + def claim? + staff? || claimable? + end + + def unclaim? + user_signed_in? && owned? + end + + private + + def owned? + staff? || (current_account.present? && record.account_id == current_account.id) + end + + def new_or_owned? + !CustomEmoji.where(domain: nil, shortcode: record.shortcode).where('account_id IS NULL OR account_id != ?', current_account.id).exists? + end + + def claimable? + record.local? ? record.account_id.blank? || record.account_id == current_account.id : new_or_owned? end end diff --git a/app/views/admin/custom_emojis/_custom_emoji.html.haml b/app/views/custom_emojis/_custom_emoji.html.haml index 526c844e9..e124373c6 100644 --- a/app/views/admin/custom_emojis/_custom_emoji.html.haml +++ b/app/views/custom_emojis/_custom_emoji.html.haml @@ -7,6 +7,7 @@ .batch-table__row__content__text %samp= ":#{custom_emoji.shortcode}:" + %p.hint.muted-hint{ title: t('admin.custom_emojis.owner') }= custom_emoji.account_id.present? ? "@#{custom_emoji.account.username}" : t('admin.custom_emojis.unclaimed') if custom_emoji.local? - if custom_emoji.local? %span.account-role.bot= custom_emoji.category&.name || t('admin.custom_emojis.uncategorized') diff --git a/app/views/admin/custom_emojis/index.html.haml b/app/views/custom_emojis/index.html.haml index b6cf7ba64..f81d91d53 100644 --- a/app/views/admin/custom_emojis/index.html.haml +++ b/app/views/custom_emojis/index.html.haml @@ -3,7 +3,9 @@ - if can?(:create, :custom_emoji) - content_for :heading_actions do - = link_to t('admin.custom_emojis.upload'), new_admin_custom_emoji_path, class: 'button' + = link_to t('admin.custom_emojis.upload'), new_custom_emoji_path, class: 'button' + +%p= t('admin.custom_emojis.ownership_warning') .filters .filter-subset @@ -11,17 +13,27 @@ %ul %li= filter_link_to t('admin.accounts.location.all'), local: nil, remote: nil %li - - if selected? local: '1', remote: nil - = filter_link_to t('admin.accounts.location.local'), {local: nil, remote: nil}, {local: '1', remote: nil} + - if selected? local: '1', remote: nil, claimed: nil, unclaimed: nil + = filter_link_to t('admin.accounts.location.local'), {local: nil, remote: nil, claimed: nil, unclaimed: nil}, {local: '1', remote: nil, claimed: nil, unclaimed: nil} + - else + = filter_link_to t('admin.accounts.location.local'), local: '1', remote: nil, claimed: nil, unclaimed: nil + %li + - if selected? remote: '1', local: nil, claimed: nil, unclaimed: nil + = filter_link_to t('admin.accounts.location.remote'), {remote: nil, local: nil, claimed: nil, unclaimed: nil}, {remote: '1', local: nil, claimed: nil, unclaimed: nil} - else - = filter_link_to t('admin.accounts.location.local'), local: '1', remote: nil + = filter_link_to t('admin.accounts.location.remote'), remote: '1', local: nil, claimed: nil, unclained: nil %li - - if selected? remote: '1', local: nil - = filter_link_to t('admin.accounts.location.remote'), {remote: nil, local: nil}, {remote: '1', local: nil} + - if selected? local: '1', remote: nil, claimed: '1', unclaimed: nil + = filter_link_to t('admin.accounts.location.claimed'), {local: '1', remote: nil, claimed: nil, unclaimed: nil}, {local: '1', remote: nil, claimed: '1', unclaimed: nil} - else - = filter_link_to t('admin.accounts.location.remote'), remote: '1', local: nil + = filter_link_to t('admin.accounts.location.claimed'), local: '1', remote: nil, claimed: '1', unclaimed: nil + %li + - if selected? local: '1', remote: nil, claimed: nil, unclaimed: '1' + = filter_link_to t('admin.accounts.location.unclaimed'), {local: '1', remote: nil, claimed: nil, unclaimed: nil}, {local: '1', remote: nil, claimed: nil, unclaimed: '1'} + - else + = filter_link_to t('admin.accounts.location.unclaimed'), local: '1', remote: nil, claimed: nil, unclaimed: '1' -= form_tag admin_custom_emojis_url, method: 'GET', class: 'simple_form' do += form_tag custom_emojis_url, method: 'GET', class: 'simple_form' do .fields-group - CustomEmojiFilter::KEYS.each do |key| = hidden_field_tag key, params[key] if params[key].present? @@ -32,9 +44,9 @@ .actions %button.button= t('admin.accounts.search') - = link_to t('admin.accounts.reset'), admin_custom_emojis_path, class: 'button negative' + = link_to t('admin.accounts.reset'), custom_emojis_path, class: 'button negative' -= form_for(@form, url: batch_admin_custom_emojis_path) do |f| += form_for(@form, url: batch_custom_emojis_path) do |f| = hidden_field_tag :page, params[:page] || 1 - CustomEmojiFilter::KEYS.each do |key| @@ -45,6 +57,10 @@ %label.batch-table__toolbar__select.batch-checkbox-all = check_box_tag :batch_checkbox_all, nil, false .batch-table__toolbar__actions + = f.button safe_join([fa_icon('lock'), t('admin.custom_emojis.claim')]), name: :claim, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } + + = f.button safe_join([fa_icon('unlock'), t('admin.custom_emojis.unclaim')]), name: :unclaim, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } + - if params[:local] == '1' = f.button safe_join([fa_icon('save'), t('generic.save_changes')]), name: :update, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } @@ -56,10 +72,9 @@ = f.button safe_join([fa_icon('power-off'), t('admin.custom_emojis.disable')]), name: :disable, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } - - if can?(:destroy, :custom_emoji) - = f.button safe_join([fa_icon('times'), t('admin.custom_emojis.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } + = f.button safe_join([fa_icon('times'), t('admin.custom_emojis.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } - - if can?(:copy, :custom_emoji) && params[:local] != '1' + - if params[:local] != '1' = f.button safe_join([fa_icon('copy'), t('admin.custom_emojis.copy')]), name: :copy, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } - if params[:local] == '1' diff --git a/app/views/admin/custom_emojis/new.html.haml b/app/views/custom_emojis/new.html.haml index e15a07cb8..fe9d8fc64 100644 --- a/app/views/admin/custom_emojis/new.html.haml +++ b/app/views/custom_emojis/new.html.haml @@ -1,7 +1,7 @@ - content_for :page_title do = t('.title') -= simple_form_for @custom_emoji, url: admin_custom_emojis_path do |f| += simple_form_for @custom_emoji, url: custom_emojis_path do |f| = render 'shared/error_messages', object: @custom_emoji .fields-group |