From 0ef9d45d0581dddf2f325033c43721f42fcfca9e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 11 Sep 2017 23:50:37 +0200 Subject: Fix error when following locked accounts (#4896) --- app/controllers/api/v1/accounts_controller.rb | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'app/controllers') diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 656cacd8a..b3fc4e561 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -15,16 +15,9 @@ class Api::V1::AccountsController < Api::BaseController def follow FollowService.new.call(current_user.account, @account.acct) - unless @account.locked? - relationships = AccountRelationshipsPresenter.new( - [@account.id], - current_user.account_id, - following_map: { @account.id => true }, - requested_map: { @account.id => false } - ) - end + options = @account.locked? ? {} : { following_map: { @account.id => true }, requested_map: { @account.id => false } } - render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships + render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options) end def block @@ -58,7 +51,7 @@ class Api::V1::AccountsController < Api::BaseController @account = Account.find(params[:id]) end - def relationships - AccountRelationshipsPresenter.new([@account.id], current_user.account_id) + def relationships(options = {}) + AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options) end end -- cgit From da77f65c4684a8a9ee25c3e18f6f09824c765c2d Mon Sep 17 00:00:00 2001 From: nullkal Date: Wed, 13 Sep 2017 19:30:07 +0900 Subject: Add instance search feature (#4925) --- app/controllers/admin/instances_controller.rb | 12 +++++++++++- app/models/account.rb | 1 + app/models/instance_filter.rb | 28 +++++++++++++++++++++++++++ app/views/admin/instances/index.html.haml | 10 ++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 app/models/instance_filter.rb (limited to 'app/controllers') diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb index 3296e08db..22f02e5d0 100644 --- a/app/controllers/admin/instances_controller.rb +++ b/app/controllers/admin/instances_controller.rb @@ -14,8 +14,12 @@ module Admin private + def filtered_instances + InstanceFilter.new(filter_params).results + end + def paginated_instances - Account.remote.by_domain_accounts.page(params[:page]) + filtered_instances.page(params[:page]) end helper_method :paginated_instances @@ -27,5 +31,11 @@ module Admin def subscribeable_accounts Account.with_followers.remote.where(domain: params[:by_domain]) end + + def filter_params + params.permit( + :domain_name + ) + end end end diff --git a/app/models/account.rb b/app/models/account.rb index 864b3cb6e..f175c7081 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -104,6 +104,7 @@ class Account < ApplicationRecord scope :by_domain_accounts, -> { group(:domain).select(:domain, 'COUNT(*) AS accounts_count').order('accounts_count desc') } scope :matches_username, ->(value) { where(arel_table[:username].matches("#{value}%")) } scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) } + scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } delegate :email, :current_sign_in_ip, diff --git a/app/models/instance_filter.rb b/app/models/instance_filter.rb new file mode 100644 index 000000000..5073cf1fa --- /dev/null +++ b/app/models/instance_filter.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class InstanceFilter + attr_reader :params + + def initialize(params) + @params = params + end + + def results + scope = Account.remote.by_domain_accounts + 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 'domain_name' + Account.matches_domain(value) + else + raise "Unknown filter: #{key}" + end + end +end diff --git a/app/views/admin/instances/index.html.haml b/app/views/admin/instances/index.html.haml index edbd3b217..3314ce077 100644 --- a/app/views/admin/instances/index.html.haml +++ b/app/views/admin/instances/index.html.haml @@ -1,6 +1,16 @@ - content_for :page_title do = t('admin.instances.title') += form_tag admin_instances_url, method: 'GET', class: 'simple_form' do + .fields-group + - %i(domain_name).each do |key| + .input.string.optional + = text_field_tag key, params[key], class: 'string optional', placeholder: I18n.t("admin.instances.#{key}") + + .actions + %button= t('admin.instances.search') + = link_to t('admin.instances.reset'), admin_instances_path, class: 'button negative' + .table-wrapper %table.table %thead -- cgit From 9239e4ce4d4e958e62552d4a01183d0295c020f5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 14 Sep 2017 00:04:30 +0200 Subject: Uploads for admin site settings (#4913) * Improve OpenGraph tags for about pages * Add thumbnail admin setting * Fix error * Fix up --- app/controllers/admin/settings_controller.rb | 14 ++++++-- app/javascript/images/mastodon_small.jpg | Bin 25199 -> 0 bytes app/javascript/images/preview.jpg | Bin 0 -> 292252 bytes app/models/site_upload.rb | 44 +++++++++++++++++++++++ app/presenters/instance_presenter.rb | 4 +++ app/serializers/rest/instance_serializer.rb | 8 ++++- app/views/about/_og.html.haml | 10 ++++++ app/views/about/more.html.haml | 11 +----- app/views/about/show.html.haml | 11 +----- app/views/admin/settings/edit.html.haml | 5 +++ config/locales/en.yml | 3 ++ db/migrate/20170913000752_create_site_uploads.rb | 10 ++++++ db/schema.rb | 14 +++++++- spec/fabricators/site_upload_fabricator.rb | 3 ++ spec/models/site_upload_spec.rb | 5 +++ spec/views/about/show.html.haml_spec.rb | 9 ++--- 16 files changed, 123 insertions(+), 28 deletions(-) delete mode 100644 app/javascript/images/mastodon_small.jpg create mode 100644 app/javascript/images/preview.jpg create mode 100644 app/models/site_upload.rb create mode 100644 app/views/about/_og.html.haml create mode 100644 db/migrate/20170913000752_create_site_uploads.rb create mode 100644 spec/fabricators/site_upload_fabricator.rb create mode 100644 spec/models/site_upload_spec.rb (limited to 'app/controllers') diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index c5e6fe4e5..a2f86b8a9 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -14,6 +14,7 @@ module Admin open_deletion timeline_preview bootstrap_timeline_accounts + thumbnail ).freeze BOOLEAN_SETTINGS = %w( @@ -22,14 +23,23 @@ module Admin timeline_preview ).freeze + UPLOAD_SETTINGS = %w( + thumbnail + ).freeze + def edit @admin_settings = Form::AdminSettings.new end def update settings_params.each do |key, value| - setting = Setting.where(var: key).first_or_initialize(var: key) - setting.update(value: value_for_update(key, value)) + if UPLOAD_SETTINGS.include?(key) + upload = SiteUpload.where(var: key).first_or_initialize(var: key) + upload.update(file: value) + else + setting = Setting.where(var: key).first_or_initialize(var: key) + setting.update(value: value_for_update(key, value)) + end end flash[:notice] = I18n.t('generic.changes_saved_msg') diff --git a/app/javascript/images/mastodon_small.jpg b/app/javascript/images/mastodon_small.jpg deleted file mode 100644 index 9c88ce3f7..000000000 Binary files a/app/javascript/images/mastodon_small.jpg and /dev/null differ diff --git a/app/javascript/images/preview.jpg b/app/javascript/images/preview.jpg new file mode 100644 index 000000000..ec2856748 Binary files /dev/null and b/app/javascript/images/preview.jpg differ diff --git a/app/models/site_upload.rb b/app/models/site_upload.rb new file mode 100644 index 000000000..8ffdc8313 --- /dev/null +++ b/app/models/site_upload.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: site_uploads +# +# id :integer not null, primary key +# var :string default(""), not null +# file_file_name :string +# file_content_type :string +# file_file_size :integer +# file_updated_at :datetime +# meta :json +# created_at :datetime not null +# updated_at :datetime not null +# + +class SiteUpload < ApplicationRecord + has_attached_file :file + + validates_attachment_content_type :file, content_type: /\Aimage\/.*\z/ + validates :var, presence: true, uniqueness: true + + before_save :set_meta + after_commit :clear_cache + + def cache_key + "site_uploads/#{var}" + end + + private + + def set_meta + tempfile = file.queued_for_write[:original] + + return if tempfile.nil? + + geometry = Paperclip::Geometry.from_file(tempfile) + self.meta = { width: geometry.width.to_i, height: geometry.height.to_i } + end + + def clear_cache + Rails.cache.delete(cache_key) + end +end diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb index 8104b7531..c9e3c31a1 100644 --- a/app/presenters/instance_presenter.rb +++ b/app/presenters/instance_presenter.rb @@ -35,4 +35,8 @@ class InstancePresenter def source_url Mastodon::Version.source_url end + + def thumbnail + @thumbnail ||= Rails.cache.fetch('site_uploads/thumbnail') { SiteUpload.find_by(var: 'thumbnail') } + end end diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index a97137909..2898011fd 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true class REST::InstanceSerializer < ActiveModel::Serializer + include RoutingHelper + attributes :uri, :title, :description, :email, - :version, :urls, :stats + :version, :urls, :stats, :thumbnail def uri Rails.configuration.x.local_domain @@ -24,6 +26,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer Mastodon::Version.to_s end + def thumbnail + full_asset_url(instance_presenter.thumbnail.file.url) if instance_presenter.thumbnail + end + def stats { user_count: instance_presenter.user_count, diff --git a/app/views/about/_og.html.haml b/app/views/about/_og.html.haml new file mode 100644 index 000000000..dbd476915 --- /dev/null +++ b/app/views/about/_og.html.haml @@ -0,0 +1,10 @@ +- thumbnail = @instance_presenter.thumbnail += opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname) += opengraph 'og:url', about_url += opengraph 'og:type', 'website' += opengraph 'og:title', @instance_presenter.site_title += opengraph 'og:description', strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) += opengraph 'og:image', full_asset_url(thumbnail&.file&.url || asset_pack_path('preview.jpg', protocol: :request)) += opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '1200' += opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '630' += opengraph 'twitter:card', 'summary_large_image' diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml index 094188472..1a4e74643 100644 --- a/app/views/about/more.html.haml +++ b/app/views/about/more.html.haml @@ -3,16 +3,7 @@ - content_for :header_tags do = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' - - %meta{ property: 'og:site_name', content: site_title }/ - %meta{ property: 'og:url', content: about_url }/ - %meta{ property: 'og:type', content: 'website' }/ - %meta{ property: 'og:title', content: site_hostname }/ - %meta{ property: 'og:description', content: strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) }/ - %meta{ property: 'og:image', content: asset_pack_path('mastodon_small.jpg', protocol: :request) }/ - %meta{ property: 'og:image:width', content: '400' }/ - %meta{ property: 'og:image:height', content: '400' }/ - %meta{ property: 'twitter:card', content: 'summary' }/ + = render partial: 'og' .landing-page .header-wrapper.compact diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index 93270fe3d..0d311b895 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -4,16 +4,7 @@ - content_for :header_tags do %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) = javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous' - - %meta{ property: 'og:site_name', content: site_title }/ - %meta{ property: 'og:url', content: about_url }/ - %meta{ property: 'og:type', content: 'website' }/ - %meta{ property: 'og:title', content: site_hostname }/ - %meta{ property: 'og:description', content: strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) }/ - %meta{ property: 'og:image', content: asset_pack_path('mastodon_small.jpg', protocol: :request) }/ - %meta{ property: 'og:image:width', content: '400' }/ - %meta{ property: 'og:image:height', content: '400' }/ - %meta{ property: 'twitter:card', content: 'summary' }/ + = render partial: 'og' .landing-page .header-wrapper diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index 50d019ec4..468166035 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -10,6 +10,11 @@ %hr/ + .fields-group + = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html') + + %hr/ + .fields-group = f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html') diff --git a/config/locales/en.yml b/config/locales/en.yml index 0cd57a64f..8b5f52b02 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -195,6 +195,9 @@ en: desc_html: You can write your own privacy policy, terms of service or other legalese. You can use HTML tags title: Custom terms of service site_title: Instance name + thumbnail: + desc_html: Used for previews via OpenGraph and API. 1200x630px recommended + title: Instance thumbnail timeline_preview: desc_html: Display public timeline on landing page title: Timeline preview diff --git a/db/migrate/20170913000752_create_site_uploads.rb b/db/migrate/20170913000752_create_site_uploads.rb new file mode 100644 index 000000000..2246e48cd --- /dev/null +++ b/db/migrate/20170913000752_create_site_uploads.rb @@ -0,0 +1,10 @@ +class CreateSiteUploads < ActiveRecord::Migration[5.1] + def change + create_table :site_uploads do |t| + t.string :var, default: '', null: false, index: { unique: true } + t.attachment :file + t.json :meta + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index d8af0a1f8..f2ca2af69 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170905165803) do +ActiveRecord::Schema.define(version: 20170913000752) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -288,6 +288,18 @@ ActiveRecord::Schema.define(version: 20170905165803) do t.index ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true end + create_table "site_uploads", force: :cascade do |t| + t.string "var", default: "", null: false + t.string "file_file_name" + t.string "file_content_type" + t.integer "file_file_size" + t.datetime "file_updated_at" + t.json "meta" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["var"], name: "index_site_uploads_on_var", unique: true + end + create_table "status_pins", force: :cascade do |t| t.bigint "account_id", null: false t.bigint "status_id", null: false diff --git a/spec/fabricators/site_upload_fabricator.rb b/spec/fabricators/site_upload_fabricator.rb new file mode 100644 index 000000000..8f4e43ac9 --- /dev/null +++ b/spec/fabricators/site_upload_fabricator.rb @@ -0,0 +1,3 @@ +Fabricator(:site_upload) do + +end diff --git a/spec/models/site_upload_spec.rb b/spec/models/site_upload_spec.rb new file mode 100644 index 000000000..8745d54b8 --- /dev/null +++ b/spec/models/site_upload_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe SiteUpload, type: :model do + +end diff --git a/spec/views/about/show.html.haml_spec.rb b/spec/views/about/show.html.haml_spec.rb index aa151dd27..724643cbc 100644 --- a/spec/views/about/show.html.haml_spec.rb +++ b/spec/views/about/show.html.haml_spec.rb @@ -15,15 +15,16 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do version_number: '1.0', source_url: 'https://github.com/tootsuite/mastodon', open_registrations: false, + thumbnail: nil, closed_registrations_message: 'yes') assign(:instance_presenter, instance_presenter) render header_tags = view.content_for(:header_tags) - expect(header_tags).to match(%r{}) - expect(header_tags).to match(%r{}) - expect(header_tags).to match(%r{}) - expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) end end -- cgit From 472df245799949631646f90d894486e4dbeaaaf9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 15 Sep 2017 00:57:08 +0200 Subject: When web UI URL used while logged out, redirect to static page (#4954) --- app/controllers/home_controller.rb | 35 +++++++++++++++++++++++++++++++- spec/controllers/home_controller_spec.rb | 2 ++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'app/controllers') diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 1585bc810..21dde20ce 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -11,7 +11,30 @@ class HomeController < ApplicationController private def authenticate_user! - redirect_to(single_user_mode? ? account_path(Account.first) : about_path) unless user_signed_in? + return if user_signed_in? + + matches = request.path.match(/\A\/web\/(statuses|accounts)\/([\d]+)\z/) + + if matches + case matches[1] + when 'statuses' + status = Status.find_by(id: matches[2]) + + if status && (status.public_visibility? || status.unlisted_visibility?) + redirect_to(ActivityPub::TagManager.instance.url_for(status)) + return + end + when 'accounts' + account = Account.find_by(id: matches[2]) + + if account + redirect_to(ActivityPub::TagManager.instance.url_for(account)) + return + end + end + end + + redirect_to(default_redirect_path) end def set_initial_state_json @@ -28,4 +51,14 @@ class HomeController < ApplicationController admin: Account.find_local(Setting.site_contact_username), } end + + def default_redirect_path + if request.path.start_with?('/web') + new_user_session_path + elsif single_user_mode? + short_account_path(Account.first) + else + about_path + end + end end diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index d44d720b1..1077a7288 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -6,6 +6,7 @@ RSpec.describe HomeController, type: :controller do describe 'GET #index' do context 'when not signed in' do it 'redirects to about page' do + @request.path = '/' get :index expect(response).to redirect_to(about_path) end @@ -13,6 +14,7 @@ RSpec.describe HomeController, type: :controller do context 'when signed in' do let(:user) { Fabricate(:user) } + subject do sign_in(user) get :index -- cgit From 54edb4b853522b322922b65989ddfc5fdf928014 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 16 Sep 2017 03:01:45 +0200 Subject: When accessing uncached media attachment, redownload it (#4955) * When accessing uncached media attachment, redownload it * Prevent re-download of rejected media --- app/controllers/media_proxy_controller.rb | 40 ++++++++++++++++++++++ app/models/media_attachment.rb | 10 ++++-- .../rest/media_attachment_serializer.rb | 12 +++++-- config/routes.rb | 2 ++ lib/tasks/mastodon.rake | 1 - 5 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 app/controllers/media_proxy_controller.rb (limited to 'app/controllers') diff --git a/app/controllers/media_proxy_controller.rb b/app/controllers/media_proxy_controller.rb new file mode 100644 index 000000000..6a83cf9dc --- /dev/null +++ b/app/controllers/media_proxy_controller.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class MediaProxyController < ApplicationController + include RoutingHelper + + def show + RedisLock.acquire(lock_options) do |lock| + if lock.acquired? + @media_attachment = MediaAttachment.remote.find(params[:id]) + redownload! if @media_attachment.needs_redownload? && !reject_media? + end + end + + redirect_to full_asset_url(@media_attachment.file.url(version)) + end + + private + + def redownload! + @media_attachment.file_remote_url = @media_attachment.remote_url + @media_attachment.touch(:created_at) + @media_attachment.save! + end + + def version + if request.path.ends_with?('/small') + :small + else + :original + end + end + + def lock_options + { redis: Redis.current, key: "media_download:#{params[:id]}" } + end + + def reject_media? + DomainBlock.find_by(domain: @media_attachment.account.domain)&.reject_media? + end +end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index d83ca44f1..d913e7372 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -56,15 +56,21 @@ class MediaAttachment < ApplicationRecord validates :account, presence: true - scope :attached, -> { where.not(status_id: nil) } + scope :attached, -> { where.not(status_id: nil) } scope :unattached, -> { where(status_id: nil) } - scope :local, -> { where(remote_url: '') } + scope :local, -> { where(remote_url: '') } + scope :remote, -> { where.not(remote_url: '') } + default_scope { order(id: :asc) } def local? remote_url.blank? end + def needs_redownload? + file.blank? && remote_url.present? + end + def to_param shortcode end diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb index 9055b8db4..31189406a 100644 --- a/app/serializers/rest/media_attachment_serializer.rb +++ b/app/serializers/rest/media_attachment_serializer.rb @@ -7,11 +7,19 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer :remote_url, :text_url, :meta def url - full_asset_url(object.file.url(:original)) + if object.needs_redownload? + media_proxy_url(object.id, :original) + else + full_asset_url(object.file.url(:original)) + end end def preview_url - full_asset_url(object.file.url(:small)) + if object.needs_redownload? + media_proxy_url(object.id, :small) + else + full_asset_url(object.file.url(:small)) + end end def text_url diff --git a/config/routes.rb b/config/routes.rb index 63e94fb49..bf5428869 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -98,6 +98,8 @@ Rails.application.routes.draw do resources :media, only: [:show] resources :tags, only: [:show] + get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy + # Remote follow resource :authorize_follow, only: [:show, :create] resource :share, only: [:show, :create] diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 2aef752ca..5614ddf48 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -83,7 +83,6 @@ namespace :mastodon do MediaAttachment.where.not(remote_url: '').where('created_at < ?', time_ago).find_each do |media| media.file.destroy - media.type = :unknown media.save end end -- cgit From 09a94b575e90dc7f6e179a1ec717156e725f915a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 19 Sep 2017 03:52:38 +0200 Subject: Admin interface for listing, adding and removing custom emojis (#5002) * Admin interface for listing, adding and removing custom emojis * Only display local ones in the list --- app/controllers/admin/custom_emojis_controller.rb | 34 ++++++++++++++++++++++ app/services/block_domain_service.rb | 9 ++++++ .../admin/custom_emojis/_custom_emoji.html.haml | 7 +++++ app/views/admin/custom_emojis/index.html.haml | 14 +++++++++ app/views/admin/custom_emojis/new.html.haml | 12 ++++++++ config/locales/en.yml | 12 ++++++++ config/navigation.rb | 1 + config/routes.rb | 2 ++ 8 files changed, 91 insertions(+) create mode 100644 app/controllers/admin/custom_emojis_controller.rb create mode 100644 app/views/admin/custom_emojis/_custom_emoji.html.haml create mode 100644 app/views/admin/custom_emojis/index.html.haml create mode 100644 app/views/admin/custom_emojis/new.html.haml (limited to 'app/controllers') diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb new file mode 100644 index 000000000..616a279b3 --- /dev/null +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Admin + class CustomEmojisController < BaseController + def index + @custom_emojis = CustomEmoji.where(uri: nil) + end + + def new + @custom_emoji = CustomEmoji.new + end + + def create + @custom_emoji = CustomEmoji.new(resource_params) + + if @custom_emoji.save + redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.created_msg') + else + render :new + end + end + + def destroy + CustomEmoji.find(params[:id]).destroy + redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg') + end + + private + + def resource_params + params.require(:custom_emoji).permit(:shortcode, :image) + end + end +end diff --git a/app/services/block_domain_service.rb b/app/services/block_domain_service.rb index 1473bc841..eefdc0dbf 100644 --- a/app/services/block_domain_service.rb +++ b/app/services/block_domain_service.rb @@ -26,6 +26,7 @@ class BlockDomainService < BaseService def clear_media! clear_account_images clear_account_attachments + clear_emojos end def suspend_accounts! @@ -51,6 +52,10 @@ class BlockDomainService < BaseService end end + def clear_emojos + emojis_from_blocked_domains.destroy_all + end + def blocked_domain domain_block.domain end @@ -62,4 +67,8 @@ class BlockDomainService < BaseService def media_from_blocked_domain MediaAttachment.joins(:account).merge(blocked_domain_accounts).reorder(nil) end + + def emojis_from_blocked_domains + CustomEmoji.where(domain: blocked_domain) + end end diff --git a/app/views/admin/custom_emojis/_custom_emoji.html.haml b/app/views/admin/custom_emojis/_custom_emoji.html.haml new file mode 100644 index 000000000..ff1aa9925 --- /dev/null +++ b/app/views/admin/custom_emojis/_custom_emoji.html.haml @@ -0,0 +1,7 @@ +%tr + %td + = image_tag custom_emoji.image.url, class: 'emojione', alt: ":#{custom_emoji.shortcode}:" + %td + %samp= ":#{custom_emoji.shortcode}:" + %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') } diff --git a/app/views/admin/custom_emojis/index.html.haml b/app/views/admin/custom_emojis/index.html.haml new file mode 100644 index 000000000..d5f32e84b --- /dev/null +++ b/app/views/admin/custom_emojis/index.html.haml @@ -0,0 +1,14 @@ +- content_for :page_title do + = t('admin.custom_emojis.title') + +.table-wrapper + %table.table + %thead + %tr + %th= t('admin.custom_emojis.emoji') + %th= t('admin.custom_emojis.shortcode') + %th + %tbody + = render @custom_emojis + += link_to t('admin.custom_emojis.upload'), new_admin_custom_emoji_path, class: 'button' diff --git a/app/views/admin/custom_emojis/new.html.haml b/app/views/admin/custom_emojis/new.html.haml new file mode 100644 index 000000000..672afe435 --- /dev/null +++ b/app/views/admin/custom_emojis/new.html.haml @@ -0,0 +1,12 @@ +- content_for :page_title do + = t('.title') + += simple_form_for @custom_emoji, url: admin_custom_emojis_path do |f| + = render 'shared/error_messages', object: @custom_emoji + + .fields-group + = f.input :shortcode, placeholder: t('admin.custom_emojis.shortcode'), hint: t('admin.custom_emojis.shortcode_hint') + = f.input :image, input_html: { accept: 'image/png' }, hint: t('admin.custom_emojis.image_hint') + + .actions + = f.button :button, t('admin.custom_emojis.upload'), type: :submit diff --git a/config/locales/en.yml b/config/locales/en.yml index 0f6bac9e1..9013f0ac9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -108,6 +108,18 @@ en: unsubscribe: Unsubscribe username: Username web: Web + custom_emojis: + created_msg: Emoji successfully created! + delete: Delete + destroyed_msg: Emojo successfully destroyed! + emoji: Emoji + image_hint: PNG up to 50KB + new: + title: Add new custom emoji + shortcode: Shortcode + shortcode_hint: At least 2 characters, only alphanumeric characters and underscores + title: Custom emojis + upload: Upload domain_blocks: add_new: Add new created_msg: Domain block is now being processed diff --git a/config/navigation.rb b/config/navigation.rb index 4b454b3fc..0a6ab6d3d 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -28,6 +28,7 @@ SimpleNavigation::Configuration.run do |navigation| admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' } admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' } admin.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url + admin.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis} end primary.item :logout, safe_join([fa_icon('sign-out fw'), t('auth.logout')]), destroy_user_session_url, link_html: { 'data-method' => 'delete' } diff --git a/config/routes.rb b/config/routes.rb index bf5428869..d38f5308a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -136,6 +136,8 @@ Rails.application.routes.draw do resources :users, only: [] do resource :two_factor_authentication, only: [:destroy] end + + resources :custom_emojis, only: [:index, :new, :create, :destroy] end get '/admin', to: redirect('/admin/settings/edit', status: 302) -- cgit From 1664e52cbb5ec08db896127640bd0554cee1d384 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Tue, 19 Sep 2017 12:06:13 +0900 Subject: Fix custom emojis index (#5006) --- app/controllers/admin/custom_emojis_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/controllers') diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index 616a279b3..572ad1ac2 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -3,7 +3,7 @@ module Admin class CustomEmojisController < BaseController def index - @custom_emojis = CustomEmoji.where(uri: nil) + @custom_emojis = CustomEmoji.where(domain: nil) end def new -- cgit From 41e6c8b151da937acbb73b14df74fbd230dea981 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 19 Sep 2017 06:53:16 +0200 Subject: Fix incomplete account records being read (#4998) * Fix incomplete account records being read - Put account processing into redis lock - Do not save until record is complete * Fix spaces --- app/controllers/media_proxy_controller.rb | 2 +- .../activitypub/process_account_service.rb | 80 +++++++++++++++------- 2 files changed, 57 insertions(+), 25 deletions(-) (limited to 'app/controllers') diff --git a/app/controllers/media_proxy_controller.rb b/app/controllers/media_proxy_controller.rb index 6a83cf9dc..155670837 100644 --- a/app/controllers/media_proxy_controller.rb +++ b/app/controllers/media_proxy_controller.rb @@ -18,7 +18,7 @@ class MediaProxyController < ApplicationController def redownload! @media_attachment.file_remote_url = @media_attachment.remote_url - @media_attachment.touch(:created_at) + @media_attachment.created_at = Time.now.utc @media_attachment.save! end diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index a45681078..811209537 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -12,14 +12,21 @@ class ActivityPub::ProcessAccountService < BaseService @uri = @json['id'] @username = username @domain = domain - @account = Account.find_by(uri: @uri) @collections = {} - old_public_key = @account&.public_key - create_account if @account.nil? - upgrade_account if @account.ostatus? - update_account - RefollowWorker.perform_async(@account.id) if !old_public_key.nil? && old_public_key != @account.public_key + RedisLock.acquire(lock_options) do |lock| + if lock.acquired? + @account = Account.find_by(uri: @uri) + @old_public_key = @account&.public_key + @old_protocol = @account&.protocol + + create_account if @account.nil? + update_account + end + end + + after_protocol_change! if protocol_changed? + after_key_change! if key_changed? @account rescue Oj::ParseError @@ -37,33 +44,46 @@ class ActivityPub::ProcessAccountService < BaseService @account.suspended = true if auto_suspend? @account.silenced = true if auto_silence? @account.private_key = nil - @account.save! end def update_account @account.last_webfingered_at = Time.now.utc @account.protocol = :activitypub - @account.inbox_url = @json['inbox'] || '' - @account.outbox_url = @json['outbox'] || '' - @account.shared_inbox_url = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || '' - @account.followers_url = @json['followers'] || '' - @account.url = url || @uri - @account.display_name = @json['name'] || '' - @account.note = @json['summary'] || '' - @account.avatar_remote_url = image_url('icon') unless skip_download? - @account.header_remote_url = image_url('image') unless skip_download? - @account.public_key = public_key || '' - @account.locked = @json['manuallyApprovesFollowers'] || false - @account.statuses_count = outbox_total_items if outbox_total_items.present? - @account.following_count = following_total_items if following_total_items.present? - @account.followers_count = followers_total_items if followers_total_items.present? + + set_immediate_attributes! + set_fetchable_attributes! + @account.save_with_optional_media! end - def upgrade_account + def set_immediate_attributes! + @account.inbox_url = @json['inbox'] || '' + @account.outbox_url = @json['outbox'] || '' + @account.shared_inbox_url = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || '' + @account.followers_url = @json['followers'] || '' + @account.url = url || @uri + @account.display_name = @json['name'] || '' + @account.note = @json['summary'] || '' + @account.locked = @json['manuallyApprovesFollowers'] || false + end + + def set_fetchable_attributes! + @account.avatar_remote_url = image_url('icon') unless skip_download? + @account.header_remote_url = image_url('image') unless skip_download? + @account.public_key = public_key || '' + @account.statuses_count = outbox_total_items if outbox_total_items.present? + @account.following_count = following_total_items if following_total_items.present? + @account.followers_count = followers_total_items if followers_total_items.present? + end + + def after_protocol_change! ActivityPub::PostUpgradeWorker.perform_async(@account.domain) end + def after_key_change! + RefollowWorker.perform_async(@account.id) + end + def image_url(key) value = first_of_value(@json[key]) @@ -122,15 +142,27 @@ class ActivityPub::ProcessAccountService < BaseService end def auto_suspend? - domain_block && domain_block.suspend? + domain_block&.suspend? end def auto_silence? - domain_block && domain_block.silence? + domain_block&.silence? end def domain_block return @domain_block if defined?(@domain_block) @domain_block = DomainBlock.find_by(domain: @domain) end + + def key_changed? + !@old_public_key.nil? && @old_public_key != @account.public_key + end + + def protocol_changed? + !@old_protocol.nil? && @old_protocol != @account.protocol + end + + def lock_options + { redis: Redis.current, key: "process_account:#{@uri}" } + end end -- cgit