diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml index 0d0215bc06b5ed..f2d2d02fc0d875 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -113,6 +113,7 @@ jobs: CAS_ENABLED: true BUNDLE_WITH: 'pam_authentication test' CI_JOBS: ${{ matrix.ci_job }}/4 + GITHUB_RSPEC: ${{ matrix.ruby-version == '.ruby-version' && github.event.pull_request && 'true' }} strategy: fail-fast: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 296976ff72032d..452711e3d446fb 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -48,27 +48,6 @@ Lint/UnusedBlockArgument: - 'config/initializers/paperclip.rb' - 'config/initializers/simple_form.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -Lint/UselessAssignment: - Exclude: - - 'app/services/activitypub/process_status_update_service.rb' - - 'config/initializers/3_omniauth.rb' - - 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb' - - 'db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb' - - 'spec/controllers/api/v1/favourites_controller_spec.rb' - - 'spec/controllers/concerns/account_controller_concern_spec.rb' - - 'spec/helpers/jsonld_helper_spec.rb' - - 'spec/models/account_spec.rb' - - 'spec/models/domain_block_spec.rb' - - 'spec/models/status_spec.rb' - - 'spec/models/user_spec.rb' - - 'spec/models/webauthn_credentials_spec.rb' - - 'spec/services/account_search_service_spec.rb' - - 'spec/services/post_status_service_spec.rb' - - 'spec/services/precompute_feed_service_spec.rb' - - 'spec/services/resolve_url_service_spec.rb' - - 'spec/views/statuses/show.html.haml_spec.rb' - # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: Max: 144 @@ -88,26 +67,6 @@ Metrics/CyclomaticComplexity: Metrics/PerceivedComplexity: Max: 27 -# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns. -# SupportedStyles: snake_case, normalcase, non_integer -# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64 -Naming/VariableNumber: - Exclude: - - 'db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb' - - 'db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb' - - 'db/migrate/20190820003045_update_statuses_index.rb' - - 'db/migrate/20190823221802_add_local_index_to_statuses.rb' - - 'db/migrate/20200119112504_add_public_index_to_statuses.rb' - - 'spec/models/account_spec.rb' - - 'spec/models/domain_block_spec.rb' - - 'spec/models/user_spec.rb' - -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: SafeMultiline. -Performance/DeletePrefix: - Exclude: - - 'app/models/featured_tag.rb' - Performance/MapMethodChain: Exclude: - 'app/models/feed.rb' diff --git a/app/controllers/api/v1/apps/credentials_controller.rb b/app/controllers/api/v1/apps/credentials_controller.rb index 0475b2d4a208d4..6256bed64cf831 100644 --- a/app/controllers/api/v1/apps/credentials_controller.rb +++ b/app/controllers/api/v1/apps/credentials_controller.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true class Api::V1::Apps::CredentialsController < Api::BaseController - before_action -> { doorkeeper_authorize! :read } - def show - render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key) + return doorkeeper_render_error unless valid_doorkeeper_token? + + render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key client_id scopes) end end diff --git a/app/helpers/admin/disputes_helper.rb b/app/helpers/admin/disputes_helper.rb new file mode 100644 index 00000000000000..366a470ed2a451 --- /dev/null +++ b/app/helpers/admin/disputes_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Admin + module DisputesHelper + def strike_action_label(appeal) + t(key_for_action(appeal), + scope: 'admin.strikes.actions', + name: content_tag(:span, appeal.strike.account.username, class: 'username'), + target: content_tag(:span, appeal.account.username, class: 'target')) + .html_safe + end + + private + + def key_for_action(appeal) + AccountWarning.actions.slice(appeal.strike.action).keys.first + end + end +end diff --git a/app/javascript/flavours/glitch/features/home_timeline/index.jsx b/app/javascript/flavours/glitch/features/home_timeline/index.jsx index ac378291e52b7b..d3547ed3be578f 100644 --- a/app/javascript/flavours/glitch/features/home_timeline/index.jsx +++ b/app/javascript/flavours/glitch/features/home_timeline/index.jsx @@ -37,7 +37,7 @@ const getHomeFeedSpeed = createSelector([ state => state.getIn(['timelines', 'home', 'pendingItems'], ImmutableList()), state => state.get('statuses'), ], (statusIds, pendingStatusIds, statusMap) => { - const recentStatusIds = pendingStatusIds.size > 0 ? pendingStatusIds : statusIds; + const recentStatusIds = pendingStatusIds.concat(statusIds); const statuses = recentStatusIds.filter(id => id !== null).map(id => statusMap.get(id)).filter(status => status?.get('account') !== me).take(20); if (statuses.isEmpty()) { diff --git a/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx b/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx index 0de77b893f38ff..6741552731f8aa 100644 --- a/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx @@ -100,7 +100,7 @@ class LinkFooter extends PureComponent { {DividingCircle} {DividingCircle} - v{version} + v{version}

); diff --git a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx index f6984d5adbf2fd..9689f307956ca0 100644 --- a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx @@ -57,10 +57,10 @@ class NavigationPanel extends Component {
{transientSingleColumn && (
-
+
{intl.formatMessage(messages.openedInClassicInterface)} {" "} - + {intl.formatMessage(messages.advancedInterface)}
diff --git a/app/javascript/mastodon/features/home_timeline/index.jsx b/app/javascript/mastodon/features/home_timeline/index.jsx index 93f9376285e4be..f19eaf935ef13a 100644 --- a/app/javascript/mastodon/features/home_timeline/index.jsx +++ b/app/javascript/mastodon/features/home_timeline/index.jsx @@ -37,7 +37,7 @@ const getHomeFeedSpeed = createSelector([ state => state.getIn(['timelines', 'home', 'pendingItems'], ImmutableList()), state => state.get('statuses'), ], (statusIds, pendingStatusIds, statusMap) => { - const recentStatusIds = pendingStatusIds.size > 0 ? pendingStatusIds : statusIds; + const recentStatusIds = pendingStatusIds.concat(statusIds); const statuses = recentStatusIds.filter(id => id !== null).map(id => statusMap.get(id)).filter(status => status?.get('account') !== me).take(20); if (statuses.isEmpty()) { diff --git a/app/javascript/mastodon/features/ui/components/link_footer.jsx b/app/javascript/mastodon/features/ui/components/link_footer.jsx index 9585df2ec49854..6b1555243b7668 100644 --- a/app/javascript/mastodon/features/ui/components/link_footer.jsx +++ b/app/javascript/mastodon/features/ui/components/link_footer.jsx @@ -100,7 +100,7 @@ class LinkFooter extends PureComponent { {DividingCircle} {DividingCircle} - v{version} + v{version}

); diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx index 8006ca89a24a39..22eee79c0ace88 100644 --- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx @@ -59,10 +59,10 @@ class NavigationPanel extends Component { {transientSingleColumn ? ( -
+
{intl.formatMessage(messages.openedInClassicInterface)} {" "} - + {intl.formatMessage(messages.advancedInterface)}
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index a7a68533d677e3..aac4256ffdbf96 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -71,11 +71,11 @@ "account.unmute_notifications_short": "Poista ilmoitusten mykistys", "account.unmute_short": "Poista mykistys", "account_note.placeholder": "Lisää muistiinpano napsauttamalla", - "admin.dashboard.daily_retention": "Käyttäjän pysyminen rekisteröitymisen jälkeiseen päivään mennessä", - "admin.dashboard.monthly_retention": "Käyttäjän pysyminen rekisteröitymisen jälkeiseen kuukauteen mennessä", + "admin.dashboard.daily_retention": "Käyttäjien pysyvyys rekisteröitymisen jälkeen päivittäin", + "admin.dashboard.monthly_retention": "Käyttäjien pysyvyys rekisteröitymisen jälkeen kuukausittain", "admin.dashboard.retention.average": "Keskimäärin", - "admin.dashboard.retention.cohort": "Kirjautumiset", - "admin.dashboard.retention.cohort_size": "Uudet käyttäjät", + "admin.dashboard.retention.cohort": "Rekisteröitymis-kk.", + "admin.dashboard.retention.cohort_size": "Uusia käyttäjiä", "admin.impact_report.instance_accounts": "Tilien profiilit, jotka tämä poistaisi", "admin.impact_report.instance_followers": "Seuraajat, jotka käyttäjämme menettäisivät", "admin.impact_report.instance_follows": "Seuraajat, jotka heidän käyttäjänsä menettäisivät", @@ -114,7 +114,7 @@ "column.directory": "Selaa profiileja", "column.domain_blocks": "Estetyt verkkotunnukset", "column.favourites": "Suosikit", - "column.firehose": "Live-syötteet", + "column.firehose": "Livesyötteet", "column.follow_requests": "Seuraamispyynnöt", "column.home": "Koti", "column.lists": "Listat", @@ -135,7 +135,7 @@ "community.column_settings.remote_only": "Vain etätilit", "compose.language.change": "Vaihda kieli", "compose.language.search": "Hae kieliä...", - "compose.published.body": "Julkaisusi julkaistiin.", + "compose.published.body": "Julkaisu lähetetty.", "compose.published.open": "Avaa", "compose.saved.body": "Julkaisu tallennettu.", "compose_form.direct_message_warning_learn_more": "Lisätietoja", @@ -436,10 +436,10 @@ "notifications.clear": "Tyhjennä ilmoitukset", "notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?", "notifications.column_settings.admin.report": "Uudet ilmoitukset:", - "notifications.column_settings.admin.sign_up": "Uudet kirjautumiset:", + "notifications.column_settings.admin.sign_up": "Uudet rekisteröitymiset:", "notifications.column_settings.alert": "Työpöytäilmoitukset", "notifications.column_settings.favourite": "Suosikit:", - "notifications.column_settings.filter_bar.advanced": "Näytä kaikki kategoriat", + "notifications.column_settings.filter_bar.advanced": "Näytä kaikki luokat", "notifications.column_settings.filter_bar.category": "Pikasuodatuspalkki", "notifications.column_settings.filter_bar.show_bar": "Näytä suodatinpalkki", "notifications.column_settings.follow": "Uudet seuraajat:", @@ -517,7 +517,7 @@ "privacy.private.short": "Vain seuraajat", "privacy.public.long": "Näkyy kaikille", "privacy.public.short": "Julkinen", - "privacy.unlisted.long": "Näkyy kaikille, mutta jää pois löytämisominaisuuksista", + "privacy.unlisted.long": "Näkyy kaikille mutta jää pois löytämisominaisuuksista", "privacy.unlisted.short": "Listaamaton", "privacy_policy.last_updated": "Viimeksi päivitetty {date}", "privacy_policy.title": "Tietosuojakäytäntö", @@ -589,13 +589,13 @@ "search.quick_action.go_to_hashtag": "Siirry aihetunnisteeseen {x}", "search.quick_action.open_url": "Avaa URL-osoite Mastodonissa", "search.quick_action.status_search": "Julkaisut haulla {x}", - "search.search_or_paste": "Hae tai kirjoita URL-osoite", + "search.search_or_paste": "Hae tai liitä URL-osoite", "search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.", "search_popout.language_code": "ISO-kielikoodi", "search_popout.options": "Hakuvalinnat", "search_popout.quick_actions": "Pikatoiminnot", "search_popout.recent": "Viimeaikaiset haut", - "search_popout.specific_date": "tietty päivämäärä", + "search_popout.specific_date": "tarkka päiväys", "search_popout.user": "käyttäjä", "search_results.accounts": "Profiilit", "search_results.all": "Kaikki", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index c5817c199eec75..a01354463f7f91 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -137,7 +137,7 @@ "compose.language.search": "言語を検索...", "compose.published.body": "投稿されました!", "compose.published.open": "開く", - "compose.saved.body": "投稿が保存されました", + "compose.saved.body": "変更を保存しました。", "compose_form.direct_message_warning_learn_more": "もっと詳しく", "compose_form.encryption_warning": "Mastodonの投稿はエンドツーエンド暗号化に対応していません。安全に送受信されるべき情報をMastodonで共有しないでください。", "compose_form.hashtag_warning": "この投稿は公開設定ではないのでハッシュタグの一覧に表示されません。公開投稿だけがハッシュタグで検索できます。", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index b1cd0ca753ce22..f8dcb6a89fc0f5 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -114,7 +114,7 @@ "column.directory": "瀏覽個人檔案", "column.domain_blocks": "已封鎖網域", "column.favourites": "最愛", - "column.firehose": "即時內容", + "column.firehose": "即時河道", "column.follow_requests": "跟隨請求", "column.home": "首頁", "column.lists": "列表", diff --git a/app/models/featured_tag.rb b/app/models/featured_tag.rb index 587dcf9912ae29..df23114a3e7a15 100644 --- a/app/models/featured_tag.rb +++ b/app/models/featured_tag.rb @@ -51,7 +51,7 @@ def decrement(deleted_status_id) private def strip_name - self.name = name&.strip&.gsub(/\A#/, '') + self.name = name&.strip&.delete_prefix('#') end def set_tag diff --git a/app/serializers/rest/application_serializer.rb b/app/serializers/rest/application_serializer.rb index ab68219ade8fb2..e4806a3c9fc5b4 100644 --- a/app/serializers/rest/application_serializer.rb +++ b/app/serializers/rest/application_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::ApplicationSerializer < ActiveModel::Serializer - attributes :id, :name, :website, :redirect_uri, + attributes :id, :name, :website, :scopes, :redirect_uri, :client_id, :client_secret, :vapid_key def id diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index ec983510b91414..4ff92da01fb2c7 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -97,8 +97,6 @@ def update_media_attachments! end end - added_media_attachments = @next_media_attachments - previous_media_attachments - @status.ordered_media_attachment_ids = @next_media_attachments.map(&:id) @media_attachments_changed = true if @status.ordered_media_attachment_ids != previous_media_attachments_ids diff --git a/app/views/admin/disputes/appeals/_appeal.html.haml b/app/views/admin/disputes/appeals/_appeal.html.haml index 3f6efb856e5046..d5611211ed134b 100644 --- a/app/views/admin/disputes/appeals/_appeal.html.haml +++ b/app/views/admin/disputes/appeals/_appeal.html.haml @@ -4,7 +4,7 @@ = image_tag appeal.account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar' .log-entry__content .log-entry__title - = t(appeal.strike.action, scope: 'admin.strikes.actions', name: content_tag(:span, appeal.strike.account.username, class: 'username'), target: content_tag(:span, appeal.account.username, class: 'target')).html_safe + = strike_action_label(appeal) .log-entry__timestamp %time.formatted{ datetime: appeal.strike.created_at.iso8601 } = l(appeal.strike.created_at) diff --git a/config/brakeman.ignore b/config/brakeman.ignore index 9f85ccb6a4b2ca..d5c0b944360cd2 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -1,38 +1,5 @@ { "ignored_warnings": [ - { - "warning_type": "Cross-Site Scripting", - "warning_code": 2, - "fingerprint": "71cf98c8235b5cfa9946b5db8fdc1a2f3a862566abb34e4542be6f3acae78233", - "check_name": "CrossSiteScripting", - "message": "Unescaped model attribute", - "file": "app/views/admin/disputes/appeals/_appeal.html.haml", - "line": 7, - "link": "https://brakemanscanner.org/docs/warning_types/cross_site_scripting", - "code": "t((Unresolved Model).new.strike.action, :scope => \"admin.strikes.actions\", :name => content_tag(:span, (Unresolved Model).new.strike.account.username, :class => \"username\"), :target => content_tag(:span, (Unresolved Model).new.account.username, :class => \"target\"))", - "render_path": [ - { - "type": "template", - "name": "admin/disputes/appeals/index", - "line": 20, - "file": "app/views/admin/disputes/appeals/index.html.haml", - "rendered": { - "name": "admin/disputes/appeals/_appeal", - "file": "app/views/admin/disputes/appeals/_appeal.html.haml" - } - } - ], - "location": { - "type": "template", - "template": "admin/disputes/appeals/_appeal" - }, - "user_input": "(Unresolved Model).new.strike", - "confidence": "Weak", - "cwe_id": [ - 79 - ], - "note": "" - }, { "warning_type": "Cross-Site Scripting", "warning_code": 4, diff --git a/config/initializers/3_omniauth.rb b/config/initializers/3_omniauth.rb index 566e7362a53d65..d316c3b73a7411 100644 --- a/config/initializers/3_omniauth.rb +++ b/config/initializers/3_omniauth.rb @@ -9,9 +9,6 @@ end Devise.setup do |config| - # Devise omniauth strategies - options = {} - # CAS strategy if ENV['CAS_ENABLED'] == 'true' cas_options = {} diff --git a/config/locales/activerecord.sk.yml b/config/locales/activerecord.sk.yml index 33f53a88ed988f..d13c416e516a63 100644 --- a/config/locales/activerecord.sk.yml +++ b/config/locales/activerecord.sk.yml @@ -53,3 +53,7 @@ sk: position: elevated: nemôže byť vyššia ako vaša súčasná rola own_role: nie je možné zmeniť s vašou aktuálnou rolou + webhook: + attributes: + events: + invalid_permissions: nemožno zahrnúť udalosti, ku ktorým nemáte práva diff --git a/config/locales/doorkeeper.sk.yml b/config/locales/doorkeeper.sk.yml index acfd59b3e77011..91c9430b3029c5 100644 --- a/config/locales/doorkeeper.sk.yml +++ b/config/locales/doorkeeper.sk.yml @@ -129,6 +129,7 @@ sk: crypto: Šifrovanie End-to-end favourites: Obľúbené filters: Filtre + follow: Sledovanie, stlmenie a blokovanie follows: Sledovania lists: Zoznamy media: Mediálne prílohy @@ -148,9 +149,19 @@ sk: scopes: admin:read: prezeraj všetky dáta na serveri admin:read:accounts: prezeraj chúlostivé informácie na všetkých účtoch + admin:read:canonical_email_blocks: čítať citlivé informácie všetkých kanonických e-mailových blokov + admin:read:domain_allows: čítať citlivé informácie zo všetkých povolených domén + admin:read:domain_blocks: čítať citlivé informácie zo všetkých blokov domén + admin:read:email_domain_blocks: čítať citlivé informácie zo všetkých blokov emailových domén + admin:read:ip_blocks: čítať citlivé informácie zo všetkých blokov IP admin:read:reports: čítaj chulostivé informácie o všetkých hláseniach a nahlásených účtoch admin:write: uprav všetky dáta na serveri admin:write:accounts: urob moderovacie úkony na účtoch + admin:write:canonical_email_blocks: vykonať akcie moderácie na kanonických emailových blokoch + admin:write:domain_allows: vykonať akcie moderácie na povolených doménach + admin:write:domain_blocks: vykonať akcie moderácie na doménových blokoch + admin:write:email_domain_blocks: vykonať akcie moderácie na blokoch emailových domén + admin:write:ip_blocks: vykonať akcie moderácie na blokoch IP admin:write:reports: urob moderovacie úkony voči hláseniam crypto: používať end-to-end šifrovanie follow: uprav vzťahy svojho účtu @@ -159,6 +170,7 @@ sk: read:accounts: prezri si informácie o účte read:blocks: prezri svoje bloky read:bookmarks: pozri svoje záložky + read:favourites: zobraziť vaše obľúbené read:filters: prezri svoje filtrovanie read:follows: prezri si svoje sledovania read:lists: prezri si svoje zoznamy diff --git a/config/locales/fi.yml b/config/locales/fi.yml index cdc5d12678730e..09d2a68779e882 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -33,7 +33,7 @@ fi: accounts: add_email_domain_block: Estä sähköpostiverkkotunnus approve: Hyväksy - approved_msg: Käyttäjän %{username} liittymishakemus hyväksyttiin + approved_msg: Käyttäjän %{username} rekisteröitymishakemus hyväksyttiin are_you_sure: Oletko varma? avatar: Profiilikuva by_domain: Verkkotunnus @@ -364,7 +364,7 @@ fi: other: "%{count} odottavaa käyttäjää" resolved_reports: ratkaistut raportit software: Ohjelmisto - sources: Rekisteröitymisen lähteet + sources: Rekisteröitymislähteet space: Tilankäyttö title: Hallintapaneeli top_languages: Aktiivisimmat kielet @@ -440,7 +440,7 @@ fi: title: Estä uusi sähköpostiverkkotunnus no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei ollut valittuna not_permitted: Ei sallittu - resolved_dns_records_hint_html: Verkkotunnuksen nimi määräytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää kirjautumisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. Varo estämästä suuria sähköpostin palveluntarjoajia. + resolved_dns_records_hint_html: Verkkotunnuksen nimi määräytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää rekisteröitymisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. Varo estämästä suuria sähköpostin palveluntarjoajia. resolved_through_html: Ratkaistu %{domain} kautta title: Estetyt sähköpostiverkkotunnukset export_domain_allows: @@ -1405,7 +1405,7 @@ fi: migrations: acct: Muuttanut tunnukselle cancel: Peruuta uudelleenohjaus - cancel_explanation: Uudelleenohjauksen peruuttaminen aktivoi uudelleen nykyisen tilisi, mutta ei palauta seuraajia, jotka on siirretty kyseiselle tilille. + cancel_explanation: Uudelleenohjauksen peruuttaminen aktivoi nykyisen tilisi uudelleen mutta ei palauta seuraajia, jotka on siirretty kyseiselle tilille. cancelled_msg: Uudelleenohjaus peruttu onnistuneesti. errors: already_moved: on sama tili, jonka olet jo siirtänyt diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index 6c8875327bee31..403162b8203525 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -59,14 +59,14 @@ fi: setting_display_media_default: Piilota arkaluonteiseksi merkitty media setting_display_media_hide_all: Piilota media aina setting_display_media_show_all: Näytä media aina - setting_use_blurhash: Liukuvärit perustuvat piilotettujen kuvien väreihin, mutta sumentavat yksityiskohdat + setting_use_blurhash: Liukuvärit perustuvat piilotettujen kuvien väreihin mutta sumentavat yksityiskohdat setting_use_pending_items: Piilota aikajanan päivitykset napsautuksen taakse syötteen automaattisen vierityksen sijaan username: Voit käyttää kirjaimia, numeroita ja alaviivoja whole_word: Kun avainsana tai -fraasi on kokonaan aakkosnumeerinen, se on voimassa vain, jos se vastaa koko sanaa domain_allow: domain: Tämä verkkotunnus voi noutaa tietoja tältä palvelimelta ja sieltä saapuvat tiedot käsitellään ja tallennetaan email_domain_block: - domain: Tämä voi olla se verkkotunnus, joka näkyy sähköpostiosoitteessa tai MX tietueessa jota se käyttää. Ne tarkistetaan rekisteröitymisen yhteydessä. + domain: Tämä voi olla verkkotunnus, joka näkyy sähköpostiosoitteessa tai sen käyttämässä MX-tietueessa. Ne tarkistetaan rekisteröitymisen yhteydessä. with_dns_records: Annetun verkkotunnuksen DNS-tietueet yritetään ratkaista ja tulokset myös estetään featured_tag: name: 'Tässä muutamia hiljattain käyttämiäsi aihetunnisteita:' @@ -112,7 +112,7 @@ fi: ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi ulos! severities: no_access: Estä pääsy kaikkiin resursseihin - sign_up_block: Uudet kirjautumiset eivät ole mahdollisia + sign_up_block: Uudet rekisteröitymiset eivät ole mahdollisia sign_up_requires_approval: Uudet rekisteröitymiset edellyttävät hyväksyntääsi severity: Valitse, mitä tapahtuu tämän IP-osoitteen pyynnöille rule: diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index c48c659fa6a37b..4580e772fcb4e1 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -30,7 +30,7 @@ zh-TW: suspend: 禁止所有對該帳號任何互動,並且刪除其內容。三十天內可以撤銷此動作。關閉所有對此帳號之檢舉報告。 warning_preset_id: 選用。您仍可在預設的結尾新增自訂文字 announcement: - all_day: 核取後,只會顯示出時間範圍中的日期部分 + all_day: 當選取時,僅顯示出時間範圍中的日期部分 ends_at: 可選的,公告會於該時間點自動取消發布 scheduled_at: 空白則立即發布公告 starts_at: 可選的,讓公告在特定時間範圍內顯示 @@ -60,7 +60,7 @@ zh-TW: setting_display_media_hide_all: 總是隱藏所有媒體 setting_display_media_show_all: 總是顯示標為敏感內容的媒體 setting_use_blurhash: 彩色漸層圖樣是基於隱藏媒體內容顏色產生,所有細節將變得模糊 - setting_use_pending_items: 關閉自動捲動更新,時間軸只會於點擊後更新 + setting_use_pending_items: 關閉自動捲動更新,時間軸僅於點擊後更新 username: 您可以使用字幕、數字與底線 whole_word: 如果關鍵字或詞組僅有字母與數字,則其將只在符合整個單字的時候才會套用 domain_allow: diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index e139742ff17e54..fd934815096d64 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -578,7 +578,7 @@ zh-TW: mark_as_sensitive_description_html: 被檢舉的嘟文中的媒體將會被標記為敏感內容,並將會記錄一次警告,以協助您升級同一帳號未來的違規行為。 other_description_html: 檢視更多控制帳號行為以及自訂檢舉帳號通知之選項。 resolve_description_html: 被檢舉的帳號將不被採取任何行動,不會加以刪除線標記,並且此份報告將被關閉。 - silence_description_html: 此帳號僅會對已跟隨帳號之使用者或手動查詢可見,將大幅度限制觸及範圍。此設定可隨時被還原。關閉所有對此帳號之檢舉報告。 + silence_description_html: 此帳號僅對已跟隨帳號之使用者或手動查詢可見,將大幅度限制觸及範圍。此設定可隨時被還原。關閉所有對此帳號之檢舉報告。 suspend_description_html: 此帳號及其所有內容將不可被存取並且最終被移除,並且無法與之進行互動。三十天內可以撤銷此動作。關閉所有對此帳號之檢舉報告。 actions_description_html: 決定應對此報告採取何種行動。若您對檢舉之帳號採取懲罰措施,則將對他們發送 e-mail 通知,如非選擇了 垃圾郵件 類別。 actions_description_remote_html: 決定將對此檢舉報告採取何種動作。這將僅作用於您的伺服器與此遠端帳號及其內容之通訊行為。 diff --git a/db/migrate/.rubocop.yml b/db/migrate/.rubocop.yml new file mode 100644 index 00000000000000..4e23800dd14965 --- /dev/null +++ b/db/migrate/.rubocop.yml @@ -0,0 +1,4 @@ +inherit_from: ../../.rubocop.yml + +Naming/VariableNumber: + CheckSymbols: false diff --git a/db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb b/db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb index 7301e960d55da7..c9f0849557d532 100644 --- a/db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb +++ b/db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb @@ -19,7 +19,6 @@ def up # Record suspend date of blocks and silences for users whose limitations match # a domain block DomainBlock.where(severity: [:silence, :suspend]).find_each do |block| - scope = block.accounts if block.suspend? block.accounts.where(suspended: true).in_batches.update_all(suspended_at: block.created_at) else diff --git a/db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb b/db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb index 615f35cd0d205c..7788431cd5af77 100644 --- a/db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb +++ b/db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb @@ -18,7 +18,6 @@ def up # Record suspend date of blocks and silences for users whose limitations match # a domain block DomainBlock.where(severity: [:silence, :suspend]).find_each do |block| - scope = block.accounts if block.suspend? block.accounts.where(suspended: true).in_batches.update_all(suspended_at: block.created_at) else diff --git a/spec/controllers/admin/disputes/appeals_controller_spec.rb b/spec/controllers/admin/disputes/appeals_controller_spec.rb index 4afe074921aa3a..3f4175a28177c9 100644 --- a/spec/controllers/admin/disputes/appeals_controller_spec.rb +++ b/spec/controllers/admin/disputes/appeals_controller_spec.rb @@ -18,10 +18,14 @@ describe 'GET #index' do let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - it 'lists appeals' do + before { appeal } + + it 'returns a page that lists details of appeals' do get :index - expect(response).to have_http_status(200) + expect(response).to have_http_status(:success) + expect(response.body).to include("#{strike.account.username}") + expect(response.body).to include("#{appeal.account.username}") end end diff --git a/spec/controllers/concerns/account_controller_concern_spec.rb b/spec/controllers/concerns/account_controller_concern_spec.rb index d080475c32a835..56ffcfb047c844 100644 --- a/spec/controllers/concerns/account_controller_concern_spec.rb +++ b/spec/controllers/concerns/account_controller_concern_spec.rb @@ -62,7 +62,7 @@ def success end it 'sets link headers' do - account = Fabricate(:account, username: 'username') + Fabricate(:account, username: 'username') get 'success', params: { account_username: 'username' } expect(response.headers['Link'].to_s).to eq '; rel="lrdd"; type="application/jrd+json", ; rel="alternate"; type="application/activity+json"' end diff --git a/spec/helpers/admin/disputes_helper_spec.rb b/spec/helpers/admin/disputes_helper_spec.rb new file mode 100644 index 00000000000000..5f9a85df869140 --- /dev/null +++ b/spec/helpers/admin/disputes_helper_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Admin::DisputesHelper do + describe 'strike_action_label' do + it 'returns html describing the appeal' do + adam = Account.new(username: 'Adam') + becky = Account.new(username: 'Becky') + strike = AccountWarning.new(account: adam, action: :suspend) + appeal = Appeal.new(strike: strike, account: becky) + + expected = <<~OUTPUT.strip + Adam suspended Becky's account + OUTPUT + result = helper.strike_action_label(appeal) + + expect(result).to eq(expected) + end + end +end diff --git a/spec/helpers/jsonld_helper_spec.rb b/spec/helpers/jsonld_helper_spec.rb index 3575bba859815b..5124bcf855b488 100644 --- a/spec/helpers/jsonld_helper_spec.rb +++ b/spec/helpers/jsonld_helper_spec.rb @@ -158,14 +158,14 @@ it 'deems a safe compacting as such' do json['object'].delete('convo') compacted = compact(json) - deemed_compatible = patch_for_forwarding!(json, compacted) + patch_for_forwarding!(json, compacted) expect(compacted['to']).to eq ['https://www.w3.org/ns/activitystreams#Public'] expect(safe_for_forwarding?(json, compacted)).to be true end it 'deems an unsafe compacting as such' do compacted = compact(json) - deemed_compatible = patch_for_forwarding!(json, compacted) + patch_for_forwarding!(json, compacted) expect(compacted['to']).to eq ['https://www.w3.org/ns/activitystreams#Public'] expect(safe_for_forwarding?(json, compacted)).to be false end diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb index 5ecea5ea162b4e..2c8c994712d069 100644 --- a/spec/lib/mastodon/cli/accounts_spec.rb +++ b/spec/lib/mastodon/cli/accounts_spec.rb @@ -1356,4 +1356,254 @@ def stub_parallelize_with_progress! end end end + + describe '#prune' do + let!(:local_account) { Fabricate(:account) } + let!(:bot_account) { Fabricate(:account, bot: true, domain: 'example.com') } + let!(:group_account) { Fabricate(:account, actor_type: 'Group', domain: 'example.com') } + let!(:mentioned_account) { Fabricate(:account, domain: 'example.com') } + let!(:prunable_accounts) do + Fabricate.times(3, :account, domain: 'example.com', bot: false, suspended_at: nil, silenced_at: nil) + end + + before do + Fabricate(:mention, account: mentioned_account, status: Fabricate(:status, account: Fabricate(:account))) + stub_parallelize_with_progress! + end + + it 'prunes all remote accounts with no interactions with local users' do + cli.prune + + prunable_account_ids = prunable_accounts.pluck(:id) + + expect(Account.where(id: prunable_account_ids).count).to eq(0) + end + + it 'displays a successful message' do + expect { cli.prune }.to output( + a_string_including("OK, pruned #{prunable_accounts.size} accounts") + ).to_stdout + end + + it 'does not prune local accounts' do + cli.prune + + expect(Account.exists?(id: local_account.id)).to be(true) + end + + it 'does not prune bot accounts' do + cli.prune + + expect(Account.exists?(id: bot_account.id)).to be(true) + end + + it 'does not prune group accounts' do + cli.prune + + expect(Account.exists?(id: group_account.id)).to be(true) + end + + it 'does not prune accounts that have been mentioned' do + cli.prune + + expect(Account.exists?(id: mentioned_account.id)).to be true + end + + context 'with --dry-run option' do + before do + cli.options = { dry_run: true } + end + + it 'does not prune any account' do + cli.prune + + prunable_account_ids = prunable_accounts.pluck(:id) + + expect(Account.where(id: prunable_account_ids).count).to eq(prunable_accounts.size) + end + + it 'displays a successful message with (DRY RUN)' do + expect { cli.prune }.to output( + a_string_including("OK, pruned #{prunable_accounts.size} accounts (DRY RUN)") + ).to_stdout + end + end + end + + describe '#migrate' do + let!(:source_account) { Fabricate(:account) } + let!(:target_account) { Fabricate(:account, domain: 'example.com') } + let(:arguments) { [source_account.username] } + let(:resolve_account_service) { instance_double(ResolveAccountService, call: nil) } + let(:move_service) { instance_double(MoveService, call: nil) } + + before do + allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service) + allow(MoveService).to receive(:new).and_return(move_service) + end + + shared_examples 'a successful migration' do + it 'calls the MoveService for the last migration' do + cli.invoke(:migrate, arguments, options) + + last_migration = source_account.migrations.last + + expect(move_service).to have_received(:call).with(last_migration).once + end + + it 'displays a successful message' do + expect { cli.invoke(:migrate, arguments, options) }.to output( + a_string_including("OK, migrated #{source_account.acct} to #{target_account.acct}") + ).to_stdout + end + end + + context 'when both --replay and --target options are given' do + let(:options) { { replay: true, target: "#{target_account.username}@example.com" } } + + it 'exits with an error message indicating that using both options is not possible' do + expect { cli.invoke(:migrate, arguments, options) }.to output( + a_string_including('Use --replay or --target, not both') + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'when no option is given' do + it 'exits with an error message indicating that at least one option must be used' do + expect { cli.invoke(:migrate, arguments, {}) }.to output( + a_string_including('Use either --replay or --target') + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'when the given username is not found' do + let(:arguments) { ['non_existent_username'] } + + it 'exits with an error message indicating that there is no such account' do + expect { cli.invoke(:migrate, arguments, replay: true) }.to output( + a_string_including("No such account: #{arguments.first}") + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'with --replay option' do + let(:options) { { replay: true } } + + context 'when the specified account has no previous migrations' do + it 'exits with an error message indicating that the given account has no previous migrations' do + expect { cli.invoke(:migrate, arguments, options) }.to output( + a_string_including('The specified account has not performed any migration') + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'when the specified account has a previous migration' do + before do + allow(resolve_account_service).to receive(:call).with(source_account.acct, any_args).and_return(source_account) + allow(resolve_account_service).to receive(:call).with(target_account.acct, any_args).and_return(target_account) + target_account.aliases.create!(acct: source_account.acct) + source_account.migrations.create!(acct: target_account.acct) + source_account.update!(moved_to_account: target_account) + end + + it_behaves_like 'a successful migration' + + context 'when the specified account is redirecting to a different target account' do + before do + source_account.update!(moved_to_account: nil) + end + + it 'exits with an error message' do + expect { cli.invoke(:migrate, arguments, options) }.to output( + a_string_including('The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway') + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'with --force option' do + let(:options) { { replay: true, force: true } } + + it_behaves_like 'a successful migration' + end + end + end + + context 'with --target option' do + let(:options) { { target: target_account.acct } } + + before do + allow(resolve_account_service).to receive(:call).with(source_account.acct, any_args).and_return(source_account) + allow(resolve_account_service).to receive(:call).with(target_account.acct, any_args).and_return(target_account) + end + + context 'when the specified target account is not found' do + before do + allow(resolve_account_service).to receive(:call).with(target_account.acct).and_return(nil) + end + + it 'exits with an error message indicating that there is no such account' do + expect { cli.invoke(:migrate, arguments, options) }.to output( + a_string_including("The specified target account could not be found: #{options[:target]}") + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'when the specified target account exists' do + before do + target_account.aliases.create!(acct: source_account.acct) + end + + it 'creates a migration for the specified account with the target account' do + cli.invoke(:migrate, arguments, options) + + last_migration = source_account.migrations.last + + expect(last_migration.acct).to eq(target_account.acct) + end + + it_behaves_like 'a successful migration' + end + + context 'when the migration record is invalid' do + it 'exits with an error indicating that the validation failed' do + expect { cli.invoke(:migrate, arguments, options) }.to output( + a_string_including('Error: Validation failed') + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'when the specified account is redirecting to a different target account' do + before do + allow(Account).to receive(:find_local).with(source_account.username).and_return(source_account) + allow(source_account).to receive(:moved_to_account_id).and_return(-1) + end + + it 'exits with an error message' do + expect { cli.invoke(:migrate, arguments, options) }.to output( + a_string_including('The specified account is redirecting to a different target account. Use --force if you want to change the migration target') + ).to_stdout + .and raise_error(SystemExit) + end + end + + context 'with --target and --force options' do + let(:options) { { target: target_account.acct, force: true } } + + before do + target_account.aliases.create!(acct: source_account.acct) + allow(Account).to receive(:find_local).with(source_account.username).and_return(source_account) + allow(source_account).to receive(:moved_to_account_id).and_return(-1) + end + + it_behaves_like 'a successful migration' + end + end + end end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index fc7a43110b20e4..b5d942412e1cc8 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -356,7 +356,7 @@ end it 'does not return suspended users' do - match = Fabricate( + Fabricate( :account, display_name: 'Display Name', username: 'username', @@ -483,7 +483,7 @@ end it 'does not return non-followed accounts' do - match = Fabricate( + Fabricate( :account, display_name: 'A & l & i & c & e', username: 'username', @@ -495,7 +495,7 @@ end it 'does not return suspended users' do - match = Fabricate( + Fabricate( :account, display_name: 'Display Name', username: 'username', @@ -535,7 +535,7 @@ end it 'does not return suspended users' do - match = Fabricate( + Fabricate( :account, display_name: 'Display Name', username: 'username', @@ -719,10 +719,10 @@ context 'when is local' do it 'is invalid if the username is not unique in case-insensitive comparison among local accounts' do - account_1 = Fabricate(:account, username: 'the_doctor') - account_2 = Fabricate.build(:account, username: 'the_Doctor') - account_2.valid? - expect(account_2).to model_have_error_on_field(:username) + _account = Fabricate(:account, username: 'the_doctor') + non_unique_account = Fabricate.build(:account, username: 'the_Doctor') + non_unique_account.valid? + expect(non_unique_account).to model_have_error_on_field(:username) end it 'is invalid if the username is reserved' do @@ -743,9 +743,9 @@ end it 'is valid if we are creating a possibly-conflicting instance actor account' do - account_1 = Fabricate(:account, username: 'examplecom') - account_2 = Fabricate.build(:account, id: -99, actor_type: 'Application', locked: true, username: 'example.com') - expect(account_2.valid?).to be true + _account = Fabricate(:account, username: 'examplecom') + instance_account = Fabricate.build(:account, id: -99, actor_type: 'Application', locked: true, username: 'example.com') + expect(instance_account.valid?).to be true end it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do @@ -877,17 +877,17 @@ describe 'remote' do it 'returns an array of accounts who have a domain' do - account_1 = Fabricate(:account, domain: nil) - account_2 = Fabricate(:account, domain: 'example.com') - expect(described_class.remote).to contain_exactly(account_2) + _account = Fabricate(:account, domain: nil) + account_with_domain = Fabricate(:account, domain: 'example.com') + expect(described_class.remote).to contain_exactly(account_with_domain) end end describe 'local' do it 'returns an array of accounts who do not have a domain' do - account_1 = Fabricate(:account, domain: nil) - account_2 = Fabricate(:account, domain: 'example.com') - expect(described_class.where('id > 0').local).to contain_exactly(account_1) + local_account = Fabricate(:account, domain: nil) + _account_with_domain = Fabricate(:account, domain: 'example.com') + expect(described_class.where('id > 0').local).to contain_exactly(local_account) end end @@ -911,17 +911,17 @@ describe 'silenced' do it 'returns an array of accounts who are silenced' do - account_1 = Fabricate(:account, silenced: true) - account_2 = Fabricate(:account, silenced: false) - expect(described_class.silenced).to contain_exactly(account_1) + silenced_account = Fabricate(:account, silenced: true) + _account = Fabricate(:account, silenced: false) + expect(described_class.silenced).to contain_exactly(silenced_account) end end describe 'suspended' do it 'returns an array of accounts who are suspended' do - account_1 = Fabricate(:account, suspended: true) - account_2 = Fabricate(:account, suspended: false) - expect(described_class.suspended).to contain_exactly(account_1) + suspended_account = Fabricate(:account, suspended: true) + _account = Fabricate(:account, suspended: false) + expect(described_class.suspended).to contain_exactly(suspended_account) end end diff --git a/spec/models/domain_block_spec.rb b/spec/models/domain_block_spec.rb index 67f53fa7851349..d595441fd30a8d 100644 --- a/spec/models/domain_block_spec.rb +++ b/spec/models/domain_block_spec.rb @@ -11,10 +11,10 @@ end it 'is invalid if the same normalized domain already exists' do - domain_block_1 = Fabricate(:domain_block, domain: 'にゃん') - domain_block_2 = Fabricate.build(:domain_block, domain: 'xn--r9j5b5b') - domain_block_2.valid? - expect(domain_block_2).to model_have_error_on_field(:domain) + _domain_block = Fabricate(:domain_block, domain: 'にゃん') + domain_block_with_normalized_value = Fabricate.build(:domain_block, domain: 'xn--r9j5b5b') + domain_block_with_normalized_value.valid? + expect(domain_block_with_normalized_value).to model_have_error_on_field(:domain) end end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index f38e7c23719129..8868308d323692 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -166,7 +166,7 @@ describe '#replies_count' do it 'is the number of replies' do - reply = Fabricate(:status, account: bob, thread: subject) + Fabricate(:status, account: bob, thread: subject) expect(subject.replies_count).to eq 1 end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index bb61c02a637ce1..92ce87e3696329 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -55,17 +55,17 @@ describe 'scopes' do describe 'recent' do it 'returns an array of recent users ordered by id' do - user_1 = Fabricate(:user) - user_2 = Fabricate(:user) - expect(described_class.recent).to eq [user_2, user_1] + first_user = Fabricate(:user) + second_user = Fabricate(:user) + expect(described_class.recent).to eq [second_user, first_user] end end describe 'confirmed' do it 'returns an array of users who are confirmed' do - user_1 = Fabricate(:user, confirmed_at: nil) - user_2 = Fabricate(:user, confirmed_at: Time.zone.now) - expect(described_class.confirmed).to contain_exactly(user_2) + Fabricate(:user, confirmed_at: nil) + confirmed_user = Fabricate(:user, confirmed_at: Time.zone.now) + expect(described_class.confirmed).to contain_exactly(confirmed_user) end end diff --git a/spec/models/webauthn_credentials_spec.rb b/spec/models/webauthn_credentials_spec.rb index 4579ebb82e99a4..9631245e11bbc7 100644 --- a/spec/models/webauthn_credentials_spec.rb +++ b/spec/models/webauthn_credentials_spec.rb @@ -37,7 +37,7 @@ end it 'is invalid if already exist a webauthn credential with the same external id' do - existing_webauthn_credential = Fabricate(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw') + Fabricate(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw') new_webauthn_credential = Fabricate.build(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw') new_webauthn_credential.valid? @@ -47,7 +47,7 @@ it 'is invalid if user already registered a webauthn credential with the same nickname' do user = Fabricate(:user) - existing_webauthn_credential = Fabricate(:webauthn_credential, user_id: user.id, nickname: 'USB Key') + Fabricate(:webauthn_credential, user_id: user.id, nickname: 'USB Key') new_webauthn_credential = Fabricate.build(:webauthn_credential, user_id: user.id, nickname: 'USB Key') new_webauthn_credential.valid? diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb index 1268b36f8ae08a..e1455fe799a068 100644 --- a/spec/requests/api/v1/apps/credentials_spec.rb +++ b/spec/requests/api/v1/apps/credentials_spec.rb @@ -9,7 +9,8 @@ end context 'with an oauth token' do - let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) } + let(:application) { Fabricate(:application, scopes: 'read') } + let(:token) { Fabricate(:accessible_access_token, application: application) } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } it 'returns the app information correctly', :aggregate_failures do @@ -21,7 +22,35 @@ a_hash_including( name: token.application.name, website: token.application.website, - vapid_key: Rails.configuration.x.vapid_public_key + vapid_key: Rails.configuration.x.vapid_public_key, + scopes: token.application.scopes.map(&:to_s), + client_id: token.application.uid + ) + ) + end + end + + context 'with a non-read scoped oauth token' do + let(:application) { Fabricate(:application, scopes: 'admin:write') } + let(:token) { Fabricate(:accessible_access_token, application: application) } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + it 'returns http success' do + subject + + expect(response).to have_http_status(200) + end + + it 'returns the app information correctly' do + subject + + expect(body_as_json).to match( + a_hash_including( + name: token.application.name, + website: token.application.website, + vapid_key: Rails.configuration.x.vapid_public_key, + scopes: token.application.scopes.map(&:to_s), + client_id: token.application.uid ) ) end @@ -36,5 +65,49 @@ expect(response).to have_http_status(401) end end + + context 'with a revoked oauth token' do + let(:application) { Fabricate(:application, scopes: 'read') } + let(:token) { Fabricate(:accessible_access_token, application: application, revoked_at: DateTime.now.utc) } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + it 'returns http authorization error' do + subject + + expect(response).to have_http_status(401) + end + + it 'returns the error in the json response' do + subject + + expect(body_as_json).to match( + a_hash_including( + error: 'The access token was revoked' + ) + ) + end + end + + context 'with an invalid oauth token' do + let(:application) { Fabricate(:application, scopes: 'read') } + let(:token) { Fabricate(:accessible_access_token, application: application) } + let(:headers) { { 'Authorization' => "Bearer #{token.token}-invalid" } } + + it 'returns http authorization error' do + subject + + expect(response).to have_http_status(401) + end + + it 'returns the error in the json response' do + subject + + expect(body_as_json).to match( + a_hash_including( + error: 'The access token is invalid' + ) + ) + end + end end end diff --git a/spec/services/account_search_service_spec.rb b/spec/services/account_search_service_spec.rb index 1cd036f4848878..4f89cd220c8df8 100644 --- a/spec/services/account_search_service_spec.rb +++ b/spec/services/account_search_service_spec.rb @@ -56,7 +56,7 @@ service = instance_double(ResolveAccountService, call: nil) allow(ResolveAccountService).to receive(:new).and_return(service) - results = subject.call('newuser@remote.com', nil, limit: 10, resolve: true) + subject.call('newuser@remote.com', nil, limit: 10, resolve: true) expect(service).to have_received(:call).with('newuser@remote.com') end @@ -64,14 +64,14 @@ service = instance_double(ResolveAccountService, call: nil) allow(ResolveAccountService).to receive(:new).and_return(service) - results = subject.call('newuser@remote.com', nil, limit: 10, resolve: false) + subject.call('newuser@remote.com', nil, limit: 10, resolve: false) expect(service).to_not have_received(:call) end end it 'returns the fuzzy match first, and does not return suspended exacts' do partial = Fabricate(:account, username: 'exactness') - exact = Fabricate(:account, username: 'exact', suspended: true) + Fabricate(:account, username: 'exact', suspended: true) results = subject.call('exact', nil, limit: 10) expect(results.size).to eq 1 @@ -79,7 +79,7 @@ end it 'does not return suspended remote accounts' do - remote = Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e', suspended: true) + Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e', suspended: true) results = subject.call('a@example.com', nil, limit: 2) expect(results.size).to eq 0 diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 7d7679c889bcc2..1e5c420a63b245 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -155,7 +155,7 @@ it 'processes duplicate mentions correctly' do account = Fabricate(:account) - mentioned_account = Fabricate(:account, username: 'alice') + Fabricate(:account, username: 'alice') expect do subject.call(account, text: '@alice @alice @alice hey @alice') @@ -212,7 +212,7 @@ account = Fabricate(:account) media = Fabricate(:media_attachment, account: Fabricate(:account)) - status = subject.call( + subject.call( account, text: 'test status update', media_ids: [media.id] diff --git a/spec/services/precompute_feed_service_spec.rb b/spec/services/precompute_feed_service_spec.rb index 54e0d94ee0a80e..663babae8a9c02 100644 --- a/spec/services/precompute_feed_service_spec.rb +++ b/spec/services/precompute_feed_service_spec.rb @@ -27,7 +27,7 @@ muted_account = Fabricate(:account) Fabricate(:mute, account: account, target_account: muted_account) reblog = Fabricate(:status, account: muted_account) - status = Fabricate(:status, account: account, reblog: reblog) + Fabricate(:status, account: account, reblog: reblog) subject.call(account) diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb index 7991aa6ef14383..bcfb9dbfb0f893 100644 --- a/spec/services/resolve_url_service_spec.rb +++ b/spec/services/resolve_url_service_spec.rb @@ -7,8 +7,8 @@ describe '#call' do it 'returns nil when there is no resource url' do - url = 'http://example.com/missing-resource' - known_account = Fabricate(:account, uri: url, domain: 'example.com') + url = 'http://example.com/missing-resource' + Fabricate(:account, uri: url, domain: 'example.com') service = instance_double(FetchResourceService) allow(FetchResourceService).to receive(:new).and_return service diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4d3c234a0e8f1b..6ff0a8f8420f87 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -38,7 +38,7 @@ end # Use the GitHub Annotations formatter for CI - if ENV['GITHUB_ACTIONS'] == 'true' + if ENV['GITHUB_ACTIONS'] == 'true' && ENV['GITHUB_RSPEC'] == 'true' require 'rspec/github' config.add_formatter RSpec::Github::Formatter end diff --git a/spec/views/statuses/show.html.haml_spec.rb b/spec/views/statuses/show.html.haml_spec.rb index 354f9d3e63e73f..a9d3edf7a1253b 100644 --- a/spec/views/statuses/show.html.haml_spec.rb +++ b/spec/views/statuses/show.html.haml_spec.rb @@ -13,7 +13,7 @@ it 'has valid opengraph tags' do alice = Fabricate(:account, username: 'alice', display_name: 'Alice') status = Fabricate(:status, account: alice, text: 'Hello World') - media = Fabricate(:media_attachment, account: alice, status: status, type: :video) + Fabricate(:media_attachment, account: alice, status: status, type: :video) assign(:status, status) assign(:account, alice) @@ -32,7 +32,7 @@ it 'has twitter player tag' do alice = Fabricate(:account, username: 'alice', display_name: 'Alice') status = Fabricate(:status, account: alice, text: 'Hello World') - media = Fabricate(:media_attachment, account: alice, status: status, type: :video) + Fabricate(:media_attachment, account: alice, status: status, type: :video) assign(:status, status) assign(:account, alice)