From 5d2fc6de321ac556ded72e5a8fa9fcf47d172e16 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 24 Dec 2018 19:12:38 +0100 Subject: Add REST API for creating an account (#9572) * Add REST API for creating an account The method is available to apps with a token obtained via the client credentials grant. It creates a user and account records, as well as an access token for the app that initiated the request. The user is unconfirmed, and an e-mail is sent as usual. The method returns the access token, which the app should save for later. The REST API is not available to users with unconfirmed accounts, so the app must be smart to wait for the user to click a link in their e-mail inbox. The method is rate-limited by IP to 5 requests per 30 minutes. * Redirect users back to app from confirmation if they were created with an app * Add tests * Return 403 on the method if registrations are not open * Require agreement param to be true in the API when creating an account --- app/models/user.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/models/user.rb') diff --git a/app/models/user.rb b/app/models/user.rb index 44e0d1113..77e48ed4b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -36,6 +36,7 @@ # invite_id :bigint(8) # remember_token :string # chosen_languages :string is an Array +# created_by_application_id :bigint(8) # class User < ApplicationRecord @@ -66,6 +67,7 @@ class User < ApplicationRecord belongs_to :account, inverse_of: :user belongs_to :invite, counter_cache: :uses, optional: true + belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true accepts_nested_attributes_for :account has_many :applications, class_name: 'Doorkeeper::Application', as: :owner @@ -74,6 +76,7 @@ class User < ApplicationRecord validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale? validates_with BlacklistedEmailValidator, if: :email_changed? validates_with EmailMxValidator, if: :validate_email_dns? + validates :agreement, acceptance: { allow_nil: false, accept: [true, 'true', '1'] }, on: :create scope :recent, -> { order(id: :desc) } scope :admins, -> { where(admin: true) } @@ -294,7 +297,7 @@ class User < ApplicationRecord end if resource.blank? - resource = new(email: attributes[:email]) + resource = new(email: attributes[:email], agreement: true) if Devise.check_at_sign && !resource[:email].index('@') resource[:email] = Rpam2.getenv(resource.find_pam_service, attributes[:email], attributes[:password], 'email', false) resource[:email] = "#{attributes[:email]}@#{resource.find_pam_suffix}" unless resource[:email] @@ -307,7 +310,7 @@ class User < ApplicationRecord resource = joins(:account).find_by(accounts: { username: attributes[Devise.ldap_uid.to_sym].first }) if resource.blank? - resource = new(email: attributes[:mail].first, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first }) + resource = new(email: attributes[:mail].first, agreement: true, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first }) resource.ldap_setup(attributes) end -- cgit From 6e49907ecfc7036b6bf2dd91b9ebf4ba62d16080 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 28 Dec 2018 03:38:41 +0100 Subject: Improve admin UI for account view (#9643) --- app/controllers/admin/accounts_controller.rb | 5 +- app/javascript/styles/mastodon/dashboard.scss | 8 +- app/models/user.rb | 4 + app/services/resolve_account_service.rb | 1 + app/views/admin/accounts/show.html.haml | 349 ++++++++++++-------------- app/views/admin/followers/index.html.haml | 9 +- app/views/admin/statuses/index.html.haml | 2 +- config/locales/ar.yml | 1 - config/locales/ca.yml | 1 - config/locales/co.yml | 1 - config/locales/cs.yml | 1 - config/locales/cy.yml | 1 - config/locales/da.yml | 1 - config/locales/de.yml | 1 - config/locales/el.yml | 1 - config/locales/en.yml | 30 +-- config/locales/eo.yml | 1 - config/locales/es.yml | 1 - config/locales/eu.yml | 1 - config/locales/fa.yml | 1 - config/locales/fi.yml | 1 - config/locales/fr.yml | 1 - config/locales/gl.yml | 1 - config/locales/he.yml | 1 - config/locales/hu.yml | 1 - config/locales/id.yml | 1 - config/locales/io.yml | 1 - config/locales/it.yml | 1 - config/locales/ja.yml | 1 - config/locales/ka.yml | 1 - config/locales/ko.yml | 1 - config/locales/ms.yml | 1 - config/locales/nl.yml | 1 - config/locales/no.yml | 1 - config/locales/oc.yml | 1 - config/locales/pl.yml | 1 - config/locales/pt-BR.yml | 1 - config/locales/pt.yml | 1 - config/locales/ru.yml | 1 - config/locales/sk.yml | 1 - config/locales/sr-Latn.yml | 1 - config/locales/sr.yml | 1 - config/locales/sv.yml | 1 - config/locales/th.yml | 1 - config/locales/tr.yml | 1 - config/locales/uk.yml | 1 - config/locales/zh-CN.yml | 1 - config/locales/zh-HK.yml | 1 - config/locales/zh-TW.yml | 1 - 49 files changed, 201 insertions(+), 248 deletions(-) (limited to 'app/models/user.rb') diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index f5e5f7ed5..562fba996 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -62,9 +62,8 @@ module Admin def redownload authorize @account, :redownload? - @account.reset_avatar! - @account.reset_header! - @account.save! + @account.update!(last_webfingered_at: nil) + ResolveAccountService.new.call(@account) redirect_to admin_account_path(@account.id) end diff --git a/app/javascript/styles/mastodon/dashboard.scss b/app/javascript/styles/mastodon/dashboard.scss index 86cf6c61b..1f96e7368 100644 --- a/app/javascript/styles/mastodon/dashboard.scss +++ b/app/javascript/styles/mastodon/dashboard.scss @@ -30,15 +30,21 @@ } } - &__num { + &__num, + &__text { text-align: center; font-weight: 500; font-size: 24px; + line-height: 21px; color: $primary-text-color; font-family: $font-display, sans-serif; margin-bottom: 20px; } + &__text { + font-size: 18px; + } + &__label { font-size: 14px; color: $darker-text-color; diff --git a/app/models/user.rb b/app/models/user.rb index 77e48ed4b..1684b9bea 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -139,6 +139,10 @@ class User < ApplicationRecord confirmed_at.present? end + def invited? + invite_id.present? + end + def staff? admin? || moderator? end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index c3064211d..4ff351c5f 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -19,6 +19,7 @@ class ResolveAccountService < BaseService @account = uri @username = @account.username @domain = @account.domain + uri = "#{@username}@#{@domain}" return @account if @account.local? || !webfinger_update_due? else diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml index 47cf41073..280a834ba 100644 --- a/app/views/admin/accounts/show.html.haml +++ b/app/views/admin/accounts/show.html.haml @@ -1,202 +1,185 @@ - content_for :page_title do = @account.acct -.table-wrapper - %table.table.inline-table - %tbody - %tr - %th= t('admin.accounts.username') - %td= @account.username - %tr - %th= t('admin.accounts.domain') - %td= @account.domain - %tr - %th= t('admin.accounts.display_name') - %td= @account.display_name - - %tr - %th= t('admin.accounts.avatar') - %td - = link_to @account.avatar.url(:original) do - = image_tag @account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar' - - if @account.local? && @account.avatar? - = table_link_to 'trash', t('admin.accounts.remove_avatar'), remove_avatar_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:remove_avatar, @account) - %tr - %th= t('admin.accounts.header') - %td - = link_to @account.header.url(:original) do - = image_tag @account.header.url(:original), alt: '', width: 128, height: 40, class: 'header' - - if @account.local? && @account.header? - = table_link_to 'trash', t('admin.accounts.remove_header'), remove_header_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:remove_header, @account) - - - if @account.local? - %tr - %th= t('admin.accounts.role') - %td - - if @account.user.nil? - = t("admin.accounts.moderation.suspended") - - else - = t("admin.accounts.roles.#{@account.user&.role}") - = table_link_to 'angle-double-up', t('admin.accounts.promote'), promote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:promote, @account.user) - = table_link_to 'angle-double-down', t('admin.accounts.demote'), demote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:demote, @account.user) - %tr - %th= t('admin.accounts.email') - %td - = @account.user_email - = table_link_to 'edit', t('admin.accounts.change_email.label'), admin_account_change_email_path(@account.id) if can?(:change_email, @account.user) - - if @account.user_unconfirmed_email.present? - %th= t('admin.accounts.unconfirmed_email') - %td - = @account.user_unconfirmed_email - %tr - %th= t('admin.accounts.email_status') - %td - - if @account.user&.confirmed? - = t('admin.accounts.confirmed') - - else - = t('admin.accounts.confirming') - = table_link_to 'refresh', t('admin.accounts.resend_confirmation.send'), resend_admin_account_confirmation_path(@account.id), method: :post if can?(:confirm, @account.user) - %tr - %th= t('admin.accounts.login_status') - %td - - if @account.user&.disabled? - = t('admin.accounts.disabled') - = table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post if can?(:enable, @account.user) - - else - = t('admin.accounts.enabled') - = table_link_to 'lock', t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable') if can?(:disable, @account.user) - %tr - %th= t('admin.accounts.most_recent_ip') - %td= @account.user_current_sign_in_ip - %tr - %th= t('admin.accounts.most_recent_activity') - %td - - if @account.user_current_sign_in_at - %time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) } - = l @account.user_current_sign_in_at - - else - \- - - else - %tr - %th= t('admin.accounts.profile_url') - %td= link_to @account.url, @account.url - %tr - %th= t('admin.accounts.protocol') - %td= @account.protocol.humanize - - %tr - %th= t('admin.accounts.follows') - %td= number_to_human @account.following_count - %tr - %th= t('admin.accounts.followers') - %td - = number_to_human @account.followers_count - = link_to t('admin.accounts.followers_local', local: number_to_human(@account.local_followers_count)), admin_account_followers_path(@account.id) - %tr - %th= t('admin.accounts.statuses') - %td= link_to number_to_human(@account.statuses_count), admin_account_statuses_path(@account.id) - %tr - %th= t('admin.accounts.media_attachments') - %td - = link_to number_to_human(@account.media_attachments.count), admin_account_statuses_path(@account.id, { media: true }) - = surround '(', ')' do - = number_to_human_size @account.media_attachments.sum('file_file_size') - %tr - %th= t('.created_reports') - %td= link_to pluralize(@account.reports.count, t('.report')), admin_reports_path(account_id: @account.id) - %tr - %th= t('.targeted_reports') - %td= link_to pluralize(@account.targeted_reports.count, t('.report')), admin_reports_path(target_account_id: @account.id) - -%div{ style: 'overflow: hidden' } - %div{ style: 'float: right' } - - if @account.local? - = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button' if can?(:reset_password, @account.user) - - if @account.user&.otp_required_for_login? - = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' if can?(:disable_2fa, @account.user) - - unless @account.memorial? - = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, @account) - - else - = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button' if can?(:redownload, @account) - - %div{ style: 'float: left' } - - if @account.silenced? - = link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account) - - else - = link_to t('admin.accounts.silence'), new_admin_account_action_path(@account.id, type: 'silence'), class: 'button button--destructive' if can?(:silence, @account) - - - if @account.local? - - unless @account.user_confirmed? - = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' if can?(:confirm, @account.user) - - - if @account.suspended? - = link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsuspend, @account) - - else - = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@account.id, type: 'suspend'), class: 'button button--destructive' if can?(:suspend, @account) - -- if !@account.local? && @account.hub_url.present? - %hr.spacer/ - - %h3 OStatus - += render 'application/card', account: @account + +.dashboard__counters{ style: 'margin-top: 10px' } + %div + = link_to admin_account_statuses_path(@account.id) do + .dashboard__counters__num= number_with_delimiter @account.statuses_count + .dashboard__counters__label= t 'admin.accounts.statuses' + %div + = link_to admin_account_statuses_path(@account.id, { media: true }) do + .dashboard__counters__num= number_to_human_size @account.media_attachments.sum('file_file_size') + .dashboard__counters__label= t 'admin.accounts.media_attachments' + %div + = link_to admin_account_followers_path(@account.id) do + .dashboard__counters__num= number_with_delimiter @account.local_followers_count + .dashboard__counters__label= t 'admin.accounts.followers' + %div + = link_to admin_reports_path(account_id: @account.id) do + .dashboard__counters__num= number_with_delimiter @account.reports.count + .dashboard__counters__label= t '.created_reports' + %div + = link_to admin_reports_path(target_account_id: @account.id) do + .dashboard__counters__num= number_with_delimiter @account.targeted_reports.count + .dashboard__counters__label= t '.targeted_reports' + %div + %div + .dashboard__counters__text + - if @account.local? && @account.user.nil? + %span.neutral= t('admin.accounts.deleted') + - elsif @account.suspended? + %span.red= t('admin.accounts.suspended') + - elsif @account.silenced? + %span.red= t('admin.accounts.silenced') + - elsif @account.local? && @account.user&.disabled? + %span.red= t('admin.accounts.disabled') + - elsif @account.local? && !@account.user&.confirmed? + %span.neutral= t('admin.accounts.confirming') + - else + %span.neutral= t('admin.accounts.no_limits_imposed') + .dashboard__counters__label= t 'admin.accounts.login_status' + +- unless @account.local? && @account.user.nil? .table-wrapper %table.table.inline-table %tbody - %tr - %th= t('admin.accounts.feed_url') - %td= link_to @account.remote_url, @account.remote_url - %tr - %th= t('admin.accounts.push_subscription_expires') - %td - - if @account.subscribed? - %time.formatted{ datetime: @account.subscription_expires_at.iso8601, title: l(@account.subscription_expires_at) } - = l @account.subscription_expires_at - - else - = t('admin.accounts.not_subscribed') - %tr - %th= t('admin.accounts.salmon_url') - %td= link_to @account.salmon_url, @account.salmon_url + - if @account.local? + - if @account.avatar? + %tr + %th= t('admin.accounts.avatar') + %td= table_link_to 'trash', t('admin.accounts.remove_avatar'), remove_avatar_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:remove_avatar, @account) + %td + + - if @account.header? + %tr + %th= t('admin.accounts.header') + %td= table_link_to 'trash', t('admin.accounts.remove_header'), remove_header_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:remove_header, @account) + %td + + %tr + %th= t('admin.accounts.role') + %td= t("admin.accounts.roles.#{@account.user&.role}") + %td + = table_link_to 'angle-double-up', t('admin.accounts.promote'), promote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:promote, @account.user) + = table_link_to 'angle-double-down', t('admin.accounts.demote'), demote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:demote, @account.user) + + %tr + %th= t('admin.accounts.email') + %td= @account.user_email + %td= table_link_to 'edit', t('admin.accounts.change_email.label'), admin_account_change_email_path(@account.id) if can?(:change_email, @account.user) + + - if @account.user_unconfirmed_email.present? + %tr + %th= t('admin.accounts.unconfirmed_email') + %td= @account.user_unconfirmed_email + %td + + %tr + %th= t('admin.accounts.email_status') + %td + - if @account.user&.confirmed? + = t('admin.accounts.confirmed') + - else + = t('admin.accounts.confirming') + %td= table_link_to 'refresh', t('admin.accounts.resend_confirmation.send'), resend_admin_account_confirmation_path(@account.id), method: :post if can?(:confirm, @account.user) + + %tr + %th= t('admin.accounts.login_status') + %td + - if @account.user&.disabled? + = t('admin.accounts.disabled') + - else + = t('admin.accounts.enabled') + %td + - if @account.user&.disabled? + = table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post if can?(:enable, @account.user) + - else + = table_link_to 'lock', t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable') if can?(:disable, @account.user) + + %tr + %th= t('simple_form.labels.defaults.locale') + %td= @account.user_locale + %td + + %tr + %th= t('admin.accounts.joined') + %td + %time.formatted{ datetime: @account.created_at.iso8601, title: l(@account.created_at) }= l @account.created_at + %td + + %tr + %th= t('admin.accounts.most_recent_ip') + %td= @account.user_current_sign_in_ip + %td + + %tr + %th= t('admin.accounts.most_recent_activity') + %td + - if @account.user_current_sign_in_at + %time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) }= l @account.user_current_sign_in_at + + - if @account.user&.invited? + %tr + %th= t('admin.accounts.invited_by') + %td= admin_account_link_to @account.user.invite.user.account + %td + + - else + %tr + %th= t('admin.accounts.inbox_url') + %td + = @account.inbox_url + = fa_icon DeliveryFailureTracker.unavailable?(@account.inbox_url) ? 'times' : 'check' + %tr + %th= t('admin.accounts.shared_inbox_url') + %td + = @account.shared_inbox_url + = fa_icon DeliveryFailureTracker.unavailable?(@account.shared_inbox_url) ? 'times' : 'check' %div{ style: 'overflow: hidden' } %div{ style: 'float: right' } - = link_to @account.subscribed? ? t('admin.accounts.resubscribe') : t('admin.accounts.subscribe'), subscribe_admin_account_path(@account.id), method: :post, class: 'button' if can?(:subscribe, @account) - - if @account.subscribed? - = link_to t('admin.accounts.unsubscribe'), unsubscribe_admin_account_path(@account.id), method: :post, class: 'button negative' if can?(:unsubscribe, @account) + - if @account.local? + = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button' if can?(:reset_password, @account.user) + - if @account.user&.otp_required_for_login? + = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' if can?(:disable_2fa, @account.user) + - unless @account.memorial? + = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, @account) + - else + = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button' if can?(:redownload, @account) -- if !@account.local? && @account.inbox_url.present? - %hr.spacer/ + %div{ style: 'float: left' } + - if @account.local? + = link_to t('admin.accounts.warn'), new_admin_account_action_path(@account.id, type: 'none'), class: 'button' if can?(:warn, @account) + - if @account.silenced? + = link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account) + - else + = link_to t('admin.accounts.silence'), new_admin_account_action_path(@account.id, type: 'silence'), class: 'button button--destructive' if can?(:silence, @account) - %h3 ActivityPub + - if @account.local? + - unless @account.user_confirmed? + = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' if can?(:confirm, @account.user) - .table-wrapper - %table.table.inline-table - %tbody - %tr - %th= t('admin.accounts.inbox_url') - %td= link_to @account.inbox_url, @account.inbox_url - %tr - %th= t('admin.accounts.outbox_url') - %td= link_to @account.outbox_url, @account.outbox_url - %tr - %th= t('admin.accounts.shared_inbox_url') - %td= link_to @account.shared_inbox_url, @account.shared_inbox_url - %tr - %th= t('admin.accounts.followers_url') - %td= link_to @account.followers_url, @account.followers_url + - if @account.suspended? + = link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsuspend, @account) + - else + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@account.id, type: 'suspend'), class: 'button button--destructive' if can?(:suspend, @account) -%hr.spacer/ + %hr.spacer/ -= render @warnings + - unless @warnings.empty? + = render @warnings -%hr.spacer/ + %hr.spacer/ -= render @moderation_notes + = render @moderation_notes -= simple_form_for @account_moderation_note, url: admin_account_moderation_notes_path do |f| - = render 'shared/error_messages', object: @account_moderation_note + = simple_form_for @account_moderation_note, url: admin_account_moderation_notes_path do |f| + = render 'shared/error_messages', object: @account_moderation_note - = f.input :content, placeholder: t('admin.reports.notes.placeholder'), rows: 6 - = f.hidden_field :target_account_id + = f.input :content, placeholder: t('admin.reports.notes.placeholder'), rows: 6 + = f.hidden_field :target_account_id - .actions - = f.button :button, t('admin.account_moderation_notes.create'), type: :submit + .actions + = f.button :button, t('admin.account_moderation_notes.create'), type: :submit diff --git a/app/views/admin/followers/index.html.haml b/app/views/admin/followers/index.html.haml index baf34bc95..31b321bac 100644 --- a/app/views/admin/followers/index.html.haml +++ b/app/views/admin/followers/index.html.haml @@ -1,6 +1,3 @@ -- content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' - - content_for :page_title do = t('admin.followers.title', acct: @account.acct) @@ -11,9 +8,11 @@ %li= link_to t('admin.accounts.location.local'), admin_account_followers_path(@account.id), class: 'selected' .back-link{ style: 'flex: 1 1 auto; text-align: right' } = link_to admin_account_path(@account.id) do - %i.fa.fa-chevron-left.fa-fw + = fa_icon 'chevron-left fw' = t('admin.followers.back_to_account') +%hr.spacer/ + .table-wrapper %table.table %thead @@ -24,6 +23,6 @@ %th= t('admin.accounts.most_recent_activity') %th %tbody - = render partial: 'admin/accounts/account', collection: @followers.map{|a| a.account} + = render partial: 'admin/accounts/account', collection: @followers.map(&:account) = paginate @followers diff --git a/app/views/admin/statuses/index.html.haml b/app/views/admin/statuses/index.html.haml index 880a24f76..dd3c79815 100644 --- a/app/views/admin/statuses/index.html.haml +++ b/app/views/admin/statuses/index.html.haml @@ -14,7 +14,7 @@ %li= link_to t('admin.statuses.with_media'), admin_account_statuses_path(@account.id, current_params.merge(media: true)), class: params[:media] && 'selected' .back-link{ style: 'flex: 1 1 auto; text-align: right' } = link_to admin_account_path(@account.id) do - %i.fa.fa-chevron-left.fa-fw + = fa_icon 'chevron-left fw' = t('admin.statuses.back_to_account') %hr.spacer/ diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 2e0989f8f..49ee567f3 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -170,7 +170,6 @@ ar: shared_inbox_url: رابط الصندوق المُشترَك للبريد الوارد show: created_reports: البلاغات التي أنشأها هذا الحساب - report: التقرير targeted_reports: التقريرات التي أُنشِأت ضد هذا الحساب silence: سكتهم silenced: تم كتمه diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 5b9acd799..ed23a0e8b 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -152,7 +152,6 @@ ca: shared_inbox_url: URL de la safata d'entrada compartida show: created_reports: Informes creats per aquest compte - report: informe targeted_reports: Informes realitzats sobre aquest compte silence: Silenci silenced: Silenciat diff --git a/config/locales/co.yml b/config/locales/co.yml index 206aabb6d..47c094f43 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -154,7 +154,6 @@ co: shared_inbox_url: URL di l’inbox spartuta show: created_reports: Signalamenti creati da stu contu - report: Signalamentu targeted_reports: Signalamenti creati contr’à stu contu silence: Silenzà silenced: Silenzatu diff --git a/config/locales/cs.yml b/config/locales/cs.yml index d2c0508ff..f7b1fbef0 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -158,7 +158,6 @@ cs: shared_inbox_url: URL sdílené schránky show: created_reports: Nahlášení vytvořené z tohoto účtu - report: nahlášení targeted_reports: Nahlášení vytvořena o tomto účtu silence: Utišit silenced: Utišen/a diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 9f8144ff2..af37278e2 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -142,7 +142,6 @@ cy: shared_inbox_url: URL Mewnflwch wedi ei rannu show: created_reports: Adroddiadau a grewyd gan y cyfri hwn - report: adrodd targeted_reports: Adroddiadau am y cyfri hwn silence: Tawelu silenced: Tawelwyd diff --git a/config/locales/da.yml b/config/locales/da.yml index f989549d7..074a774f0 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -149,7 +149,6 @@ da: shared_inbox_url: Link til delt indbakke show: created_reports: Anmeldelser oprettet af denne konto - report: anmeld targeted_reports: Anmeldelser fra denne konto silence: Dæmp silenced: Dæmpet diff --git a/config/locales/de.yml b/config/locales/de.yml index e6f35992e..5be292896 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -154,7 +154,6 @@ de: shared_inbox_url: Geteilter Posteingang URL show: created_reports: Meldungen durch dieses Konto - report: Meldung targeted_reports: Meldungen über dieses Konto silence: Stummschalten silenced: Stummgeschaltet diff --git a/config/locales/el.yml b/config/locales/el.yml index edf24a004..9f2da4c73 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -154,7 +154,6 @@ el: shared_inbox_url: URL κοινόχρηστων εισερχομένων show: created_reports: Αναφορές από αυτόν το λογαριασμό - report: καταγγελία targeted_reports: Αναφορές για αυτόν το λογαριασμό silence: Αποσιώπησε silenced: Αποσιωπημένοι diff --git a/config/locales/en.yml b/config/locales/en.yml index 7ccff2ffd..6c78b9fc9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -84,14 +84,15 @@ en: by_domain: Domain change_email: changed_msg: Account email successfully changed! - current_email: Current Email - label: Change Email - new_email: New Email - submit: Change Email - title: Change Email for %{username} + current_email: Current email + label: Change email + new_email: New email + submit: Change email + title: Change email for %{username} confirm: Confirm confirmed: Confirmed confirming: Confirming + deleted: Deleted demote: Demote disable: Disable disable_two_factor_authentication: Disable 2FA @@ -99,18 +100,19 @@ en: display_name: Display name domain: Domain edit: Edit - email: E-mail - email_status: E-mail Status + email: Email + email_status: Email status enable: Enable enabled: Enabled feed_url: Feed URL followers: Followers - followers_local: "(%{local} local)" followers_url: Followers URL follows: Follows header: Header inbox_url: Inbox URL + invited_by: Invited by ip: IP + joined: Joined location: all: All local: Local @@ -137,7 +139,7 @@ en: protocol: Protocol public: Public push_subscription_expires: PuSH subscription expires - redownload: Refresh avatar + redownload: Refresh profile remove_avatar: Remove avatar remove_header: Remove header resend_confirmation: @@ -155,22 +157,22 @@ en: user: User salmon_url: Salmon URL search: Search - shared_inbox_url: Shared Inbox URL + shared_inbox_url: Shared inbox URL show: - created_reports: Reports created by this account - report: report - targeted_reports: Reports made about this account + created_reports: Made reports + targeted_reports: Reported by others silence: Silence silenced: Silenced statuses: Statuses subscribe: Subscribe suspended: Suspended title: Accounts - unconfirmed_email: Unconfirmed E-mail + unconfirmed_email: Unconfirmed email undo_silenced: Undo silence undo_suspension: Undo suspension unsubscribe: Unsubscribe username: Username + warn: Warn web: Web action_logs: actions: diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 04a33d3d0..8e30ed679 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -152,7 +152,6 @@ eo: shared_inbox_url: URL de kunhavigita leterkesto show: created_reports: Signaloj kreitaj de ĉi tiu konto - report: signalo targeted_reports: Signaloj kreitaj de ĉi tiu konto silence: Kaŝi silenced: Silentigita diff --git a/config/locales/es.yml b/config/locales/es.yml index 117e7ccdd..957d852b8 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -150,7 +150,6 @@ es: shared_inbox_url: URL de bandeja compartida show: created_reports: Reportes hechos por esta cuenta - report: reportar targeted_reports: Reportes hechos sobre esta cuenta silence: Silenciar silenced: Silenciado diff --git a/config/locales/eu.yml b/config/locales/eu.yml index 6d39a6533..819e22b26 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -152,7 +152,6 @@ eu: shared_inbox_url: Partekatutako sarrera ontziaren URL-a show: created_reports: Kontu honek sortutako txostenak - report: salatu targeted_reports: Kontu honek egindako salaketak silence: Isilarazi silenced: Isilarazita diff --git a/config/locales/fa.yml b/config/locales/fa.yml index c24465236..d8f89a91b 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -150,7 +150,6 @@ fa: shared_inbox_url: نشانی صندوق ورودی مشترک show: created_reports: گزارش‌ها از طرف این حساب - report: گزارش targeted_reports: گزارش‌ها دربارهٔ این حساب silence: بی‌صدا silenced: بی‌صداشده diff --git a/config/locales/fi.yml b/config/locales/fi.yml index e210a490c..b48635e21 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -129,7 +129,6 @@ fi: shared_inbox_url: Jaetun saapuvan postilaatikon osoite show: created_reports: Tämän tilin luomat raportit - report: raportti targeted_reports: Tästä tilistä tehdyt raportit silence: Hiljennä statuses: Tilat diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f127fe9da..b38e9f8e4 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -154,7 +154,6 @@ fr: shared_inbox_url: URL de la boite de réception partagée show: created_reports: Signalements créés par ce compte - report: signalement targeted_reports: Signalements créés visant ce compte silence: Masquer silenced: Silencié diff --git a/config/locales/gl.yml b/config/locales/gl.yml index b97e76af4..ac7d55cda 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -154,7 +154,6 @@ gl: shared_inbox_url: URL da caixa de entrada compartida show: created_reports: Informes creados por esta conta - report: informar targeted_reports: Informes feitos sobre esta conta silence: Acalar silenced: Acalada diff --git a/config/locales/he.yml b/config/locales/he.yml index 8f651052a..f45afe3a1 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -120,7 +120,6 @@ he: shared_inbox_url: תיבה משותפת לדואר נכנס show: created_reports: דיווחים מאת חשבון זה - report: דו"ח targeted_reports: דיווחים נגד חשבון זה silence: השתקה statuses: הודעות diff --git a/config/locales/hu.yml b/config/locales/hu.yml index ab93ba12d..4fa74228d 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -118,7 +118,6 @@ hu: shared_inbox_url: Bejövő üzenetek URL keresése show: created_reports: Ezen fiók által létrehozott jelentések - report: jelentés targeted_reports: Jelentések ezzel a fiókkal kapcsolatban silence: Némítás statuses: Tülkök diff --git a/config/locales/id.yml b/config/locales/id.yml index e18207e24..5cc928823 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -62,7 +62,6 @@ id: salmon_url: URL Salmon show: created_reports: Laporan yang dibuat oleh akun ini - report: laporan targeted_reports: Laporan yang dibuat tentang akun ini silence: Diam statuses: Status diff --git a/config/locales/io.yml b/config/locales/io.yml index f52f2bc80..358ce4ca9 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -52,7 +52,6 @@ io: salmon_url: Salmon URL show: created_reports: Reports created by this account - report: report targeted_reports: Reports made about this account silence: Silence statuses: Statuses diff --git a/config/locales/it.yml b/config/locales/it.yml index 8f62f34e3..cc23b8cf7 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -150,7 +150,6 @@ it: shared_inbox_url: URL Inbox Condiviso show: created_reports: Rapporti creati da questo account - report: segnala targeted_reports: Rapporti che riguardano questo account silence: Silenzia silenced: Silenziato diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 5c8686a4f..a8773c4d2 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -154,7 +154,6 @@ ja: shared_inbox_url: Shared Inbox URL show: created_reports: このアカウントで作られたレポート - report: レポート targeted_reports: このアカウントについてのレポート silence: サイレンス silenced: サイレンス済み diff --git a/config/locales/ka.yml b/config/locales/ka.yml index 7cb767452..21e01c8c9 100644 --- a/config/locales/ka.yml +++ b/config/locales/ka.yml @@ -139,7 +139,6 @@ ka: shared_inbox_url: გაზიარებული ინბოქსის ურლ show: created_reports: ამ ანგარიშის მიერ შექმნილი რეპორტები - report: რეპორტი targeted_reports: ამ ანგარიშზე მიღებული რეპორტები silence: სიჩუმე statuses: სტატუსები diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 49ee0d3ce..9ac1cd6b9 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -154,7 +154,6 @@ ko: shared_inbox_url: 공유된 inbox URL show: created_reports: 이 계정에서 제출된 신고 - report: 신고 targeted_reports: 이 계정에 대한 신고 silence: 침묵 silenced: 침묵 됨 diff --git a/config/locales/ms.yml b/config/locales/ms.yml index c361371fe..7c6148e3b 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -150,7 +150,6 @@ ms: shared_inbox_url: URL Peti Masuk Berkongsi show: created_reports: Laporan yang dicipta oleh akaun ini - report: laporan targeted_reports: Laporan yang dicipta berkaitan akaun ini silence: Senyap silenced: Disenyapkan diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 1e0d11a95..1d85ab4c9 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -154,7 +154,6 @@ nl: shared_inbox_url: Gedeelde inbox-URL show: created_reports: Door dit account aangemaakte rapportages - report: gerapporteerd targeted_reports: Over dit account aangemaakte rapportages silence: Negeren silenced: Genegeerd diff --git a/config/locales/no.yml b/config/locales/no.yml index 230e6b3f0..a446fa1f6 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -118,7 +118,6 @@ shared_inbox_url: Delt Innboks URL show: created_reports: Rapporter laget av denne kontoen - report: rapport targeted_reports: Rapporter laget om denne kontoen silence: Målbind statuses: Statuser diff --git a/config/locales/oc.yml b/config/locales/oc.yml index e79aa0f54..daabea18a 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -154,7 +154,6 @@ oc: shared_inbox_url: URL de recepcion partejada show: created_reports: Rapòrts creat per aqueste compte - report: rapòrt targeted_reports: Rapòrts faches tocant aqueste compte silence: Silenci silenced: Rescondut diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 759ad1332..7478d0ea7 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -160,7 +160,6 @@ pl: shared_inbox_url: Adres udostępnianej skrzynki show: created_reports: Zgłoszenia tego użytkownika - report: zgłoszeń targeted_reports: Zgłoszenia dotyczące tego użytkownika silence: Wycisz silenced: Wyciszono diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 39a2a13c0..bd5cd7b36 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -152,7 +152,6 @@ pt-BR: shared_inbox_url: URL da caixa de entrada compartilhada show: created_reports: Denúncias criadas por esta conta - report: relatórios targeted_reports: Denúncias feitas sobre esta conta silence: Silenciar silenced: Silenciado diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 4c23c9cf4..a67223069 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -118,7 +118,6 @@ pt: shared_inbox_url: URL da caixa de entrada compartilhada show: created_reports: Relatórios gerados por esta conta - report: relatórios targeted_reports: Relatórios feitos sobre esta conta silence: Silêncio statuses: Status diff --git a/config/locales/ru.yml b/config/locales/ru.yml index a9a02caf8..3b81c9ebc 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -155,7 +155,6 @@ ru: shared_inbox_url: URL общих входящих show: created_reports: Жалобы, отправленные этим аккаунтом - report: жалоба targeted_reports: Жалобы на этот аккаунт silence: Глушение statuses: Статусы diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 135325fca..d30978e46 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -158,7 +158,6 @@ sk: shared_inbox_url: URL zdieľanej schránky show: created_reports: Reportované týmto používateľom - report: report targeted_reports: Nahlásenia pre tento účet silence: Stíšiť silenced: Utíšení diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index 93ba091cb..62ad744f3 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -118,7 +118,6 @@ sr-Latn: shared_inbox_url: Adresa deljenog sandučeta show: created_reports: Prijave koje je napravio ovaj nalog - report: prijava targeted_reports: Prijave napravljene o ovom nalogu silence: Ućutkaj statuses: Statusi diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 9ca5e412b..8dc869c8f 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -158,7 +158,6 @@ sr: shared_inbox_url: Адреса дељеног сандучета show: created_reports: Пријаве које је направио овај налог - report: пријава targeted_reports: Пријаве направљене о овом налогу silence: Ућуткај silenced: Ућуткан diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 706e4c570..79040b46c 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -130,7 +130,6 @@ sv: shared_inbox_url: Delad inkorg URL show: created_reports: Anmälningar som skapats av det här kontot - report: anmäla targeted_reports: Anmälningar gjorda om detta konto silence: Tystnad statuses: Status diff --git a/config/locales/th.yml b/config/locales/th.yml index 42d52af26..1a1ffae3b 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -61,7 +61,6 @@ th: salmon_url: Salmon URL show: created_reports: รายงานที่ถูกสร้างโดย แอคเคาท์นี้ - report: รายงาน targeted_reports: รายงานเกี่ยวกับแอคเคาท์นี้ silence: ปิดเสียง statuses: สถานะ diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 486210af6..aae1549f7 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -60,7 +60,6 @@ tr: salmon_url: Salmon Linki show: created_reports: Bu hesap tarafından gelen şikayetler - report: şikayet targeted_reports: Bu hesaba gelen şikayetler silence: Sustur statuses: Durumlar diff --git a/config/locales/uk.yml b/config/locales/uk.yml index f6d14c854..b3fc4cd36 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -135,7 +135,6 @@ uk: shared_inbox_url: URL спільного вхідного кошика show: created_reports: Скарги створені цим аккаунтом - report: скарга targeted_reports: Скарги щодо цього аккаунту silence: Глушення statuses: Статуси diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 2c1005a9a..d03bf1217 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -141,7 +141,6 @@ zh-CN: shared_inbox_url: 公用收件箱(Shared Inbox)URL show: created_reports: 这个帐户提交的举报 - report: 个举报 targeted_reports: 针对这个帐户的举报 silence: 隐藏 statuses: 嘟文 diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index c03946f0a..35b774120 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -130,7 +130,6 @@ zh-HK: shared_inbox_url: 公共收件箱(Shared Inbox)URL show: created_reports: 此用戶所提舉報的紀錄 - report: 舉報 targeted_reports: 此用戶被舉報的紀錄 silence: 靜音 statuses: 文章 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index d6a7abea9..5e209d2ff 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -135,7 +135,6 @@ zh-TW: shared_inbox_url: 公共收件箱 (Shared Inbox) URL show: created_reports: 這個使用者提交的檢舉 - report: 檢舉 targeted_reports: 針對這個使用者的檢舉 silence: 靜音 statuses: 嘟文 -- cgit From 66436d08959998be20c6c6bf631177d8c1f3e0d1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 2 Jan 2019 10:47:32 +0100 Subject: Improve e-mail digest (#9689) - Reduce time-to-digest from 20 to 7 days - Fetch mentions starting from +1 day since last login - Fix case when last login is more recent than last e-mail - Do not render all mentions, only 40, but show number in subject - Do not send digest to moved accounts - Do send digest to silenced accounts --- app/mailers/notification_mailer.rb | 16 ++++++++++------ app/models/account.rb | 5 +++-- app/models/user.rb | 4 +++- app/views/notification_mailer/digest.html.haml | 2 +- app/views/notification_mailer/digest.text.erb | 2 +- app/workers/scheduler/email_scheduler.rb | 12 ++++++------ spec/mailers/notification_mailer_spec.rb | 14 +------------- 7 files changed, 25 insertions(+), 30 deletions(-) (limited to 'app/models/user.rb') diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index b45844296..66fa337c1 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -66,16 +66,20 @@ class NotificationMailer < ApplicationMailer end def digest(recipient, **opts) - @me = recipient - @since = opts[:since] || @me.user.last_emailed_at || @me.user.current_sign_in_at - @notifications = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since) - @follows_since = Notification.where(account: @me, activity_type: 'Follow').where('created_at > ?', @since).count + return if recipient.user.disabled? + + @me = recipient + @since = opts[:since] || [@me.user.last_emailed_at, (@me.user.current_sign_in_at + 1.day)].compact.max + @notifications_count = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since).count - return if @me.user.disabled? || @notifications.empty? + return if @notifications_count.zero? + + @notifications = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since).limit(40) + @follows_since = Notification.where(account: @me, activity_type: 'Follow').where('created_at > ?', @since).count locale_for_account(@me) do mail to: @me.user.email, - subject: I18n.t(:subject, scope: [:notification_mailer, :digest], count: @notifications.size) + subject: I18n.t(:subject, scope: [:notification_mailer, :digest], count: @notifications_count) end end diff --git a/app/models/account.rb b/app/models/account.rb index f354bc29b..97beb416a 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -85,6 +85,7 @@ class Account < ApplicationRecord scope :silenced, -> { where(silenced: true) } scope :suspended, -> { where(suspended: true) } scope :without_suspended, -> { where(suspended: false) } + scope :without_silenced, -> { where(silenced: false) } scope :recent, -> { reorder(id: :desc) } scope :bots, -> { where(actor_type: %w(Application Service)) } scope :alphabetic, -> { order(domain: :asc, username: :asc) } @@ -92,8 +93,8 @@ class Account < ApplicationRecord 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}%")) } - scope :searchable, -> { where(suspended: false).where(moved_to_account_id: nil) } - scope :discoverable, -> { searchable.where(silenced: false).where(discoverable: true).joins(:account_stat).where(AccountStat.arel_table[:followers_count].gteq(MIN_FOLLOWERS_DISCOVERY)).by_recent_status } + scope :searchable, -> { without_suspended.where(moved_to_account_id: nil) } + scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat).where(AccountStat.arel_table[:followers_count].gteq(MIN_FOLLOWERS_DISCOVERY)).by_recent_status } scope :tagged_with, ->(tag) { joins(:accounts_tags).where(accounts_tags: { tag_id: tag }) } scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc')) } scope :popular, -> { order('account_stats.followers_count desc') } diff --git a/app/models/user.rb b/app/models/user.rb index 1684b9bea..8b374c182 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -50,7 +50,7 @@ class User < ApplicationRecord # every day. Raising the duration reduces the amount of expensive # RegenerationWorker jobs that need to be run when those people come # to check their feed - ACTIVE_DURATION = ENV.fetch('USER_ACTIVE_DAYS', 7).to_i.days + ACTIVE_DURATION = ENV.fetch('USER_ACTIVE_DAYS', 7).to_i.days.freeze devise :two_factor_authenticatable, otp_secret_encryption_key: Rails.configuration.x.otp_secret @@ -83,9 +83,11 @@ class User < ApplicationRecord scope :moderators, -> { where(moderator: true) } scope :staff, -> { admins.or(moderators) } scope :confirmed, -> { where.not(confirmed_at: nil) } + scope :enabled, -> { where(disabled: false) } scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) } scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended: false }) } scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) } + scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) } before_validation :sanitize_languages diff --git a/app/views/notification_mailer/digest.html.haml b/app/views/notification_mailer/digest.html.haml index 10e44f8dd..a94ace228 100644 --- a/app/views/notification_mailer/digest.html.haml +++ b/app/views/notification_mailer/digest.html.haml @@ -14,7 +14,7 @@ %tr %td.column-cell.text-center.padded %h1= t 'notification_mailer.digest.title' - %p.lead= t('notification_mailer.digest.body', since: l(@since.to_date, format: :short), instance: site_hostname) + %p.lead= t('notification_mailer.digest.body', since: l((@me.user_current_sign_in_at || @since).to_date, format: :short), instance: site_hostname) %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 } %tbody %tr diff --git a/app/views/notification_mailer/digest.text.erb b/app/views/notification_mailer/digest.text.erb index e0d1f9b8b..b2c85a9e3 100644 --- a/app/views/notification_mailer/digest.text.erb +++ b/app/views/notification_mailer/digest.text.erb @@ -1,6 +1,6 @@ <%= raw t('application_mailer.salutation', name: display_name(@me)) %> -<%= raw t('notification_mailer.digest.body', since: l(@since), instance: root_url) %> +<%= raw t('notification_mailer.digest.body', since: l(@me.user_current_sign_in_at || @since), instance: root_url) %> <% @notifications.each do |notification| %> * <%= raw t('notification_mailer.digest.mention', name: notification.from_account.acct) %> diff --git a/app/workers/scheduler/email_scheduler.rb b/app/workers/scheduler/email_scheduler.rb index 24ec89b29..1eeeee412 100644 --- a/app/workers/scheduler/email_scheduler.rb +++ b/app/workers/scheduler/email_scheduler.rb @@ -5,6 +5,9 @@ class Scheduler::EmailScheduler sidekiq_options unique: :until_executed, retry: 0 + FREQUENCY = 7.days.freeze + SIGN_IN_OFFSET = 1.day.freeze + def perform eligible_users.reorder(nil).find_each do |user| next unless user.allows_digest_emails? @@ -15,11 +18,8 @@ class Scheduler::EmailScheduler private def eligible_users - User.confirmed - .joins(:account) - .where(accounts: { silenced: false, suspended: false }) - .where(disabled: false) - .where('current_sign_in_at < ?', 20.days.ago) - .where('last_emailed_at IS NULL OR last_emailed_at < ?', 20.days.ago) + User.emailable + .where('current_sign_in_at < ?', (FREQUENCY + SIGN_IN_OFFSET).ago) + .where('last_emailed_at IS NULL OR last_emailed_at < ?', FREQUENCY.ago) end end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index 1be01e8ba..38916b54f 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -126,19 +126,7 @@ RSpec.describe NotificationMailer, type: :mailer do end end - it 'includes activities since the date specified by :since option' do - receiver.update!(last_emailed_at: '2000-02-01T00:00:00Z', current_sign_in_at: '2000-03-01T00:00:00Z') - mail = NotificationMailer.digest(receiver.account, since: Time.parse('2000-01-01T00:00:00Z')) - expect(mail.body.encoded).to include 'Jan 01, 2000, 00:00' - end - - it 'includes activities since the receiver was last emailed if :since option is unavailable' do - receiver.update!(last_emailed_at: '2000-02-01T00:00:00Z', current_sign_in_at: '2000-03-01T00:00:00Z') - mail = NotificationMailer.digest(receiver.account) - expect(mail.body.encoded).to include 'Feb 01, 2000, 00:00' - end - - it 'includes activities since the receiver last signed in if :since option and the last emailed date are unavailable' do + it 'includes activities since the receiver last signed in' do receiver.update!(last_emailed_at: nil, current_sign_in_at: '2000-03-01T00:00:00Z') mail = NotificationMailer.digest(receiver.account) expect(mail.body.encoded).to include 'Mar 01, 2000, 00:00' -- cgit