diff --git a/.rubocop.yml b/.rubocop.yml index a8310489ea7084..dce33eab30d1b1 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -96,12 +96,6 @@ Rails/FilePath: Rails/HttpStatus: EnforcedStyle: numeric -# Reason: Allowed in boot ENV checker -# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit -Rails/Exit: - Exclude: - - 'config/boot.rb' - # Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions # https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter Rails/LexicallyScopedActionFilter: diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f775fcfa8cc5e..a53790afafb8d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,101 @@ All notable changes to this project will be documented in this file. +## [4.2.7] - 2024-02-16 + +### Fixed + +- Fix OmniAuth tests and edge cases in error handling ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/29201), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/29207)) +- Fix new installs by upgrading to the latest release of the `nsa` gem, instead of a no longer existing commit ([mjankowski](https://github.com/mastodon/mastodon/pull/29065)) + +### Security + +- Fix insufficient checking of remote posts ([GHSA-jhrq-qvrm-qr36](https://github.com/mastodon/mastodon/security/advisories/GHSA-jhrq-qvrm-qr36)) + +## [4.2.6] - 2024-02-14 + +### Security + +- Update the `sidekiq-unique-jobs` dependency (see [GHSA-cmh9-rx85-xj38](https://github.com/mhenrixon/sidekiq-unique-jobs/security/advisories/GHSA-cmh9-rx85-xj38)) + In addition, we have disabled the web interface for `sidekiq-unique-jobs` out of caution. + If you need it, you can re-enable it by setting `ENABLE_SIDEKIQ_UNIQUE_JOBS_UI=true`. + If you only need to clear all locks, you can now use `bundle exec rake sidekiq_unique_jobs:delete_all_locks`. +- Update the `nokogiri` dependency (see [GHSA-xc9x-jj77-9p9j](https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j)) +- Disable administrative Doorkeeper routes ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/29187)) +- Fix ongoing streaming sessions not being invalidated when applications get deleted in some cases ([GHSA-7w3c-p9j8-mq3x](https://github.com/mastodon/mastodon/security/advisories/GHSA-7w3c-p9j8-mq3x)) + In some rare cases, the streaming server was not notified of access tokens revocation on application deletion. +- Change external authentication behavior to never reattach a new identity to an existing user by default ([GHSA-vm39-j3vx-pch3](https://github.com/mastodon/mastodon/security/advisories/GHSA-vm39-j3vx-pch3)) + Up until now, Mastodon has allowed new identities from external authentication providers to attach to an existing local user based on their verified e-mail address. + This allowed upgrading users from a database-stored password to an external authentication provider, or move from one authentication provider to another. + However, this behavior may be unexpected, and means that when multiple authentication providers are configured, the overall security would be that of the least secure authentication provider. + For these reasons, this behavior is now locked under the `ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH` environment variable. + In addition, regardless of this environment variable, Mastodon will refuse to attach two identities from the same authentication provider to the same account. + +## [4.2.5] - 2024-02-01 + +### Security + +- Fix insufficient origin validation (CVE-2024-23832, [GHSA-3fjr-858r-92rw](https://github.com/mastodon/mastodon/security/advisories/GHSA-3fjr-858r-92rw)) + +## [4.2.4] - 2024-01-24 + +### Fixed + +- Fix error when processing remote files with unusually long names ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28823)) +- Fix processing of compacted single-item JSON-LD collections ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28816)) +- Retry 401 errors on replies fetching ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/28788)) +- Fix `RecordNotUnique` errors in LinkCrawlWorker ([tribela](https://github.com/mastodon/mastodon/pull/28748)) +- Fix Mastodon not correctly processing HTTP Signatures with query strings ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28443), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28476)) +- Fix potential redirection loop of streaming endpoint ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28665)) +- Fix streaming API redirection ignoring the port of `streaming_api_base_url` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28558)) +- Fix error when processing link preview with an array as `inLanguage` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28252)) +- Fix unsupported time zone or locale preventing sign-up ([Gargron](https://github.com/mastodon/mastodon/pull/28035)) +- Fix "Hide these posts from home" list setting not refreshing when switching lists ([brianholley](https://github.com/mastodon/mastodon/pull/27763)) +- Fix missing background behind dismissable banner in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/27479)) +- Fix line wrapping of language selection button with long locale codes ([gunchleoc](https://github.com/mastodon/mastodon/pull/27100), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27127)) +- Fix `Undo Announce` activity not being sent to non-follower authors ([MitarashiDango](https://github.com/mastodon/mastodon/pull/18482)) +- Fix N+1s because of association preloaders not actually getting called ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28339)) +- Fix empty column explainer getting cropped under certain conditions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28337)) +- Fix `LinkCrawlWorker` error when encountering empty OEmbed response ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28268)) +- Fix call to inefficient `delete_matched` cache method in domain blocks ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28367)) + +### Security + +- Add rate-limit of TOTP authentication attempts at controller level ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28801)) + +## [4.2.3] - 2023-12-05 + +### Fixed + +- Fix dependency on `json-canonicalization` version that has been made unavailable since last release + +## [4.2.2] - 2023-12-04 + +### Changed + +- Change dismissed banners to be stored server-side ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27055)) +- Change GIF max matrix size error to explicitly mention GIF files ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27927)) +- Change `Follow` activities delivery to bypass availability check ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/27586)) +- Change single-column navigation notice to be displayed outside of the logo container ([renchap](https://github.com/mastodon/mastodon/pull/27462), [renchap](https://github.com/mastodon/mastodon/pull/27476)) +- Change Content-Security-Policy to be tighter on media paths ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26889)) +- Change post language code to include country code when relevant ([gunchleoc](https://github.com/mastodon/mastodon/pull/27099), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27207)) + +### Fixed + +- Fix upper border radius of onboarding columns ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27890)) +- Fix incoming status creation date not being restricted to standard ISO8601 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27655), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28081)) +- Fix some posts from threads received out-of-order sometimes not being inserted into timelines ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27653)) +- Fix posts from force-sensitized accounts being able to trend ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27620)) +- Fix error when trying to delete already-deleted file with OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27569)) +- Fix batch attachment deletion when using OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27554)) +- Fix processing LDSigned activities from actors with unknown public keys ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27474)) +- Fix error and incorrect URLs in `/api/v1/accounts/:id/featured_tags` for remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27459)) +- Fix report processing notice not mentioning the report number when performing a custom action ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27442)) +- Fix handling of `inLanguage` attribute in preview card processing ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27423)) +- Fix own posts being removed from home timeline when unfollowing a used hashtag ([kmycode](https://github.com/mastodon/mastodon/pull/27391)) +- Fix some link anchors being recognized as hashtags ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27271), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27584)) +- Fix format-dependent redirects being cached regardless of requested format ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27634)) + ## [4.2.1] - 2023-10-10 ### Added diff --git a/Gemfile.lock b/Gemfile.lock index 00ca4663a848ca..79d3b1e637d90c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,7 +219,7 @@ GEM docile (1.4.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - doorkeeper (5.6.8) + doorkeeper (5.6.9) railties (>= 5) dotenv (2.8.1) dotenv-rails (2.8.1) @@ -505,7 +505,7 @@ GEM parslet (2.0.0) pastel (0.8.0) tty-color (~> 0.5) - pg (1.5.4) + pg (1.5.5) pghero (3.4.1) activerecord (>= 6) posix-spawn (0.3.15) @@ -811,7 +811,7 @@ GEM xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.12) + zeitwerk (2.6.13) PLATFORMS ruby diff --git a/README.md b/README.md index 267f0ed29578ab..6cf722b355af8b 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre - **PostgreSQL** 12+ - **Redis** 4+ -- **Ruby** 2.7+ +- **Ruby** 3.0+ - **Node.js** 16+ The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. diff --git a/app/controllers/auth/omniauth_callbacks_controller.rb b/app/controllers/auth/omniauth_callbacks_controller.rb index 9b83de945bee2a..9d496220a3d277 100644 --- a/app/controllers/auth/omniauth_callbacks_controller.rb +++ b/app/controllers/auth/omniauth_callbacks_controller.rb @@ -17,6 +17,9 @@ def self.provides_callback_for(provider) session["devise.#{provider}_data"] = request.env['omniauth.auth'] redirect_to new_user_registration_url end + rescue ActiveRecord::RecordInvalid + flash[:alert] = I18n.t('devise.failure.omniauth_user_creation_failure') if is_navigational_format? + redirect_to new_user_session_url end end diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index cc05b7a403483e..b0f2077db0e501 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -174,7 +174,19 @@ def fetch_resource_without_id_validation(uri, on_behalf_of = nil, raise_on_tempo build_request(uri, on_behalf_of, options: request_options).perform do |response| raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error - body_to_json(response.body_with_limit) if response.code == 200 + body_to_json(response.body_with_limit) if response.code == 200 && valid_activitypub_content_type?(response) + end + end + + def valid_activitypub_content_type?(response) + return true if response.mime_type == 'application/activity+json' + + # When the mime type is `application/ld+json`, we need to check the profile, + # but `http.rb` does not parse it for us. + return false unless response.mime_type == 'application/ld+json' + + response.headers[HTTP::Headers::CONTENT_TYPE]&.split(';')&.map(&:strip)&.any? do |str| + str.start_with?('profile="') && str[9...-1].split.include?('https://www.w3.org/ns/activitystreams') end end diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 5a6fa175e8abe5..3e7f6e51b218f4 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -201,7 +201,7 @@ "disabled_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен.", "dismissable_banner.community_timeline": "Ето най-скорошните публични публикации от хора, чиито акаунти са разположени в {domain}.", "dismissable_banner.dismiss": "Отхвърляне", - "dismissable_banner.explore_links": "Тези новини се разказват от хората в този и други сървъри на децентрализираната мрежа точно сега.", + "dismissable_banner.explore_links": "Това са най-споделяните новини в социалната мрежа днес. По-нови истории, споделени от повече хора се показват по-напред.", "dismissable_banner.explore_statuses": "Има публикации през социалната мрежа, които днес набират популярност. По-новите публикации с повече подсилвания и любими са класирани по-високо.", "dismissable_banner.explore_tags": "Тези хаштагове сега набират популярност сред хората в този и други сървъри на децентрализирата мрежа.", "dismissable_banner.public_timeline": "Ето най-новите обществени публикации от хора в социална мрежа, която хората в {domain} следват.", @@ -231,7 +231,7 @@ "empty_column.community": "Локалният инфопоток е празен. Публикувайте нещо, за да започнете!", "empty_column.direct": "Още нямате никакви частни споменавания. Тук ще се показват, изпращайки или получавайки едно.", "empty_column.domain_blocks": "Още няма блокирани домейни.", - "empty_column.explore_statuses": "Няма нищо налагащо се в момента. Проверете пак по-късно!", + "empty_column.explore_statuses": "Няма тенденции в момента. Проверете пак по-късно!", "empty_column.favourited_statuses": "Още нямате никакви любими публикации. Правейки любима, то тя ще се покаже тук.", "empty_column.favourites": "Още никого не е слагал публикацията в любими. Когато някой го направи, този човек ще се покаже тук.", "empty_column.follow_requests": "Още нямате заявки за последване. Получавайки такава, то тя ще се покаже тук.", @@ -407,7 +407,7 @@ "navigation_bar.direct": "Частни споменавания", "navigation_bar.discover": "Откриване", "navigation_bar.domain_blocks": "Блокирани домейни", - "navigation_bar.explore": "Изследване", + "navigation_bar.explore": "Разглеждане", "navigation_bar.favourites": "Любими", "navigation_bar.filters": "Заглушени думи", "navigation_bar.follow_requests": "Заявки за последване", @@ -474,10 +474,10 @@ "notifications_permission_banner.title": "Никога не пропускате нещо", "onboarding.action.back": "Върнете ме обратно", "onboarding.actions.back": "Върнете ме обратно", - "onboarding.actions.go_to_explore": "Вижте какво изгрява", + "onboarding.actions.go_to_explore": "Виж тенденции", "onboarding.actions.go_to_home": "Към началния ви инфоканал", "onboarding.compose.template": "Здравейте, #Mastodon!", - "onboarding.follows.empty": "За съжаление, в момента не могат да се показват резултати. Може да опитате да употребявате търсене или да прегледате страницата за изследване, за да намерите страница за последване, или да опитате пак по-късно.", + "onboarding.follows.empty": "За съжаление, в момента не могат да бъдат показани резултати. Може да опитате да търсите или да разгледате, за да намерите кого да последвате, или опитайте отново по-късно.", "onboarding.follows.lead": "Може да бъдете куратор на началния си инфоканал. Последвайки повече хора, по-деен и по-интересен ще става. Тези профили може да са добра начална точка, от която винаги по-късно да спрете да следвате!", "onboarding.follows.title": "Популярно в Mastodon", "onboarding.profile.discoverable": "Правене на моя профил откриваем", @@ -530,7 +530,7 @@ "privacy.private.short": "Последователи", "privacy.public.long": "Всеки във и извън Mastodon", "privacy.public.short": "Публично", - "privacy.unlisted.additional": "Това поведение е точно като публичното, с изключение на това, че публикацията няма да се появява в каналите на живо, хаштаговете, проучването или търсенето в Mastodon, дори ако сте се включили в целия акаунт.", + "privacy.unlisted.additional": "Това действие е точно като публичното, с изключение на това, че публикацията няма да се появява в каналите на живо, хаштаговете, разглеждането или търсенето в Mastodon, дори ако сте избрали да се публично видими на ниво акаунт.", "privacy.unlisted.long": "По-малко алгоритмични фанфари", "privacy.unlisted.short": "Тиха публика", "privacy_policy.last_updated": "Последно осъвременяване на {date}", diff --git a/app/javascript/mastodon/locales/ie.json b/app/javascript/mastodon/locales/ie.json index d39aa6cf61bcda..0c21832ed62e0d 100644 --- a/app/javascript/mastodon/locales/ie.json +++ b/app/javascript/mastodon/locales/ie.json @@ -158,6 +158,7 @@ "compose_form.save_changes": "Actualisar", "compose_form.spoiler.marked": "Remover avise pri li contenete", "compose_form.spoiler.unmarked": "Adjunter avise pri li contenete", + "compose_form.spoiler_placeholder": "Advertiment de contenete (optional)", "confirmation_modal.cancel": "Anullar", "confirmations.block.block_and_report": "Bloccar & Raportar", "confirmations.block.confirm": "Bloccar", @@ -276,6 +277,12 @@ "follow_request.authorize": "Autorisar", "follow_request.reject": "Rejecter", "follow_requests.unlocked_explanation": "Benque tu conto ne es cludet, li administratores de {domain} pensat que tu fórsan vell voler tractar seque-petitiones de tis-ci contos manualmen.", + "follow_suggestions.curated_suggestion": "Selection del Servitor", + "follow_suggestions.dismiss": "Ne monstrar plu", + "follow_suggestions.personalized_suggestion": "Personalisat suggestion", + "follow_suggestions.popular_suggestion": "Populari suggestion", + "follow_suggestions.view_all": "Vider omnicos", + "follow_suggestions.who_to_follow": "Persones a sequer", "followed_tags": "Sequet hashtags", "footer.about": "Information", "footer.directory": "Profilarium", @@ -517,11 +524,15 @@ "poll_button.add_poll": "Adjunter un balotation", "poll_button.remove_poll": "Remover balotation", "privacy.change": "Changear li privatie del posta", + "privacy.direct.long": "Omnes mentionat in li posta", "privacy.direct.short": "Specific persones", "privacy.private.long": "Solmen tui sequitores", "privacy.private.short": "Sequitores", "privacy.public.long": "Quicunc in e ex Mastodon", "privacy.public.short": "Public", + "privacy.unlisted.additional": "It acte just quam public, except que li posta ne va aparir in tendentie o hashtags, explorar, o sercha de Mastodon, mem si tu ha optet por les sur tui tot conto.", + "privacy.unlisted.long": "Minu fanfare algoritmic", + "privacy.unlisted.short": "Quiet public", "privacy_policy.last_updated": "Ultimmen actualisat ye {date}", "privacy_policy.title": "Politica pri Privatie", "recommended": "Recomandat", @@ -539,7 +550,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "relative_time.today": "hodie", + "reply_indicator.attachments": "{count, plural, one {# atachament} other {# atachamentes}}", "reply_indicator.cancel": "Anullar", + "reply_indicator.poll": "Balotar", "report.block": "Bloccar", "report.block_explanation": "Tu ne va vider su postas. Li usator ni va posser vider tui postas, ni sequer te, ni va posser saver pri li statu de esser bloccat.", "report.categories.legal": "Legal", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 7fb617518ca0ef..b69e93952b5548 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -11,11 +11,13 @@ "account.blocked": "Yettusewḥel", "account.browse_more_on_origin_server": "Snirem ugar deg umeɣnu aneẓli", "account.cancel_follow_request": "Withdraw follow request", + "account.copy": "Nɣel assaɣ ɣer umaɣnu", "account.disable_notifications": "Ḥbes ur iyi-d-ttazen ara ilɣa mi ara d-isuffeɣ @{name}", "account.domain_blocked": "Taɣult yeffren", "account.edit_profile": "Ẓreg amaɣnu", "account.enable_notifications": "Azen-iyi-d ilɣa mi ara d-isuffeɣ @{name}", "account.endorse": "Welleh fell-as deg umaɣnu-inek", + "account.featured_tags.last_status_never": "Ulac tisuffaɣ", "account.follow": "Ḍfer", "account.followers": "Imeḍfaren", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", @@ -65,7 +67,7 @@ "bundle_modal_error.message": "Tella-d kra n tuccḍa mi d-yettali ugbur-agi.", "bundle_modal_error.retry": "Ɛreḍ tikelt-nniḍen", "closed_registrations_modal.find_another_server": "Aff-d aqeddac nniḍen", - "column.about": "Γef", + "column.about": "Ɣef", "column.blocks": "Imiḍanen yettusḥebsen", "column.bookmarks": "Ticraḍ", "column.community": "Tasuddemt tadigant", @@ -77,7 +79,7 @@ "column.lists": "Tibdarin", "column.mutes": "Imiḍanen yettwasgugmen", "column.notifications": "Tilɣa", - "column.pins": "Tijewwaqin yettwasenṭḍen", + "column.pins": "Tisuffaɣ yettwasenṭḍen", "column.public": "Tasuddemt tamatut", "column_back_button.label": "Tuɣalin", "column_header.hide_settings": "Ffer iɣewwaṛen", @@ -88,32 +90,36 @@ "column_header.unpin": "Kkes asenteḍ", "column_subheading.settings": "Iɣewwaṛen", "community.column_settings.local_only": "Adigan kan", - "community.column_settings.media_only": "Allal n teywalt kan", + "community.column_settings.media_only": "Imidyaten kan", "community.column_settings.remote_only": "Anmeggag kan", "compose.language.change": "Beddel tutlayt", "compose.language.search": "Nadi tutlayin …", "compose.published.open": "Ldi", "compose_form.direct_message_warning_learn_more": "Issin ugar", - "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.", - "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", + "compose_form.encryption_warning": "", + "compose_form.hashtag_warning": "", "compose_form.lock_disclaimer": "Amiḍan-ik·im ur yelli ara {locked}. Menwala yezmer ad k·kem-yeḍfeṛ akken ad iẓer acu tbeṭṭuḍ akked yimeḍfaṛen-ik·im.", "compose_form.lock_disclaimer.lock": "yettwacekkel", "compose_form.placeholder": "D acu i itezzin deg wallaɣ?", "compose_form.poll.duration": "Tanzagt n tefrant", + "compose_form.poll.option_placeholder": "Taxtiṛt {number}", "compose_form.poll.single": "Fren yiwen", - "compose_form.publish_form": "Suffeɣ", + "compose_form.publish_form": "Tasuffeɣt tamaynut", + "compose_form.reply": "Err", + "compose_form.save_changes": "Leqqem", "compose_form.spoiler.marked": "Kkes aḍris yettwaffren deffir n walɣu", "compose_form.spoiler.unmarked": "Rnu aḍris yettwaffren deffir n walɣu", "confirmation_modal.cancel": "Sefsex", "confirmations.block.block_and_report": "Sewḥel & sewɛed", "confirmations.block.confirm": "Sewḥel", - "confirmations.block.message": "Tebγiḍ s tidet ad tesḥebseḍ {name}?", + "confirmations.block.message": "Tebɣiḍ s tidet ad tesḥebseḍ {name}?", "confirmations.delete.confirm": "Kkes", "confirmations.delete.message": "Tebɣiḍ s tidet ad tekkseḍ tasuffeɣt-agi?", "confirmations.delete_list.confirm": "Kkes", "confirmations.delete_list.message": "Tebɣiḍ s tidet ad tekkseḍ umuɣ-agi i lebda?", "confirmations.discard_edit_media.confirm": "Sefsex", "confirmations.domain_block.confirm": "Ffer taɣult meṛṛa", + "confirmations.edit.confirm": "Ẓreg", "confirmations.logout.confirm": "Ffeɣ", "confirmations.logout.message": "D tidet tebɣiḍ ad teffɣeḍ?", "confirmations.mute.confirm": "Sgugem", @@ -133,12 +139,13 @@ "directory.local": "Seg {domain} kan", "directory.new_arrivals": "Imaynuten id yewḍen", "directory.recently_active": "Yermed xas melmi kan", - "disabled_account_banner.account_settings": "Iγewwaṛen n umiḍan", + "disabled_account_banner.account_settings": "Iɣewwaṛen n umiḍan", "dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.", "dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.", "embed.instructions": "Ẓẓu addad-agi deg usmel-inek s wenγal n tangalt yellan sdaw-agi.", "embed.preview": "Akka ara d-iban:", "emoji_button.activity": "Aqeddic", + "emoji_button.clear": "Sfeḍ", "emoji_button.custom": "Udmawan", "emoji_button.flags": "Innayen", "emoji_button.food": "Tegwella & Tissit", @@ -153,7 +160,7 @@ "emoji_button.symbols": "Izamulen", "emoji_button.travel": "Imeḍqan d Yinigen", "empty_column.account_suspended": "Amiḍan yettwaḥbas", - "empty_column.account_timeline": "Ulac tijewwaqin dagi!", + "empty_column.account_timeline": "Ulac tisuffaɣ da !", "empty_column.account_unavailable": "Ur nufi ara amaɣnu-ayi", "empty_column.blocks": "Ur tesḥebseḍ ula yiwen n umseqdac ar tura.", "empty_column.bookmarked_statuses": "Ulac tijewwaqin i terniḍ ɣer yismenyifen-ik ar tura. Ticki terniḍ yiwet, ad d-tettwasken da.", @@ -174,7 +181,7 @@ "explore.suggested_follows": "Imdanen", "explore.title": "Snirem", "explore.trending_links": "Isallen", - "explore.trending_statuses": "Tisuffiɣin", + "explore.trending_statuses": "Tisuffaɣ", "explore.trending_tags": "Ihacṭagen", "filter_modal.added.settings_link": "asebter n yiɣewwaṛen", "filter_modal.select_filter.prompt_new": "Taggayt tamaynutt : {name}", @@ -183,8 +190,9 @@ "firehose.local": "Deg uqeddac-ayi", "follow_request.authorize": "Ssireg", "follow_request.reject": "Agi", - "footer.about": "Γef", - "footer.directory": "Akaram n imaγnuten", + "followed_tags": "Ihacṭagen yettwaḍfaren", + "footer.about": "Ɣef", + "footer.directory": "Akaram n imaɣnuten", "footer.get_app": "Awi-d asnas", "footer.invite": "Ɛreḍ-d kra n yimdanen", "footer.keyboard_shortcuts": "Inegzumen n unasiw", @@ -207,6 +215,7 @@ "home.column_settings.show_replies": "Ssken-d tiririyin", "home.hide_announcements": "Ffer ulɣuyen", "home.show_announcements": "Ssken-d ulɣuyen", + "interaction_modal.no_account_yet": "Ulac-ik·ikem deg Maṣṭudun?", "interaction_modal.on_this_server": "Deg uqeddac-ayi", "interaction_modal.title.follow": "Ḍfer {name}", "intervals.full.days": "{number, plural, one {# n wass} other {# n wussan}}", @@ -247,8 +256,8 @@ "lightbox.close": "Mdel", "lightbox.compress": "Ḥemmeẓ tamnaḍt n uskan n tugna", "lightbox.expand": "Simeɣer tamnaḍt n uskan n tugna", - "lightbox.next": "Γer zdat", - "lightbox.previous": "Γer deffir", + "lightbox.next": "Ɣer zdat", + "lightbox.previous": "Ɣer deffir", "link_preview.author": "S-ɣur {name}", "lists.account.add": "Rnu ɣer tebdart", "lists.account.remove": "Kkes seg tebdart", @@ -264,11 +273,12 @@ "lists.search": "Nadi gar yemdanen i teṭṭafaṛeḍ", "lists.subheading": "Tibdarin-ik·im", "load_pending": "{count, plural, one {# n uferdis amaynut} other {# n yiferdisen imaynuten}}", - "media_gallery.toggle_visible": "Ffer {number, plural, one {tugna} other {tugniwin}}", + "loading_indicator.label": "Yessalay-d …", + "media_gallery.toggle_visible": "{number, plural, one {Ffer tugna} other {Ffer tugniwin}}", "mute_modal.duration": "Tanzagt", "mute_modal.hide_notifications": "Tebɣiḍ ad teffreḍ talɣutin n umseqdac-a?", "mute_modal.indefinite": "Ur yettwasbadu ara", - "navigation_bar.about": "Γef", + "navigation_bar.about": "Ɣef", "navigation_bar.blocks": "Imseqdacen yettusḥebsen", "navigation_bar.bookmarks": "Ticraḍ", "navigation_bar.community_timeline": "Tasuddemt tadigant", @@ -284,7 +294,7 @@ "navigation_bar.logout": "Ffeɣ", "navigation_bar.mutes": "Iseqdacen yettwasusmen", "navigation_bar.personal": "Udmawan", - "navigation_bar.pins": "Tijewwiqin yettwasentḍen", + "navigation_bar.pins": "Tisuffaɣ yettwasenṭḍen", "navigation_bar.preferences": "Imenyafen", "navigation_bar.public_timeline": "Tasuddemt tazayezt tamatut", "navigation_bar.search": "Nadi", @@ -311,7 +321,7 @@ "notifications.column_settings.reblog": "Seǧhed:", "notifications.column_settings.show": "Ssken-d tilɣa deg ujgu", "notifications.column_settings.sound": "Rmed imesli", - "notifications.column_settings.status": "Tiẓenẓunin timaynutin:", + "notifications.column_settings.status": "Tisuffaɣ timaynutin :", "notifications.filter.all": "Akk", "notifications.filter.boosts": "Seǧhed", "notifications.filter.favourites": "Imenyafen", @@ -325,11 +335,15 @@ "notifications.permission_denied": "D awezɣi ad yili wermad n yilɣa n tnarit axateṛ turagt tettwagdel.", "notifications_permission_banner.enable": "Rmed talɣutin n tnarit", "notifications_permission_banner.title": "Ur zeggel acemma", + "onboarding.action.back": "Tuɣalin ɣer deffir", + "onboarding.actions.back": "Tuɣalin ɣer deffir", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Go to your home feed", "onboarding.compose.template": "Azul a #Mastodon!", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Popular on Mastodon", + "onboarding.profile.display_name": "Isem ara d-yettwaskanen", + "onboarding.share.title": "Bḍu amaɣnu-inek·inem", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.skip": "Want to skip right ahead?", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", @@ -365,7 +379,7 @@ "report.block": "Sewḥel", "report.categories.other": "Tiyyaḍ", "report.categories.spam": "Aspam", - "report.category.title_account": "ameγnu", + "report.category.title_account": "ameɣnu", "report.category.title_status": "tasuffeɣt", "report.close": "Immed", "report.forward": "Bren-it ɣeṛ {target}", @@ -383,6 +397,7 @@ "report_notification.open": "Ldi aneqqis", "search.placeholder": "Nadi", "search.search_or_paste": "Nadi neɣ senṭeḍ URL", + "search_popout.user": "amseqdac", "search_results.all": "Akk", "search_results.hashtags": "Ihacṭagen", "search_results.statuses": "Tisuffaɣ", @@ -405,7 +420,7 @@ "status.embed": "Seddu", "status.filtered": "Yettwasizdeg", "status.load_more": "Sali ugar", - "status.media_hidden": "Taɣwalt tettwaffer", + "status.media_hidden": "Amidya yettwaffer", "status.mention": "Bder-d @{name}", "status.more": "Ugar", "status.mute": "Sussem @{name}", @@ -425,7 +440,7 @@ "status.sensitive_warning": "Agbur amḥulfu", "status.share": "Bḍu", "status.show_less": "Ssken-d drus", - "status.show_less_all": "Semẓi akk tisuffγin", + "status.show_less_all": "Semẓi akk tisuffɣin", "status.show_more": "Ssken-d ugar", "status.show_more_all": "Ẓerr ugar lebda", "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", @@ -444,7 +459,7 @@ "timeline_hint.remote_resource_not_displayed": "{resource} seg yiqeddacen-nniḍen ur d-ttwaskanent ara.", "timeline_hint.resources.followers": "Imeḍfaṛen", "timeline_hint.resources.follows": "T·Yeṭafaṛ", - "timeline_hint.resources.statuses": "Tijewwaqin tiqdimin", + "timeline_hint.resources.statuses": "Tisuffaɣ tiqdimin", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {# days}}", "trends.trending_now": "Ayen mucaɛen tura", "ui.beforeunload": "Arewway-ik·im ad iruḥ ma yella tefeɣ-d deg Maṣṭudun.", @@ -465,7 +480,7 @@ "upload_modal.choose_image": "Fren tugna", "upload_modal.description_placeholder": "Aberraɣ arurad ineggez nnig n uqjun amuṭṭis", "upload_modal.detect_text": "Sefru-d aḍris seg tugna", - "upload_modal.edit_media": "Ẓreg taɣwalt", + "upload_modal.edit_media": "Ẓreg amidya", "upload_modal.preparing_ocr": "Aheyyi n OCR…", "upload_modal.preview_label": "Taskant ({ratio})", "upload_progress.label": "Asali iteddu...", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index abf60aeef14077..0c6a355b3392f0 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -524,6 +524,7 @@ "poll_button.add_poll": "Pridaj anketu", "poll_button.remove_poll": "Odstráň anketu", "privacy.change": "Uprav súkromie príspevku", + "privacy.direct.long": "Všetci spomenutí v príspevku", "privacy.direct.short": "Konkrétni ľudia", "privacy.private.long": "Iba tvoji nasledovatelia", "privacy.private.short": "Sledovatelia", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 72ecb11ed1ca05..e0aa072a77cc45 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -279,8 +279,8 @@ "follow_requests.unlocked_explanation": "แม้ว่าไม่มีการล็อคบัญชีของคุณ พนักงานของ {domain} คิดว่าคุณอาจต้องการตรวจทานคำขอติดตามจากบัญชีเหล่านี้ด้วยตนเอง", "follow_suggestions.curated_suggestion": "คัดสรรโดยบรรณาธิการ", "follow_suggestions.dismiss": "ไม่ต้องแสดงอีก", - "follow_suggestions.personalized_suggestion": "คำแนะนำเฉพาะบุคคล", - "follow_suggestions.popular_suggestion": "คำแนะนำยอดนิยม", + "follow_suggestions.personalized_suggestion": "ข้อเสนอแนะเฉพาะบุคคล", + "follow_suggestions.popular_suggestion": "ข้อเสนอแนะยอดนิยม", "follow_suggestions.view_all": "ดูทั้งหมด", "follow_suggestions.who_to_follow": "ติดตามใครดี", "followed_tags": "แฮชแท็กที่ติดตาม", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 85f62f404ae718..4d2cc3d1dc6c72 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -2,6 +2,9 @@ "about.blocks": "ma lawa", "about.contact": "toki:", "about.domain_blocks.no_reason_available": "mi sona ala e tan", + "about.domain_blocks.preamble": "ilo Masoton li ken e ni: sina lukin e toki jan pi ma ilo mute. sina ken toki tawa ona lon kulupu ma. taso, ma ni li ken ala e ni tawa ma ni:", + "about.domain_blocks.silenced.explanation": "sina lukin ala e toki e jan tan ma ni. taso, sina wile la, sina ken ni.", + "about.domain_blocks.silenced.title": "ken lili lukin", "about.domain_blocks.suspended.title": "weka", "about.not_available": "lon kulupu ni la sina ken alasa ala e sona ni.", "about.rules": "lawa kulupu", @@ -32,6 +35,7 @@ "account.follows.empty": "jan ni li kute e jan ala", "account.go_to_profile": "o tawa lipu jan", "account.hide_reblogs": "o lukin ala e pana toki tan @{name}", + "account.in_memoriam": "jan ni li moli. pona o tawa ona.", "account.languages": "sina wile lukin e sitelen pi toki seme", "account.locked_info": "sina wile kute e jan ni la ona o toki e ken", "account.media": "sitelen", @@ -53,6 +57,7 @@ "account.unblock": "o weka ala e jan {name}", "account.unblock_domain": "o weka ala e ma {domain}", "account.unblock_short": "o pini weka", + "account.unendorse": "lipu jan la o suli ala e ni", "account.unfollow": "o pini kute", "account.unmute": "o len ala e @{name}", "account.unmute_notifications_short": "o kute e mu tan jan ni", @@ -65,6 +70,9 @@ "alert.unexpected.title": "pakala a!", "announcement.announcement": "toki suli", "audio.hide": "o len e kalama", + "boost_modal.combo": "sina ken luka e nena {combo} tawa ni: sina wile ala luka e nena lon tenpo kama", + "bundle_column_error.copy_stacktrace": "o awen e sona pakala lon ilo sina", + "bundle_column_error.error.body": "ilo li ken ala pana e lipu ni. ni li ken tan pakala ilo.", "bundle_column_error.error.title": "ike a!", "bundle_column_error.network.title": "pakala la ilo sina li toki ala tawa ilo ante", "bundle_column_error.retry": "o ni sin", @@ -75,7 +83,9 @@ "bundle_modal_error.message": "ilo li wile kama e ijo ni, taso pakala li lon.", "bundle_modal_error.retry": "o ni sin", "closed_registrations_modal.find_another_server": "o alasa e ma ante", + "column.about": "sona", "column.blocks": "kulupu pi jan weka", + "column.bookmarks": "awen toki", "column.home": "lipu open", "column.lists": "kulupu lipu", "column.mutes": "jan len", diff --git a/app/models/account.rb b/app/models/account.rb index 2a9f4fd724797b..3fe55ce5ba8bc3 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -85,8 +85,8 @@ class Account < ApplicationRecord include DomainNormalizable include Paginable - enum protocol: { ostatus: 0, activitypub: 1 } - enum suspension_origin: { local: 0, remote: 1 }, _prefix: true + enum :protocol, { ostatus: 0, activitypub: 1 } + enum :suspension_origin, { local: 0, remote: 1 }, prefix: true validates :username, presence: true validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? } diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb index 9286577f516e65..a54387a562f222 100644 --- a/app/models/account_warning.rb +++ b/app/models/account_warning.rb @@ -17,7 +17,7 @@ # class AccountWarning < ApplicationRecord - enum action: { + enum :action, { none: 0, disable: 1_000, mark_statuses_as_sensitive: 1_250, @@ -25,7 +25,7 @@ class AccountWarning < ApplicationRecord sensitive: 2_000, silence: 3_000, suspend: 4_000, - }, _suffix: :action + }, suffix: :action normalizes :text, with: ->(text) { text.to_s }, apply_to_nil: true diff --git a/app/models/bulk_import.rb b/app/models/bulk_import.rb index 406fb2aba26c7a..4cd228705a860a 100644 --- a/app/models/bulk_import.rb +++ b/app/models/bulk_import.rb @@ -24,7 +24,7 @@ class BulkImport < ApplicationRecord belongs_to :account has_many :rows, class_name: 'BulkImportRow', inverse_of: :bulk_import, dependent: :delete_all - enum type: { + enum :type, { following: 0, blocking: 1, muting: 2, @@ -33,7 +33,7 @@ class BulkImport < ApplicationRecord lists: 5, } - enum state: { + enum :state, { unconfirmed: 0, scheduled: 1, in_progress: 2, diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index c8120c239547a0..5e2d152e34895e 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -31,7 +31,7 @@ class CustomFilter < ApplicationRecord include Expireable include Redisable - enum action: { warn: 0, hide: 1 }, _suffix: :action + enum :action, { warn: 0, hide: 1 }, suffix: :action belongs_to :account has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index a05db099a8d1d8..e310918e9b436e 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -21,7 +21,7 @@ class DomainBlock < ApplicationRecord include DomainNormalizable include DomainMaterializable - enum severity: { silence: 0, suspend: 1, noop: 2 } + enum :severity, { silence: 0, suspend: 1, noop: 2 } validates :domain, presence: true, uniqueness: true, domain: true diff --git a/app/models/import.rb b/app/models/import.rb index 7cd6cccf7cec0b..4bdb392014b70d 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -28,7 +28,7 @@ class Import < ApplicationRecord belongs_to :account - enum type: { following: 0, blocking: 1, muting: 2, domain_blocking: 3, bookmarks: 4 } + enum :type, { following: 0, blocking: 1, muting: 2, domain_blocking: 3, bookmarks: 4 } validates :type, presence: true diff --git a/app/models/ip_block.rb b/app/models/ip_block.rb index 99783050b8aac7..9def5b0cde1016 100644 --- a/app/models/ip_block.rb +++ b/app/models/ip_block.rb @@ -19,7 +19,7 @@ class IpBlock < ApplicationRecord include Expireable include Paginable - enum severity: { + enum :severity, { sign_up_requires_approval: 5000, sign_up_block: 5500, no_access: 9999, diff --git a/app/models/list.rb b/app/models/list.rb index fcef49e6e9ad5f..b45bd057bc7caa 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -18,7 +18,7 @@ class List < ApplicationRecord PER_ACCOUNT_LIMIT = 50 - enum replies_policy: { list: 0, followed: 1, none: 2 }, _prefix: :show + enum :replies_policy, { list: 0, followed: 1, none: 2 }, prefix: :show belongs_to :account, optional: true diff --git a/app/models/login_activity.rb b/app/models/login_activity.rb index 2b7b37f8e499f6..654dd623ad13ca 100644 --- a/app/models/login_activity.rb +++ b/app/models/login_activity.rb @@ -16,7 +16,7 @@ # class LoginActivity < ApplicationRecord - enum authentication_method: { password: 'password', otp: 'otp', webauthn: 'webauthn', sign_in_token: 'sign_in_token', omniauth: 'omniauth' } + enum :authentication_method, { password: 'password', otp: 'otp', webauthn: 'webauthn', sign_in_token: 'sign_in_token', omniauth: 'omniauth' } belongs_to :user diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index e353640654c801..d0c43c1f1c2695 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -34,8 +34,8 @@ class MediaAttachment < ApplicationRecord include Attachmentable - enum type: { image: 0, gifv: 1, video: 2, unknown: 3, audio: 4 } - enum processing: { queued: 0, in_progress: 1, complete: 2, failed: 3 }, _prefix: true + enum :type, { image: 0, gifv: 1, video: 2, unknown: 3, audio: 4 } + enum :processing, { queued: 0, in_progress: 1, complete: 2, failed: 3 }, prefix: true MAX_DESCRIPTION_LENGTH = 1_500 diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index 83759274306cf3..9fe02bd1681014 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -47,8 +47,8 @@ class PreviewCard < ApplicationRecord self.inheritance_column = false - enum type: { link: 0, photo: 1, video: 2, rich: 3 } - enum link_type: { unknown: 0, article: 1 } + enum :type, { link: 0, photo: 1, video: 2, rich: 3 } + enum :link_type, { unknown: 0, article: 1 } has_many :preview_cards_statuses, dependent: :delete_all, inverse_of: :preview_card has_many :statuses, through: :preview_cards_statuses diff --git a/app/models/relay.rb b/app/models/relay.rb index 8d697b891f9360..f652b4864b66c0 100644 --- a/app/models/relay.rb +++ b/app/models/relay.rb @@ -15,7 +15,7 @@ class Relay < ApplicationRecord validates :inbox_url, presence: true, uniqueness: true, url: true, if: :will_save_change_to_inbox_url? - enum state: { idle: 0, pending: 1, accepted: 2, rejected: 3 } + enum :state, { idle: 0, pending: 1, accepted: 2, rejected: 3 } scope :enabled, -> { accepted } diff --git a/app/models/report.rb b/app/models/report.rb index 1b132753b515f5..df7e3d2efc0f62 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -55,7 +55,7 @@ class Report < ApplicationRecord # - app/javascript/mastodon/features/notifications/components/report.jsx # - app/javascript/mastodon/features/report/category.jsx # - app/javascript/mastodon/components/admin/ReportReasonSelector.jsx - enum category: { + enum :category, { other: 0, spam: 1_000, legal: 1_500, diff --git a/app/models/software_update.rb b/app/models/software_update.rb index cb3a6df2aeb96e..51a73c27311d9a 100644 --- a/app/models/software_update.rb +++ b/app/models/software_update.rb @@ -16,7 +16,7 @@ class SoftwareUpdate < ApplicationRecord self.inheritance_column = nil - enum type: { patch: 0, minor: 1, major: 2 }, _suffix: :type + enum :type, { patch: 0, minor: 1, major: 2 }, suffix: :type def gem_version Gem::Version.new(version) diff --git a/app/models/status.rb b/app/models/status.rb index cf68d02ce4dcf7..ba7e10d93a63cf 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -50,7 +50,7 @@ class Status < ApplicationRecord update_index('statuses', :proper) update_index('public_statuses', :proper) - enum visibility: { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4 }, _suffix: :visibility + enum :visibility, { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4 }, suffix: :visibility belongs_to :application, class_name: 'Doorkeeper::Application', optional: true diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb index 71c6cca790c6ee..84c36f6a1014b8 100644 --- a/app/services/fetch_resource_service.rb +++ b/app/services/fetch_resource_service.rb @@ -44,7 +44,7 @@ def process_response(response, terminal = false) @response_code = response.code return nil if response.code != 200 - if ['application/activity+json', 'application/ld+json'].include?(response.mime_type) + if valid_activitypub_content_type?(response) body = response.body_with_limit json = body_to_json(body) diff --git a/config/boot.rb b/config/boot.rb index 717de85f20f5e7..70ffe22c04d979 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,8 +1,15 @@ # frozen_string_literal: true unless ENV.key?('RAILS_ENV') - warn 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".' - exit 1 + abort <<~ERROR + The RAILS_ENV environment variable is not set. + + Please set it correctly depending on context: + + - Use "production" for a live deployment of the application + - Use "development" for local feature work + - Use "test" when running the automated spec suite + ERROR end ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) diff --git a/config/locales/de.yml b/config/locales/de.yml index b77f4151904498..57ce5268a8b910 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -979,7 +979,7 @@ de: next_steps: Du kannst dem Einspruch zustimmen, um die Moderationsentscheidung rückgängig zu machen, oder ihn ignorieren. subject: "%{username} hat Einspruch gegen eine Moderationsentscheidung auf %{instance} erhoben" new_critical_software_updates: - body: Kritische Updates wurden für Mastodon veröffentlicht – du solltest so schnell wie möglich aktualisieren! + body: ein neues Sicherheitsupdate wurde veröffentlicht. Du solltest Mastodon so schnell wie möglich aktualisieren! subject: Kritische Mastodon-Updates sind für %{instance} verfügbar! new_pending_account: body: Die Details von diesem neuem Konto sind unten. Du kannst die Anfrage akzeptieren oder ablehnen. @@ -1023,7 +1023,7 @@ de: salutation: "%{name}," settings: 'E-Mail-Einstellungen ändern: %{link}' unsubscribe: Abbestellen - view: 'Hier überprüfen:' + view: 'Siehe:' view_profile: Profil anzeigen view_status: Beitrag anschauen applications: diff --git a/config/locales/devise.be.yml b/config/locales/devise.be.yml index 18785d16ab956b..81f3120a885f59 100644 --- a/config/locales/devise.be.yml +++ b/config/locales/devise.be.yml @@ -12,6 +12,7 @@ be: last_attempt: У вас ёсць яшчэ адна спроба, перш чым ваш рахунак будзе заблакаваны locked: Ваш уліковы запіс заблакіраваны. not_found_in_database: Няправільны %{authentication_keys} або пароль. + omniauth_user_creation_failure: Памылка пры стварэнні ўліковага запісу для гэтай асобы. pending: Ваш уліковы запіс яшчэ разглядаецца. timeout: Ваш сеанс скончыўся. Каб працягнуць, увайдзіце яшчэ раз. unauthenticated: Вам патрэбна зайсьці альбо зарэгістравацца, каб працягнуць diff --git a/config/locales/devise.ca.yml b/config/locales/devise.ca.yml index 3720d3c5f7067c..9b4ccccff7937e 100644 --- a/config/locales/devise.ca.yml +++ b/config/locales/devise.ca.yml @@ -14,6 +14,7 @@ ca: last_attempt: Tens un intent més abans no es bloqui el teu compte. locked: El teu compte s'ha blocat. not_found_in_database: "%{authentication_keys} o contrasenya no són vàlids." + omniauth_user_creation_failure: S'ha produït un error en crear un compte per a aquesta identitat. pending: El teu compte encara està en revisió. timeout: La teva sessió ha expirat. Torna a iniciar-la per a continuar. unauthenticated: Necessites iniciar sessió o registrar-te abans de continuar. diff --git a/config/locales/devise.da.yml b/config/locales/devise.da.yml index daf802cdb734de..c472242ba7a1b7 100644 --- a/config/locales/devise.da.yml +++ b/config/locales/devise.da.yml @@ -12,6 +12,7 @@ da: last_attempt: Du har ét forsøg mere, før din konto bliver låst. locked: Din konto er låst. not_found_in_database: Ugyldig %{authentication_keys} eller adgangskode. + omniauth_user_creation_failure: Fejl under oprettelse af konto for denne identitet. pending: Din konto er stadig under revision. timeout: Session udløbet. Log ind igen for at fortsætte. unauthenticated: Log ind eller tilmeld dig for at fortsætte. diff --git a/config/locales/devise.de.yml b/config/locales/devise.de.yml index cf05ddc16b1994..7982f8a743237b 100644 --- a/config/locales/devise.de.yml +++ b/config/locales/devise.de.yml @@ -12,6 +12,7 @@ de: last_attempt: Du hast nur noch einen Versuch, bevor dein Zugang gesperrt wird. locked: Dein Konto ist gesperrt. not_found_in_database: "%{authentication_keys} oder Passwort ungültig." + omniauth_user_creation_failure: Fehler beim Erstellen eines Kontos für diese Identität. pending: Dein Konto wird weiterhin überprüft. timeout: Deine Sitzung ist abgelaufen. Bitte melde dich erneut an, um fortzufahren. unauthenticated: Du musst dich anmelden oder registrieren, bevor du fortfahren kannst. diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 4439397c8eead1..61bd33851b6fca 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -12,6 +12,7 @@ en: last_attempt: You have one more attempt before your account is locked. locked: Your account is locked. not_found_in_database: Invalid %{authentication_keys} or password. + omniauth_user_creation_failure: Error creating an account for this identity. pending: Your account is still under review. timeout: Your session expired. Please login again to continue. unauthenticated: You need to login or sign up before continuing. diff --git a/config/locales/devise.es-AR.yml b/config/locales/devise.es-AR.yml index ca60ee5debca62..62492945974185 100644 --- a/config/locales/devise.es-AR.yml +++ b/config/locales/devise.es-AR.yml @@ -12,6 +12,7 @@ es-AR: last_attempt: Tenés un intento más antes de que se bloquee tu cuenta. locked: Se bloqueó tu cuenta. not_found_in_database: "%{authentication_keys} o contraseña no válidas." + omniauth_user_creation_failure: Error al crear una cuenta para esta identidad. pending: Tu cuenta todavía está bajo revisión. timeout: Venció tu sesión. Por favor, volvé a iniciar sesión para continuar. unauthenticated: Necesitás iniciar sesión o registrarte antes de continuar. diff --git a/config/locales/devise.eu.yml b/config/locales/devise.eu.yml index 624f9ee93d8972..3e675659fe6064 100644 --- a/config/locales/devise.eu.yml +++ b/config/locales/devise.eu.yml @@ -12,6 +12,7 @@ eu: last_attempt: Saiakera bat geratzen zaizu zure kontua giltzapetu aurretik. locked: Zure kontua giltzapetuta dago. not_found_in_database: Baliogabeko %{authentication_keys} edo pasahitza. + omniauth_user_creation_failure: Errorea identitate honen kontu bat sortzean. pending: Zure kontua oraindik berrikusteke dago. timeout: Zure saioa iraungitu da. Hasi saioa berriro jarraitzeko. unauthenticated: Saioa hasi edo izena eman behar duzu jarraitu aurretik. diff --git a/config/locales/devise.fi.yml b/config/locales/devise.fi.yml index 66616d16b115fb..003d48417b6869 100644 --- a/config/locales/devise.fi.yml +++ b/config/locales/devise.fi.yml @@ -12,6 +12,7 @@ fi: last_attempt: Sinulla on vielä yksi yritys ennen kuin tilisi lukitaan. locked: Tilisi on lukittu. not_found_in_database: Virheellinen %{authentication_keys} tai salasana. + omniauth_user_creation_failure: Virhe luotaessa tiliä tälle henkilöllisyydelle. pending: Tilisi on vielä tarkistamatta. timeout: Istuntosi on vanhentunut. Jatkaaksesi käyttöä, kirjaudu uudelleen. unauthenticated: Sinun on kirjauduttava tai rekisteröidyttävä ennen kuin voit jatkaa. diff --git a/config/locales/devise.fo.yml b/config/locales/devise.fo.yml index 1f7708bb44fe26..30f83ba0da28d0 100644 --- a/config/locales/devise.fo.yml +++ b/config/locales/devise.fo.yml @@ -12,6 +12,7 @@ fo: last_attempt: Tú kanst royna einaferð afturat áðrenn kontan verður stongd. locked: Kontan hjá tær er læst. not_found_in_database: Ogyldigur %{authentication_keys} ella loyniorð. + omniauth_user_creation_failure: Feilur í sambandi við, at ein konta fyri hendan samleikan bleiv stovnað. pending: Kontan hjá tær verður kannað enn. timeout: Tín innritan er útgingin. Innrita av nýggjum, fyri at hada fram. unauthenticated: Tú mást skriva teg inn aftur fyri at halda fram. diff --git a/config/locales/devise.fy.yml b/config/locales/devise.fy.yml index 05fd7b807108b3..c8a04a740501fc 100644 --- a/config/locales/devise.fy.yml +++ b/config/locales/devise.fy.yml @@ -12,6 +12,7 @@ fy: last_attempt: Jo hawwe noch ien besykjen oer eardat jo account blokkearre wurdt. locked: Jo account is blokkearre. not_found_in_database: "%{authentication_keys} of wachtwurd ûnjildich." + omniauth_user_creation_failure: Flater by it oanmeitsjen fan in account foar dizze identiteit. pending: Jo account moat noch hieltyd beoardiele wurde. timeout: Jo sesje is ferrûn. Meld jo opnij oan om troch te gean. unauthenticated: Jo moatte oanmelde of registrearje. diff --git a/config/locales/devise.gl.yml b/config/locales/devise.gl.yml index b9f4a0a0056381..00b1824808af37 100644 --- a/config/locales/devise.gl.yml +++ b/config/locales/devise.gl.yml @@ -12,6 +12,7 @@ gl: last_attempt: Tes un intento máis antes de que a túa conta fique bloqueada. locked: A túa conta está bloqueada. not_found_in_database: "%{authentication_keys} ou contrasinal non válidos." + omniauth_user_creation_failure: Erro ao crear unha conta para esta identidade. pending: A túa conta aínda está baixo revisión. timeout: A túa sesión caducou. Accede outra vez para continuar. unauthenticated: Precisas iniciar sesión ou rexistrarte antes de continuar. diff --git a/config/locales/devise.he.yml b/config/locales/devise.he.yml index f2ec3a6716e1cd..02e307ae1cda2a 100644 --- a/config/locales/devise.he.yml +++ b/config/locales/devise.he.yml @@ -12,6 +12,7 @@ he: last_attempt: יש לך עוד ניסיון אחד לפני נעילת החשבון. locked: חשבון זה נעול. not_found_in_database: "%{authentication_keys} או סיסמה לא נכונים." + omniauth_user_creation_failure: שגיאה ביצירת חשבון לזהות הזו. pending: חשבונך נמצא עדיין בבדיקה. timeout: פג תוקף השהיה בחשבון. נא להכנס מחדש על מנת להמשיך. unauthenticated: יש להרשם או להכנס לחשבון על מנת להמשיך. diff --git a/config/locales/devise.hu.yml b/config/locales/devise.hu.yml index fea56ab24a9286..8c9fdf6a5037ad 100644 --- a/config/locales/devise.hu.yml +++ b/config/locales/devise.hu.yml @@ -12,6 +12,7 @@ hu: last_attempt: Már csak egy próbálkozásod maradt, mielőtt a fiókodat zároljuk. locked: A fiókodat zároltuk. not_found_in_database: Helytelen %{authentication_keys} vagy jelszó. + omniauth_user_creation_failure: Hiba történt a fiók létrehozása során ehhez az identitáshoz. pending: A fiókod még engedélyezésre vár. timeout: A munkameneted lejárt. A folytatáshoz jelentkezz be újra. unauthenticated: A folytatás előtt be kell jelentkezned vagy regisztrálnod kell. diff --git a/config/locales/devise.ie.yml b/config/locales/devise.ie.yml index 332c9da4563d88..9c82bd45299700 100644 --- a/config/locales/devise.ie.yml +++ b/config/locales/devise.ie.yml @@ -12,6 +12,7 @@ ie: last_attempt: Hay solmen un prova ante que tui conto deveni serrat. locked: Tui conto es serrat. not_found_in_database: Ínvalid %{authentication_keys} o passa-parol. + omniauth_user_creation_failure: Errore in li creation de un conto por ti-ci identitá. pending: Tui conto es ancor sub revision. timeout: Tui session ha expirat. Ples reintrar denov por continuar. unauthenticated: Tu deve intrar o registrar te ante continuar. diff --git a/config/locales/devise.is.yml b/config/locales/devise.is.yml index 12015fa29d628a..a045bdd80c0f07 100644 --- a/config/locales/devise.is.yml +++ b/config/locales/devise.is.yml @@ -12,6 +12,7 @@ is: last_attempt: Þú getur reynt einu sinni í viðbót áður en aðgangnum þínum verður læst. locked: Notandaaðgangurinn þinn er læstur. not_found_in_database: Ógilt %{authentication_keys} eða lykilorð. + omniauth_user_creation_failure: Villa við að útbúa aðgang fyrir þetta auðkenni. pending: Notandaaðgangurinn þinn er enn til yfirferðar. timeout: Setan þín er útrunnin. Skráðu þig aftur inn til að halda áfram. unauthenticated: Þú þarft að skrá þig inn eða nýskrá þig áður en lengra er haldið. diff --git a/config/locales/devise.it.yml b/config/locales/devise.it.yml index 19bd999aade12e..8aaea3c15be681 100644 --- a/config/locales/devise.it.yml +++ b/config/locales/devise.it.yml @@ -12,6 +12,7 @@ it: last_attempt: Hai un altro tentativo, prima che il tuo profilo venga bloccato. locked: Il tuo profilo è bloccato. not_found_in_database: "%{authentication_keys} o password non valida." + omniauth_user_creation_failure: Errore nella creazione di un account per questa identità. pending: Il tuo profilo è ancora in revisione. timeout: La tua sessione è scaduta. Sei pregato di accedere nuovamente per continuare. unauthenticated: Devi accedere o registrarti, per continuare. diff --git a/config/locales/devise.kab.yml b/config/locales/devise.kab.yml index 2f60629fd70cbb..f878a5b5039058 100644 --- a/config/locales/devise.kab.yml +++ b/config/locales/devise.kab.yml @@ -13,13 +13,13 @@ kab: locked: Amiḍan-ik yettwargel. not_found_in_database: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir. pending: Amiḍan-inek mazal-it deg ɛiwed n tmuγli. - timeout: Tiγimit n tuqqna tezri. Ma ulac aγilif ɛiwed tuqqna akken ad tkemmleḍ. - unauthenticated: Ilaq ad teqqneḍ neγ ad tjerrḍeḍ akken ad tkemmelḍ. + timeout: Tiɣimit n tuqqna tezri. Ma ulac aɣilif ɛiwed tuqqna akken ad tkemmleḍ. + unauthenticated: Ilaq ad teqqneḍ neɣ ad tjerrḍeḍ akken ad tkemmelḍ. unconfirmed: Ilaq ad wekdeḍ tansa-inek imayl akken ad tkemmelḍ. mailer: confirmation_instructions: action: Senqed tansa-inek imayl - action_with_app: Wekked sakkin uγal γer %{app} + action_with_app: Sentem sakkin uɣal ɣer %{app} explanation: Aqla-k terniḍ amiḍan deg %{host} s tansa imayl-agi. Mazal-ak yiwen utekki akken ad t-tremdeḍ. Ma mačči d kečč i yessutren ay-agi, ttxil-k ssinef izen-a. explanation_when_pending: Tsutreḍ-d ajerred deg %{host} s tansa-agi imayl. Ad nγeṛ asuter-ik ticki tsentmeḍ tansa-ik imayl. Send asentem, ur tezmireḍ ara ad teqqneḍ γer umiḍan-ik. Ma yella nugi asuter-ik, isefka-ik ad ttwakksen seg uqeddac, ihi ulac tigawt-nniḍen ara k-d-yettuqeblen. Ma mačči d kečč i yellan deffir n usuter-agi, ttxil-k ssinef izen-agi. extra_html: Ttxil-k ẓer daγen ilugan n uqeddac akked twetlin n useqdec-nneγ. @@ -87,7 +87,7 @@ kab: unlocks: send_instructions: Deg kra n tesdatin, ad teṭṭfeḍ imayl deg-s iwellihen i yilaqen i userreḥ n umiḍan-ik·im. Ma yella ur tufiḍ ara izen-agi, ttxil-k·m ẓer deg ukaram spam. send_paranoid_instructions: Ma yella umiḍan-ik·im yella, ad teṭṭfeḍ imayl deg tesdatin i d-iteddun, deg-s iwellihen i yilaqen i userreḥ n umiḍan-ik·im. Ma yella ur tufiḍ ara izen-agi, ttxil-k·m ẓer deg ukaram spam. - unlocked: Iserreḥ umiḍan-ik·im akken iwata. ttxil qqen akken ad tkemleḍ. + unlocked: Iserreḥ umiḍan-ik·im akken iwata. Ttxil qqen akken ad tkemleḍ. errors: messages: already_confirmed: ittwasentem yakan, ttxil εreḍ ad teqneḍ diff --git a/config/locales/devise.ko.yml b/config/locales/devise.ko.yml index 0c848e4bac35c5..198d44a4f799b2 100644 --- a/config/locales/devise.ko.yml +++ b/config/locales/devise.ko.yml @@ -12,6 +12,7 @@ ko: last_attempt: 계정이 잠기기까지 한 번의 시도가 남았습니다. locked: 계정이 잠겼습니다. not_found_in_database: 올바르지 않은 %{authentication_keys} 혹은 암호입니다. + omniauth_user_creation_failure: 이 신원으로 계정을 만드는데 실패했습니다. pending: 이 계정은 아직 검토 중입니다. timeout: 세션이 만료되었습니다. 다시 로그인 하세요. unauthenticated: 계속 하려면 로그인을 해야 합니다. diff --git a/config/locales/devise.lad.yml b/config/locales/devise.lad.yml index d2ce53760c5257..7d447140f4f7c6 100644 --- a/config/locales/devise.lad.yml +++ b/config/locales/devise.lad.yml @@ -12,6 +12,7 @@ lad: last_attempt: Aprova una vez mas antes de ke tu kuento sea blokado. locked: Tu kuento esta blokado. not_found_in_database: Inkorekto %{authentication_keys} o kod. + omniauth_user_creation_failure: Ay un error en kriyar un kuento para esta identita. pending: Tu kuento ainda esta basho revizyon. timeout: Tu sesyon tiene kadukado. Por favor konektate kon tu kuento de muevo para kontinuar. unauthenticated: Kale konektarte kon tu kuento o enregistrarte antes de kontinuar. diff --git a/config/locales/devise.nl.yml b/config/locales/devise.nl.yml index 0aaf376f7fca8d..ab6ae84db4d229 100644 --- a/config/locales/devise.nl.yml +++ b/config/locales/devise.nl.yml @@ -12,6 +12,7 @@ nl: last_attempt: Je hebt nog één poging over voordat jouw account wordt opgeschort. locked: Jouw account is opgeschort. not_found_in_database: "%{authentication_keys} of wachtwoord ongeldig." + omniauth_user_creation_failure: Fout bij het aanmaken van een account voor deze identiteit. pending: Jouw account moet nog steeds worden beoordeeld. timeout: Jouw sessie is verlopen, log opnieuw in. unauthenticated: Je dient in te loggen of te registreren. diff --git a/config/locales/devise.pl.yml b/config/locales/devise.pl.yml index a6d48f11ef0e09..f34fd04633a67e 100644 --- a/config/locales/devise.pl.yml +++ b/config/locales/devise.pl.yml @@ -12,6 +12,7 @@ pl: last_attempt: Masz jeszcze jedną próbę; Twoje konto zostanie zablokowane jeśli się nie powiedzie. locked: Twoje konto zostało zablokowane. not_found_in_database: Nieprawidłowy %{authentication_keys} lub hasło. + omniauth_user_creation_failure: Błąd przy tworzeniu konta dla tej tożsamości. pending: Twoje konto oczekuje na przegląd. timeout: Twoja sesja wygasła. Zaloguj się ponownie, aby kontynuować.. unauthenticated: Zapisz się lub zaloguj, aby kontynuować. diff --git a/config/locales/devise.pt-PT.yml b/config/locales/devise.pt-PT.yml index c169ddeb971887..c66181fc5b8e3b 100644 --- a/config/locales/devise.pt-PT.yml +++ b/config/locales/devise.pt-PT.yml @@ -12,6 +12,7 @@ pt-PT: last_attempt: Tem só mais uma tentativa antes da sua conta ser bloqueada. locked: A tua conta está bloqueada. not_found_in_database: "%{authentication_keys} ou palavra-passe inválida." + omniauth_user_creation_failure: Erro ao criar uma conta para esta identidade. pending: A sua conta está ainda a aguardar revisão. timeout: A tua sessão expirou. Por favor, entra de novo para continuares. unauthenticated: Precisas de entrar na tua conta ou de te registares antes de continuar. diff --git a/config/locales/devise.sk.yml b/config/locales/devise.sk.yml index 3eb4b5304cf31f..bc01b73ccfca26 100644 --- a/config/locales/devise.sk.yml +++ b/config/locales/devise.sk.yml @@ -12,6 +12,7 @@ sk: last_attempt: Máš posledný pokus pred zamknutím tvojho účtu. locked: Tvoj účet je zamknutý. not_found_in_database: Nesprávny %{authentication_keys}, alebo heslo. + omniauth_user_creation_failure: Chyba pri vytváraní účtu pre túto identitu. pending: Tvoj účet je stále prehodnocovaný. timeout: Tvoja aktívna sezóna vypršala. Pre pokračovanie sa prosím prihlás znovu. unauthenticated: K pokračovaniu sa musíš zaregistrovať alebo prihlásiť. diff --git a/config/locales/devise.sl.yml b/config/locales/devise.sl.yml index 2d567e63f47797..0eb9b6330a8a26 100644 --- a/config/locales/devise.sl.yml +++ b/config/locales/devise.sl.yml @@ -12,6 +12,7 @@ sl: last_attempt: Pred zaklepom računa imate še en poskus. locked: Vaš račun je zaklenjen. not_found_in_database: Neveljavno %{authentication_keys} ali geslo. + omniauth_user_creation_failure: Napaka pri ustvarjanju računa za to identiteto. pending: Vaš račun je še vedno pod drobnogledom. timeout: Vaša seja je potekla. Če želite nadaljevati, se znova prijavite. unauthenticated: Pred nadaljevanjem se morate prijaviti ali vpisati. diff --git a/config/locales/devise.sq.yml b/config/locales/devise.sq.yml index 32136a0baa8e87..76dd493245f332 100644 --- a/config/locales/devise.sq.yml +++ b/config/locales/devise.sq.yml @@ -12,6 +12,7 @@ sq: last_attempt: Mund të provoni edhe një herë, përpara se llogaria juaj të kyçet. locked: Llogaria juaj është e kyçur. not_found_in_database: "%{authentication_keys} ose fjalëkalim i pavlefshëm." + omniauth_user_creation_failure: Gabim në krijim llogarie për këtë identitet. pending: Llogaria juaj është ende nën shqyrtim. timeout: Sesioni juaj ka skaduar. Ju lutemi, që të vazhdohet, ribëni hyrjen. unauthenticated: Përpara se të vazhdohet më tej, lypset të bëni hyrjen ose të regjistroheni. diff --git a/config/locales/devise.sr-Latn.yml b/config/locales/devise.sr-Latn.yml index c48ed87dca6b88..3947b2d84f2462 100644 --- a/config/locales/devise.sr-Latn.yml +++ b/config/locales/devise.sr-Latn.yml @@ -12,6 +12,7 @@ sr-Latn: last_attempt: Imate još jedan pokušaj pre nego što Vaš nalog bude zaključan. locked: Vaš nalog je zaključan. not_found_in_database: Neispravna %{authentication_keys} ili lozinka. + omniauth_user_creation_failure: Greška pri kreiranju naloga za ovaj identitet. pending: Vaš račun je još uvek u pregledu. timeout: Vreme trajanja Vaše sesije je isteklo. Za nastavak prijavite se ponovo. unauthenticated: Za nastavak se morate prijaviti ili registrovati. diff --git a/config/locales/devise.sr.yml b/config/locales/devise.sr.yml index 3e49cf97eeb5a6..a4c08dfaf0c511 100644 --- a/config/locales/devise.sr.yml +++ b/config/locales/devise.sr.yml @@ -12,6 +12,7 @@ sr: last_attempt: Имате још један покушај пре него што Ваш налог буде закључан. locked: Ваш налог је закључан. not_found_in_database: Неисправна %{authentication_keys} или лозинка. + omniauth_user_creation_failure: Грешка при креирању налога за овај идентитет. pending: Ваш налог се још увек прегледа. timeout: Ваша сесија је истекла. Пријавите се поново да бисте наставили. unauthenticated: Морате да се пријавите или региструјете пре него што наставите. diff --git a/config/locales/devise.tr.yml b/config/locales/devise.tr.yml index 66ca9b2816956a..e709d3fff156f4 100644 --- a/config/locales/devise.tr.yml +++ b/config/locales/devise.tr.yml @@ -12,6 +12,7 @@ tr: last_attempt: Hesabınız kilitlenmeden önce bir kez daha denemeniz gerekir. locked: Hesabınız kilitlendi. not_found_in_database: Geçersiz %{authentication_keys} ya da parola. + omniauth_user_creation_failure: Bu kimlik için hesap oluşturmada hata. pending: Hesabınız hala inceleniyor. timeout: Oturum süreniz sona erdi. Lütfen devam etmek için tekrar giriş yapınız. unauthenticated: Devam etmeden önce oturum açmanız veya kayıt olmanız gerek. diff --git a/config/locales/devise.uk.yml b/config/locales/devise.uk.yml index 3b3883fa9c9d63..65e89a274f953c 100644 --- a/config/locales/devise.uk.yml +++ b/config/locales/devise.uk.yml @@ -12,6 +12,7 @@ uk: last_attempt: У вас залишилась ще одна спроба, після якої ваш обліковий запис буде заблоковано. locked: Ваш обліковий запис заблоковано. not_found_in_database: Неправильний %{authentication_keys} або пароль. + omniauth_user_creation_failure: Помилка створення облікового запису для цієї особи. pending: Ваш обліковий запис ще перебуває на розгляді. timeout: Час сеансу минув. Будь ласка, увійдіть знову, щоб продовжити. unauthenticated: Щоб продовжити, увійдіть або зареєструйтеся. diff --git a/config/locales/devise.zh-CN.yml b/config/locales/devise.zh-CN.yml index 9b4b3ae2039c50..3eb722b96187be 100644 --- a/config/locales/devise.zh-CN.yml +++ b/config/locales/devise.zh-CN.yml @@ -12,6 +12,7 @@ zh-CN: last_attempt: 你只有最后一次尝试机会,若未通过,帐号将被锁定。 locked: 你的账户已被锁定。 not_found_in_database: "%{authentication_keys}或密码错误。" + omniauth_user_creation_failure: 为此身份创建账户时出错。 pending: 你的账号仍在审核中。 timeout: 你的会话已过期。请重新登录再继续操作。 unauthenticated: 继续操作前请注册或者登录。 diff --git a/config/locales/devise.zh-HK.yml b/config/locales/devise.zh-HK.yml index 7f728bf0adc8fc..a2620a8e4a98f3 100644 --- a/config/locales/devise.zh-HK.yml +++ b/config/locales/devise.zh-HK.yml @@ -12,6 +12,7 @@ zh-HK: last_attempt: 若你再一次嘗試失敗,我們將鎖定你的帳號,以策安全。 locked: 你的帳號已被鎖定。 not_found_in_database: 不正確的%{authentication_keys}或密碼。 + omniauth_user_creation_failure: 為此身份建立帳號時出錯。 pending: 你的帳號仍在審核中 timeout: 你的登入階段已經過期,請重新登入以繼續使用。 unauthenticated: 你必須先登入或登記,以繼續使用。 diff --git a/config/locales/devise.zh-TW.yml b/config/locales/devise.zh-TW.yml index 06438971a794a1..7ead831e4f75aa 100644 --- a/config/locales/devise.zh-TW.yml +++ b/config/locales/devise.zh-TW.yml @@ -12,6 +12,7 @@ zh-TW: last_attempt: 帳號鎖定前,您還有最後一次嘗試機會。 locked: 已鎖定您的帳號。 not_found_in_database: 無效的 %{authentication_keys} 或密碼。 + omniauth_user_creation_failure: 以此身分新增帳號時發生錯誤。 pending: 您的帳號仍在審核中。 timeout: 登入階段逾時。請重新登入以繼續。 unauthenticated: 您必須先登入或註冊才能繼續使用。 diff --git a/config/locales/doorkeeper.kab.yml b/config/locales/doorkeeper.kab.yml index fe1a8d9c50da34..d7f8904a35e9b1 100644 --- a/config/locales/doorkeeper.kab.yml +++ b/config/locales/doorkeeper.kab.yml @@ -36,7 +36,7 @@ kab: application: Asnas callback_url: URL n tririt n wawal delete: Kkes - empty: Ulac γur-ek·em isnasen. + empty: Ulac ɣur-k·m isnasen. name: Isem new: Asnas amaynut show: Ẓer @@ -57,7 +57,7 @@ kab: new: title: Tlaq tsiregt show: - title: Nγel tangalt n wurag sakkin senteḍ-itt deg usnas. + title: Nɣel tangalt n wurag sakkin senteḍ-itt deg usnas. authorized_applications: buttons: revoke: Ḥwi @@ -113,13 +113,13 @@ kab: read:notifications: ẓer tilγa-ik read:reports: ẓer ineqqisen-ik·im read:search: anadi deg umkan-ik·im - read:statuses: ẓer meṛṛa tisuffaγ + read:statuses: ẓer meṛṛa tisuffaɣ write: beddel meṛṛa isefka n umiḍan-ik write:accounts: ẓreg amaγnu-ik write:blocks: seḥbes imiḍanen d tγula - write:bookmarks: ad yernu tisuffγin γer ticraḍ + write:bookmarks: ad yernu tisuffaɣ ɣer ticraḍ write:filters: rnu-d imsizedgen write:follows: ḍfeṛ imdanen write:lists: ad yesnulfu tibdarin - write:media: ad yessali ifayluyen n teγwalt + write:media: ad yessali ifuyla n umidya write:notifications: sfeḍ tilɣa-k·m diff --git a/config/locales/ie.yml b/config/locales/ie.yml index a8287da5338735..7ab7f953bec191 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -1793,6 +1793,12 @@ ie: extra: It es ja pret a descargar! subject: Tui archive es pret por descargar title: Descargar archive + failed_2fa: + details: 'Vi li detallies del prova de intrar:' + explanation: Alqui provat accesser tui conto ma usat un ínvalid duesim factor de autentication. + further_actions_html: Si it ne esset tu, noi recomanda que tu strax %{action} nam li conto posse esser compromisset. + subject: Falliment de autentication de duesim factor + title: Fallit autentication de duesim factor suspicious_sign_in: change_password: changear tui passa-parol details: 'Vi li detallies del apertion de session:' diff --git a/config/locales/kab.yml b/config/locales/kab.yml index 66aeafde603aca..bf574fc016b159 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -5,7 +5,7 @@ kab: contact_missing: Ur yettusbadu ara contact_unavailable: Wlac hosted_on: Maṣṭudun yersen deg %{domain} - title: Γef + title: Ɣef accounts: follow: Ḍfeṛ followers: @@ -15,9 +15,9 @@ kab: last_active: armud aneggaru nothing_here: Ulac kra da! posts: - one: Tajewwiqt - other: Tijewwiqin - posts_tab_heading: Tijewwiqin + one: Tasuffeɣt + other: Tisuffaɣ + posts_tab_heading: Tisuffaɣ admin: account_actions: action: Eg tigawt @@ -47,7 +47,7 @@ kab: disable_two_factor_authentication: Gdel 2FA disabled: Yensa display_name: Isem ara d-yettwaskanen - domain: Taγult + domain: Taɣult edit: Ẓreg email: Imayl email_status: Addad n imayl @@ -111,7 +111,7 @@ kab: targeted_reports: Yettwazen uneqqis sɣur wiyaḍ silence: Sgugem silenced: Yettwasgugem - statuses: Tisuffɣin + statuses: Tisuffaɣ subscribe: Jerred suspended: Yeḥbes title: Imiḍanen @@ -203,22 +203,22 @@ kab: announcements: destroyed_msg: Tamselɣut tettwakkes akken iwata! edit: - title: Ẓreg ulγu - empty: Ulac kra n ulγuyen. + title: Ẓreg ulɣu + empty: Ulac kra n yilɣa yettwafen. live: Srid new: - create: Rnu-d ulγu - title: Ulγu amaynut + create: Snlufu-d ulɣu + title: Ulɣu amaynut publish: Sufeɣ published_msg: Tamselɣut tettwasufeɣ-d akken iwata! scheduled_for: Yettusɣiwsen i %{time} scheduled_msg: Tamselɣut tettusɣiwes i usufeɣ! - title: Ulγuyen + title: Ilɣa custom_emojis: assign_category: Efk taggayt - by_domain: Taγult + by_domain: Taɣult copied_msg: Takna tadigant n imuji yettwarna-d mebla ugur - copy: Nγel + copy: Nɣel create_new_category: Rnu-d taggayt tamaynut created_msg: Imuji yettwarna-d mebla ugur! delete: Kkes @@ -229,7 +229,7 @@ kab: enable: Rmed enabled: Yermed enabled_msg: Imuji yermed mebla ugur - list: Umuγ + list: Tabdart new: title: Timerna n imuji udmawan amaynut overwrite: Semselsi @@ -256,7 +256,7 @@ kab: add_new: Rni iḥder amaynut n taɣult confirm_suspension: cancel: Sefsex - domain: Taγult + domain: Taɣult export: Sifeḍ import: Kter new: @@ -274,9 +274,9 @@ kab: email_domain_blocks: add_new: Rnu amaynut delete: Kkes - domain: Taγult + domain: Taɣult new: - create: Rnu taγult + create: Rnu taɣult title: Timerna n taɣult tamaynut n imayl ɣer tebdart taberkant title: Tabdart taberkant n imayl follow_recommendations: @@ -286,8 +286,8 @@ kab: instances: back_to_all: Akk back_to_limited: Ɣur-s talast - back_to_warning: Γur-wat - by_domain: Taγult + back_to_warning: Ɣur-wat + by_domain: Taɣult content_policies: policy: Tasertit delivery: @@ -306,7 +306,7 @@ kab: private_comment: Awennit uslig public_comment: Awennit azayez title: Tamatut - total_blocked_by_us: Ttwasḥebsen sγur-neγ + total_blocked_by_us: Ttwasḥebsen sɣur-neɣ total_followed_by_them: Ṭtafaṛen-t total_followed_by_us: Neṭṭafaṛ-it total_reported: Ineqqisen fell-asen @@ -354,12 +354,15 @@ kab: other: "%{count} n timawin" action_taken_by: Tigawt yettwaṭṭfen sɣur are_you_sure: Tetḥaq-eḍ? + cancel: Sefsex category: Taggayt comment: none: Ula yiwen confirm: Sentem + delete_and_resolve: Kkes tisuffaɣ mark_as_resolved: Creḍ-it yefra mark_as_unresolved: Creḍ-it ur yefra ara + no_one_assigned: Ula yiwen notes: create: Rnu tazmilt create_and_resolve: Fru s tamawt @@ -390,16 +393,16 @@ kab: title: Ilugan n uqeddac settings: about: - title: Γef + title: Ɣef appearance: title: Udem discovery: - profile_directory: Akaram n imaγnuten + profile_directory: Akaram n imaɣnuten trends: Ayen mucaɛen domain_blocks: all: I medden akk - disabled: Γef ula yiwen - users: Γef yimseqdacen idiganen i yeqqnen + disabled: Ɣef ula yiwen + users: Ɣef yimseqdacen idiganen i yeqqnen registrations: title: Ajerred registrations_mode: @@ -408,19 +411,26 @@ kab: open: Zemren akk ad jerden site_uploads: delete: Kkes afaylu yulin + software_updates: + documentation_link: Issin ugar statuses: application: Asnas - back_to_account: Tuγalin γer usebter n umiḍan + back_to_account: Tuɣalin ɣer usebter n umiḍan deleted: Yettwakkes favourites: Imenyafen language: Tutlayt media: - title: Taγwalt - title: Tisuffiγin n umiḍan - with_media: S taγwalt + title: Amidya + title: Tisuffaɣ n umiḍan + trending: Ayen mucaɛen + visibility: Abani + with_media: S umidya title: Tadbelt trends: allow: Sireg + statuses: + title: Tisuffaɣ mucaɛen + trending: Ayen mucaɛen warning_presets: add_new: Rnu amaynut delete: Kkes @@ -431,7 +441,11 @@ kab: new_report: body: "%{reporter} yettwazen ɣef %{target}" subject: Aneqqis amaynut i %{instance} (#%{id}) + new_trends: + new_trending_statuses: + title: Tisuffaɣ mucaɛen appearance: + advanced_web_interface: Agrudem n web leqqayen discovery: Asnirem localization: guide_link: https://crowdin.com/project/mastodon @@ -448,6 +462,8 @@ kab: your_token: Ajiṭun-ik·im n unekcum auth: apply_for_account: Suter amiḍan + confirmations: + welcome_title: Ansuf yessek·em, %{name}! delete_account: Kkes amiḍan description: prefix_invited_by_user: "@%{name} inced-ik·ikem ad ternuḍ ɣer uqeddac-a n Mastodon!" @@ -455,9 +471,11 @@ kab: forgot_password: Tettud awal-ik uffir? log_in_with: Qqen s login: Qqen - logout: Ffeγ - migrate_account: Gujj γer umiḍan nniḍen - or_log_in_with: Neγ eqqen s + logout: Ffeɣ + migrate_account: Gujj ɣer umiḍan nniḍen + or_log_in_with: Neɣ eqqen s + progress: + confirm: Sentem imayl providers: cas: CAS saml: SAML @@ -466,8 +484,11 @@ kab: reset_password: Wennez awal uffir rules: back: Tuɣalin - security: Taγellist + security: Taɣellist set_new_password: Egr-d awal uffir amaynut + sign_in: + preamble_html: Kcem ar %{domain} s inekcam-inek n tuqqna. Ma yella yezga-d umiḍan-ik deg uqeddac-nniḍen, ur tezmireḍ ara ad tkecmeḍ sya. + title: Akeččum ɣer %{domain} status: account_status: Addad n umiḍan use_security_key: Seqdec tasarut n teɣlist @@ -498,16 +519,21 @@ kab: warning: username_available: Isem-ik·im n useqdac ad yuɣal yella i tikkelt-nniḍen username_unavailable: Isem-ik·im n useqdac ad yeqqim ulac-it + disputes: + strikes: + status: 'Tasuffeɣt #%{id}' + title_actions: + none: Ɣur-wat errors: '500': - title: Asebter-ayi d arameγtu + title: Asebter-ayi d arameɣtu existing_username_validator: not_found_multiple: ur yezmir ara ad yaf %{usernames} exports: archive_takeout: date: Azemz download: Sider-d aḥraz-ik·im - size: Teγzi + size: Teɣzi bookmarks: Ticraḍ csv: CSV lists: Tibdarin @@ -516,8 +542,8 @@ kab: add_new: Rnu amaynut filters: contexts: - account: Imuγna - notifications: Tilγa + account: Imuɣna + notifications: Ilɣa thread: Idiwenniyen edit: title: Ẓreg amzizdig @@ -534,8 +560,10 @@ kab: remove: Kkes seg umsizdeg generic: all: Akk + cancel: Sefsex changes_saved_msg: Ttwaskelsen ibelliden-ik·im akken ilaq! - copy: Nγel + confirm: Sentem + copy: Nɣel delete: Kkes order_by: Sizwer s save_changes: Sekles ibeddilen @@ -575,7 +603,7 @@ kab: sign_in_token: tangalt n tɣellist n tansa imayl webauthn: tisura n tɣellist migrations: - acct: Ibeddel γer + acct: Ibeddel ɣer incoming_migrations: Tusiḍ-d seg umiḍan nniḍen proceed_with_move: Awid imeḍfaṛen-ik moderation: @@ -597,7 +625,7 @@ kab: reblog: subject: "%{name} yesselha addad-ik·im" notifications: - other_settings: Iγewwaṛen nniḍen n tilγa + other_settings: Iɣewwaṛen nniḍen n yilɣa number: human: decimal_units: @@ -611,11 +639,13 @@ kab: setup: Sbadu pagination: newer: Amaynut - next: Γer zdat + next: Ɣer zdat older: Aqbuṛ prev: Win iɛeddan preferences: other: Wiyaḍ + privacy: + privacy: Tabaḍnit privacy_policy: title: Tasertit tabaḍnit relationships: @@ -634,6 +664,7 @@ kab: browser: Iminig browsers: alipay: Alipay + blackberry: BlackBerry chrome: Chrome edge: Microsoft Edge electron: Electron @@ -648,37 +679,41 @@ kab: qq: Iminig QQ safari: Safari weibo: Weibo - current_session: Tiγimit tamirant + current_session: Tiɣimit tamirant + date: Azemz description: "%{browser} s %{platform}" ip: IP platforms: adobe_air: Adobe Air android: Android + blackberry: BlackBerry + chrome_os: ChromeOS firefox_os: Firefox OS ios: iOS + kai_os: KaiOS linux: Linux mac: macOS windows: Windows windows_mobile: Windows Mobile - windows_phone: Tiliγri Windows Phone + windows_phone: Tiliɣri Windows Phone revoke: Ḥwi title: Tiɣimiyin settings: account: Amiḍan - account_settings: Iγewwaṛen n umiḍan + account_settings: Iɣewwaṛen n umiḍan appearance: Udem authorized_apps: Isnasen yettussirgen - back: Uγal γer Maṣṭudun + back: Uɣal ɣer Maṣṭudun delete: Tukksa n umiḍan development: Taneflit - edit_profile: Ẓreg amaγnu + edit_profile: Ẓreg amaɣnu export: Taktert n yisefka import: Kter import_and_export: Taktert d usifeḍ migrate: Tunigin n umiḍan - notifications: Tilγa + notifications: Ilɣa preferences: Imenyafen - profile: Ameγnu + profile: Ameɣnu relationships: Imeḍfaṛen akked wid i teṭṭafaṛeḍ statuses_cleanup: Tukksa tawurmant n tsuffaɣ two_factor_authentication: Asesteb s snat n tarrayin @@ -745,22 +780,25 @@ kab: otp: Asnas n usesteb webauthn: Tisura n teɣlist user_mailer: + appeal_approved: + action: Iɣewwaṛen n umiḍan warning: categories: spam: Aspam title: disable: Amiḍan i igersen - none: Γur-wat + none: Ɣur-wat silence: Amiḍan yesɛa talast suspend: Amiḍan yettwaḥbas welcome: final_action: Bdu asuffeɣ full_handle: Tansa umiḍan-ik takemmalit - subject: Ansuf γer Maṣṭudun + subject: Ansuf ɣer Maṣṭudun title: Ansuf yessek·em, %{name}! users: signed_in_as: 'Teqqneḍ amzun d:' verification: + here_is_how: Ha-t-a amek verification: Asenqed webauthn_credentials: add: Rnu tasarut n teɣlist tamaynut diff --git a/config/locales/simple_form.kab.yml b/config/locales/simple_form.kab.yml index 1e1c52da24e37b..546336660c7327 100644 --- a/config/locales/simple_form.kab.yml +++ b/config/locales/simple_form.kab.yml @@ -12,7 +12,7 @@ kab: defaults: autofollow: Imdanen ara ijerrden s usnebgi-inek, ad k-ḍefṛen s wudem awurman email: Ad n-teṭṭfeḍ imayl i usentem - irreversible: Tijewwaqin i tessazedgeḍ ad ttwakksent i lebda, ula ma tekkseḍ imsizdeg-nni ar zdat + irreversible: Tisuffaɣ i tessazedgeḍ ad ttwakksent i lebda, ula ma tekkseḍ imsizdeg-nni ar zdat locale: Tutlayt n ugrudem, imaylen d tilγa password: Seqdec ma drus 8 n yisekkilen setting_display_media_default: Ffer teywalt yettwacreḍ d tanafrit @@ -69,12 +69,12 @@ kab: setting_display_media_show_all: Ssken kullec setting_hide_network: Ffer azetta-k·m setting_theme: Asental n wesmel - setting_use_pending_items: Askar aleγwayan + setting_use_pending_items: Askar aleɣwayan sign_in_token_attempt: Tangalt n tɣellist title: Azwel type: Anaw n uktar username: Isem n useqdac - username_or_email: Isem n useqdac neγ imal + username_or_email: Isem n useqdac neɣ imal whole_word: Awal akk featured_tag: name: Ahacṭag @@ -84,7 +84,7 @@ kab: invite: comment: Awennit invite_request: - text: Acimi tebγiḍ ad ternuḍ iman-ik? + text: Acimi tebɣiḍ ad ternuḍ iman-ik? ip_block: comment: Awennit ip: IP diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 3dd47312096656..460fd82dc08506 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -188,7 +188,7 @@ sq: create_user_role: Krijoni Rol demote_user: Zhgradoje Përdoruesin destroy_announcement: Fshije Lajmërimin - destroy_canonical_email_block: Fshi Bllokim El-esh + destroy_canonical_email_block: Fshi Bllokim Email-esh destroy_custom_emoji: Fshi Emotikon Vetjak destroy_domain_allow: Fshi Lejim Përkatësie destroy_domain_block: Fshi Bllokim Përkatësie @@ -283,7 +283,7 @@ sq: unsuspend_account_html: "%{name} hoqi pezullimin për llogarinë e %{target}" update_announcement_html: "%{name} përditësoi lajmërimin %{target}" update_custom_emoji_html: "%{name} përditësoi emoxhin %{target}" - update_domain_block_html: "%{name} përditësoi bllokimin e përkatësish për %{target}" + update_domain_block_html: "%{name} përditësoi bllokim përkatësish për %{target}" update_ip_block_html: "%{name} ndryshoi rregull për IP-në %{target}" update_status_html: "%{name} përditësoi gjendjen me %{target}" update_user_role_html: "%{name} ndryshoi rolin për %{target}" diff --git a/config/locales/th.yml b/config/locales/th.yml index 74fc1b26b72c94..b76f6992ad2c6c 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -452,7 +452,7 @@ th: title: นำเข้าการปิดกั้นโดเมน no_file: ไม่ได้เลือกไฟล์ follow_recommendations: - description_html: "คำแนะนำการติดตามช่วยให้ผู้ใช้ใหม่ค้นหาเนื้อหาที่น่าสนใจได้อย่างรวดเร็ว เมื่อผู้ใช้ไม่ได้โต้ตอบกับผู้อื่นมากพอที่จะสร้างคำแนะนำการติดตามส่วนบุคคล จะแนะนำบัญชีเหล่านี้แทน จะคำนวณคำแนะนำใหม่เป็นประจำทุกวันจากบัญชีต่าง ๆ ที่มีการมีส่วนร่วมล่าสุดสูงสุดและจำนวนผู้ติดตามในเซิร์ฟเวอร์สูงสุดสำหรับภาษาที่กำหนด" + description_html: "คำแนะนำการติดตามช่วยให้ผู้ใช้ใหม่ค้นหาเนื้อหาที่น่าสนใจได้อย่างรวดเร็ว เมื่อผู้ใช้ไม่ได้โต้ตอบกับผู้อื่นมากพอที่จะสร้างคำแนะนำการติดตามเฉพาะบุคคล จะแนะนำบัญชีเหล่านี้แทน จะคำนวณคำแนะนำใหม่เป็นประจำทุกวันจากบัญชีต่าง ๆ ที่มีการมีส่วนร่วมล่าสุดสูงสุดและจำนวนผู้ติดตามในเซิร์ฟเวอร์สูงสุดสำหรับภาษาที่กำหนด" language: สำหรับภาษา status: สถานะ suppress: ระงับคำแนะนำการติดตาม diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 03881075345afb..58d8dabb9bac97 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ def patch end def default_prerelease - 'alpha.2' + 'alpha.3' end def prerelease diff --git a/spec/controllers/admin/disputes/appeals_controller_spec.rb b/spec/controllers/admin/disputes/appeals_controller_spec.rb index f830c3b95c974c..d36523316746aa 100644 --- a/spec/controllers/admin/disputes/appeals_controller_spec.rb +++ b/spec/controllers/admin/disputes/appeals_controller_spec.rb @@ -30,21 +30,19 @@ end describe 'POST #approve' do + subject { post :approve, params: { id: appeal.id } } + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - before do - post :approve, params: { id: appeal.id } - end + it 'redirects back to the strike page and notifies target account about approved appeal', :sidekiq_inline do + subject - it 'unsuspends a suspended account' do - expect(target_account.reload.suspended?).to be false - end + expect(response) + .to redirect_to(disputes_strike_path(appeal.strike)) - it 'redirects back to the strike page' do - expect(response).to redirect_to(disputes_strike_path(appeal.strike)) - end + expect(target_account.reload) + .to_not be_suspended - it 'notifies target account about approved appeal', :sidekiq_inline do expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at))) @@ -52,17 +50,16 @@ end describe 'POST #reject' do + subject { post :reject, params: { id: appeal.id } } + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - before do - post :reject, params: { id: appeal.id } - end + it 'redirects back to the strike page and notifies target account about rejected appeal', :sidekiq_inline do + subject - it 'redirects back to the strike page' do - expect(response).to redirect_to(disputes_strike_path(appeal.strike)) - end + expect(response) + .to redirect_to(disputes_strike_path(appeal.strike)) - it 'notifies target account about rejected appeal', :sidekiq_inline do expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_rejected.subject', date: I18n.l(appeal.created_at))) diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index b663f55afacd51..dcbaf1fcbb78c9 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -57,11 +57,9 @@ post :create, params: { user: { email: 'pam_user1', password: '123456' } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to be_instance_of(User) end end @@ -71,11 +69,9 @@ post :create, params: { user: { email: 'pam_user1', password: 'WRONGPW' } } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email')) - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -92,11 +88,9 @@ post :create, params: { user: { email: user.email, password: '123456' } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -110,16 +104,16 @@ post :create, params: { user: { email: user.email, password: user.password } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end context 'when using a valid password on a previously-used account with a new IP address' do + subject { post :create, params: { user: { email: user.email, password: user.password } } } + let(:previous_ip) { '1.2.3.4' } let(:current_ip) { '4.3.2.1' } @@ -127,18 +121,17 @@ Fabricate(:login_activity, user: user, ip: previous_ip) allow(controller.request).to receive(:remote_ip).and_return(current_ip) user.update(current_sign_in_at: 1.month.ago) - post :create, params: { user: { email: user.email, password: user.password } } end - it 'redirects to home' do - expect(response).to redirect_to(root_path) - end + it 'logs the user in and sends suspicious email and redirects home', :sidekiq_inline do + subject - it 'logs the user in' do - expect(controller.current_user).to eq user - end + expect(response) + .to redirect_to(root_path) + + expect(controller.current_user) + .to eq user - it 'sends a suspicious sign-in mail', :sidekiq_inline do expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(user.email) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.suspicious_sign_in.subject')) @@ -150,11 +143,9 @@ post :create, params: { user: { email: user.email.upcase, password: user.password } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -164,11 +155,9 @@ post :create, params: { user: { email: user.email, password: 'wrongpw' } } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email')) - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -270,7 +259,7 @@ travel_to '2023-12-20T10:00:00Z' end - it 'does not log the user in' do + it 'does not log the user in, sets a flash message, and sends a suspicious sign in email', :sidekiq_inline do Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } expect(controller.current_user).to be_nil @@ -278,17 +267,10 @@ post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } - expect(controller.current_user).to be_nil - expect(flash[:alert]).to match I18n.t('users.rate_limited') - end - - it 'sends a suspicious sign-in mail', :sidekiq_inline do - Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do - post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } - expect(controller.current_user).to be_nil - end - - post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + expect(controller.current_user) + .to be_nil + expect(flash[:alert]) + .to match I18n.t('users.rate_limited') expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(user.email) @@ -301,11 +283,9 @@ post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -318,11 +298,9 @@ post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -332,11 +310,9 @@ post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -346,11 +322,9 @@ post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -417,15 +391,11 @@ post :create, params: { user: { credential: fake_credential } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'instructs the browser to redirect to home' do + it 'instructs the browser to redirect to home, logs the user in, and updates the sign count' do expect(body_as_json[:redirect_path]).to eq(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user - end - it 'updates the sign count' do expect(webauthn_credential.reload.sign_count).to eq(sign_count) end end diff --git a/spec/controllers/disputes/appeals_controller_spec.rb b/spec/controllers/disputes/appeals_controller_spec.rb index da2f86ade5efeb..d763068ebe8c67 100644 --- a/spec/controllers/disputes/appeals_controller_spec.rb +++ b/spec/controllers/disputes/appeals_controller_spec.rb @@ -10,19 +10,17 @@ let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } describe '#create' do + subject { post :create, params: params } + context 'with valid params' do let(:current_user) { Fabricate(:user) } let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } + let(:params) { { strike_id: strike.id, appeal: { text: 'Foo' } } } - before do - post :create, params: { strike_id: strike.id, appeal: { text: 'Foo' } } - end + it 'notifies staff about new appeal and redirects back to strike page', :sidekiq_inline do + subject - it 'notifies staff about new appeal', :sidekiq_inline do expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email]) - end - - it 'redirects back to the strike page' do expect(response).to redirect_to(disputes_strike_path(strike.id)) end end @@ -30,16 +28,12 @@ context 'with invalid params' do let(:current_user) { Fabricate(:user) } let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } + let(:params) { { strike_id: strike.id, appeal: { text: '' } } } - before do - post :create, params: { strike_id: strike.id, appeal: { text: '' } } - end + it 'does not send email and renders strike show page', :sidekiq_inline do + subject - it 'does not send email', :sidekiq_inline do expect(ActionMailer::Base.deliveries.size).to eq(0) - end - - it 'renders the strike show page' do expect(response).to render_template('disputes/strikes/show') end end diff --git a/spec/controllers/instance_actors_controller_spec.rb b/spec/controllers/instance_actors_controller_spec.rb index 36b9049fbcf3c4..be1eefa7b22747 100644 --- a/spec/controllers/instance_actors_controller_spec.rb +++ b/spec/controllers/instance_actors_controller_spec.rb @@ -13,17 +13,19 @@ end it 'returns http success with correct media type, headers, and session values' do - expect(response).to have_http_status(200) + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json'), + cookies: be_empty + ) - expect(response.media_type).to eq 'application/activity+json' - - expect(response.cookies).to be_empty - expect(response.headers['Set-Cookies']).to be_nil + expect(response.headers) + .to include('Cache-Control' => include('public')) + .and not_include('Set-Cookies') expect(session).to be_empty - expect(response.headers['Cache-Control']).to include 'public' - expect(body_as_json) .to include(:id, :type, :preferredUsername, :inbox, :publicKey, :inbox, :outbox, :url) end diff --git a/spec/features/captcha_spec.rb b/spec/features/captcha_spec.rb index 15c37eb463aebb..06c823adf258eb 100644 --- a/spec/features/captcha_spec.rb +++ b/spec/features/captcha_spec.rb @@ -19,12 +19,10 @@ # It presents the user with a captcha form expect(page).to have_title(I18n.t('auth.captcha_confirmation.title')) - # It does not confirm the user just yet - expect(user.reload.confirmed?).to be false - # It redirects to app and confirms user - click_on I18n.t('challenge.confirm') - expect(user.reload.confirmed?).to be true + expect { click_on I18n.t('challenge.confirm') } + .to change { user.reload.confirmed? }.from(false).to(true) + expect(page).to have_current_path(/\A#{client_app.confirmation_redirect_uri}/, url: true) # Browsers will generally reload the original page upon redirection @@ -32,8 +30,9 @@ visit "/auth/confirmation?confirmation_token=#{user.confirmation_token}&redirect_to_app=true" # It presents a page with a link to the app callback - expect(page).to have_content(I18n.t('auth.confirmations.registration_complete', domain: 'cb6e6126.ngrok.io')) - expect(page).to have_link(I18n.t('auth.confirmations.clicking_this_link'), href: client_app.confirmation_redirect_uri) + expect(page) + .to have_content(I18n.t('auth.confirmations.registration_complete', domain: 'cb6e6126.ngrok.io')) + .and have_link(I18n.t('auth.confirmations.clicking_this_link'), href: client_app.confirmation_redirect_uri) end end diff --git a/spec/helpers/json_ld_helper_spec.rb b/spec/helpers/json_ld_helper_spec.rb index 99857278a14c66..48550850274e01 100644 --- a/spec/helpers/json_ld_helper_spec.rb +++ b/spec/helpers/json_ld_helper_spec.rb @@ -56,15 +56,15 @@ describe '#fetch_resource' do context 'when the second argument is false' do it 'returns resource even if the retrieved ID and the given URI does not match' do - stub_request(:get, 'https://bob.test/').to_return body: '{"id": "https://alice.test/"}' - stub_request(:get, 'https://alice.test/').to_return body: '{"id": "https://alice.test/"}' + stub_request(:get, 'https://bob.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://alice.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' }) end it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do - stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://marvin.test/"}' - stub_request(:get, 'https://marvin.test/').to_return body: '{"id": "https://alice.test/"}' + stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://marvin.test/"}', headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://marvin.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource('https://mallory.test/', false)).to be_nil end @@ -72,7 +72,7 @@ context 'when the second argument is true' do it 'returns nil if the retrieved ID and the given URI does not match' do - stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://alice.test/"}' + stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource('https://mallory.test/', true)).to be_nil end end @@ -80,12 +80,12 @@ describe '#fetch_resource_without_id_validation' do it 'returns nil if the status code is not 200' do - stub_request(:get, 'https://host.test/').to_return status: 400, body: '{}' + stub_request(:get, 'https://host.test/').to_return(status: 400, body: '{}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource_without_id_validation('https://host.test/')).to be_nil end it 'returns hash' do - stub_request(:get, 'https://host.test/').to_return status: 200, body: '{}' + stub_request(:get, 'https://host.test/').to_return(status: 200, body: '{}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource_without_id_validation('https://host.test/')).to eq({}) end end diff --git a/spec/lib/activitypub/activity/announce_spec.rb b/spec/lib/activitypub/activity/announce_spec.rb index 8ad892975d13c5..b556bfd6c2ece3 100644 --- a/spec/lib/activitypub/activity/announce_spec.rb +++ b/spec/lib/activitypub/activity/announce_spec.rb @@ -35,7 +35,7 @@ context 'when sender is followed by a local account' do before do Fabricate(:account).follow!(sender) - stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json)) + stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) subject.perform end @@ -120,7 +120,7 @@ let(:object_json) { 'https://example.com/actor/hello-world' } before do - stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json)) + stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) end context 'when the relay is enabled' do diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index e4966cffa33f1f..dec17b916b803b 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -970,12 +970,15 @@ def activity_for_object(json) it 'creates an encrypted message' do encrypted_message = target_device.encrypted_messages.reload.first - expect(encrypted_message).to_not be_nil - expect(encrypted_message.from_device_id).to eq '1234' - expect(encrypted_message.from_account).to eq sender - expect(encrypted_message.type).to eq 1 - expect(encrypted_message.body).to eq 'Foo' - expect(encrypted_message.digest).to eq 'Foo123' + expect(encrypted_message) + .to be_present + .and have_attributes( + from_device_id: eq('1234'), + from_account: eq(sender), + type: eq(1), + body: eq('Foo'), + digest: eq('Foo123') + ) end it 'creates a message franking' do diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index 89916f9f500eee..1b9a13c38c2d62 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -91,20 +91,15 @@ end it 'saves media attachment with correct file metadata' do - expect(media.persisted?).to be true - expect(media.file).to_not be_nil - - # completes processing - expect(media.processing_complete?).to be true - - # sets type - expect(media.type).to eq 'image' - - # sets content type - expect(media.file_content_type).to eq content_type - - # sets file extension - expect(media.file_file_name).to end_with extension + expect(media) + .to be_persisted + .and be_processing_complete + .and have_attributes( + file: be_present, + type: eq('image'), + file_content_type: eq(content_type), + file_file_name: end_with(extension) + ) # Rack::Mime (used by PublicFileServerMiddleware) recognizes file extension expect(Rack::Mime.mime_type(extension, nil)).to eq content_type @@ -112,17 +107,23 @@ it 'saves media attachment with correct size metadata' do # strips original file name - expect(media.file_file_name).to_not start_with '600x400' - - # sets meta for original - expect(media.file.meta['original']['width']).to eq 600 - expect(media.file.meta['original']['height']).to eq 400 - expect(media.file.meta['original']['aspect']).to eq 1.5 - - # sets meta for thumbnail - expect(media.file.meta['small']['width']).to eq 588 - expect(media.file.meta['small']['height']).to eq 392 - expect(media.file.meta['small']['aspect']).to eq 1.5 + expect(media.file_file_name) + .to_not start_with '600x400' + + # sets meta for original and thumbnail + expect(media.file.meta.deep_symbolize_keys) + .to include( + original: include( + width: eq(600), + height: eq(400), + aspect: eq(1.5) + ), + small: include( + width: eq(588), + height: eq(392), + aspect: eq(1.5) + ) + ) end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 845335e87341e9..1baa3ccbf9c957 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -451,35 +451,32 @@ end describe '#mark_email_as_confirmed!' do - subject(:user) { Fabricate(:user, confirmed_at: confirmed_at) } + subject { user.mark_email_as_confirmed! } - before do - ActionMailer::Base.deliveries.clear - user.mark_email_as_confirmed! - end + let!(:user) { Fabricate(:user, confirmed_at: confirmed_at) } + + before { ActionMailer::Base.deliveries.clear } after { ActionMailer::Base.deliveries.clear } context 'when user is new' do let(:confirmed_at) { nil } - it 'confirms user' do - expect(user.confirmed_at).to be_present - end + it 'confirms user and delivers welcome email', :sidekiq_inline do + subject - it 'delivers mails', :sidekiq_inline do - expect(ActionMailer::Base.deliveries.count).to eq 2 + expect(user.confirmed_at).to be_present + expect(ActionMailer::Base.deliveries.count).to eq 1 end end context 'when user is not new' do let(:confirmed_at) { Time.zone.now } - it 'confirms user' do - expect(user.confirmed_at).to be_present - end + it 'confirms user but does not deliver welcome email' do + subject - it 'does not deliver mail' do + expect(user.confirmed_at).to be_present expect(ActionMailer::Base.deliveries.count).to eq 0 end end diff --git a/spec/requests/omniauth_callbacks_spec.rb b/spec/requests/omniauth_callbacks_spec.rb index b478ca1ce614f6..095535e48598e0 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -39,16 +39,35 @@ Fabricate(:user, email: 'user@host.example') end - it 'matches the existing user, creates an identity, and redirects to root path' do - expect { subject } - .to not_change(User, :count) - .and change(Identity, :count) - .by(1) - .and change(LoginActivity, :count) - .by(1) + context 'when ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH is set to true' do + around do |example| + ClimateControl.modify ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH: 'true' do + example.run + end + end + + it 'matches the existing user, creates an identity, and redirects to root path' do + expect { subject } + .to not_change(User, :count) + .and change(Identity, :count) + .by(1) + .and change(LoginActivity, :count) + .by(1) + + expect(Identity.find_by(user: User.last).uid).to eq('123') + expect(response).to redirect_to(root_path) + end + end - expect(Identity.find_by(user: User.last).uid).to eq('123') - expect(response).to redirect_to(root_path) + context 'when ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH is not set to true' do + it 'does not match the existing user or create an identity, and redirects to login page' do + expect { subject } + .to not_change(User, :count) + .and not_change(Identity, :count) + .and not_change(LoginActivity, :count) + + expect(response).to redirect_to(new_user_session_url) + end end end diff --git a/spec/services/activitypub/fetch_featured_collection_service_spec.rb b/spec/services/activitypub/fetch_featured_collection_service_spec.rb index b9e95b825f553c..dab204406bbb23 100644 --- a/spec/services/activitypub/fetch_featured_collection_service_spec.rb +++ b/spec/services/activitypub/fetch_featured_collection_service_spec.rb @@ -72,11 +72,11 @@ shared_examples 'sets pinned posts' do before do - stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known)) - stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined)) + stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known), headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404) - stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) - stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null)) + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null), headers: { 'Content-Type': 'application/activity+json' }) subject.call(actor, note: true, hashtag: false) end @@ -94,7 +94,7 @@ describe '#call' do context 'when the endpoint is a Collection' do before do - stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets pinned posts' @@ -111,7 +111,7 @@ end before do - stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets pinned posts' @@ -120,7 +120,7 @@ let(:items) { 'https://example.com/account/pinned/unknown-reachable' } before do - stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) subject.call(actor, note: true, hashtag: false) end @@ -147,7 +147,7 @@ end before do - stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets pinned posts' @@ -156,7 +156,7 @@ let(:items) { 'https://example.com/account/pinned/unknown-reachable' } before do - stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) subject.call(actor, note: true, hashtag: false) end diff --git a/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb b/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb index 071e4d92d59865..638278a10e5375 100644 --- a/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb +++ b/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb @@ -38,7 +38,7 @@ describe '#call' do context 'when the endpoint is a Collection' do before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets featured tags' @@ -46,7 +46,7 @@ context 'when the account already has featured tags' do before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) actor.featured_tags.create!(name: 'FoO') actor.featured_tags.create!(name: 'baz') @@ -67,7 +67,7 @@ end before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets featured tags' @@ -88,7 +88,7 @@ end before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets featured tags' diff --git a/spec/services/activitypub/fetch_remote_account_service_spec.rb b/spec/services/activitypub/fetch_remote_account_service_spec.rb index e7f6bb8dd83401..799a70d0916d3f 100644 --- a/spec/services/activitypub/fetch_remote_account_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_account_service_spec.rb @@ -38,7 +38,7 @@ before do actor[:inbox] = nil - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -54,7 +54,7 @@ let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -75,7 +75,7 @@ let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -98,7 +98,7 @@ let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -114,7 +114,7 @@ let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end diff --git a/spec/services/activitypub/fetch_remote_actor_service_spec.rb b/spec/services/activitypub/fetch_remote_actor_service_spec.rb index e622c7d4c30d84..4ce42ea5609f0c 100644 --- a/spec/services/activitypub/fetch_remote_actor_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_actor_service_spec.rb @@ -38,7 +38,7 @@ before do actor[:inbox] = nil - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -54,7 +54,7 @@ let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -75,7 +75,7 @@ let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -98,7 +98,7 @@ let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -114,7 +114,7 @@ let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end diff --git a/spec/services/activitypub/fetch_remote_key_service_spec.rb b/spec/services/activitypub/fetch_remote_key_service_spec.rb index 0b14da4f446e5f..478778cc9f5762 100644 --- a/spec/services/activitypub/fetch_remote_key_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_key_service_spec.rb @@ -50,7 +50,7 @@ end before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -59,7 +59,7 @@ context 'when the key is a sub-object from the actor' do before do - stub_request(:get, public_key_id).to_return(body: Oj.dump(actor)) + stub_request(:get, public_key_id).to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) end it 'returns the expected account' do @@ -71,7 +71,7 @@ let(:public_key_id) { 'https://example.com/alice-public-key.json' } before do - stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }))) + stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) end it 'returns the expected account' do @@ -84,7 +84,7 @@ let(:actor_public_key) { 'https://example.com/alice-public-key.json' } before do - stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }))) + stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) end it 'returns the nil' do diff --git a/spec/services/activitypub/fetch_replies_service_spec.rb b/spec/services/activitypub/fetch_replies_service_spec.rb index a76b996c20fcd6..8e1f606e26e794 100644 --- a/spec/services/activitypub/fetch_replies_service_spec.rb +++ b/spec/services/activitypub/fetch_replies_service_spec.rb @@ -58,7 +58,7 @@ context 'when passing the URL to the collection' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it 'spawns workers for up to 5 replies on the same server' do @@ -93,7 +93,7 @@ context 'when passing the URL to the collection' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it 'spawns workers for up to 5 replies on the same server' do @@ -132,7 +132,7 @@ context 'when passing the URL to the collection' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it 'spawns workers for up to 5 replies on the same server' do diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 53cbaf4cc1aaaa..67f2f27276537d 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -218,7 +218,8 @@ def poll_option_json(name, votes) end it 'does not update the text, spoiler_text or edited_at' do - expect { subject.call(status, json, json) }.to_not(change { s = status.reload; [s.text, s.spoiler_text, s.edited_at] }) + expect { subject.call(status, json, json) } + .to_not(change { status.reload.attributes.slice('text', 'spoiler_text', 'edited_at').values }) end end diff --git a/spec/services/activitypub/synchronize_followers_service_spec.rb b/spec/services/activitypub/synchronize_followers_service_spec.rb index c9a513e24b7c3b..f62376ab95b24e 100644 --- a/spec/services/activitypub/synchronize_followers_service_spec.rb +++ b/spec/services/activitypub/synchronize_followers_service_spec.rb @@ -60,7 +60,7 @@ describe '#call' do context 'when the endpoint is a Collection of actor URIs' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'synchronizes followers' @@ -77,7 +77,7 @@ end before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'synchronizes followers' @@ -98,7 +98,7 @@ end before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'synchronizes followers' diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index d10a82607e009b..acbebc5056b794 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -32,27 +32,27 @@ let!(:future) { Time.now.utc + 2.hours } let!(:previous_status) { Fabricate(:status, account: account) } - it 'schedules a status' do - status = subject.call(account, text: 'Hi future!', scheduled_at: future) - expect(status).to be_a ScheduledStatus - expect(status.scheduled_at).to eq future - expect(status.params['text']).to eq 'Hi future!' - end - - it 'does not immediately create a status' do + it 'schedules a status for future creation and does not create one immediately' do media = Fabricate(:media_attachment, account: account) status = subject.call(account, text: 'Hi future!', media_ids: [media.id], scheduled_at: future) - expect(status).to be_a ScheduledStatus - expect(status.scheduled_at).to eq future - expect(status.params['text']).to eq 'Hi future!' - expect(status.params['media_ids']).to eq [media.id] + expect(status) + .to be_a(ScheduledStatus) + .and have_attributes( + scheduled_at: eq(future), + params: include( + 'text' => eq('Hi future!'), + 'media_ids' => contain_exactly(media.id) + ) + ) expect(media.reload.status).to be_nil expect(Status.where(text: 'Hi future!')).to_not exist end - it 'does not change statuses count' do - expect { subject.call(account, text: 'Hi future!', scheduled_at: future, thread: previous_status) }.to_not(change { [account.statuses_count, previous_status.replies_count] }) + it 'does not change statuses_count of account or replies_count of thread previous status' do + expect { subject.call(account, text: 'Hi future!', scheduled_at: future, thread: previous_status) } + .to not_change { account.statuses_count } + .and(not_change { previous_status.replies_count }) end end diff --git a/spec/validators/blacklisted_email_validator_spec.rb b/spec/validators/blacklisted_email_validator_spec.rb index 6292f0737ed757..86760df2e7f4b0 100644 --- a/spec/validators/blacklisted_email_validator_spec.rb +++ b/spec/validators/blacklisted_email_validator_spec.rb @@ -4,7 +4,7 @@ RSpec.describe BlacklistedEmailValidator do describe '#validate' do - subject { described_class.new.validate(user); errors } + subject { described_class.new.validate(user) } let(:user) { instance_double(User, email: 'info@mail.com', sign_up_ip: '1.2.3.4', errors: errors) } let(:errors) { instance_double(ActiveModel::Errors, add: nil) } @@ -18,7 +18,8 @@ let(:blocked_email) { true } it 'adds error' do - described_class.new.validate(user) + subject + expect(errors).to have_received(:add).with(:email, :blocked).once end end @@ -27,7 +28,8 @@ let(:blocked_email) { false } it 'does not add errors' do - described_class.new.validate(user) + subject + expect(errors).to_not have_received(:add) end @@ -39,7 +41,8 @@ end it 'adds error' do - described_class.new.validate(user) + subject + expect(errors).to have_received(:add).with(:email, :taken).once end end diff --git a/spec/workers/activitypub/fetch_replies_worker_spec.rb b/spec/workers/activitypub/fetch_replies_worker_spec.rb index ff4d049a269ed9..2d080e286ecc98 100644 --- a/spec/workers/activitypub/fetch_replies_worker_spec.rb +++ b/spec/workers/activitypub/fetch_replies_worker_spec.rb @@ -21,7 +21,7 @@ describe 'perform' do it 'performs a request if the collection URI is from the same host' do - stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json) + stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json, headers: { 'Content-Type': 'application/activity+json' }) subject.perform(status.id, 'https://example.com/statuses_replies/1') expect(a_request(:get, 'https://example.com/statuses_replies/1')).to have_been_made.once end