about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.browserslistrc4
-rw-r--r--SECURITY.md2
-rw-r--r--app/controllers/activitypub/base_controller.rb1
-rw-r--r--app/controllers/api/base_controller.rb5
-rw-r--r--app/controllers/auth/confirmations_controller.rb2
-rw-r--r--app/lib/application_extension.rb4
-rw-r--r--app/models/account_stat.rb12
-rw-r--r--app/models/admin/status_batch_action.rb6
-rw-r--r--app/models/status_stat.rb12
-rw-r--r--app/services/appeal_service.rb3
-rw-r--r--app/services/approve_appeal_service.rb3
-rw-r--r--app/services/report_service.rb2
-rw-r--r--app/services/unfollow_service.rb6
-rw-r--r--app/services/vote_service.rb2
-rw-r--r--config/initializers/doorkeeper.rb7
15 files changed, 61 insertions, 10 deletions
diff --git a/.browserslistrc b/.browserslistrc
index d5734664c..54dd3aaf3 100644
--- a/.browserslistrc
+++ b/.browserslistrc
@@ -4,6 +4,4 @@ not IE 11
 not dead
 
 [development]
-last 1 chrome version
-last 1 firefox version
-last 1 safari version
+supports es6-module
diff --git a/SECURITY.md b/SECURITY.md
index 12f50ed88..62e23f736 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -14,7 +14,7 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
 | ------- | ------------------ |
 | 3.5.x   | Yes                |
 | 3.4.x   | Yes                |
-| 3.3.x   | Yes                |
+| 3.3.x   | No                 |
 | < 3.3   | No                 |
 
 [bug-bounty]: https://app.intigriti.com/programs/mastodon/mastodonio/detail
diff --git a/app/controllers/activitypub/base_controller.rb b/app/controllers/activitypub/base_controller.rb
index 196d85a32..b8a7e0ab9 100644
--- a/app/controllers/activitypub/base_controller.rb
+++ b/app/controllers/activitypub/base_controller.rb
@@ -2,6 +2,7 @@
 
 class ActivityPub::BaseController < Api::BaseController
   skip_before_action :require_authenticated_user!
+  skip_before_action :require_not_suspended!
   skip_around_action :set_locale
 
   private
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index d96285b44..2e393fbb6 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -11,6 +11,7 @@ class Api::BaseController < ApplicationController
   skip_before_action :require_functional!, unless: :whitelist_mode?
 
   before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
+  before_action :require_not_suspended!
   before_action :set_cache_headers
 
   protect_from_forgery with: :null_session
@@ -97,6 +98,10 @@ class Api::BaseController < ApplicationController
     render json: { error: 'This method requires an authenticated user' }, status: 401 unless current_user
   end
 
+  def require_not_suspended!
+    render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.suspended?
+  end
+
   def require_user!
     if !current_user
       render json: { error: 'This method requires an authenticated user' }, status: 422
diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb
index 17ad56fa8..0817a905c 100644
--- a/app/controllers/auth/confirmations_controller.rb
+++ b/app/controllers/auth/confirmations_controller.rb
@@ -89,7 +89,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
 
   def after_confirmation_path_for(_resource_name, user)
     if user.created_by_application && truthy_param?(:redirect_to_app)
-      user.created_by_application.redirect_uri
+      user.created_by_application.confirmation_redirect_uri
     else
       super
     end
diff --git a/app/lib/application_extension.rb b/app/lib/application_extension.rb
index a1fea6430..d61ec0e6e 100644
--- a/app/lib/application_extension.rb
+++ b/app/lib/application_extension.rb
@@ -12,4 +12,8 @@ module ApplicationExtension
   def most_recently_used_access_token
     @most_recently_used_access_token ||= access_tokens.where.not(last_used_at: nil).order(last_used_at: :desc).first
   end
+
+  def confirmation_redirect_uri
+    redirect_uri.lines.first.strip
+  end
 end
diff --git a/app/models/account_stat.rb b/app/models/account_stat.rb
index b49827267..a5d71a5b8 100644
--- a/app/models/account_stat.rb
+++ b/app/models/account_stat.rb
@@ -20,4 +20,16 @@ class AccountStat < ApplicationRecord
   belongs_to :account, inverse_of: :account_stat
 
   update_index('accounts', :account)
+
+  def following_count
+    [attributes['following_count'], 0].max
+  end
+
+  def followers_count
+    [attributes['followers_count'], 0].max
+  end
+
+  def statuses_count
+    [attributes['statuses_count'], 0].max
+  end
 end
diff --git a/app/models/admin/status_batch_action.rb b/app/models/admin/status_batch_action.rb
index 631af183c..7bf6fa6da 100644
--- a/app/models/admin/status_batch_action.rb
+++ b/app/models/admin/status_batch_action.rb
@@ -103,7 +103,7 @@ class Admin::StatusBatchAction
 
   def handle_report!
     @report = Report.new(report_params) unless with_report?
