diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml new file mode 100644 index 0000000000..6c4869f12d --- /dev/null +++ b/.github/workflows/bundler-audit.yml @@ -0,0 +1,40 @@ +name: Bundler Audit +on: + push: + branches-ignore: + - 'dependabot/**' + paths: + - 'Gemfile*' + - '.ruby-version' + - '.bundler-audit.yml' + - '.github/workflows/bundler-audit.yml' + + pull_request: + paths: + - 'Gemfile*' + - '.ruby-version' + - '.bundler-audit.yml' + - '.github/workflows/bundler-audit.yml' + + schedule: + - cron: '0 5 * * 1' + +jobs: + security: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v3 + + - name: Install native Ruby dependencies + run: sudo apt-get install -y libicu-dev libidn11-dev + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: .ruby-version + bundler-cache: true + + - name: Run bundler-audit + run: bundle exec bundler-audit diff --git a/.github/workflows/lint-ruby.yml b/.github/workflows/lint-ruby.yml index 0395c8639f..c898b26325 100644 --- a/.github/workflows/lint-ruby.yml +++ b/.github/workflows/lint-ruby.yml @@ -8,7 +8,7 @@ on: - 'Gemfile*' - '.rubocop*.yml' - '.ruby-version' - - '.bundler-audit.yml' + - 'config/brakeman.ignore' - '**/*.rb' - '**/*.rake' - '.github/workflows/lint-ruby.yml' @@ -18,7 +18,7 @@ on: - 'Gemfile*' - '.rubocop*.yml' - '.ruby-version' - - '.bundler-audit.yml' + - 'config/brakeman.ignore' - '**/*.rb' - '**/*.rake' - '.github/workflows/lint-ruby.yml' @@ -46,5 +46,6 @@ jobs: - name: Run rubocop run: bundle exec rubocop - - name: Run bundler-audit - run: bundle exec bundler-audit + - name: Run brakeman + if: always() # Run both checks, even if the first failed + run: bundle exec brakeman diff --git a/.github/workflows/rebase-needed.yml b/.github/workflows/rebase-needed.yml index 131a62a576..295039c414 100644 --- a/.github/workflows/rebase-needed.yml +++ b/.github/workflows/rebase-needed.yml @@ -1,17 +1,8 @@ name: PR Needs Rebase on: - push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' - - 'l10n_main' - pull_request_target: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' - - 'l10n_main' - types: [synchronize] + schedule: + - cron: '0 * * * *' permissions: pull-requests: write diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index c601683907..31b79f7db2 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,73 +1,23 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-03-15 00:55:01 -0400 using Haml-Lint version 0.45.0. +# on 2023-07-11 23:58:05 +0200 using Haml-Lint version 0.48.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of Haml-Lint, may require this file to be generated again. linters: - # Offense count: 63 + # Offense count: 94 RuboCop: - exclude: - - 'app/views/accounts/_og.html.haml' - - 'app/views/admin/account_warnings/_account_warning.html.haml' - - 'app/views/admin/accounts/index.html.haml' - - 'app/views/admin/accounts/show.html.haml' - - 'app/views/admin/announcements/edit.html.haml' - - 'app/views/admin/announcements/new.html.haml' - - 'app/views/admin/disputes/appeals/_appeal.html.haml' - - 'app/views/admin/domain_blocks/edit.html.haml' - - 'app/views/admin/domain_blocks/new.html.haml' - - 'app/views/admin/ip_blocks/new.html.haml' - - 'app/views/admin/reports/actions/preview.html.haml' - - 'app/views/admin/reports/index.html.haml' - - 'app/views/admin/reports/show.html.haml' - - 'app/views/admin/roles/_form.html.haml' - - 'app/views/admin/settings/about/show.html.haml' - - 'app/views/admin/settings/appearance/show.html.haml' - - 'app/views/admin/settings/registrations/show.html.haml' - - 'app/views/admin/statuses/show.html.haml' - - 'app/views/auth/registrations/new.html.haml' - - 'app/views/disputes/strikes/show.html.haml' - - 'app/views/filters/_filter_fields.html.haml' - - 'app/views/invites/_form.html.haml' - - 'app/views/layouts/application.html.haml' - - 'app/views/layouts/error.html.haml' - - 'app/views/notification_mailer/_status.html.haml' - - 'app/views/settings/applications/_fields.html.haml' - - 'app/views/settings/imports/show.html.haml' - - 'app/views/settings/preferences/appearance/show.html.haml' - - 'app/views/settings/preferences/other/show.html.haml' - - 'app/views/statuses/_detailed_status.html.haml' - - 'app/views/statuses/_poll.html.haml' - - 'app/views/statuses/show.html.haml' - - 'app/views/statuses_cleanup/show.html.haml' - - 'app/views/user_mailer/warning.html.haml' + enabled: false - # Offense count: 913 + # Offense count: 960 LineLength: enabled: false # Offense count: 22 UnnecessaryStringOutput: - exclude: - - 'app/views/accounts/show.html.haml' - - 'app/views/admin/custom_emojis/_custom_emoji.html.haml' - - 'app/views/admin/relays/_relay.html.haml' - - 'app/views/admin/rules/_rule.html.haml' - - 'app/views/admin/statuses/index.html.haml' - - 'app/views/auth/registrations/_sessions.html.haml' - - 'app/views/disputes/strikes/show.html.haml' - - 'app/views/notification_mailer/_status.html.haml' - - 'app/views/settings/two_factor_authentication_methods/index.html.haml' - - 'app/views/statuses/_detailed_status.html.haml' - - 'app/views/statuses/_poll.html.haml' - - 'app/views/statuses/_simple_status.html.haml' - - 'app/views/user_mailer/suspicious_sign_in.html.haml' - - 'app/views/user_mailer/webauthn_credential_added.html.haml' - - 'app/views/user_mailer/webauthn_credential_deleted.html.haml' - - 'app/views/user_mailer/welcome.html.haml' + enabled: false # Offense count: 3 ViewLength: diff --git a/.rubocop.yml b/.rubocop.yml index eff89bdaee..597dfcb9e0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -24,7 +24,6 @@ AllCops: Exclude: - db/schema.rb - 'bin/*' - - 'Rakefile' - 'node_modules/**/*' - 'Vagrantfile' - 'vendor/**/*' @@ -192,6 +191,11 @@ Style/RedundantBegin: Style/RescueStandardError: EnforcedStyle: implicit +# Reason: Simplify some spec layouts +# https://docs.rubocop.org/rubocop/cops_style.html#stylesemicolon +Style/Semicolon: + AllowAsExpressionSeparator: true + # Reason: Originally disabled for CodeClimate, and no config consensus has been found # https://docs.rubocop.org/rubocop/cops_style.html#stylesymbolarray Style/SymbolArray: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c1d580e515..f186d7955f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -48,15 +48,6 @@ Layout/SpaceInLambdaLiteral: - 'config/environments/production.rb' - 'config/initializers/content_security_policy.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowedMethods, AllowedPatterns. -Lint/AmbiguousBlockAssociation: - Exclude: - - 'spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb' - - 'spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb' - - 'spec/services/activitypub/process_status_update_service_spec.rb' - - 'spec/services/post_status_service_spec.rb' - # Configuration parameters: AllowComments, AllowEmptyLambdas. Lint/EmptyBlock: Exclude: @@ -106,11 +97,6 @@ Lint/OrAssignmentToConstant: Exclude: - 'lib/sanitize_ext/sanitize_config.rb' -# This cop supports safe autocorrection (--autocorrect). -Lint/SendWithMixinArgument: - Exclude: - - 'config/application.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: @@ -167,10 +153,6 @@ Metrics/CyclomaticComplexity: Metrics/PerceivedComplexity: Max: 27 -Naming/AccessorMethodName: - Exclude: - - 'app/controllers/auth/sessions_controller.rb' - # Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. # CheckDefinitionPathHierarchyRoots: lib, spec, test, src # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS @@ -178,19 +160,6 @@ Naming/FileName: Exclude: - 'config/locales/sr-Latn.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyleForLeadingUnderscores. -# SupportedStylesForLeadingUnderscores: disallowed, required, optional -Naming/MemoizedInstanceVariableName: - Exclude: - - 'app/controllers/api/v1/bookmarks_controller.rb' - - 'app/controllers/api/v1/favourites_controller.rb' - - 'app/controllers/concerns/rate_limit_headers.rb' - - 'app/lib/activitypub/activity.rb' - - 'app/services/resolve_url_service.rb' - - 'app/services/search_service.rb' - - 'config/initializers/rack_attack.rb' - # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns. # SupportedStyles: snake_case, normalcase, non_integer # AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64 @@ -400,45 +369,6 @@ RSpec/PendingWithoutReason: Exclude: - 'spec/models/account_spec.rb' -RSpec/StubbedMock: - Exclude: - - 'spec/controllers/api/base_controller_spec.rb' - - 'spec/controllers/api/v1/media_controller_spec.rb' - - 'spec/controllers/auth/registrations_controller_spec.rb' - - 'spec/helpers/application_helper_spec.rb' - - 'spec/lib/status_filter_spec.rb' - - 'spec/lib/status_finder_spec.rb' - - 'spec/lib/webfinger_resource_spec.rb' - - 'spec/services/activitypub/process_collection_service_spec.rb' - -RSpec/SubjectDeclaration: - Exclude: - - 'spec/controllers/admin/domain_blocks_controller_spec.rb' - - 'spec/models/account_migration_spec.rb' - - 'spec/models/account_spec.rb' - - 'spec/models/relationship_filter_spec.rb' - - 'spec/models/user_role_spec.rb' - - 'spec/policies/account_moderation_note_policy_spec.rb' - - 'spec/policies/account_policy_spec.rb' - - 'spec/policies/backup_policy_spec.rb' - - 'spec/policies/custom_emoji_policy_spec.rb' - - 'spec/policies/domain_block_policy_spec.rb' - - 'spec/policies/email_domain_block_policy_spec.rb' - - 'spec/policies/instance_policy_spec.rb' - - 'spec/policies/invite_policy_spec.rb' - - 'spec/policies/relay_policy_spec.rb' - - 'spec/policies/report_note_policy_spec.rb' - - 'spec/policies/report_policy_spec.rb' - - 'spec/policies/settings_policy_spec.rb' - - 'spec/policies/tag_policy_spec.rb' - - 'spec/policies/user_policy_spec.rb' - - 'spec/services/activitypub/process_account_service_spec.rb' - -RSpec/SubjectStub: - Exclude: - - 'spec/services/unallow_domain_service_spec.rb' - - 'spec/validators/blacklisted_email_validator_spec.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). Rails/ApplicationController: Exclude: @@ -779,406 +709,6 @@ Style/FormatStringToken: - 'config/initializers/devise.rb' - 'lib/paperclip/color_extractor.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: always, always_true, never -Style/FrozenStringLiteralComment: - Exclude: - - 'app/views/accounts/show.rss.ruby' - - 'app/views/tags/show.rss.ruby' - - 'app/views/well_known/host_meta/show.xml.ruby' - - 'config/application.rb' - - 'config/boot.rb' - - 'config/environment.rb' - - 'config/environments/development.rb' - - 'config/environments/production.rb' - - 'config/environments/test.rb' - - 'config/initializers/0_post_deployment_migrations.rb' - - 'config/initializers/active_model_serializers.rb' - - 'config/initializers/application_controller_renderer.rb' - - 'config/initializers/assets.rb' - - 'config/initializers/backtrace_silencers.rb' - - 'config/initializers/cache_logging.rb' - - 'config/initializers/chewy.rb' - - 'config/initializers/content_security_policy.rb' - - 'config/initializers/cookies_serializer.rb' - - 'config/initializers/cors.rb' - - 'config/initializers/devise.rb' - - 'config/initializers/doorkeeper.rb' - - 'config/initializers/fast_blank.rb' - - 'config/initializers/ffmpeg.rb' - - 'config/initializers/filter_parameter_logging.rb' - - 'config/initializers/http_client_proxy.rb' - - 'config/initializers/httplog.rb' - - 'config/initializers/inflections.rb' - - 'config/initializers/mail_delivery_job.rb' - - 'config/initializers/makara.rb' - - 'config/initializers/mime_types.rb' - - 'config/initializers/oj.rb' - - 'config/initializers/omniauth.rb' - - 'config/initializers/open_uri_redirection.rb' - - 'config/initializers/permissions_policy.rb' - - 'config/initializers/pghero.rb' - - 'config/initializers/preload_link_headers.rb' - - 'config/initializers/premailer_rails.rb' - - 'config/initializers/rack_attack_logging.rb' - - 'config/initializers/redis.rb' - - 'config/initializers/session_store.rb' - - 'config/initializers/simple_form.rb' - - 'config/initializers/stoplight.rb' - - 'config/initializers/trusted_proxies.rb' - - 'config/initializers/twitter_regex.rb' - - 'config/initializers/webauthn.rb' - - 'config/initializers/wrap_parameters.rb' - - 'config/locales/sr-Latn.rb' - - 'config/locales/sr.rb' - - 'config/puma.rb' - - 'db/migrate/20160220174730_create_accounts.rb' - - 'db/migrate/20160220211917_create_statuses.rb' - - 'db/migrate/20160221003140_create_users.rb' - - 'db/migrate/20160221003621_create_follows.rb' - - 'db/migrate/20160222122600_create_stream_entries.rb' - - 'db/migrate/20160222143943_add_profile_fields_to_accounts.rb' - - 'db/migrate/20160223162837_add_metadata_to_statuses.rb' - - 'db/migrate/20160223164502_make_uris_nullable_in_statuses.rb' - - 'db/migrate/20160223165723_add_url_to_statuses.rb' - - 'db/migrate/20160223165855_add_url_to_accounts.rb' - - 'db/migrate/20160223171800_create_favourites.rb' - - 'db/migrate/20160224223247_create_mentions.rb' - - 'db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb' - - 'db/migrate/20160305115639_add_devise_to_users.rb' - - 'db/migrate/20160306172223_create_doorkeeper_tables.rb' - - 'db/migrate/20160312193225_add_attachment_header_to_accounts.rb' - - 'db/migrate/20160314164231_add_owner_to_application.rb' - - 'db/migrate/20160316103650_add_missing_indices.rb' - - 'db/migrate/20160322193748_add_avatar_remote_url_to_accounts.rb' - - 'db/migrate/20160325130944_add_admin_to_users.rb' - - 'db/migrate/20160826155805_add_superapp_to_oauth_applications.rb' - - 'db/migrate/20160905150353_create_media_attachments.rb' - - 'db/migrate/20160919221059_add_subscription_expires_at_to_accounts.rb' - - 'db/migrate/20160920003904_remove_verify_token_from_accounts.rb' - - 'db/migrate/20160926213048_remove_owner_from_application.rb' - - 'db/migrate/20161003142332_add_confirmable_to_users.rb' - - 'db/migrate/20161003145426_create_blocks.rb' - - 'db/migrate/20161006213403_rails_settings_migration.rb' - - 'db/migrate/20161009120834_create_domain_blocks.rb' - - 'db/migrate/20161027172456_add_silenced_to_accounts.rb' - - 'db/migrate/20161104173623_create_tags.rb' - - 'db/migrate/20161105130633_create_statuses_tags_join_table.rb' - - 'db/migrate/20161116162355_add_locale_to_users.rb' - - 'db/migrate/20161119211120_create_notifications.rb' - - 'db/migrate/20161122163057_remove_unneeded_indexes.rb' - - 'db/migrate/20161123093447_add_sensitive_to_statuses.rb' - - 'db/migrate/20161128103007_create_subscriptions.rb' - - 'db/migrate/20161130142058_add_last_successful_delivery_at_to_subscriptions.rb' - - 'db/migrate/20161130185319_add_visibility_to_statuses.rb' - - 'db/migrate/20161202132159_add_in_reply_to_account_id_to_statuses.rb' - - 'db/migrate/20161203164520_add_from_account_id_to_notifications.rb' - - 'db/migrate/20161205214545_add_suspended_to_accounts.rb' - - 'db/migrate/20161221152630_add_hidden_to_stream_entries.rb' - - 'db/migrate/20161222201034_add_locked_to_accounts.rb' - - 'db/migrate/20161222204147_create_follow_requests.rb' - - 'db/migrate/20170105224407_add_shortcode_to_media_attachments.rb' - - 'db/migrate/20170109120109_create_web_settings.rb' - - 'db/migrate/20170112154826_migrate_settings.rb' - - 'db/migrate/20170114194937_add_application_to_statuses.rb' - - 'db/migrate/20170114203041_add_website_to_oauth_application.rb' - - 'db/migrate/20170119214911_create_preview_cards.rb' - - 'db/migrate/20170123162658_add_severity_to_domain_blocks.rb' - - 'db/migrate/20170123203248_add_reject_media_to_domain_blocks.rb' - - 'db/migrate/20170125145934_add_spoiler_text_to_statuses.rb' - - 'db/migrate/20170127165745_add_devise_two_factor_to_users.rb' - - 'db/migrate/20170205175257_remove_devices.rb' - - 'db/migrate/20170209184350_add_reply_to_statuses.rb' - - 'db/migrate/20170214110202_create_reports.rb' - - 'db/migrate/20170217012631_add_reblog_of_id_foreign_key_to_statuses.rb' - - 'db/migrate/20170301222600_create_mutes.rb' - - 'db/migrate/20170303212857_add_last_emailed_at_to_users.rb' - - 'db/migrate/20170304202101_add_type_to_media_attachments.rb' - - 'db/migrate/20170317193015_add_search_index_to_accounts.rb' - - 'db/migrate/20170318214217_add_header_remote_url_to_accounts.rb' - - 'db/migrate/20170322021028_add_lowercase_index_to_accounts.rb' - - 'db/migrate/20170322143850_change_primary_key_to_bigint_on_statuses.rb' - - 'db/migrate/20170322162804_add_search_index_to_tags.rb' - - 'db/migrate/20170330021336_add_counter_caches.rb' - - 'db/migrate/20170330163835_create_imports.rb' - - 'db/migrate/20170330164118_add_attachment_data_to_imports.rb' - - 'db/migrate/20170403172249_add_action_taken_by_account_id_to_reports.rb' - - 'db/migrate/20170405112956_add_index_on_mentions_status_id.rb' - - 'db/migrate/20170406215816_add_notifications_and_favourites_indices.rb' - - 'db/migrate/20170409170753_add_last_webfingered_at_to_accounts.rb' - - 'db/migrate/20170414080609_add_devise_two_factor_backupable_to_users.rb' - - 'db/migrate/20170414132105_add_language_to_statuses.rb' - - 'db/migrate/20170418160728_add_indexes_to_reports_for_accounts.rb' - - 'db/migrate/20170423005413_add_allowed_languages_to_user.rb' - - 'db/migrate/20170424003227_create_account_domain_blocks.rb' - - 'db/migrate/20170424112722_add_status_id_index_to_statuses_tags.rb' - - 'db/migrate/20170425131920_add_media_attachment_meta.rb' - - 'db/migrate/20170425202925_add_oembed_to_preview_cards.rb' - - 'db/migrate/20170427011934_re_add_owner_to_application.rb' - - 'db/migrate/20170506235850_create_conversations.rb' - - 'db/migrate/20170507000211_add_conversation_id_to_statuses.rb' - - 'db/migrate/20170507141759_optimize_index_subscriptions.rb' - - 'db/migrate/20170508230434_create_conversation_mutes.rb' - - 'db/migrate/20170516072309_add_index_accounts_on_uri.rb' - - 'db/migrate/20170520145338_change_language_filter_to_opt_out.rb' - - 'db/migrate/20170601210557_add_index_on_media_attachments_account_id.rb' - - 'db/migrate/20170604144747_add_foreign_keys_for_accounts.rb' - - 'db/migrate/20170606113804_change_tag_search_index_to_btree.rb' - - 'db/migrate/20170609145826_remove_default_language_from_statuses.rb' - - 'db/migrate/20170610000000_add_statuses_index_on_account_id_id.rb' - - 'db/migrate/20170623152212_create_session_activations.rb' - - 'db/migrate/20170624134742_add_description_to_session_activations.rb' - - 'db/migrate/20170625140443_add_access_token_id_to_session_activations.rb' - - 'db/migrate/20170711225116_fix_null_booleans.rb' - - 'db/migrate/20170713112503_make_tag_search_case_insensitive.rb' - - 'db/migrate/20170713175513_create_web_push_subscriptions.rb' - - 'db/migrate/20170713190709_add_web_push_subscription_to_session_activations.rb' - - 'db/migrate/20170714184731_add_domain_to_subscriptions.rb' - - 'db/migrate/20170716191202_add_hide_notifications_to_mute.rb' - - 'db/migrate/20170718211102_add_activitypub_to_accounts.rb' - - 'db/migrate/20170720000000_add_index_favourites_on_account_id_and_id.rb' - - 'db/migrate/20170823162448_create_status_pins.rb' - - 'db/migrate/20170824103029_add_timestamps_to_status_pins.rb' - - 'db/migrate/20170829215220_remove_status_pins_account_index.rb' - - 'db/migrate/20170901141119_truncate_preview_cards.rb' - - 'db/migrate/20170901142658_create_join_table_preview_cards_statuses.rb' - - 'db/migrate/20170905044538_add_index_id_account_id_activity_type_on_notifications.rb' - - 'db/migrate/20170905165803_add_local_to_statuses.rb' - - 'db/migrate/20170913000752_create_site_uploads.rb' - - 'db/migrate/20170917153509_create_custom_emojis.rb' - - 'db/migrate/20170918125918_ids_to_bigints.rb' - - 'db/migrate/20170920024819_status_ids_to_timestamp_ids.rb' - - 'db/migrate/20170920032311_fix_reblogs_in_feeds.rb' - - 'db/migrate/20170924022025_ids_to_bigints2.rb' - - 'db/migrate/20170927215609_add_description_to_media_attachments.rb' - - 'db/migrate/20170928082043_create_email_domain_blocks.rb' - - 'db/migrate/20171005102658_create_account_moderation_notes.rb' - - 'db/migrate/20171005171936_add_disabled_to_custom_emojis.rb' - - 'db/migrate/20171006142024_add_uri_to_custom_emojis.rb' - - 'db/migrate/20171010023049_add_foreign_key_to_account_moderation_notes.rb' - - 'db/migrate/20171010025614_change_accounts_nonnullable_in_account_moderation_notes.rb' - - 'db/migrate/20171020084748_add_visible_in_picker_to_custom_emoji.rb' - - 'db/migrate/20171028221157_add_reblogs_to_follows.rb' - - 'db/migrate/20171107143332_add_memorial_to_accounts.rb' - - 'db/migrate/20171107143624_add_disabled_to_users.rb' - - 'db/migrate/20171109012327_add_moderator_to_accounts.rb' - - 'db/migrate/20171114080328_add_index_domain_to_email_domain_blocks.rb' - - 'db/migrate/20171114231651_create_lists.rb' - - 'db/migrate/20171116161857_create_list_accounts.rb' - - 'db/migrate/20171118012443_add_moved_to_account_id_to_accounts.rb' - - 'db/migrate/20171119172437_create_admin_action_logs.rb' - - 'db/migrate/20171122120436_add_index_account_and_reblog_of_id_to_statuses.rb' - - 'db/migrate/20171125024930_create_invites.rb' - - 'db/migrate/20171125031751_add_invite_id_to_users.rb' - - 'db/migrate/20171125185353_add_index_reblog_of_id_and_account_to_statuses.rb' - - 'db/migrate/20171125190735_remove_old_reblog_index_on_statuses.rb' - - 'db/migrate/20171129172043_add_index_on_stream_entries.rb' - - 'db/migrate/20171130000000_add_embed_url_to_preview_cards.rb' - - 'db/migrate/20171201000000_change_account_id_nonnullable_in_lists.rb' - - 'db/migrate/20171212195226_remove_duplicate_indexes_in_lists.rb' - - 'db/migrate/20171226094803_more_faster_index_on_notifications.rb' - - 'db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb' - - 'db/migrate/20180109143959_add_remember_token_to_users.rb' - - 'db/migrate/20180204034416_create_identities.rb' - - 'db/migrate/20180206000000_change_user_id_nonnullable.rb' - - 'db/migrate/20180211015820_create_backups.rb' - - 'db/migrate/20180304013859_add_featured_collection_url_to_accounts.rb' - - 'db/migrate/20180310000000_change_columns_in_notifications_nonnullable.rb' - - 'db/migrate/20180402031200_add_assigned_account_id_to_reports.rb' - - 'db/migrate/20180402040909_create_report_notes.rb' - - 'db/migrate/20180410204633_add_fields_to_accounts.rb' - - 'db/migrate/20180416210259_add_uri_to_relationships.rb' - - 'db/migrate/20180506221944_add_actor_type_to_accounts.rb' - - 'db/migrate/20180510214435_add_access_token_id_to_web_push_subscriptions.rb' - - 'db/migrate/20180510230049_migrate_web_push_subscriptions.rb' - - 'db/migrate/20180528141303_fix_accounts_unique_index.rb' - - 'db/migrate/20180608213548_reject_following_blocked_users.rb' - - 'db/migrate/20180609104432_migrate_web_push_subscriptions2.rb' - - 'db/migrate/20180615122121_add_autofollow_to_invites.rb' - - 'db/migrate/20180616192031_add_chosen_languages_to_users.rb' - - 'db/migrate/20180617162849_remove_unused_indexes.rb' - - 'db/migrate/20180628181026_create_custom_filters.rb' - - 'db/migrate/20180707154237_add_whole_word_to_custom_filter.rb' - - 'db/migrate/20180711152640_create_relays.rb' - - 'db/migrate/20180808175627_create_account_pins.rb' - - 'db/migrate/20180812123222_change_relays_enabled.rb' - - 'db/migrate/20180812162710_create_status_stats.rb' - - 'db/migrate/20180812173710_copy_status_stats.rb' - - 'db/migrate/20180814171349_add_confidential_to_doorkeeper_application.rb' - - 'db/migrate/20180831171112_create_bookmarks.rb' - - 'db/migrate/20180929222014_create_account_conversations.rb' - - 'db/migrate/20181007025445_create_pghero_space_stats.rb' - - 'db/migrate/20181010141500_add_silent_to_mentions.rb' - - 'db/migrate/20181017170937_add_reject_reports_to_domain_blocks.rb' - - 'db/migrate/20181018205649_add_unread_to_account_conversations.rb' - - 'db/migrate/20181024224956_migrate_account_conversations.rb' - - 'db/migrate/20181026034033_remove_faux_remote_account_duplicates.rb' - - 'db/migrate/20181116165755_create_account_stats.rb' - - 'db/migrate/20181116173541_copy_account_stats.rb' - - 'db/migrate/20181127130500_identity_id_to_bigint.rb' - - 'db/migrate/20181127165847_add_show_replies_to_lists.rb' - - 'db/migrate/20181203003808_create_accounts_tags_join_table.rb' - - 'db/migrate/20181203021853_add_discoverable_to_accounts.rb' - - 'db/migrate/20181204193439_add_last_status_at_to_account_stats.rb' - - 'db/migrate/20181204215309_create_account_tag_stats.rb' - - 'db/migrate/20181207011115_downcase_custom_emoji_domains.rb' - - 'db/migrate/20181213184704_create_account_warnings.rb' - - 'db/migrate/20181213185533_create_account_warning_presets.rb' - - 'db/migrate/20181219235220_add_created_by_application_id_to_users.rb' - - 'db/migrate/20181226021420_add_also_known_as_to_accounts.rb' - - 'db/migrate/20190103124649_create_scheduled_statuses.rb' - - 'db/migrate/20190103124754_add_scheduled_status_id_to_media_attachments.rb' - - 'db/migrate/20190117114553_create_tombstones.rb' - - 'db/migrate/20190201012802_add_overwrite_to_imports.rb' - - 'db/migrate/20190203180359_create_featured_tags.rb' - - 'db/migrate/20190225031541_create_polls.rb' - - 'db/migrate/20190225031625_create_poll_votes.rb' - - 'db/migrate/20190226003449_add_poll_id_to_statuses.rb' - - 'db/migrate/20190304152020_add_uri_to_poll_votes.rb' - - 'db/migrate/20190306145741_add_lock_version_to_polls.rb' - - 'db/migrate/20190307234537_add_approved_to_users.rb' - - 'db/migrate/20190314181829_migrate_open_registrations_setting.rb' - - 'db/migrate/20190316190352_create_account_identity_proofs.rb' - - 'db/migrate/20190317135723_add_uri_to_reports.rb' - - 'db/migrate/20190403141604_add_comment_to_invites.rb' - - 'db/migrate/20190409054914_create_user_invite_requests.rb' - - 'db/migrate/20190420025523_add_blurhash_to_media_attachments.rb' - - 'db/migrate/20190509164208_add_by_moderator_to_tombstone.rb' - - 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb' - - 'db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb' - - 'db/migrate/20190627222225_create_custom_emoji_categories.rb' - - 'db/migrate/20190627222826_add_category_id_to_custom_emojis.rb' - - 'db/migrate/20190701022101_add_trust_level_to_accounts.rb' - - 'db/migrate/20190705002136_create_domain_allows.rb' - - 'db/migrate/20190715164535_add_instance_actor.rb' - - 'db/migrate/20190726175042_add_case_insensitive_index_to_tags.rb' - - 'db/migrate/20190729185330_add_score_to_tags.rb' - - 'db/migrate/20190805123746_add_capabilities_to_tags.rb' - - 'db/migrate/20190807135426_add_comments_to_domain_blocks.rb' - - 'db/migrate/20190815225426_add_last_status_at_to_tags.rb' - - 'db/migrate/20190819134503_add_deleted_at_to_statuses.rb' - - 'db/migrate/20190820003045_update_statuses_index.rb' - - 'db/migrate/20190823221802_add_local_index_to_statuses.rb' - - 'db/migrate/20190901035623_add_max_score_to_tags.rb' - - 'db/migrate/20190904222339_create_markers.rb' - - 'db/migrate/20190914202517_create_account_migrations.rb' - - 'db/migrate/20190915194355_create_account_aliases.rb' - - 'db/migrate/20190927232842_add_voters_count_to_polls.rb' - - 'db/migrate/20191001213028_add_lock_version_to_account_stats.rb' - - 'db/migrate/20191007013357_update_pt_locales.rb' - - 'db/migrate/20191031163205_change_list_account_follow_nullable.rb' - - 'db/migrate/20191212003415_increase_backup_size.rb' - - 'db/migrate/20191212163405_add_hide_collections_to_accounts.rb' - - 'db/migrate/20191218153258_create_announcements.rb' - - 'db/migrate/20200113125135_create_announcement_mutes.rb' - - 'db/migrate/20200114113335_create_announcement_reactions.rb' - - 'db/migrate/20200119112504_add_public_index_to_statuses.rb' - - 'db/migrate/20200126203551_add_published_at_to_announcements.rb' - - 'db/migrate/20200306035625_add_processing_to_media_attachments.rb' - - 'db/migrate/20200309150742_add_forwarded_to_reports.rb' - - 'db/migrate/20200312144258_add_title_to_account_warning_presets.rb' - - 'db/migrate/20200312162302_add_status_ids_to_announcements.rb' - - 'db/migrate/20200312185443_add_parent_id_to_email_domain_blocks.rb' - - 'db/migrate/20200317021758_add_expires_at_to_mutes.rb' - - 'db/migrate/20200407201300_create_unavailable_domains.rb' - - 'db/migrate/20200407202420_migrate_unavailable_inboxes.rb' - - 'db/migrate/20200417125749_add_storage_schema_version.rb' - - 'db/migrate/20200508212852_reset_unique_jobs_locks.rb' - - 'db/migrate/20200510110808_reset_web_app_secret.rb' - - 'db/migrate/20200510181721_remove_duplicated_indexes_pghero.rb' - - 'db/migrate/20200516180352_create_devices.rb' - - 'db/migrate/20200516183822_create_one_time_keys.rb' - - 'db/migrate/20200518083523_create_encrypted_messages.rb' - - 'db/migrate/20200521180606_encrypted_message_ids_to_timestamp_ids.rb' - - 'db/migrate/20200529214050_add_devices_url_to_accounts.rb' - - 'db/migrate/20200601222558_create_system_keys.rb' - - 'db/migrate/20200605155027_add_blurhash_to_preview_cards.rb' - - 'db/migrate/20200608113046_add_sign_in_token_to_users.rb' - - 'db/migrate/20200614002136_add_sensitized_to_accounts.rb' - - 'db/migrate/20200620164023_add_fixed_lowercase_index_to_accounts.rb' - - 'db/migrate/20200622213645_media_attachment_ids_to_timestamp_ids.rb' - - 'db/migrate/20200627125810_add_thumbnail_columns_to_media_attachments.rb' - - 'db/migrate/20200628133322_create_account_notes.rb' - - 'db/migrate/20200630190240_create_webauthn_credentials.rb' - - 'db/migrate/20200630190544_add_webauthn_id_to_users.rb' - - 'db/migrate/20200908193330_create_account_deletion_requests.rb' - - 'db/migrate/20200917192924_add_notify_to_follows.rb' - - 'db/migrate/20200917193034_add_type_to_notifications.rb' - - 'db/migrate/20200917222316_add_index_notifications_on_type.rb' - - 'db/migrate/20201008202037_create_ip_blocks.rb' - - 'db/migrate/20201008220312_add_sign_up_ip_to_users.rb' - - 'db/migrate/20201017233919_add_suspension_origin_to_accounts.rb' - - 'db/migrate/20201206004238_create_instances.rb' - - 'db/migrate/20201218054746_add_obfuscate_to_domain_blocks.rb' - - 'db/migrate/20210221045109_create_rules.rb' - - 'db/migrate/20210306164523_account_ids_to_timestamp_ids.rb' - - 'db/migrate/20210322164601_create_account_summaries.rb' - - 'db/migrate/20210323114347_create_follow_recommendations.rb' - - 'db/migrate/20210324171613_create_follow_recommendation_suppressions.rb' - - 'db/migrate/20210416200740_create_canonical_email_blocks.rb' - - 'db/migrate/20210421121431_add_case_insensitive_btree_index_to_tags.rb' - - 'db/migrate/20210425135952_add_index_on_media_attachments_account_id_status_id.rb' - - 'db/migrate/20210505174616_update_follow_recommendations_to_version_2.rb' - - 'db/migrate/20210609202149_create_login_activities.rb' - - 'db/migrate/20210616214526_create_user_ips.rb' - - 'db/migrate/20210621221010_add_skip_sign_in_token_to_users.rb' - - 'db/migrate/20210630000137_fix_canonical_email_blocks_foreign_key.rb' - - 'db/migrate/20210722120340_create_account_statuses_cleanup_policies.rb' - - 'db/migrate/20210904215403_add_edited_at_to_statuses.rb' - - 'db/migrate/20210908220918_create_status_edits.rb' - - 'db/migrate/20211031031021_create_preview_card_providers.rb' - - 'db/migrate/20211112011713_add_language_to_preview_cards.rb' - - 'db/migrate/20211115032527_add_trendable_to_preview_cards.rb' - - 'db/migrate/20211123212714_add_link_type_to_preview_cards.rb' - - 'db/migrate/20211213040746_update_account_summaries_to_version_2.rb' - - 'db/migrate/20211231080958_add_category_to_reports.rb' - - 'db/migrate/20220105163928_remove_mentions_status_id_index.rb' - - 'db/migrate/20220115125126_add_report_id_to_account_warnings.rb' - - 'db/migrate/20220115125341_fix_account_warning_actions.rb' - - 'db/migrate/20220116202951_add_deleted_at_index_on_statuses.rb' - - 'db/migrate/20220124141035_create_appeals.rb' - - 'db/migrate/20220202200743_add_trendable_to_accounts.rb' - - 'db/migrate/20220202200926_add_trendable_to_statuses.rb' - - 'db/migrate/20220210153119_add_overruled_at_to_account_warnings.rb' - - 'db/migrate/20220224010024_add_ips_to_email_domain_blocks.rb' - - 'db/migrate/20220227041951_add_last_used_at_to_oauth_access_tokens.rb' - - 'db/migrate/20220302232632_add_ordered_media_attachment_ids_to_statuses.rb' - - 'db/migrate/20220303000827_add_ordered_media_attachment_ids_to_status_edits.rb' - - 'db/migrate/20220304195405_migrate_hide_network_preference.rb' - - 'db/migrate/20220307094650_fix_featured_tags_constraints.rb' - - 'db/migrate/20220309213005_fix_reblog_deleted_at.rb' - - 'db/migrate/20220316233212_update_kurdish_locales.rb' - - 'db/migrate/20220428112511_add_index_statuses_on_account_id.rb' - - 'db/migrate/20220428112727_add_index_statuses_pins_on_status_id.rb' - - 'db/migrate/20220428114454_add_index_reports_on_assigned_account_id.rb' - - 'db/migrate/20220428114902_add_index_reports_on_action_taken_by_account_id.rb' - - 'db/migrate/20220606044941_create_webhooks.rb' - - 'db/migrate/20220611210335_create_user_roles.rb' - - 'db/migrate/20220611212541_add_role_id_to_users.rb' - - 'db/migrate/20220710102457_add_display_name_to_tags.rb' - - 'db/migrate/20220714171049_create_tag_follows.rb' - - 'db/migrate/20220824164433_add_human_identifier_to_admin_action_logs.rb' - - 'db/migrate/20220824233535_create_status_trends.rb' - - 'db/migrate/20220827195229_change_canonical_email_blocks_nullable.rb' - - 'db/migrate/20220829192633_add_languages_to_follows.rb' - - 'db/migrate/20220829192658_add_languages_to_follow_requests.rb' - - 'db/migrate/20221006061337_create_preview_card_trends.rb' - - 'db/migrate/20221012181003_add_blurhash_to_site_uploads.rb' - - 'db/migrate/20221021055441_add_index_featured_tags_on_account_id_and_tag_id.rb' - - 'db/migrate/20221025171544_add_index_ip_blocks_on_ip.rb' - - 'db/migrate/20221104133904_add_name_to_featured_tags.rb' - - 'db/post_migrate/20190519130537_remove_boosts_widening_audience.rb' - - 'db/post_migrate/20210308133107_remove_subscription_expires_at_from_accounts.rb' - - 'db/post_migrate/20220118183123_remove_rememberable_from_users.rb' - - 'db/seeds/01_web_app.rb' - - 'db/seeds/02_instance_actor.rb' - - 'db/seeds/03_roles.rb' - - 'db/seeds/04_admin.rb' - - 'lib/rails/engine_extensions.rb' - - 'lib/tasks/branding.rake' - - 'spec/fabricators_spec.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). Style/GlobalStdStream: Exclude: @@ -1340,13 +870,6 @@ Style/SafeNavigation: - 'app/models/concerns/account_finder_concern.rb' - 'app/models/status.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowAsExpressionSeparator. -Style/Semicolon: - Exclude: - - 'spec/services/activitypub/process_status_update_service_spec.rb' - - 'spec/validators/blacklisted_email_validator_spec.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: only_raise, only_fail, semantic @@ -1360,21 +883,6 @@ Style/SingleArgumentDig: Exclude: - 'lib/webpacker/manifest_extensions.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/SlicingWithRange: - Exclude: - - 'app/lib/emoji_formatter.rb' - - 'app/lib/text_formatter.rb' - - 'app/models/account_alias.rb' - - 'app/models/domain_block.rb' - - 'app/models/email_domain_block.rb' - - 'app/models/preview_card_provider.rb' - - 'app/validators/status_length_validator.rb' - - 'db/migrate/20190726175042_add_case_insensitive_index_to_tags.rb' - - 'lib/active_record/batches.rb' - - 'lib/mastodon/premailer_webpack_strategy.rb' - - 'lib/tasks/repo.rake' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: require_parentheses, require_no_parentheses diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f1b7bcb3..5383d426b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -143,7 +143,7 @@ All notable changes to this project will be documented in this file. - Add instance activity API endpoint toggle back to the admin interface ([dariusk](https://github.com/mastodon/mastodon/pull/22833)) - Add setting for status page URL ([Gargron](https://github.com/mastodon/mastodon/pull/23390), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/23499)) - REST API changes: - - Add `configuration.urls.status` attribute to the object returned by `GET /api/v1/instance` + - Add `configuration.urls.status` attribute to the object returned by `GET /api/v2/instance` - Add `account.approved` webhook ([Saiv46](https://github.com/mastodon/mastodon/pull/22938)) - Add 12 hours option to polls ([Pleclown](https://github.com/mastodon/mastodon/pull/21131)) - Add dropdown menu item to open admin interface for remote domains ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21895)) diff --git a/Gemfile b/Gemfile index 7a0fbdc82d..f9d0f3c749 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,6 @@ gem 'rack', '~> 2.2.7' gem 'haml-rails', '~>2.0' gem 'pg', '~> 1.5' -gem 'makara', '~> 0.5' gem 'pghero' gem 'dotenv-rails', '~> 2.8' @@ -159,7 +158,7 @@ group :development do gem 'letter_opener_web', '~> 2.0' # Security analysis CLI tools - gem 'brakeman', '~> 5.4', require: false + gem 'brakeman', '~> 6.0', require: false gem 'bundler-audit', '~> 0.9', require: false # Linter CLI for HAML files diff --git a/Gemfile.lock b/Gemfile.lock index 985e36c20c..9286cd991b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -130,7 +130,7 @@ GEM blurhash (0.1.7) bootsnap (1.16.0) msgpack (~> 1.2) - brakeman (5.4.1) + brakeman (6.0.0) browser (5.3.1) brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) @@ -146,7 +146,7 @@ GEM sshkit (>= 1.9.0) capistrano-bundler (2.1.0) capistrano (~> 3.1) - capistrano-rails (1.6.2) + capistrano-rails (1.6.3) capistrano (~> 3.1) capistrano-bundler (>= 1.1, < 3) capistrano-rbenv (2.2.0) @@ -291,11 +291,11 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.45.0) + haml_lint (0.48.0) haml (>= 4.0, < 6.2) parallel (~> 1.10) rainbow - rubocop (>= 0.50.0) + rubocop (>= 1.0) sysexits (~> 1.1) hashdiff (1.0.1) hashie (5.0.0) @@ -399,8 +399,6 @@ GEM net-imap net-pop net-smtp - makara (0.5.1) - activerecord (>= 5.2.0) marcel (1.0.2) mario-redis-lock (1.2.1) redis (>= 3.0.5) @@ -670,7 +668,7 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - sshkit (1.21.4) + sshkit (1.21.5) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) stackprof (0.2.25) @@ -767,7 +765,7 @@ DEPENDENCIES binding_of_caller (~> 1.0) blurhash (~> 0.1) bootsnap (~> 1.16.0) - brakeman (~> 5.4) + brakeman (~> 6.0) browser bundler-audit (~> 0.9) capistrano (~> 3.17) @@ -815,7 +813,6 @@ DEPENDENCIES letter_opener_web (~> 2.0) link_header (~> 0.0) lograge (~> 0.12) - makara (~> 0.5) mario-redis-lock (~> 1.2) memory_profiler mime-types (~> 3.4.1) diff --git a/Rakefile b/Rakefile index ba6b733dd2..e51cf0e17e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. -require File.expand_path('../config/application', __FILE__) +require File.expand_path('config/application', __dir__) Rails.application.load_tasks diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb index 0cc2318409..498eb16f44 100644 --- a/app/controllers/api/v1/bookmarks_controller.rb +++ b/app/controllers/api/v1/bookmarks_controller.rb @@ -21,7 +21,7 @@ class Api::V1::BookmarksController < Api::BaseController end def results - @_results ||= account_bookmarks.joins(:status).eager_load(:status).to_a_paginated_by_id( + @results ||= account_bookmarks.joins(:status).eager_load(:status).to_a_paginated_by_id( limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id) ) diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb index bd7f3d775e..faf1bda96a 100644 --- a/app/controllers/api/v1/favourites_controller.rb +++ b/app/controllers/api/v1/favourites_controller.rb @@ -21,7 +21,7 @@ class Api::V1::FavouritesController < Api::BaseController end def results - @_results ||= account_favourites.joins(:status).eager_load(:status).to_a_paginated_by_id( + @results ||= account_favourites.joins(:status).eager_load(:status).to_a_paginated_by_id( limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id) ) diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 8ff6c8fe5c..300c9faa3f 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -23,6 +23,6 @@ class Api::V1::ReportsController < Api::BaseController end def report_params - params.permit(:account_id, :comment, :category, :forward, status_ids: [], rule_ids: []) + params.permit(:account_id, :comment, :category, :forward, forward_to_domains: [], status_ids: [], rule_ids: []) end end diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb index ae6dbcb8b3..0ee28ef042 100644 --- a/app/controllers/api/v1/timelines/home_controller.rb +++ b/app/controllers/api/v1/timelines/home_controller.rb @@ -6,11 +6,14 @@ class Api::V1::Timelines::HomeController < Api::BaseController after_action :insert_pagination_headers, unless: -> { @statuses.empty? } def show - @statuses = load_statuses + ApplicationRecord.connected_to(role: :read, prevent_writes: true) do + @statuses = load_statuses + @relationships = StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) + end render json: @statuses, each_serializer: REST::StatusSerializer, - relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id), + relationships: @relationships, status: account_home_feed.regenerating? ? 206 : 200 end diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index b1abb9f1df..dc88933671 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -129,7 +129,7 @@ class Auth::SessionsController < Devise::SessionsController redirect_to new_user_session_path, alert: I18n.t('devise.failure.timeout') end - def set_attempt_session(user) + def register_attempt_in_session(user) session[:attempt_user_id] = user.id session[:attempt_user_updated_at] = user.updated_at.to_s end diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb index 30702f00e7..5b83d8575b 100644 --- a/app/controllers/concerns/rate_limit_headers.rb +++ b/app/controllers/concerns/rate_limit_headers.rb @@ -61,7 +61,7 @@ module RateLimitHeaders end def request_time - @_request_time ||= Time.now.utc + @request_time ||= Time.now.utc end def reset_period_offset diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/two_factor_authentication_concern.rb index b30cd354d2..ed0175581c 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/two_factor_authentication_concern.rb @@ -75,7 +75,7 @@ module TwoFactorAuthenticationConcern end def prompt_for_two_factor(user) - set_attempt_session(user) + register_attempt_in_session(user) use_pack 'auth' diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb index b8277ee17e..e16458d7da 100644 --- a/app/helpers/accounts_helper.rb +++ b/app/helpers/accounts_helper.rb @@ -22,7 +22,7 @@ module AccountsHelper def account_action_button(account) return if account.memorial? || account.moved? - link_to ActivityPub::TagManager.instance.url_for(account), class: 'button logo-button', target: '_new' do + link_to ActivityPub::TagManager.instance.url_for(account), class: 'button', target: '_new' do safe_join([logo_as_symbol, t('accounts.follow')]) end end diff --git a/app/javascript/flavours/glitch/components/animated_number.tsx b/app/javascript/flavours/glitch/components/animated_number.tsx index 81e0af395b..edf232bf14 100644 --- a/app/javascript/flavours/glitch/components/animated_number.tsx +++ b/app/javascript/flavours/glitch/components/animated_number.tsx @@ -5,7 +5,7 @@ import { TransitionMotion, spring } from 'react-motion'; import { reduceMotion } from '../initial_state'; -import ShortNumber from './short_number'; +import { ShortNumber } from './short_number'; const obfuscatedCount = (count: number) => { if (count < 0) { diff --git a/app/javascript/flavours/glitch/components/autosuggest_hashtag.tsx b/app/javascript/flavours/glitch/components/autosuggest_hashtag.tsx index 932370884a..71955e6b03 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_hashtag.tsx +++ b/app/javascript/flavours/glitch/components/autosuggest_hashtag.tsx @@ -1,6 +1,6 @@ import { FormattedMessage } from 'react-intl'; -import ShortNumber from 'flavours/glitch/components/short_number'; +import { ShortNumber } from 'flavours/glitch/components/short_number'; interface Props { tag: { diff --git a/app/javascript/flavours/glitch/components/common_counter.jsx b/app/javascript/flavours/glitch/components/common_counter.jsx deleted file mode 100644 index 785907bd25..0000000000 --- a/app/javascript/flavours/glitch/components/common_counter.jsx +++ /dev/null @@ -1,59 +0,0 @@ -// @ts-check -import { FormattedMessage } from 'react-intl'; -/** - * Returns custom renderer for one of the common counter types - * @param {"statuses" | "following" | "followers"} counterType - * Type of the counter - * @param {boolean} isBold Whether display number must be displayed in bold - * @returns {(displayNumber: JSX.Element, pluralReady: number) => JSX.Element} - * Renderer function - * @throws If counterType is not covered by this function - */ -export function counterRenderer(counterType, isBold = true) { - /** - * @type {(displayNumber: JSX.Element) => JSX.Element} - */ - const renderCounter = isBold - ? (displayNumber) => {displayNumber} - : (displayNumber) => displayNumber; - - switch (counterType) { - case 'statuses': { - return (displayNumber, pluralReady) => ( - - ); - } - case 'following': { - return (displayNumber, pluralReady) => ( - - ); - } - case 'followers': { - return (displayNumber, pluralReady) => ( - - ); - } - default: throw Error(`Incorrect counter name: ${counterType}. Ensure it accepted by commonCounter function`); - } -} diff --git a/app/javascript/flavours/glitch/components/counters.tsx b/app/javascript/flavours/glitch/components/counters.tsx new file mode 100644 index 0000000000..e0c818f247 --- /dev/null +++ b/app/javascript/flavours/glitch/components/counters.tsx @@ -0,0 +1,45 @@ +import React from 'react'; + +import { FormattedMessage } from 'react-intl'; + +export const StatusesCounter = ( + displayNumber: React.ReactNode, + pluralReady: number +) => ( + {displayNumber}, + }} + /> +); + +export const FollowingCounter = ( + displayNumber: React.ReactNode, + pluralReady: number +) => ( + {displayNumber}, + }} + /> +); + +export const FollowersCounter = ( + displayNumber: React.ReactNode, + pluralReady: number +) => ( + {displayNumber}, + }} + /> +); diff --git a/app/javascript/flavours/glitch/components/dismissable_banner.jsx b/app/javascript/flavours/glitch/components/dismissable_banner.jsx deleted file mode 100644 index 21063c9ed6..0000000000 --- a/app/javascript/flavours/glitch/components/dismissable_banner.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import PropTypes from 'prop-types'; -import { PureComponent } from 'react'; - -import { injectIntl, defineMessages } from 'react-intl'; - -import { bannerSettings } from 'flavours/glitch/settings'; - -import { IconButton } from './icon_button'; - -const messages = defineMessages({ - dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' }, -}); - -class DismissableBanner extends PureComponent { - - static propTypes = { - id: PropTypes.string.isRequired, - children: PropTypes.node, - intl: PropTypes.object.isRequired, - }; - - state = { - visible: !bannerSettings.get(this.props.id), - }; - - handleDismiss = () => { - const { id } = this.props; - this.setState({ visible: false }, () => bannerSettings.set(id, true)); - }; - - render () { - const { visible } = this.state; - - if (!visible) { - return null; - } - - const { children, intl } = this.props; - - return ( -
-
- {children} -
- -
- -
-
- ); - } - -} - -export default injectIntl(DismissableBanner); diff --git a/app/javascript/flavours/glitch/components/dismissable_banner.tsx b/app/javascript/flavours/glitch/components/dismissable_banner.tsx new file mode 100644 index 0000000000..0fb002832e --- /dev/null +++ b/app/javascript/flavours/glitch/components/dismissable_banner.tsx @@ -0,0 +1,47 @@ +import type { PropsWithChildren } from 'react'; +import { useCallback, useState } from 'react'; + +import { defineMessages, useIntl } from 'react-intl'; + +import { bannerSettings } from 'flavours/glitch/settings'; + +import { IconButton } from './icon_button'; + +const messages = defineMessages({ + dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' }, +}); + +interface Props { + id: string; +} + +export const DismissableBanner: React.FC> = ({ + id, + children, +}) => { + const [visible, setVisible] = useState(!bannerSettings.get(id)); + const intl = useIntl(); + + const handleDismiss = useCallback(() => { + setVisible(false); + bannerSettings.set(id, true); + }, [id]); + + if (!visible) { + return null; + } + + return ( +
+
{children}
+ +
+ +
+
+ ); +}; diff --git a/app/javascript/flavours/glitch/components/hashtag.jsx b/app/javascript/flavours/glitch/components/hashtag.jsx index 422ead01db..9821cf1858 100644 --- a/app/javascript/flavours/glitch/components/hashtag.jsx +++ b/app/javascript/flavours/glitch/components/hashtag.jsx @@ -10,7 +10,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { Sparklines, SparklinesCurve } from 'react-sparklines'; -import ShortNumber from 'flavours/glitch/components/short_number'; +import { ShortNumber } from 'flavours/glitch/components/short_number'; import { Skeleton } from 'flavours/glitch/components/skeleton'; import Permalink from './permalink'; diff --git a/app/javascript/flavours/glitch/components/media_gallery.jsx b/app/javascript/flavours/glitch/components/media_gallery.jsx index 4d8f785320..21fdc47416 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.jsx +++ b/app/javascript/flavours/glitch/components/media_gallery.jsx @@ -354,7 +354,10 @@ class MediaGallery extends PureComponent { if (uncached) { spoilerButton = ( ); } else if (visible) { @@ -362,7 +365,10 @@ class MediaGallery extends PureComponent { } else { spoilerButton = ( ); } diff --git a/app/javascript/flavours/glitch/components/server_banner.jsx b/app/javascript/flavours/glitch/components/server_banner.jsx index 4809df1ddc..677e13706b 100644 --- a/app/javascript/flavours/glitch/components/server_banner.jsx +++ b/app/javascript/flavours/glitch/components/server_banner.jsx @@ -9,7 +9,7 @@ import { connect } from 'react-redux'; import { fetchServer } from 'flavours/glitch/actions/server'; import { ServerHeroImage } from 'flavours/glitch/components/server_hero_image'; -import ShortNumber from 'flavours/glitch/components/short_number'; +import { ShortNumber } from 'flavours/glitch/components/short_number'; import { Skeleton } from 'flavours/glitch/components/skeleton'; import Account from 'flavours/glitch/containers/account_container'; import { domain } from 'flavours/glitch/initial_state'; diff --git a/app/javascript/flavours/glitch/components/short_number.jsx b/app/javascript/flavours/glitch/components/short_number.jsx deleted file mode 100644 index 0ddd26e783..0000000000 --- a/app/javascript/flavours/glitch/components/short_number.jsx +++ /dev/null @@ -1,114 +0,0 @@ -import PropTypes from 'prop-types'; -import { memo } from 'react'; - -import { FormattedMessage, FormattedNumber } from 'react-intl'; - -import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers'; -// @ts-check - -/** - * @callback ShortNumberRenderer - * @param {JSX.Element} displayNumber Number to display - * @param {number} pluralReady Number used for pluralization - * @returns {JSX.Element} Final render of number - */ - -/** - * @typedef {object} ShortNumberProps - * @property {number} value Number to display in short variant - * @property {ShortNumberRenderer} [renderer] - * Custom renderer for numbers, provided as a prop. If another renderer - * passed as a child of this component, this prop won't be used. - * @property {ShortNumberRenderer} [children] - * Custom renderer for numbers, provided as a child. If another renderer - * passed as a prop of this component, this one will be used instead. - */ - -/** - * Component that renders short big number to a shorter version - * @param {ShortNumberProps} param0 Props for the component - * @returns {JSX.Element} Rendered number - */ -function ShortNumber({ value, renderer, children }) { - const shortNumber = toShortNumber(value); - const [, division] = shortNumber; - - if (children != null && renderer != null) { - console.warn('Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.'); - } - - const customRenderer = children != null ? children : renderer; - - const displayNumber = ; - - return customRenderer != null - ? customRenderer(displayNumber, pluralReady(value, division)) - : displayNumber; -} - -ShortNumber.propTypes = { - value: PropTypes.number.isRequired, - renderer: PropTypes.func, - children: PropTypes.func, -}; - -/** - * @typedef {object} ShortNumberCounterProps - * @property {import('../utils/number').ShortNumber} value Short number - */ - -/** - * Renders short number into corresponding localizable react fragment - * @param {ShortNumberCounterProps} param0 Props for the component - * @returns {JSX.Element} FormattedMessage ready to be embedded in code - */ -function ShortNumberCounter({ value }) { - const [rawNumber, unit, maxFractionDigits = 0] = value; - - const count = ( - - ); - - let values = { count, rawNumber }; - - switch (unit) { - case DECIMAL_UNITS.THOUSAND: { - return ( - - ); - } - case DECIMAL_UNITS.MILLION: { - return ( - - ); - } - case DECIMAL_UNITS.BILLION: { - return ( - - ); - } - // Not sure if we should go farther - @Sasha-Sorokin - default: return count; - } -} - -ShortNumberCounter.propTypes = { - value: PropTypes.arrayOf(PropTypes.number), -}; - -export default memo(ShortNumber); diff --git a/app/javascript/flavours/glitch/components/short_number.tsx b/app/javascript/flavours/glitch/components/short_number.tsx new file mode 100644 index 0000000000..010586c04f --- /dev/null +++ b/app/javascript/flavours/glitch/components/short_number.tsx @@ -0,0 +1,90 @@ +import { memo } from 'react'; + +import { FormattedMessage, FormattedNumber } from 'react-intl'; + +import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers'; + +type ShortNumberRenderer = ( + displayNumber: JSX.Element, + pluralReady: number +) => JSX.Element; + +interface ShortNumberProps { + value: number; + renderer?: ShortNumberRenderer; + children?: ShortNumberRenderer; +} + +export const ShortNumberRenderer: React.FC = ({ + value, + renderer, + children, +}) => { + const shortNumber = toShortNumber(value); + const [, division] = shortNumber; + + if (children && renderer) { + console.warn( + 'Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.' + ); + } + + const customRenderer = children || renderer || null; + + const displayNumber = ; + + return ( + customRenderer?.(displayNumber, pluralReady(value, division)) || + displayNumber + ); +}; +export const ShortNumber = memo(ShortNumberRenderer); + +interface ShortNumberCounterProps { + value: number[]; +} +const ShortNumberCounter: React.FC = ({ value }) => { + const [rawNumber, unit, maxFractionDigits = 0] = value; + + const count = ( + + ); + + const values = { count, rawNumber }; + + switch (unit) { + case DECIMAL_UNITS.THOUSAND: { + return ( + + ); + } + case DECIMAL_UNITS.MILLION: { + return ( + + ); + } + case DECIMAL_UNITS.BILLION: { + return ( + + ); + } + // Not sure if we should go farther - @Sasha-Sorokin + default: + return count; + } +}; diff --git a/app/javascript/flavours/glitch/components/status_content.jsx b/app/javascript/flavours/glitch/components/status_content.jsx index 955bf661ca..4719d7dcc7 100644 --- a/app/javascript/flavours/glitch/components/status_content.jsx +++ b/app/javascript/flavours/glitch/components/status_content.jsx @@ -97,7 +97,7 @@ class TranslateButton extends PureComponent { } return ( - ); diff --git a/app/javascript/flavours/glitch/features/account/components/header.jsx b/app/javascript/flavours/glitch/features/account/components/header.jsx index 0c440dc8a3..05a4e3844d 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.jsx +++ b/app/javascript/flavours/glitch/features/account/components/header.jsx @@ -196,14 +196,14 @@ class Header extends ImmutablePureComponent { if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded actionBtn = ''; } else if (account.getIn(['relationship', 'requested'])) { - actionBtn =