diff --git a/Gemfile.lock b/Gemfile.lock
index 38e189a21b..ee5f481e34 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -537,7 +537,7 @@ GEM
opentelemetry-registry (~> 0.1)
opentelemetry-instrumentation-concurrent_ruby (0.23.1)
opentelemetry-instrumentation-base (~> 0.24)
- opentelemetry-instrumentation-excon (0.25.1)
+ opentelemetry-instrumentation-excon (0.25.2)
opentelemetry-instrumentation-base (~> 0.24)
opentelemetry-instrumentation-faraday (0.29.1)
opentelemetry-instrumentation-base (~> 0.24)
@@ -620,7 +620,7 @@ GEM
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.8.1)
- rack (3.2.2)
+ rack (3.2.3)
rack-attack (6.7.0)
rack (>= 1.0, < 4)
rack-cors (3.0.0)
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 255b41e871..92dd5014db 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -172,7 +172,7 @@
"column.domain_blocks": "Blokerede domæner",
"column.edit_list": "Redigér liste",
"column.favourites": "Favoritter",
- "column.firehose": "Live feeds",
+ "column.firehose": "Aktuelt",
"column.follow_requests": "Følgeanmodninger",
"column.home": "Hjem",
"column.list_members": "Håndtér listemedlemmer",
@@ -574,8 +574,8 @@
"navigation_bar.follows_and_followers": "Følges og følgere",
"navigation_bar.import_export": "Import og eksport",
"navigation_bar.lists": "Lister",
- "navigation_bar.live_feed_local": "Live feed (lokalt)",
- "navigation_bar.live_feed_public": "Live feed (offentligt)",
+ "navigation_bar.live_feed_local": "Aktuelt (lokalt)",
+ "navigation_bar.live_feed_public": "Aktuelt (offentligt)",
"navigation_bar.logout": "Log af",
"navigation_bar.moderation": "Moderering",
"navigation_bar.more": "Mere",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 0cc8b5b2f4..c1d848ee07 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -257,8 +257,8 @@
"confirmations.revoke_quote.confirm": "Beitrag entfernen",
"confirmations.revoke_quote.message": "Diese Aktion kann nicht rückgängig gemacht werden.",
"confirmations.revoke_quote.title": "Beitrag entfernen?",
- "confirmations.unblock.confirm": "Nicht mehr blockieren",
- "confirmations.unblock.title": "{name} nicht mehr blockieren?",
+ "confirmations.unblock.confirm": "Entsperren",
+ "confirmations.unblock.title": "{name} entsperren?",
"confirmations.unfollow.confirm": "Entfolgen",
"confirmations.unfollow.title": "{name} entfolgen?",
"confirmations.withdraw_request.confirm": "Anfrage zurückziehen",
diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json
index 092e0f6526..cf8d3e2bec 100644
--- a/app/javascript/mastodon/locales/ku.json
+++ b/app/javascript/mastodon/locales/ku.json
@@ -27,6 +27,7 @@
"account.direct": "Bi taybetî qale @{name} bike",
"account.disable_notifications": "Êdî min agahdar neke gava @{name} diweşîne",
"account.edit_profile": "Profîlê serrast bike",
+ "account.edit_profile_short": "Serrast bike",
"account.enable_notifications": "Min agahdar bike gava @{name} diweşîne",
"account.endorse": "Taybetiyên li ser profîl",
"account.featured.accounts": "Profîl",
diff --git a/app/javascript/mastodon/locales/nan.json b/app/javascript/mastodon/locales/nan.json
index d2bf7ed8b8..5d864eeddf 100644
--- a/app/javascript/mastodon/locales/nan.json
+++ b/app/javascript/mastodon/locales/nan.json
@@ -922,6 +922,7 @@
"status.quotes": "{count, plural, other {# 篇引用ê PO文}}",
"status.quotes.empty": "Iáu無lâng引用tsit篇PO文。Nā是有lâng引用,ē佇tsia顯示。.",
"status.quotes.local_other_disclaimer": "Hōo作者拒絕引用ê引文bē當顯示。",
+ "status.quotes.remote_other_disclaimer": "Kan-ta tuì {domain} 來ê引文tsiah保證佇tsia顯示。Hōo作者拒絕ê引文buē顯示。",
"status.read_more": "讀詳細",
"status.reblog": "轉送",
"status.reblog_or_quote": "轉送á是引用",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index f3cb42fb97..c11df5d0d2 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -243,6 +243,9 @@
"confirmations.redraft.message": "Určite chcete tento príspevok vymazať a prepísať? Prídete o jeho zdieľania a ohviezdičkovania a odpovede na pôvodný príspevok budú odlúčené.",
"confirmations.redraft.title": "Vymazať a prepísať príspevok?",
"confirmations.remove_from_followers.confirm": "Odstrániť nasledovateľa",
+ "confirmations.revoke_quote.title": "Vymazať príspevok?",
+ "confirmations.unblock.confirm": "Odblokovať",
+ "confirmations.unblock.title": "Odblokovať {name}?",
"confirmations.unfollow.confirm": "Zrušiť sledovanie",
"content_warning.hide": "Skryť príspevok",
"content_warning.show": "Aj tak zobraziť",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index f5e285fbeb..35e7250f0e 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -42,7 +42,7 @@
"account.follow": "跟隨",
"account.follow_back": "跟隨回去",
"account.follow_back_short": "跟隨回去",
- "account.follow_request": "要求跟隨您",
+ "account.follow_request": "要求跟隨",
"account.follow_request_cancel": "取消跟隨請求",
"account.follow_request_cancel_short": "取消",
"account.follow_request_short": "跟隨請求",
diff --git a/app/models/user.rb b/app/models/user.rb
index a6496b6ac1..13e902a06d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -180,6 +180,10 @@ class User < ApplicationRecord
def disable!
update!(disabled: true)
+
+ # This terminates all connections for the given account with the streaming
+ # server:
+ redis.publish("timeline:system:#{account.id}", Oj.dump(event: :kill))
end
def enable!
@@ -357,17 +361,22 @@ class User < ApplicationRecord
end
def reset_password!
+ # First, change password to something random, this revokes sessions and on-going access:
+ change_password!(SecureRandom.hex)
+
+ # Finally, send a reset password prompt to the user
+ send_reset_password_instructions
+ end
+
+ def change_password!(new_password)
# First, change password to something random and deactivate all sessions
transaction do
- update(password: SecureRandom.hex)
+ update(password: new_password)
session_activations.destroy_all
end
# Then, remove all authorized applications and connected push subscriptions
revoke_access!
-
- # Finally, send a reset password prompt to the user
- send_reset_password_instructions
end
protected
diff --git a/config/locales/ast.yml b/config/locales/ast.yml
index 81806695b5..e2bca6e8cb 100644
--- a/config/locales/ast.yml
+++ b/config/locales/ast.yml
@@ -326,6 +326,9 @@ ast:
all: A tol mundu
disabled: A naide
users: A los perfiles llocales
+ feed_access:
+ modes:
+ public: Tol mundu
registrations:
preamble: Controla quién pue crear una cuenta nel sirvidor.
title: Rexistros
diff --git a/config/locales/be.yml b/config/locales/be.yml
index a120dcefb5..ebbfb8bf6d 100644
--- a/config/locales/be.yml
+++ b/config/locales/be.yml
@@ -1669,6 +1669,13 @@ be:
expires_at: Дзее да
uses: Выкарыстанні
title: Запрасіць людзей
+ link_preview:
+ author_html: Ад %{name}
+ potentially_sensitive_content:
+ action: Націсніце, каб паказаць
+ confirm_visit: Вы ўпэўненыя, што хочаце адкрыць гэту спасылку?
+ hide_button: Схаваць
+ label: Патэнцыйна далікатны кантэнт
lists:
errors:
limit: Вы дасягнулі макс. колькасці спісаў
@@ -1985,6 +1992,9 @@ be:
other: "%{count} відэафайла"
boosted_from_html: Пашырыў уліковы запіс %{acct_link}
content_warning: 'Папярэджанне аб змесціве: %{warning}'
+ content_warnings:
+ hide: Схаваць допіс
+ show: Паказаць усё роўна
default_language: Такая, што і мова інтэрфэйсу
disallowed_hashtags:
few: 'змяшчае недазволеныя хэштэгі: %{tags}'
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 377ac4952d..0f8bb88cd3 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -1591,6 +1591,13 @@ da:
expires_at: Udløber
uses: Benyttelser
title: Invitér personer
+ link_preview:
+ author_html: Af %{name}
+ potentially_sensitive_content:
+ action: Klik for at vise
+ confirm_visit: Er du sikker på, at du vil åbne dette link?
+ hide_button: Skjul
+ label: Potentielt følsomt indhold
lists:
errors:
limit: Maks. listeantal nået
@@ -1901,6 +1908,9 @@ da:
other: "%{count} videoer"
boosted_from_html: Fremhævet fra %{acct_link}
content_warning: 'Indholdsadvarsel: %{warning}'
+ content_warnings:
+ hide: Skjul indlæg
+ show: Vis mere
default_language: Samme som UI-sproget
disallowed_hashtags:
one: 'indeholdte et ikke tilladt hashtag: %{tags}'
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 90b97335db..3f16ac94d9 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -1591,6 +1591,13 @@ de:
expires_at: Läuft ab
uses: Verwendungen
title: Einladungen
+ link_preview:
+ author_html: Von %{name}
+ potentially_sensitive_content:
+ action: Zum Anzeigen anklicken
+ confirm_visit: Möchtest du diesen Link wirklich öffnen?
+ hide_button: Ausblenden
+ label: Inhaltswarnung
lists:
errors:
limit: Du hast die maximale Anzahl an Listen erreicht
@@ -1901,6 +1908,9 @@ de:
other: "%{count} Videos"
boosted_from_html: Geteilt von %{acct_link}
content_warning: 'Inhaltswarnung: %{warning}'
+ content_warnings:
+ hide: Beitrag ausblenden
+ show: Beitrag anzeigen
default_language: Wie die Sprache des Webinterface
disallowed_hashtags:
one: 'enthält einen nicht-erlaubten Hashtag: %{tags}'
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 35f5fe2ff2..f5a72625f7 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -1591,6 +1591,13 @@ el:
expires_at: Λήγει
uses: Χρήσεις
title: Προσκάλεσε κόσμο
+ link_preview:
+ author_html: Από %{name}
+ potentially_sensitive_content:
+ action: Κάνε κλικ για εμφάνιση
+ confirm_visit: Σίγουρα θες να ανοίξεις αυτόν τον σύνδεσμο;
+ hide_button: Απόκρυψη
+ label: Δυνητικά ευαίσθητο περιεχόμενο
lists:
errors:
limit: Έχεις φτάσει το μέγιστο αριθμό λιστών
@@ -1901,6 +1908,9 @@ el:
other: "%{count} βίντεο"
boosted_from_html: Ενισχύθηκε από %{acct_link}
content_warning: 'Προειδοποίηση περιεχομένου: %{warning}'
+ content_warnings:
+ hide: Απόκρυψη ανάρτησης
+ show: Εμφάνιση περισσότερων
default_language: Ίδια με γλώσσα διεπαφής
disallowed_hashtags:
one: 'περιέχει μη επιτρεπτή ετικέτα: %{tags}'
diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml
index 8b58313c03..feded782ba 100644
--- a/config/locales/es-AR.yml
+++ b/config/locales/es-AR.yml
@@ -1591,6 +1591,13 @@ es-AR:
expires_at: Vence
uses: Usos
title: Invitar a gente
+ link_preview:
+ author_html: Por %{name}
+ potentially_sensitive_content:
+ action: Clic para mostrar
+ confirm_visit: "¿Está seguro de que querés abrir este enlace?"
+ hide_button: Ocultar
+ label: Contenido potencialmente sensible
lists:
errors:
limit: Alcanzaste el número máximo de listas
@@ -1901,6 +1908,9 @@ es-AR:
other: "%{count} videos"
boosted_from_html: Adherido desde %{acct_link}
content_warning: 'Advertencia de contenido: %{warning}'
+ content_warnings:
+ hide: Ocultar mensaje
+ show: Mostrar más
default_language: Igual que el idioma de la interface
disallowed_hashtags:
one: 'contenía una etiqueta no permitida: %{tags}'
diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml
index 1dde5faf22..0672b21bc4 100644
--- a/config/locales/es-MX.yml
+++ b/config/locales/es-MX.yml
@@ -1591,6 +1591,13 @@ es-MX:
expires_at: Expira
uses: Usos
title: Invitar a gente
+ link_preview:
+ author_html: Por %{name}
+ potentially_sensitive_content:
+ action: Pulsa para mostrar
+ confirm_visit: "¿Seguro que quieres abrir este enlace?"
+ hide_button: Ocultar
+ label: Contenido potencialmente sensible
lists:
errors:
limit: Has alcanzado la cantidad máxima de listas
@@ -1901,6 +1908,9 @@ es-MX:
other: "%{count} vídeos"
boosted_from_html: Impulsado desde %{acct_link}
content_warning: 'Alerta de contenido: %{warning}'
+ content_warnings:
+ hide: Ocultar publicación
+ show: Mostrar más
default_language: Igual que el idioma de la interfaz
disallowed_hashtags:
one: 'contenía una etiqueta no permitida: %{tags}'
diff --git a/config/locales/es.yml b/config/locales/es.yml
index b5c4eef3d1..15fd191ea4 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -1591,6 +1591,13 @@ es:
expires_at: Expira
uses: Usos
title: Invitar a gente
+ link_preview:
+ author_html: Por %{name}
+ potentially_sensitive_content:
+ action: Pulsa para mostrar
+ confirm_visit: "¿Seguro que quieres abrir este enlace?"
+ hide_button: Ocultar
+ label: Contenido potencialmente sensible
lists:
errors:
limit: Has alcanzado la cantidad máxima de listas
@@ -1901,6 +1908,9 @@ es:
other: "%{count} vídeos"
boosted_from_html: Impulsado desde %{acct_link}
content_warning: 'Alerta de contenido: %{warning}'
+ content_warnings:
+ hide: Ocultar publicación
+ show: Mostrar más
default_language: Igual que el idioma de la interfaz
disallowed_hashtags:
one: 'contenía una etiqueta no permitida: %{tags}'
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index eb6b143a91..7b19a0d820 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -1591,6 +1591,13 @@ fi:
expires_at: Vanhenee
uses: Käyttökertoja
title: Kutsu käyttäjiä
+ link_preview:
+ author_html: Tehnyt %{name}
+ potentially_sensitive_content:
+ action: Näytä napsauttamalla
+ confirm_visit: Haluatko varmasti avata tämän linkin?
+ hide_button: Piilota
+ label: Mahdollisesti arkaluonteista sisältöä
lists:
errors:
limit: Sinulla on enimmäismäärä listoja
@@ -1901,6 +1908,9 @@ fi:
other: "%{count} videota"
boosted_from_html: Tehosti lähteestä %{acct_link}
content_warning: 'Sisältövaroitus: %{warning}'
+ content_warnings:
+ hide: Piilota julkaisu
+ show: Näytä lisää
default_language: Sama kuin käyttöliittymän kieli
disallowed_hashtags:
one: 'sisälsi kielletyn aihetunnisteen: %{tags}'
diff --git a/config/locales/fo.yml b/config/locales/fo.yml
index dcddd66899..22ec7bbf25 100644
--- a/config/locales/fo.yml
+++ b/config/locales/fo.yml
@@ -1591,6 +1591,13 @@ fo:
expires_at: Rennir út
uses: Brúk
title: Bjóða fólki
+ link_preview:
+ author_html: Av %{name}
+ potentially_sensitive_content:
+ action: Klikka fyri at vísa
+ confirm_visit: Er tú vís/ur í, at tú vil lata hetta leinkið upp?
+ hide_button: Fjal
+ label: Tilfar, sum møguliga er viðkvæmt
lists:
errors:
limit: Tú hevur rokkið mesta talið av listum
diff --git a/config/locales/ga.yml b/config/locales/ga.yml
index 5790b4c58c..901a3a3940 100644
--- a/config/locales/ga.yml
+++ b/config/locales/ga.yml
@@ -1708,6 +1708,13 @@ ga:
expires_at: In éag
uses: Úsáidí
title: Tabhair cuireadh do dhaoine
+ link_preview:
+ author_html: Le %{name}
+ potentially_sensitive_content:
+ action: Cliceáil chun a thaispeáint
+ confirm_visit: An bhfuil tú cinnte gur mian leat an nasc seo a oscailt?
+ hide_button: Folaigh
+ label: Ábhar a d'fhéadfadh a bheith íogair
lists:
errors:
limit: Tá uaslíon na liostaí sroichte agat
@@ -2027,6 +2034,9 @@ ga:
two: "%{count} físeáin"
boosted_from_html: Molta ó %{acct_link}
content_warning: 'Rabhadh ábhair: %{warning}'
+ content_warnings:
+ hide: Folaigh an post
+ show: Taispeáin níos mó
default_language: Mar an gcéanna le teanga an chomhéadain
disallowed_hashtags:
few: 'bhí na Haischlib dícheadaithe: %{tags}'
diff --git a/config/locales/he.yml b/config/locales/he.yml
index f577d64366..3ea929f76c 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -1669,6 +1669,13 @@ he:
expires_at: פג תוקף ב-
uses: שימושים
title: הזמנת אנשים
+ link_preview:
+ author_html: מאת %{name}
+ potentially_sensitive_content:
+ action: לחץ להצגה
+ confirm_visit: האם להמשיך ליעד הקישור?
+ hide_button: להסתיר
+ label: תוכן שעלול להיות רגיש
lists:
errors:
limit: הגעת למספר הרשימות המירבי
@@ -1985,6 +1992,9 @@ he:
two: "%{count} סרטונים"
boosted_from_html: הודהד מ-%{acct_link}
content_warning: 'אזהרת תוכן: %{warning}'
+ content_warnings:
+ hide: להסתיר הודעה
+ show: הצג עוד
default_language: זהה לשפת ממשק
disallowed_hashtags:
many: 'מכיל את התגיות האסורות: %{tags}'
diff --git a/config/locales/is.yml b/config/locales/is.yml
index ba9a7680ac..39a2150fb5 100644
--- a/config/locales/is.yml
+++ b/config/locales/is.yml
@@ -1595,6 +1595,13 @@ is:
expires_at: Rennur út
uses: Afnot
title: Bjóða fólki
+ link_preview:
+ author_html: Frá %{name}
+ potentially_sensitive_content:
+ action: Smelltu til að birta
+ confirm_visit: Ertu viss um að þú viljir opna þennan tengil?
+ hide_button: Fela
+ label: Mögulega viðkvæmt efni
lists:
errors:
limit: Þú hefur náð hámarksfjölda lista
@@ -1905,6 +1912,9 @@ is:
other: "%{count} myndskeið"
boosted_from_html: Endurbirt frá %{acct_link}
content_warning: 'Aðvörun vegna efnis (CW): %{warning}'
+ content_warnings:
+ hide: Fela færslu
+ show: Sýna meira
default_language: Sama og tungumál viðmóts
disallowed_hashtags:
one: 'innihélt óleyfilegt myllumerki: %{tags}'
diff --git a/config/locales/nan.yml b/config/locales/nan.yml
index 5dbbcdac02..74d4fd813f 100644
--- a/config/locales/nan.yml
+++ b/config/locales/nan.yml
@@ -834,6 +834,10 @@ nan:
all: Kàu ta̍k ê lâng
disabled: 無kàu tó tsi̍t ê
users: Kàu ta̍k位登入ê用者
+ feed_access:
+ modes:
+ authenticated: Kan-ta hōo登入ê用者
+ public: Ta̍k lâng
registrations:
moderation_recommandation: 佇開放hōo ta̍k ê lâng註冊進前,請確認lí有夠額koh主動反應ê管理團隊!
preamble: 控制ē當佇lí ê服侍器註冊ê人。
@@ -992,6 +996,7 @@ nan:
notified_on_html: 佇 %{date} 通知ê用者
notify_users: 通知用者
preview:
+ explanation_html: Tsit封email ē送hōo tī %{date} 進前註冊 ê %{display_count} ê用者。Email ē包括下跤ê文字:
send_preview: Kā tāi先看ê內容寄kàu %{email}
send_to_all:
other: 寄出 %{display_count} 張電子phue
@@ -1014,6 +1019,7 @@ nan:
confirm_allow_provider: Lí kám確定beh允准所揀ê提供者?
confirm_disallow: Lí kám確定無愛允准所揀ê連結?
confirm_disallow_provider: Lí kám確定無愛允准所揀ê提供者?
+ description_html: Tsia是連結,現tsú時lí ê服侍器hōo通見ê用者大量分享ê。tse通幫tsān lí ê用者tshuē著tsit-má世間有siánn tāi誌。直kàu lí允准公開者,連結bē公開展示。lí通允准á是拒絕單ê連結。
disallow: 無愛允准連結
disallow_provider: 無愛允准提供者
no_link_selected: 因為無揀任何連結,所以lóng無改變
@@ -1028,6 +1034,7 @@ nan:
pending_review: Teh等審核
preview_card_providers:
allowed: Tsit ê提供者ê連結通刊tī趨勢
+ description_html: Tsiah ê域名來自定定受lí ê服侍器分享ê連結。連結bē變做公開趨勢,除非連結ê域名受允准。Lí ê允准(á是拒絕)擴展kàu kiánn域名。
rejected: Tsit ê提供者ê連結bē刊tī趨勢
title: 發布者
rejected: 拒絕ê
@@ -1038,6 +1045,7 @@ nan:
confirm_allow_account: Lí kám確定beh允准所揀ê口座?
confirm_disallow: Lí kám確定無愛允准所揀ê狀態?
confirm_disallow_account: Lí kám確定無愛允准所揀ê口座?
+ description_html: Tsiah ê是lí ê服侍器所知ê,tsit-má teh受tsē-tsē分享kap收藏ê PO文。PO文bē公開顯示,除非lí允准作者,而且作者允准in ê口座hőng推薦hōo別lâng。Lí通允准á是拒絕個別PO文。
disallow: 無允准PO文
disallow_account: 無允准作者
no_status_selected: 因為無揀任何趨勢PO文,所以lóng無改變
@@ -1050,6 +1058,42 @@ nan:
dashboard:
tag_accounts_measure: 無重複用
tag_languages_dimension: Tsia̍p用ê語言
+ tag_servers_dimension: 人氣服侍器
+ tag_servers_measure: 無kâng ê服侍器
+ tag_uses_measure: Lóng總使用
+ description_html: Tsiah ê是hashtag,tsit-má佇lí ê服侍器看見ê tsē-tsē PO文中出現。Tse通tsān lí ê用者tshuē著ta̍k家上tsē討論ê內容。除非lí核准,hashtag bē公開顯示。
+ listable: 通受建議
+ no_tag_selected: 因為無揀任何標簽,所以lóng無改變
+ not_listable: Bē當受建議
+ not_trendable: Bē刊tī趨勢
+ not_usable: Bē當用
+ peaked_on_and_decaying: 佇 %{date} 日上烘,tsit-má teh退火
+ title: 趨勢ê hashtag
+ trendable: 通刊tī趨勢
+ trending_rank: '趨勢 #%{rank}'
+ usable: Ē當用
+ usage_comparison: Tī kin-á日hōo %{today} ê lâng用,比較tsa-hng有 %{yesterday} ê
+ used_by_over_week:
+ other: 頂禮拜hōo %{count} 位用者用
+ title: 推薦kap趨勢
+ trending: 趨勢
+ username_blocks:
+ add_new: 加新ê
+ block_registrations: 封鎖註冊
+ comparison:
+ contains: 包含
+ equals: 等於
+ contains_html: 包含 %{string}
+ created_msg: 成功加添用者名規則
+ delete: Thâi掉
+ edit:
+ title: 編輯使用者號名規則
+ matches_exactly_html: 等於 %{string}
+ new:
+ create: 建立規則
+ title: 創造使用者號名規則
+ no_username_block_selected: 因為無揀任何使用者號名規則,所以lóng無改變
+ not_permitted: 無允准
scheduled_statuses:
too_soon: Tio̍h用未來ê日期。
statuses:
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index fad7cf91aa..2a814367cf 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -850,7 +850,7 @@ nl:
users: Aan ingelogde lokale gebruikers
feed_access:
modes:
- authenticated: Alleen geverifieerde gebruikers
+ authenticated: Alleen ingelogde gebruikers
public: Iedereen
registrations:
moderation_recommandation: Zorg ervoor dat je een adequaat en responsief moderatieteam hebt voordat je registraties voor iedereen openstelt!
@@ -911,7 +911,7 @@ nl:
status_title: Bericht van @%{name}
title: Accountberichten - @%{name}
trending: Trending
- view_publicly: In het openbaar bekijken
+ view_publicly: Openbaar bericht bekijken
visibility: Zichtbaarheid
with_media: Met media
strikes:
@@ -984,7 +984,7 @@ nl:
name: Naam
newest: Nieuwste
oldest: Oudste
- open: In het openbaar bekijken
+ open: Oorspronkelijk bericht bekijken
reset: Opnieuw
review: Status beoordelen
search: Zoeken
@@ -1591,6 +1591,13 @@ nl:
expires_at: Verloopt op
uses: Aantal keer te gebruiken
title: Mensen uitnodigen
+ link_preview:
+ author_html: Door %{name}
+ potentially_sensitive_content:
+ action: Klik om te tonen
+ confirm_visit: Ben je zeker dat je deze link wilt openen?
+ hide_button: Verberg
+ label: Mogelijk gevoelige inhoud
lists:
errors:
limit: Je hebt het maximum aantal lijsten bereikt
@@ -1901,6 +1908,9 @@ nl:
other: "%{count} video's"
boosted_from_html: Geboost van %{acct_link}
content_warning: 'Inhoudswaarschuwing: %{warning}'
+ content_warnings:
+ hide: Bericht verbergen
+ show: Meer tonen
default_language: Hetzelfde als de taal van de gebruikersomgeving
disallowed_hashtags:
one: 'bevatte een niet toegestane hashtag: %{tags}'
diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml
index e6c10a9c22..22e0f3fa70 100644
--- a/config/locales/simple_form.nl.yml
+++ b/config/locales/simple_form.nl.yml
@@ -283,12 +283,16 @@ nl:
content_cache_retention_period: Bewaartermijn voor externe inhoud
custom_css: Aangepaste CSS
favicon: Favicon
+ local_live_feed_access: Toegang tot openbare lokale berichten
+ local_topic_feed_access: Toegang tot overzicht met lokale hashtags en links
mascot: Aangepaste mascotte (legacy)
media_cache_retention_period: Bewaartermijn mediacache
min_age: Vereiste minimumleeftijd
peers_api_enabled: Lijst van bekende servers via de API publiceren
profile_directory: Gebruikersgids inschakelen
registrations_mode: Wie kan zich registreren
+ remote_live_feed_access: Toegang tot openbare berichten van andere servers
+ remote_topic_feed_access: Toegang tot overzicht met hashtags en links van andere servers
require_invite_text: Opgeven van een reden is verplicht
show_domain_blocks: Domeinblokkades tonen
show_domain_blocks_rationale: Redenen voor domeinblokkades tonen
diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml
index 15d9e09e29..a942a2d030 100644
--- a/config/locales/simple_form.sq.yml
+++ b/config/locales/simple_form.sq.yml
@@ -158,6 +158,10 @@ sq:
name: Emër publik për rolin, nëse roli është ujdisur të shfaqet si një stemë
permissions_as_keys: Përdoruesit me këtë rol do të mund të…
position: Role më të lartë vendosin zgjidhje përplasje në disa raste. Disa veprime mund të kryhen vetëm mbi role të një shkalle më të ulët
+ username_block:
+ allow_with_approval: Në vend të pengimit aty për aty të regjistrimit, regjistrime me përkim do të duan miratimin tuaj
+ comparison: Ju lutemi, mbani parasysh Problemin Scunthorpe, kur bllokohen përkime të pjesshme
+ username: Do të merret si përkim, pavarësisht shkrimit me të mëdha apo të vogla dhe pavarësisht homoglifesh të tilla si "4" për "a", ose "3" për "e"
webhook:
events: Përzgjidhni akte për dërgim
template: Hartoni ngarkesë tuajën JSON, duke përdorur ndërkëmbim ndryshoresh. Lëreni të zbrazët, për JSON-in parazgjedhje.
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index 3f1978f7c8..5a978ed666 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -1578,6 +1578,13 @@ sq:
expires_at: Skadon më
uses: Përdorime
title: Ftoni njerëz
+ link_preview:
+ author_html: Nga %{name}
+ potentially_sensitive_content:
+ action: Klikoni për shfaqje
+ confirm_visit: Jeni i sigurt se doni të hapet kjo lidhje?
+ hide_button: Fshihe
+ label: Lëndë potencalisht me spec
lists:
errors:
limit: Keni mbërritur në numrin maksimum të listave
@@ -1888,6 +1895,9 @@ sq:
other: "%{count} video"
boosted_from_html: Përforcuar nga %{acct_link}
content_warning: 'Sinjalizim lënde: %{warning}'
+ content_warnings:
+ hide: Fshihe postimin
+ show: Shfaq më tepër
default_language: Njësoj me gjuhën e ndërfaqes
disallowed_hashtags:
one: 'përmbante një hashtag të palejuar: %{tags}'
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index 0c470b29d1..f07a66d327 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -1901,6 +1901,9 @@ tr:
other: "%{count} videolar"
boosted_from_html: "%{acct_link} kişisinden yeniden paylaştı"
content_warning: 'İçerik uyarısı: %{warning}'
+ content_warnings:
+ hide: Gönderiyi gizle
+ show: Daha fazlasını göster
default_language: Arayüz diliyle aynı
disallowed_hashtags:
one: 'izin verilmeyen bir etiket içeriyordu: %{tags}'
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index d460f44468..b38035ab07 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -1552,6 +1552,13 @@ vi:
expires_at: Hết hạn
uses: Sử dụng
title: Mời bạn bè
+ link_preview:
+ author_html: Bởi %{name}
+ potentially_sensitive_content:
+ action: Nhấn để xem
+ confirm_visit: Bạn có chắc muốn mở liên kết này?
+ hide_button: Ẩn
+ label: Có khả năng là nội dung nhạy cảm
lists:
errors:
limit: Bạn đã đạt đến số lượng danh sách tối đa
@@ -1859,6 +1866,9 @@ vi:
other: "%{count} video"
boosted_from_html: Đã đăng lại từ %{acct_link}
content_warning: 'Cảnh báo nội dung: %{warning}'
+ content_warnings:
+ hide: Ẩn tút
+ show: Mở rộng
default_language: Giống giao diện
disallowed_hashtags:
other: 'chứa các hashtag bị cấm: %{tags}'
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 724f7287f5..60ab656e7d 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -1552,6 +1552,13 @@ zh-CN:
expires_at: 失效时间
uses: 已使用次数
title: 邀请用户
+ link_preview:
+ author_html: 来自 %{name}
+ potentially_sensitive_content:
+ action: 点击查看
+ confirm_visit: 您确定要打开此链接吗?
+ hide_button: 隐藏
+ label: 可能为敏感内容
lists:
errors:
limit: 你已达到列表数量的上限
@@ -1859,6 +1866,9 @@ zh-CN:
other: "%{count} 段视频"
boosted_from_html: 转嘟自 %{acct_link}
content_warning: 内容警告:%{warning}
+ content_warnings:
+ hide: 隐藏嘟文
+ show: 显示更多
default_language: 与界面显示语言相同
disallowed_hashtags:
other: 包含以下被禁止的话题:%{tags}
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index c5478d8a64..0a0c3a1ee5 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -1554,6 +1554,13 @@ zh-TW:
expires_at: 失效時間
uses: 已使用次數
title: 邀請使用者
+ link_preview:
+ author_html: 來自 %{name}
+ potentially_sensitive_content:
+ action: 點擊以顯示
+ confirm_visit: 您確定要開啟此連結嗎?
+ hide_button: 隱藏
+ label: 可能為敏感內容
lists:
errors:
limit: 您所建立之列表數量已達上限
@@ -1861,6 +1868,9 @@ zh-TW:
other: "%{count} 段影片"
boosted_from_html: 轉嘟自 %{acct_link}
content_warning: 內容警告: %{warning}
+ content_warnings:
+ hide: 隱藏嘟文
+ show: 顯示更多
default_language: 與介面語言相同
disallowed_hashtags:
other: 含有不得使用的標籤: %{tags}
diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb
index 1b33f56055..25e966bd8e 100644
--- a/lib/mastodon/cli/accounts.rb
+++ b/lib/mastodon/cli/accounts.rb
@@ -165,14 +165,17 @@ module Mastodon::CLI
user.role_id = nil
end
- password = SecureRandom.hex if options[:reset_password]
- user.password = password if options[:reset_password]
user.email = options[:email] if options[:email]
user.disabled = false if options[:enable]
user.disabled = true if options[:disable]
user.approved = true if options[:approve]
user.disable_two_factor! if options[:disable_2fa]
+ # Password changes are a little different, as we also need to ensure
+ # sessions, subscriptions, and access tokens are revoked after changing:
+ password = SecureRandom.hex if options[:reset_password]
+ user.change_password!(password) if options[:reset_password]
+
if user.save
user.confirm if options[:confirm]
diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb
index 111703a18b..927c6ca8de 100644
--- a/spec/lib/mastodon/cli/accounts_spec.rb
+++ b/spec/lib/mastodon/cli/accounts_spec.rb
@@ -361,11 +361,20 @@ RSpec.describe Mastodon::CLI::Accounts do
context 'with --reset-password option' do
let(:options) { { reset_password: true } }
+ let(:user) { Fabricate(:user, password: original_password) }
+ let(:original_password) { 'foobar12345' }
+ let(:new_password) { 'new_password12345' }
+
it 'returns a new password for the user' do
- allow(SecureRandom).to receive(:hex).and_return('new_password')
+ allow(SecureRandom).to receive(:hex).and_return(new_password)
+ allow(Account).to receive(:find_local).and_return(user.account)
+ allow(user).to receive(:change_password!).and_call_original
expect { subject }
- .to output_results('new_password')
+ .to output_results(new_password)
+
+ expect(user).to have_received(:change_password!).with(new_password)
+ expect(user.reload).to_not be_external_or_valid_password(original_password)
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index a9ab15a956..7088266b34 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -382,12 +382,15 @@ RSpec.describe User do
let(:current_sign_in_at) { Time.zone.now }
- before do
- user.disable!
- end
-
it 'disables user' do
+ allow(redis).to receive(:publish)
+
+ user.disable!
+
expect(user).to have_attributes(disabled: true)
+
+ expect(redis)
+ .to have_received(:publish).with("timeline:system:#{user.account.id}", Oj.dump(event: :kill)).once
end
end
diff --git a/spec/system/streaming/channel_subscriptions_spec.rb b/spec/system/streaming/channel_subscriptions_spec.rb
index 54e125c293..447ea64f22 100644
--- a/spec/system/streaming/channel_subscriptions_spec.rb
+++ b/spec/system/streaming/channel_subscriptions_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'rails_helper'
-require 'debug'
RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do
let(:application) { Fabricate(:application, confidential: false) }
@@ -15,6 +14,25 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do
streaming_client.close
end
+ context 'when the access token has insufficient scope to read statuses' do
+ let(:scopes) { 'profile' }
+
+ it 'cannot subscribe to the public:local channel' do
+ streaming_client.authenticate(access_token.token)
+
+ streaming_client.connect
+ streaming_client.subscribe('public:local')
+
+ # Receive the error back from the subscription attempt:
+ message = streaming_client.wait_for_message
+
+ expect(message).to include(
+ error: 'Access token does not have the required scopes',
+ status: 401
+ )
+ end
+ end
+
context 'when the access token has read scope' do
let(:scopes) { 'read' }
@@ -39,11 +57,52 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do
)
)
end
+
+ it 'can subscribing to the user:notifications channel' do
+ streaming_client.authenticate(access_token.token)
+
+ streaming_client.connect
+ streaming_client.subscribe('user:notification')
+
+ # We need to perform an action that triggers a notification as there is
+ # no positive acknowledgement of subscriptions:
+ first_status = PostStatusService.new.call(user_account, text: 'Test')
+ ReblogService.new.call(bob_account, first_status)
+
+ message = streaming_client.wait_for_message
+
+ expect(message).to include(
+ event: 'notification',
+ stream: ['user:notification']
+ )
+ end
end
- context 'when the access token cannot read notifications' do
+ context 'when the access token has read:statuses scope' do
let(:scopes) { 'read:statuses' }
+ it 'can subscribing to the public:local channel' do
+ streaming_client.authenticate(access_token.token)
+
+ streaming_client.connect
+ streaming_client.subscribe('public:local')
+
+ # We need to publish a status as there is no positive acknowledgement of
+ # subscriptions:
+ status = PostStatusService.new.call(bob_account, text: 'Hello @alice')
+
+ # And then we want to receive that status:
+ message = streaming_client.wait_for_message
+
+ expect(message).to include(
+ stream: be_an(Array).and(contain_exactly('public:local')),
+ event: 'update',
+ payload: include(
+ id: status.id.to_s
+ )
+ )
+ end
+
it 'cannot subscribing to the user:notifications channel' do
streaming_client.authenticate(access_token.token)
@@ -59,4 +118,27 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do
)
end
end
+
+ context 'when the access token has read:notifications scope' do
+ let(:scopes) { 'read:notifications' }
+
+ it 'can subscribing to the user:notifications channel' do
+ streaming_client.authenticate(access_token.token)
+
+ streaming_client.connect
+ streaming_client.subscribe('user:notification')
+
+ # We need to perform an action that triggers a notification as there is
+ # no positive acknowledgement of subscriptions:
+ first_status = PostStatusService.new.call(user_account, text: 'Test')
+ ReblogService.new.call(bob_account, first_status)
+
+ message = streaming_client.wait_for_message
+
+ expect(message).to include(
+ event: 'notification',
+ stream: ['user:notification']
+ )
+ end
+ end
end
diff --git a/spec/system/streaming/streaming_spec.rb b/spec/system/streaming/streaming_spec.rb
index c12bd1b18f..7370033890 100644
--- a/spec/system/streaming/streaming_spec.rb
+++ b/spec/system/streaming/streaming_spec.rb
@@ -74,4 +74,28 @@ RSpec.describe 'Streaming', :inline_jobs, :streaming do
expect(streaming_client.open?).to be(false)
end
end
+
+ context 'with a disabled user account' do
+ before do
+ user.disable!
+ end
+
+ it 'receives an 401 unauthorized error when trying to connect' do
+ streaming_client.connect
+
+ expect(streaming_client.status).to eq(401)
+ expect(streaming_client.open?).to be(false)
+ end
+ end
+
+ context 'when the user account is disabled whilst connected' do
+ it 'terminates the connection for the user' do
+ streaming_client.connect
+
+ user.disable!
+
+ expect(streaming_client.wait_for(:closed).code).to be(1000)
+ expect(streaming_client.open?).to be(false)
+ end
+ end
end
diff --git a/streaming/index.js b/streaming/index.js
index d53f4ffcd4..291c912ddd 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -78,17 +78,6 @@ const parseJSON = (json, req) => {
}
};
-const PUBLIC_CHANNELS = [
- 'public',
- 'public:media',
- 'public:local',
- 'public:local:media',
- 'public:remote',
- 'public:remote:media',
- 'hashtag',
- 'hashtag:local',
-];
-
// Used for priming the counters/gauges for the various metrics that are
// per-channel
const CHANNEL_NAMES = [
@@ -97,7 +86,14 @@ const CHANNEL_NAMES = [
'user:notification',
'list',
'direct',
- ...PUBLIC_CHANNELS
+ 'public',
+ 'public:media',
+ 'public:local',
+ 'public:local:media',
+ 'public:remote',
+ 'public:remote:media',
+ 'hashtag',
+ 'hashtag:local',
];
const startServer = async () => {
@@ -355,7 +351,7 @@ const startServer = async () => {
* @returns {Promise}
*/
const accountFromToken = async (token, req) => {
- const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token]);
+ const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL AND users.disabled IS FALSE LIMIT 1', [token]);
if (result.rows.length === 0) {
throw new AuthenticationError('Invalid access token');
@@ -434,12 +430,6 @@ const startServer = async () => {
const checkScopes = (req, logger, channelName) => new Promise((resolve, reject) => {
logger.debug(`Checking OAuth scopes for ${channelName}`);
- // When accessing public channels, no scopes are needed
- if (channelName && PUBLIC_CHANNELS.includes(channelName)) {
- resolve();
- return;
- }
-
// The `read` scope has the highest priority, if the token has it
// then it can access all streams
const requiredScopes = ['read'];