Improve admin UI for custom emojis, add copy/disable/enable (#5231)
This commit is contained in:
		| @@ -2,8 +2,10 @@ | ||||
|  | ||||
| module Admin | ||||
|   class CustomEmojisController < BaseController | ||||
|     before_action :set_custom_emoji, except: [:index, :new, :create] | ||||
|  | ||||
|     def index | ||||
|       @custom_emojis = CustomEmoji.local | ||||
|       @custom_emojis = filtered_custom_emojis.page(params[:page]) | ||||
|     end | ||||
|  | ||||
|     def new | ||||
| @@ -21,14 +23,50 @@ module Admin | ||||
|     end | ||||
|  | ||||
|     def destroy | ||||
|       CustomEmoji.find(params[:id]).destroy | ||||
|       @custom_emoji.destroy | ||||
|       redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg') | ||||
|     end | ||||
|  | ||||
|     def copy | ||||
|       emoji = @custom_emoji.dup | ||||
|       emoji.domain = nil | ||||
|  | ||||
|       if emoji.save | ||||
|         redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.copied_msg') | ||||
|       else | ||||
|         redirect_to admin_custom_emojis_path, alert: I18n.t('admin.custom_emojis.copy_failed_msg') | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     def enable | ||||
|       @custom_emoji.update!(disabled: false) | ||||
|       redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.enabled_msg') | ||||
|     end | ||||
|  | ||||
|     def disable | ||||
|       @custom_emoji.update!(disabled: true) | ||||
|       redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.disabled_msg') | ||||
|     end | ||||
|  | ||||
|     private | ||||
|  | ||||
|     def set_custom_emoji | ||||
|       @custom_emoji = CustomEmoji.find(params[:id]) | ||||
|     end | ||||
|  | ||||
|     def resource_params | ||||
|       params.require(:custom_emoji).permit(:shortcode, :image) | ||||
|     end | ||||
|  | ||||
|     def filtered_custom_emojis | ||||
|       CustomEmojiFilter.new(filter_params).results | ||||
|     end | ||||
|  | ||||
|     def filter_params | ||||
|       params.permit( | ||||
|         :local, | ||||
|         :remote | ||||
|       ) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -4,6 +4,6 @@ class Api::V1::CustomEmojisController < Api::BaseController | ||||
|   respond_to :json | ||||
|  | ||||
|   def index | ||||
|     render json: CustomEmoji.local, each_serializer: REST::CustomEmojiSerializer | ||||
|     render json: CustomEmoji.local.where(disabled: false), each_serializer: REST::CustomEmojiSerializer | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -9,9 +9,11 @@ class AccountFilter | ||||
|  | ||||
|   def results | ||||
|     scope = Account.alphabetic | ||||
|  | ||||
|     params.each do |key, value| | ||||
|       scope.merge!(scope_for(key, value)) if value.present? | ||||
|     end | ||||
|  | ||||
|     scope | ||||
|   end | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #  image_updated_at   :datetime | ||||
| #  created_at         :datetime         not null | ||||
| #  updated_at         :datetime         not null | ||||
| #  disabled           :boolean          default(FALSE), not null | ||||
| # | ||||
|  | ||||
| class CustomEmoji < ApplicationRecord | ||||
| @@ -26,10 +27,16 @@ class CustomEmoji < ApplicationRecord | ||||
|   validates_attachment :image, content_type: { content_type: 'image/png' }, presence: true, size: { in: 0..50.kilobytes } | ||||
|   validates :shortcode, uniqueness: { scope: :domain }, format: { with: /\A#{SHORTCODE_RE_FRAGMENT}\z/ }, length: { minimum: 2 } | ||||
|  | ||||
|   scope :local, -> { where(domain: nil) } | ||||
|   scope :local,      -> { where(domain: nil) } | ||||
|   scope :remote,     -> { where.not(domain: nil) } | ||||
|   scope :alphabetic, -> { order(domain: :asc, shortcode: :asc) } | ||||
|  | ||||
|   include Remotable | ||||
|  | ||||
|   def local? | ||||
|     domain.nil? | ||||
|   end | ||||
|  | ||||
|   class << self | ||||
|     def from_text(text, domain) | ||||
|       return [] if text.blank? | ||||
| @@ -38,7 +45,7 @@ class CustomEmoji < ApplicationRecord | ||||
|  | ||||
|       return [] if shortcodes.empty? | ||||
|  | ||||
|       where(shortcode: shortcodes, domain: domain) | ||||
|       where(shortcode: shortcodes, domain: domain, disabled: false) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|   | ||||
							
								
								
									
										34
									
								
								app/models/custom_emoji_filter.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/models/custom_emoji_filter.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class CustomEmojiFilter | ||||
|   attr_reader :params | ||||
|  | ||||
|   def initialize(params) | ||||
|     @params = params | ||||
|   end | ||||
|  | ||||
|   def results | ||||
|     scope = CustomEmoji.alphabetic | ||||
|  | ||||
|     params.each do |key, value| | ||||
|       scope.merge!(scope_for(key, value)) if value.present? | ||||
|     end | ||||
|  | ||||
|     scope | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def scope_for(key, value) | ||||
|     case key.to_s | ||||
|     when 'local' | ||||
|       CustomEmoji.local | ||||
|     when 'remote' | ||||
|       CustomEmoji.remote | ||||
|     when 'by_domain' | ||||
|       CustomEmoji.where(domain: value) | ||||
|     else | ||||
|       raise "Unknown filter: #{key}" | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -3,5 +3,18 @@ | ||||
|     = image_tag custom_emoji.image.url, class: 'emojione', alt: ":#{custom_emoji.shortcode}:" | ||||
|   %td | ||||
|     %samp= ":#{custom_emoji.shortcode}:" | ||||
|   %td | ||||
|     - if custom_emoji.local? | ||||
|       = t('admin.accounts.location.local') | ||||
|     - else | ||||
|       = custom_emoji.domain | ||||
|   %td | ||||
|     - unless custom_emoji.local? | ||||
|       = table_link_to 'copy', t('admin.custom_emojis.copy'), copy_admin_custom_emoji_path(custom_emoji), method: :post | ||||
|   %td | ||||
|     - if custom_emoji.disabled? | ||||
|       = table_link_to 'power-off', t('admin.custom_emojis.enable'), enable_admin_custom_emoji_path(custom_emoji), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } | ||||
|     - else | ||||
|       = table_link_to 'power-off', t('admin.custom_emojis.disable'), disable_admin_custom_emoji_path(custom_emoji), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } | ||||
|   %td | ||||
|     = table_link_to 'times', t('admin.custom_emojis.delete'), admin_custom_emoji_path(custom_emoji), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } | ||||
|   | ||||
| @@ -1,14 +1,34 @@ | ||||
| - content_for :page_title do | ||||
|   = t('admin.custom_emojis.title') | ||||
|  | ||||
| .filters | ||||
|   .filter-subset | ||||
|     %strong= t('admin.accounts.location.title') | ||||
|     %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} | ||||
|         - else | ||||
|           = filter_link_to t('admin.accounts.location.local'), local: '1', remote: nil | ||||
|       %li | ||||
|         - if selected? remote: '1', local: nil | ||||
|           = filter_link_to t('admin.accounts.location.remote'), {remote: nil, local: nil}, {remote: '1', local: nil} | ||||
|         - else | ||||
|           = filter_link_to t('admin.accounts.location.remote'), remote: '1', local: nil | ||||
|  | ||||
| .table-wrapper | ||||
|   %table.table | ||||
|     %thead | ||||
|       %tr | ||||
|         %th= t('admin.custom_emojis.emoji') | ||||
|         %th= t('admin.custom_emojis.shortcode') | ||||
|         %th= t('admin.accounts.domain') | ||||
|         %th | ||||
|         %th | ||||
|         %th | ||||
|     %tbody | ||||
|       = render @custom_emojis | ||||
|  | ||||
| = paginate @custom_emojis | ||||
| = link_to t('admin.custom_emojis.upload'), new_admin_custom_emoji_path, class: 'button' | ||||
|   | ||||
| @@ -1,5 +1,81 @@ | ||||
| { | ||||
|   "ignored_warnings": [ | ||||
|     { | ||||
|       "warning_type": "Cross-Site Scripting", | ||||
|       "warning_code": 4, | ||||
|       "fingerprint": "0adbe361b91afff22ba51e5fc2275ec703cc13255a0cb3eecd8dab223ab9f61e", | ||||
|       "check_name": "LinkToHref", | ||||
|       "message": "Potentially unsafe model attribute in link_to href", | ||||
|       "file": "app/views/admin/accounts/show.html.haml", | ||||
|       "line": 122, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", | ||||
|       "code": "link_to(Account.find(params[:id]).inbox_url, Account.find(params[:id]).inbox_url)", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":13,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/accounts/show" | ||||
|       }, | ||||
|       "user_input": "Account.find(params[:id]).inbox_url", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Cross-Site Scripting", | ||||
|       "warning_code": 4, | ||||
|       "fingerprint": "1fc29c578d0c89bf13bd5476829d272d54cd06b92ccf6df18568fa1f2674926e", | ||||
|       "check_name": "LinkToHref", | ||||
|       "message": "Potentially unsafe model attribute in link_to href", | ||||
|       "file": "app/views/admin/accounts/show.html.haml", | ||||
|       "line": 128, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", | ||||
|       "code": "link_to(Account.find(params[:id]).shared_inbox_url, Account.find(params[:id]).shared_inbox_url)", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":13,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/accounts/show" | ||||
|       }, | ||||
|       "user_input": "Account.find(params[:id]).shared_inbox_url", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Cross-Site Scripting", | ||||
|       "warning_code": 4, | ||||
|       "fingerprint": "2129d4c1e63a351d28d8d2937ff0b50237809c3df6725c0c5ef82b881dbb2086", | ||||
|       "check_name": "LinkToHref", | ||||
|       "message": "Potentially unsafe model attribute in link_to href", | ||||
|       "file": "app/views/admin/accounts/show.html.haml", | ||||
|       "line": 35, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", | ||||
|       "code": "link_to(Account.find(params[:id]).url, Account.find(params[:id]).url)", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":13,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/accounts/show" | ||||
|       }, | ||||
|       "user_input": "Account.find(params[:id]).url", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Dynamic Render Path", | ||||
|       "warning_code": 15, | ||||
|       "fingerprint": "3b0a20b08aef13cf8cf865384fae0cfd3324d8200a83262bf4abbc8091b5fec5", | ||||
|       "check_name": "Render", | ||||
|       "message": "Render path contains parameter value", | ||||
|       "file": "app/views/admin/custom_emojis/index.html.haml", | ||||
|       "line": 31, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", | ||||
|       "code": "render(action => filtered_custom_emojis.page(params[:page]), {})", | ||||
|       "render_path": [{"type":"controller","class":"Admin::CustomEmojisController","method":"index","line":9,"file":"app/controllers/admin/custom_emojis_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/custom_emojis/index" | ||||
|       }, | ||||
|       "user_input": "params[:page]", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Dynamic Render Path", | ||||
|       "warning_code": 15, | ||||
| @@ -19,6 +95,44 @@ | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Cross-Site Scripting", | ||||
|       "warning_code": 4, | ||||
|       "fingerprint": "64b5b2a02ede9c2b3598881eb5a466d63f7d27fe0946aa00d570111ec7338d2e", | ||||
|       "check_name": "LinkToHref", | ||||
|       "message": "Potentially unsafe model attribute in link_to href", | ||||
|       "file": "app/views/admin/accounts/show.html.haml", | ||||
|       "line": 131, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", | ||||
|       "code": "link_to(Account.find(params[:id]).followers_url, Account.find(params[:id]).followers_url)", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":13,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/accounts/show" | ||||
|       }, | ||||
|       "user_input": "Account.find(params[:id]).followers_url", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Cross-Site Scripting", | ||||
|       "warning_code": 4, | ||||
|       "fingerprint": "82f7b0d09beb3ab68e0fa16be63cedf4e820f2490326e9a1cec05761d92446cd", | ||||
|       "check_name": "LinkToHref", | ||||
|       "message": "Potentially unsafe model attribute in link_to href", | ||||
|       "file": "app/views/admin/accounts/show.html.haml", | ||||
|       "line": 106, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", | ||||
|       "code": "link_to(Account.find(params[:id]).salmon_url, Account.find(params[:id]).salmon_url)", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":13,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/accounts/show" | ||||
|       }, | ||||
|       "user_input": "Account.find(params[:id]).salmon_url", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Dynamic Render Path", | ||||
|       "warning_code": 15, | ||||
| @@ -26,7 +140,7 @@ | ||||
|       "check_name": "Render", | ||||
|       "message": "Render path contains parameter value", | ||||
|       "file": "app/views/admin/accounts/index.html.haml", | ||||
|       "line": 63, | ||||
|       "line": 64, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", | ||||
|       "code": "render(action => filtered_accounts.page(params[:page]), {})", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"index","line":10,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
| @@ -38,6 +152,25 @@ | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Cross-Site Scripting", | ||||
|       "warning_code": 4, | ||||
|       "fingerprint": "bb0ad5c4a42e06e3846c2089ff5269c17f65483a69414f6ce65eecf2bb11fab7", | ||||
|       "check_name": "LinkToHref", | ||||
|       "message": "Potentially unsafe model attribute in link_to href", | ||||
|       "file": "app/views/admin/accounts/show.html.haml", | ||||
|       "line": 95, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", | ||||
|       "code": "link_to(Account.find(params[:id]).remote_url, Account.find(params[:id]).remote_url)", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":13,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/accounts/show" | ||||
|       }, | ||||
|       "user_input": "Account.find(params[:id]).remote_url", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Redirect", | ||||
|       "warning_code": 18, | ||||
| @@ -65,7 +198,7 @@ | ||||
|       "check_name": "Render", | ||||
|       "message": "Render path contains parameter value", | ||||
|       "file": "app/views/admin/reports/index.html.haml", | ||||
|       "line": 24, | ||||
|       "line": 25, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", | ||||
|       "code": "render(action => filtered_reports.page(params[:page]), {})", | ||||
|       "render_path": [{"type":"controller","class":"Admin::ReportsController","method":"index","line":9,"file":"app/controllers/admin/reports_controller.rb"}], | ||||
| @@ -77,6 +210,45 @@ | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "SQL Injection", | ||||
|       "warning_code": 0, | ||||
|       "fingerprint": "cd440d9d0bcb76225f4142030cec0bdec6ad119c537c108c9d514bf87bc34d29", | ||||
|       "check_name": "SQL", | ||||
|       "message": "Possible SQL injection", | ||||
|       "file": "lib/mastodon/timestamp_ids.rb", | ||||
|       "line": 69, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/sql_injection/", | ||||
|       "code": "ActiveRecord::Base.connection.execute(\"          CREATE OR REPLACE FUNCTION timestamp_id(table_name text)\\n          RETURNS bigint AS\\n          $$\\n            DECLARE\\n              time_part bigint;\\n              sequence_base bigint;\\n              tail bigint;\\n            BEGIN\\n              -- Our ID will be composed of the following:\\n              -- 6 bytes (48 bits) of millisecond-level timestamp\\n              -- 2 bytes (16 bits) of sequence data\\n\\n              -- The 'sequence data' is intended to be unique within a\\n              -- given millisecond, yet obscure the 'serial number' of\\n              -- this row.\\n\\n              -- To do this, we hash the following data:\\n              -- * Table name (if provided, skipped if not)\\n              -- * Secret salt (should not be guessable)\\n              -- * Timestamp (again, millisecond-level granularity)\\n\\n              -- We then take the first two bytes of that value, and add\\n              -- the lowest two bytes of the table ID sequence number\\n              -- (`table_name`_id_seq). This means that even if we insert\\n              -- two rows at the same millisecond, they will have\\n              -- distinct 'sequence data' portions.\\n\\n              -- If this happens, and an attacker can see both such IDs,\\n              -- they can determine which of the two entries was inserted\\n              -- first, but not the total number of entries in the table\\n              -- (even mod 2**16).\\n\\n              -- The table name is included in the hash to ensure that\\n              -- different tables derive separate sequence bases so rows\\n              -- inserted in the same millisecond in different tables do\\n              -- not reveal the table ID sequence number for one another.\\n\\n              -- The secret salt is included in the hash to ensure that\\n              -- external users cannot derive the sequence base given the\\n              -- timestamp and table name, which would allow them to\\n              -- compute the table ID sequence number.\\n\\n              time_part := (\\n                -- Get the time in milliseconds\\n                ((date_part('epoch', now()) * 1000))::bigint\\n                -- And shift it over two bytes\\n                << 16);\\n\\n              sequence_base := (\\n                'x' ||\\n                -- Take the first two bytes (four hex characters)\\n                substr(\\n                  -- Of the MD5 hash of the data we documented\\n                  md5(table_name ||\\n                    '#{SecureRandom.hex(16)}' ||\\n                    time_part::text\\n                  ),\\n                  1, 4\\n                )\\n              -- And turn it into a bigint\\n              )::bit(16)::bigint;\\n\\n              -- Finally, add our sequence number to our base, and chop\\n              -- it to the last two bytes\\n              tail := (\\n                (sequence_base + nextval(table_name || '_id_seq'))\\n                & 65535);\\n\\n              -- Return the time part and the sequence part. OR appears\\n              -- faster here than addition, but they're equivalent:\\n              -- time_part has no trailing two bytes, and tail is only\\n              -- the last two bytes.\\n              RETURN time_part | tail;\\n            END\\n          $$ LANGUAGE plpgsql VOLATILE;\\n\")", | ||||
|       "render_path": null, | ||||
|       "location": { | ||||
|         "type": "method", | ||||
|         "class": "Mastodon::TimestampIds", | ||||
|         "method": "s(:self).define_timestamp_id" | ||||
|       }, | ||||
|       "user_input": "SecureRandom.hex(16)", | ||||
|       "confidence": "Medium", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Cross-Site Scripting", | ||||
|       "warning_code": 4, | ||||
|       "fingerprint": "e04aafe1e06cf8317fb6ac0a7f35783e45aa1274272ee6eaf28d39adfdad489b", | ||||
|       "check_name": "LinkToHref", | ||||
|       "message": "Potentially unsafe model attribute in link_to href", | ||||
|       "file": "app/views/admin/accounts/show.html.haml", | ||||
|       "line": 125, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", | ||||
|       "code": "link_to(Account.find(params[:id]).outbox_url, Account.find(params[:id]).outbox_url)", | ||||
|       "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":13,"file":"app/controllers/admin/accounts_controller.rb"}], | ||||
|       "location": { | ||||
|         "type": "template", | ||||
|         "template": "admin/accounts/show" | ||||
|       }, | ||||
|       "user_input": "Account.find(params[:id]).outbox_url", | ||||
|       "confidence": "Weak", | ||||
|       "note": "" | ||||
|     }, | ||||
|     { | ||||
|       "warning_type": "Dynamic Render Path", | ||||
|       "warning_code": 15, | ||||
| @@ -84,7 +256,7 @@ | ||||
|       "check_name": "Render", | ||||
|       "message": "Render path contains parameter value", | ||||
|       "file": "app/views/stream_entries/show.html.haml", | ||||
|       "line": 23, | ||||
|       "line": 21, | ||||
|       "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", | ||||
|       "code": "render(partial => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { :locals => ({ Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :include_threads => true }) })", | ||||
|       "render_path": [{"type":"controller","class":"StatusesController","method":"show","line":20,"file":"app/controllers/statuses_controller.rb"}], | ||||
| @@ -97,6 +269,6 @@ | ||||
|       "note": "" | ||||
|     } | ||||
|   ], | ||||
|   "updated": "2017-08-30 05:14:04 +0200", | ||||
|   "brakeman_version": "3.7.2" | ||||
|   "updated": "2017-10-05 20:06:40 +0200", | ||||
|   "brakeman_version": "4.0.1" | ||||
| } | ||||
|   | ||||
| @@ -137,7 +137,7 @@ de: | ||||
|       reject_media: Mediendateien ablehnen | ||||
|       reject_media_hint: Entfernt lokal gespeicherte Mediendateien und verhindert deren künftiges Herunterladen. Für Sperren irrelevant | ||||
|       severities: | ||||
|         none: Kein | ||||
|         noop: Kein | ||||
|         silence: Stummschaltung | ||||
|         suspend: Sperren | ||||
|       severity: Schweregrad | ||||
| @@ -180,7 +180,7 @@ de: | ||||
|       nsfw: | ||||
|         'false': Medienanhänge wieder anzeigen | ||||
|         'true': Medienanhänge verbergen | ||||
|       report: "Meldung #%{id}" | ||||
|       report: 'Meldung #%{id}' | ||||
|       report_contents: Inhalt | ||||
|       reported_account: Gemeldetes Konto | ||||
|       reported_by: Gemeldet von | ||||
| @@ -386,7 +386,7 @@ de: | ||||
|       body: "%{name} hat dich erwähnt:" | ||||
|       subject: "%{name} hat dich erwähnt" | ||||
|     reblog: | ||||
|       body: '%{name} hat deinen Beitrag geteilt:' | ||||
|       body: "%{name} hat deinen Beitrag geteilt:" | ||||
|       subject: "%{name} hat deinen Beitrag geteilt" | ||||
|   number: | ||||
|     human: | ||||
|   | ||||
| @@ -109,10 +109,17 @@ en: | ||||
|       username: Username | ||||
|       web: Web | ||||
|     custom_emojis: | ||||
|       copied_msg: Successfully created local copy of the emoji | ||||
|       copy: Copy | ||||
|       copy_failed_msg: Could not make a local copy of that emoji | ||||
|       created_msg: Emoji successfully created! | ||||
|       delete: Delete | ||||
|       destroyed_msg: Emojo successfully destroyed! | ||||
|       disable: Disable | ||||
|       disabled_msg: Successfully disabled that emoji | ||||
|       emoji: Emoji | ||||
|       enable: Enable | ||||
|       enabled_msg: Successfully enabled that emoji | ||||
|       image_hint: PNG up to 50KB | ||||
|       new: | ||||
|         title: Add new custom emoji | ||||
|   | ||||
| @@ -139,7 +139,13 @@ Rails.application.routes.draw do | ||||
|       resource :two_factor_authentication, only: [:destroy] | ||||
|     end | ||||
|  | ||||
|     resources :custom_emojis, only: [:index, :new, :create, :destroy] | ||||
|     resources :custom_emojis, only: [:index, :new, :create, :destroy] do | ||||
|       member do | ||||
|         post :copy | ||||
|         post :enable | ||||
|         post :disable | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   get '/admin', to: redirect('/admin/settings/edit', status: 302) | ||||
|   | ||||
							
								
								
									
										15
									
								
								db/migrate/20171005171936_add_disabled_to_custom_emojis.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								db/migrate/20171005171936_add_disabled_to_custom_emojis.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| require Rails.root.join('lib', 'mastodon', 'migration_helpers') | ||||