-    @report.status_ids = (@report.status_ids + status_ids.map(&:to_i)).uniq
+    @report.status_ids = (@report.status_ids + allowed_status_ids).uniq
     @report.save!
 
     @report_id = @report.id
@@ -135,4 +135,8 @@ class Admin::StatusBatchAction
   def report_params
     { account: current_account, target_account: target_account }
   end
+
+  def allowed_status_ids
+    AccountStatusesFilter.new(@report.target_account, current_account).results.with_discarded.where(id: status_ids).pluck(:id)
+  end
 end
diff --git a/app/models/status_stat.rb b/app/models/status_stat.rb
index 024c467e7..437861d1c 100644
--- a/app/models/status_stat.rb
+++ b/app/models/status_stat.rb
@@ -17,6 +17,18 @@ class StatusStat < ApplicationRecord
 
   after_commit :reset_parent_cache
 
+  def replies_count
+    [attributes['replies_count'], 0].max
+  end
+
+  def reblogs_count
+    [attributes['reblogs_count'], 0].max
+  end
+
+  def favourites_count
+    [attributes['favourites_count'], 0].max
+  end
+
   private
 
   def reset_parent_cache
diff --git a/app/services/appeal_service.rb b/app/services/appeal_service.rb
index 1397c50f5..cef9be05f 100644
--- a/app/services/appeal_service.rb
+++ b/app/services/appeal_service.rb
@@ -14,7 +14,8 @@ class AppealService < BaseService
   private
 
   def create_appeal!
-    @appeal = @strike.create_appeal!(
+    @appeal = Appeal.create!(
+      strike: @strike,
       text: @text,
       account: @strike.target_account
     )
diff --git a/app/services/approve_appeal_service.rb b/app/services/approve_appeal_service.rb
index 37a08b46e..96aaaa7d0 100644
--- a/app/services/approve_appeal_service.rb
+++ b/app/services/approve_appeal_service.rb
@@ -52,8 +52,9 @@ class ApproveAppealService < BaseService
   end
 
   def undo_mark_statuses_as_sensitive!
+    representative_account = Account.representative
     @strike.statuses.includes(:media_attachments).each do |status|
-      UpdateStatusService.new.call(status, @current_account.id, sensitive: false) if status.with_media?
+      UpdateStatusService.new.call(status, representative_account.id, sensitive: false) if status.with_media?
     end
   end
 
diff --git a/app/services/report_service.rb b/app/services/report_service.rb
index 9d784c341..d251bb33f 100644
--- a/app/services/report_service.rb
+++ b/app/services/report_service.rb
@@ -57,7 +57,7 @@ class ReportService < BaseService
   end
 
   def reported_status_ids
-    @target_account.statuses.with_discarded.find(Array(@status_ids)).pluck(:id)
+    AccountStatusesFilter.new(@target_account, @source_account).results.with_discarded.find(Array(@status_ids)).pluck(:id)
   end
 
   def payload
diff --git a/app/services/unfollow_service.rb b/app/services/unfollow_service.rb
index 151f3674f..d83a60e4e 100644
--- a/app/services/unfollow_service.rb
+++ b/app/services/unfollow_service.rb
@@ -2,6 +2,8 @@
 
 class UnfollowService < BaseService
   include Payloadable
+  include Redisable
+  include Lockable
 
   # Unfollow and notify the remote user
   # @param [Account] source_account Where to unfollow from
@@ -13,7 +15,9 @@ class UnfollowService < BaseService
     @target_account = target_account
     @options        = options
 
-    unfollow! || undo_follow_request!
+    with_lock("relationship:#{[source_account.id, target_account.id].sort.join(':')}") do
+      unfollow! || undo_follow_request!
+    end
   end
 
   private
diff --git a/app/services/vote_service.rb b/app/services/vote_service.rb
index ccd04dbfc..114ec285c 100644
--- a/app/services/vote_service.rb
+++ b/app/services/vote_service.rb
@@ -7,6 +7,8 @@ class VoteService < BaseService
   include Lockable
 
   def call(account, poll, choices)
+    return if choices.empty?
+
     authorize_with account, poll, :vote?
 
     @account = account
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index f78db8653..84b649f5c 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -128,6 +128,13 @@ Doorkeeper.configure do
   #
   force_ssl_in_redirect_uri false
 
+  # Specify what redirect URI's you want to block during Application creation.
+  # Any redirect URI is whitelisted by default.
+  #
+  # You can use this option in order to forbid URI's with 'javascript' scheme
+  # for example.
+  forbid_redirect_uri { |uri| %w[data vbscript javascript].include?(uri.scheme.to_s.downcase) }
+
   # Specify what grant flows are enabled in array of Strings. The valid
   # strings and the flows they enable are:
   #