diff --git a/.browserslistrc b/.browserslistrc index d5734664cc..54dd3aaf34 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/CHANGELOG.md b/CHANGELOG.md index 841c01bfb9..ed4cdd881a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,53 @@ Changelog All notable changes to this project will be documented in this file. +## [3.5.3] - 2022-05-26 +### Added + +- **Add language dropdown to compose form in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/18420), [ykzts](https://github.com/mastodon/mastodon/pull/18460)) +- **Add warning for limited accounts in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/18344)) +- Add `limited` attribute to accounts in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/18344)) + +### Changed + +- **Change RSS feeds** ([Gargron](https://github.com/mastodon/mastodon/pull/18356), [tribela](https://github.com/mastodon/mastodon/pull/18406)) + - Titles are now date and time of post + - Bodies now render all content faithfully, including polls and emojis + - All media attachments are included with Media RSS +- Change "dangerous" to "sensitive" in privacy policy and web UI ([Gargron](https://github.com/mastodon/mastodon/pull/18515)) +- Change unconfirmed accounts to not be visible in REST API ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17530)) +- Change `tootctl search deploy` to improve performance ([Gargron](https://github.com/mastodon/mastodon/pull/18463), [Gargron](https://github.com/mastodon/mastodon/pull/18514)) +- Change search indexing to use batches to minimize resource usage ([Gargron](https://github.com/mastodon/mastodon/pull/18451)) + +### Fixed + +- Fix follower and other counters being able to go negative ([Gargron](https://github.com/mastodon/mastodon/pull/18517)) +- Fix unnecessary query on when creating a status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17901)) +- Fix warning an account outside of a report closing all reports for that account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18387)) +- Fix error when resolving a link that redirects to a local post ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18314)) +- Fix preferred posting language returning unusable value in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/18428)) +- Fix race condition error when external status is reblogged ([ykzts](https://github.com/mastodon/mastodon/pull/18424)) +- Fix missing string for appeal validation error ([Gargron](https://github.com/mastodon/mastodon/pull/18410)) +- Fix block/mute lists showing a follow button in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18364)) +- Fix Redis configuration not being changed by `mastodon:setup` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18383)) +- Fix streaming notifications not using quick filter logic in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18316)) +- Fix ambiguous wording on appeal actions in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18328)) +- Fix floating action button obscuring last element in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18332)) +- Fix account warnings not being recorded in audit log ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18338)) +- Fix leftover icons for direct visibility statuses ([Steffo99](https://github.com/mastodon/mastodon/pull/18305)) +- Fix link verification requiring case sensitivity on links ([sgolemon](https://github.com/mastodon/mastodon/pull/18320)) +- Fix embeds not setting their height correctly ([rinsuki](https://github.com/mastodon/mastodon/pull/18301)) + +### Security + +- Fix concurrent unfollowing decrementing follower count more than once ([Gargron](https://github.com/mastodon/mastodon/pull/18527)) +- Fix being able to appeal a strike unlimited times ([Gargron](https://github.com/mastodon/mastodon/pull/18529)) +- Fix being able to report otherwise inaccessible statuses ([Gargron](https://github.com/mastodon/mastodon/pull/18528)) +- Fix empty votes arbitrarily increasing voters count in polls ([Gargron](https://github.com/mastodon/mastodon/pull/18526)) +- Fix moderator identity leak when approving appeal of sensitive marked statuses ([Gargron](https://github.com/mastodon/mastodon/pull/18525)) +- Fix suspended users being able to access APIs that don't require a user ([Gargron](https://github.com/mastodon/mastodon/pull/18524)) +- Fix confirmation redirect to app without `Location` header ([Gargron](https://github.com/mastodon/mastodon/pull/18523)) + ## [3.5.2] - 2022-05-04 ### Added diff --git a/SECURITY.md b/SECURITY.md index 12f50ed880..62e23f7360 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 196d85a326..b8a7e0ab96 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 d96285b440..2e393fbb6f 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 17ad56fa87..0817a905ca 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/helpers/formatting_helper.rb b/app/helpers/formatting_helper.rb index 526efd766f..448177bec2 100644 --- a/app/helpers/formatting_helper.rb +++ b/app/helpers/formatting_helper.rb @@ -23,7 +23,7 @@ module FormattingHelper before_html = begin if status.spoiler_text? - "

#{I18n.t('rss.content_warning', locale: valid_locale_or_nil(status.language))} #{h(status.spoiler_text)}


" + "

#{I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale)} #{h(status.spoiler_text)}


" else '' end diff --git a/app/helpers/languages_helper.rb b/app/helpers/languages_helper.rb index d39bb6c930..4077e19bdf 100644 --- a/app/helpers/languages_helper.rb +++ b/app/helpers/languages_helper.rb @@ -254,4 +254,8 @@ module LanguagesHelper def valid_locale?(locale) locale.present? && SUPPORTED_LOCALES.key?(locale.to_sym) end + + def available_locale_or_nil(locale_name) + locale_name.to_sym if locale_name.present? && I18n.available_locales.include?(locale_name.to_sym) + end end diff --git a/app/lib/application_extension.rb b/app/lib/application_extension.rb index a1fea6430a..d61ec0e6e7 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/lib/rss/media_content.rb b/app/lib/rss/media_content.rb index 7aefd8b40b..f281fe29e4 100644 --- a/app/lib/rss/media_content.rb +++ b/app/lib/rss/media_content.rb @@ -26,4 +26,10 @@ class RSS::MediaContent < RSS::Element description['type'] = 'plain' end end + + def thumbnail(str) + append_element('media:thumbnail') do |thumbnail| + thumbnail['url'] = str + end + end end diff --git a/app/models/account_stat.rb b/app/models/account_stat.rb index b49827267a..a5d71a5b8c 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 631af183c2..7bf6fa6daf 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 024c467e71..437861d1c4 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 1397c50f5f..cef9be05fd 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 37a08b46e3..96aaaa7d07 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 9d784c341a..d251bb33f0 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 151f3674fd..d83a60e4e7 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 ccd04dbfcb..114ec285c8 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 f78db86534..84b649f5c1 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: # diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index bc22539d9c..2d0b283230 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 2 + 3 end def flags