|  | ||||
| class AddDisabledToCustomEmojis < ActiveRecord::Migration[5.1] | ||||
|   include Mastodon::MigrationHelpers | ||||
|  | ||||
|   disable_ddl_transaction! | ||||
|  | ||||
|   def up | ||||
|     safety_assured { add_column_with_default :custom_emojis, :disabled, :bool, default: false } | ||||
|   end | ||||
|  | ||||
|   def down | ||||
|     remove_column :custom_emojis, :disabled | ||||
|   end | ||||
| end | ||||
| @@ -10,7 +10,7 @@ | ||||
| # | ||||
| # It's strongly recommended that you check this file into your version control system. | ||||
|  | ||||
| ActiveRecord::Schema.define(version: 20170928082043) do | ||||
| ActiveRecord::Schema.define(version: 20171005171936) do | ||||
|  | ||||
|   # These are extensions that must be enabled in order to support this database | ||||
|   enable_extension "plpgsql" | ||||
| @@ -98,6 +98,7 @@ ActiveRecord::Schema.define(version: 20170928082043) do | ||||
|     t.datetime "image_updated_at" | ||||
|     t.datetime "created_at", null: false | ||||
|     t.datetime "updated_at", null: false | ||||
|     t.boolean "disabled", default: false, null: false | ||||
|     t.index ["shortcode", "domain"], name: "index_custom_emojis_on_shortcode_and_domain", unique: true | ||||
|   end | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user