Compare commits

...

7 Commits

Author SHA1 Message Date
Matt Jankowski
c433a29371
Merge 372e0a423d into 9a2be25199 2025-09-05 09:07:27 +00:00
Claire
9a2be25199
Fix missing beforeUnload confirmation when a quote post is being authored (#36034) 2025-09-05 08:51:49 +00:00
Claire
279405f2a7
Fix incorrect change of unlisted source strings (#36033) 2025-09-05 08:34:14 +00:00
Claire
497bfbc483
Fix source string for visibility dropdown hint (#36031) 2025-09-05 08:14:34 +00:00
github-actions[bot]
dd6bd681ea
New Crowdin Translations (automated) (#36029)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-09-05 08:14:25 +00:00
Claire
0d93801bde
Fix missing beforeUnload confirmation when a poll is being authored (#36030) 2025-09-05 08:07:59 +00:00
Matt Jankowski
372e0a423d Convert to doorkeeper ORM mixin style for OAuth models 2025-09-02 11:00:04 -04:00
62 changed files with 294 additions and 185 deletions

View File

@ -4,7 +4,7 @@ class Api::V1::AppsController < Api::BaseController
skip_before_action :require_authenticated_user!
def create
@app = Doorkeeper::Application.create!(application_options)
@app = OAuth::Application.create!(application_options)
render json: @app, serializer: REST::CredentialApplicationSerializer
end

View File

@ -17,7 +17,7 @@ class OAuth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
def destroy
Web::PushSubscription.unsubscribe_for(params[:id], current_resource_owner)
Doorkeeper::Application.find_by(id: params[:id])&.close_streaming_sessions(current_resource_owner)
OAuth::Application.find_by(id: params[:id])&.close_streaming_sessions(current_resource_owner)
super
end

View File

@ -10,7 +10,7 @@ class Settings::ApplicationsController < Settings::BaseController
def show; end
def new
@application = Doorkeeper::Application.new(
@application = OAuth::Application.new(
redirect_uri: Doorkeeper.configuration.native_redirect_uri,
scopes: 'profile'
)
@ -59,6 +59,6 @@ class Settings::ApplicationsController < Settings::BaseController
end
def application_params
params.expect(doorkeeper_application: [:name, :redirect_uri, :website, scopes: []])
params.expect(oauth_application: [:name, :redirect_uri, :website, scopes: []])
end
end

View File

@ -92,8 +92,7 @@ const messages = defineMessages({
const mapStateToProps = state => ({
layout: state.getIn(['meta', 'layout']),
isComposing: state.getIn(['compose', 'is_composing']),
hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0,
hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0,
hasComposingContents: state.getIn(['compose', 'text']).trim().length !== 0 || state.getIn(['compose', 'media_attachments']).size > 0 || state.getIn(['compose', 'poll']) !== null || state.getIn(['compose', 'quoted_status_id']) !== null,
canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < state.getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments']),
firstLaunch: state.getIn(['settings', 'introductionVersion'], 0) < INTRODUCTION_VERSION,
newAccount: !state.getIn(['accounts', me, 'note']) && !state.getIn(['accounts', me, 'bot']) && state.getIn(['accounts', me, 'following_count'], 0) === 0 && state.getIn(['accounts', me, 'statuses_count'], 0) === 0,
@ -241,8 +240,7 @@ class UI extends PureComponent {
dispatch: PropTypes.func.isRequired,
children: PropTypes.node,
isComposing: PropTypes.bool,
hasComposingText: PropTypes.bool,
hasMediaAttachments: PropTypes.bool,
hasComposingContents: PropTypes.bool,
canUploadMore: PropTypes.bool,
intl: PropTypes.object.isRequired,
layout: PropTypes.string.isRequired,
@ -257,11 +255,11 @@ class UI extends PureComponent {
};
handleBeforeUnload = e => {
const { intl, dispatch, isComposing, hasComposingText, hasMediaAttachments } = this.props;
const { intl, dispatch, isComposing, hasComposingContents } = this.props;
dispatch(synchronouslySubmitMarkers());
if (isComposing && (hasComposingText || hasMediaAttachments)) {
if (isComposing && hasComposingContents) {
e.preventDefault();
// Setting returnValue to any string causes confirmation dialog.
// Many browsers no longer display this text to users,

View File

@ -29,6 +29,8 @@
"account.endorse": "Lakaat war-wel war ar profil",
"account.familiar_followers_one": "Heuilhet gant {name1}",
"account.familiar_followers_two": "Heuilhet gant {name1} ha {name2}",
"account.featured.accounts": "Profiloù",
"account.featured.hashtags": "Gerioù-klik",
"account.featured_tags.last_status_at": "Toud diwezhañ : {date}",
"account.featured_tags.last_status_never": "Embannadur ebet",
"account.follow": "Heuliañ",
@ -39,6 +41,7 @@
"account.followers_you_know_counter": "{counter} a anavezit",
"account.following": "Koumanantoù",
"account.follows.empty": "An implijer·ez-mañ na heul den ebet.",
"account.follows_you": "Ho heuilh",
"account.go_to_profile": "Gwelet ar profil",
"account.hide_reblogs": "Kuzh skignadennoù gant @{name}",
"account.in_memoriam": "E koun.",
@ -89,7 +92,10 @@
"alt_text_modal.done": "Graet",
"announcement.announcement": "Kemennad",
"annual_report.summary.followers.followers": "heulier",
"annual_report.summary.followers.total": "{count} en holl",
"annual_report.summary.highlighted_post.possessive": "{name}",
"annual_report.summary.most_used_app.most_used_app": "arload muiañ implijet",
"annual_report.summary.most_used_hashtag.most_used_hashtag": "ar gerioù-klik implijet ar muiañ",
"annual_report.summary.most_used_hashtag.none": "Hini ebet",
"annual_report.summary.new_posts.new_posts": "toudoù nevez",
"attachments_list.unprocessed": "(ket meret)",
@ -149,7 +155,7 @@
"compose.saved.body": "Enrollet.",
"compose_form.direct_message_warning_learn_more": "Gouzout hiroc'h",
"compose_form.encryption_warning": "Toudoù war Mastodon na vezont ket sifret penn-da-benn. Na rannit ket titouroù kizidik dre 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.hashtag_warning": "Ne vo ket listennet an toud-mañ dindan gerioù-klik ebet dre m'eo anlistennet. N'eus nemet an toudoù foran a c'hall bezañ klasket dre c'her-klik.",
"compose_form.lock_disclaimer": "N'eo ket {locked} ho kont. An holl a c'hal ho heuliañ evit gwelet ho toudoù prevez.",
"compose_form.lock_disclaimer.lock": "prennet",
"compose_form.placeholder": "Petra emaoc'h o soñjal e-barzh ?",
@ -168,6 +174,7 @@
"confirmations.block.confirm": "Stankañ",
"confirmations.delete.confirm": "Dilemel",
"confirmations.delete.message": "Ha sur oc'h e fell deoc'h dilemel an toud-mañ ?",
"confirmations.delete.title": "Dilemel an toud?",
"confirmations.delete_list.confirm": "Dilemel",
"confirmations.delete_list.message": "Ha sur eo hoc'h eus c'hoant da zilemel ar roll-mañ da vat ?",
"confirmations.delete_list.title": "Dilemel al listenn?",
@ -176,10 +183,14 @@
"confirmations.follow_to_list.title": "Heuliañ an implijer·ez?",
"confirmations.logout.confirm": "Digevreañ",
"confirmations.logout.message": "Ha sur oc'h e fell deoc'h digevreañ ?",
"confirmations.logout.title": "Digevreañ?",
"confirmations.mute.confirm": "Kuzhat",
"confirmations.redraft.confirm": "Diverkañ ha skrivañ en-dro",
"confirmations.unfollow.confirm": "Diheuliañ",
"confirmations.unfollow.message": "Ha sur oc'h e fell deoc'h paouez da heuliañ {name} ?",
"confirmations.unfollow.title": "Paouez da heuliañ an implijer·ez?",
"content_warning.hide": "Kuzhat an embannadur",
"content_warning.show": "Diskwel memes tra",
"content_warning.show_more": "Diskouez muioc'h",
"conversation.delete": "Dilemel ar gaozeadenn",
"conversation.mark_as_read": "Merkañ evel lennet",
@ -224,8 +235,8 @@
"empty_column.domain_blocks": "N'eus domani kuzh ebet c'hoazh.",
"empty_column.explore_statuses": "N'eus tuadur ebet evit c'hoazh. Distroit diwezhatoc'h !",
"empty_column.follow_requests": "N'ho peus reked heuliañ ebet c'hoazh. Pa vo resevet unan e teuio war wel amañ.",
"empty_column.followed_tags": "N'emaoc'h oc'h heuliañ hashtag ebet evit poent. Pa vioc'h e vo d'o gwelet amañ.",
"empty_column.hashtag": "N'eus netra en hashtag-mañ c'hoazh.",
"empty_column.followed_tags": "N'emaoc'h oc'h heuliañ ger-klik ebet evit poent. Pa vioc'h e vo d'o gwelet amañ.",
"empty_column.hashtag": "N'eus netra er ger-klik-mañ c'hoazh.",
"empty_column.home": "Goullo eo ho red-amzer degemer! Kit da weladenniñ {public} pe implijit ar c'hlask evit kregiñ ganti ha kejañ gant implijer·ien·ezed all.",
"empty_column.list": "Goullo eo al listenn-mañ evit c'hoazh. Pa vo embannet toudoù nevez gant e izili e teuint war wel amañ.",
"empty_column.mutes": "N'ho peus kuzhet implijer ebet c'hoazh.",
@ -241,7 +252,7 @@
"explore.title": "Diouzh ar c'hiz",
"explore.trending_links": "Keleier",
"explore.trending_statuses": "Embannadurioù",
"explore.trending_tags": "Hashtagoù",
"explore.trending_tags": "Gerioù-klik",
"featured_carousel.next": "War-raok",
"featured_carousel.post": "Embannadenn",
"featured_carousel.previous": "War-gil",
@ -269,7 +280,8 @@
"follow_suggestions.friends_of_friends_longer": "Diouzh ar c'hiz e-touez an dud heuliet ganeoc'h",
"follow_suggestions.popular_suggestion_longer": "Diouzh ar c'hiz war {domain}",
"follow_suggestions.view_all": "Gwelet pep tra",
"followed_tags": "Hashtagoù o heuliañ",
"follow_suggestions.who_to_follow": "Piv heuliañ",
"followed_tags": "Gerioù-klik o heuliañ",
"footer.about": "Diwar-benn",
"footer.directory": "Kavlec'h ar profiloù",
"footer.get_app": "Pellgargañ an arload",
@ -281,19 +293,23 @@
"generic.saved": "Enrollet",
"getting_started.heading": "Loc'hañ",
"hashtag.admin_moderation": "Digeriñ an etrefas evezhiañ evit #{name}",
"hashtag.browse": "Furchal dre an toudoù gant #{hashtag}",
"hashtag.browse_from_account": "Furchal dre an toudoù gant @{name} gant #{hashtag}",
"hashtag.column_header.tag_mode.all": "ha(g) {additional}",
"hashtag.column_header.tag_mode.any": "pe {additional}",
"hashtag.column_header.tag_mode.none": "hep {additional}",
"hashtag.column_settings.select.no_options_message": "N'eus bet kavet ali ebet",
"hashtag.column_settings.select.placeholder": "Ouzhpennañ hashtagoù…",
"hashtag.column_settings.select.placeholder": "Ouzhpennañ geri-klik…",
"hashtag.column_settings.tag_mode.all": "An holl anezho",
"hashtag.column_settings.tag_mode.any": "Unan e mesk anezho",
"hashtag.column_settings.tag_mode.none": "Hini ebet anezho",
"hashtag.column_settings.tag_toggle": "Endelc'her gerioù-alc'hwez ouzhpenn evit ar bannad-mañ",
"hashtag.counter_by_uses": "{count, plural, one {{counter} embannadur} other {{counter} embannadur}}",
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} embannadur} other {{counter} embannadur}} hiziv",
"hashtag.feature": "Lakaat war-wel war ar profil",
"hashtag.follow": "Heuliañ ar ger-klik",
"hashtag.unfollow": "Paouez heuliañ an hashtag",
"hashtag.mute": "Kuzhat #{hashtag}",
"hashtag.unfollow": "Diheuliañ ar ger-klik",
"hashtags.and_other": "…{count, plural, one {hag # all} other {ha # all}}",
"home.column_settings.show_quotes": "Diskouez an arroudennoù",
"home.column_settings.show_reblogs": "Diskouez ar skignadennoù",
@ -302,12 +318,14 @@
"home.pending_critical_update.body": "Hizivait ho servijer Mastodon kerkent ha ma c'hallit mar plij!",
"home.pending_critical_update.link": "Gwelet an hizivadennoù",
"home.show_announcements": "Diskouez ar c'hemennoù",
"interaction_modal.go": "Mont di",
"interaction_modal.on_another_server": "War ur servijer all",
"interaction_modal.on_this_server": "War ar servijer-mañ",
"interaction_modal.title.favourite": "Ouzhpennañ embannadur {name} d'ar re vuiañ-karet",
"interaction_modal.title.follow": "Heuliañ {name}",
"interaction_modal.title.reblog": "Skignañ toud {name}",
"interaction_modal.title.reply": "Respont da doud {name}",
"interaction_modal.username_prompt": "D.s. {example}",
"intervals.full.days": "{number, plural, one {# devezh} other{# a zevezhioù}}",
"intervals.full.hours": "{number, plural, one {# eurvezh} other{# eurvezh}}",
"intervals.full.minutes": "{number, plural, one {# munut} other{# a vunutoù}}",
@ -345,12 +363,14 @@
"keyboard_shortcuts.toot": "Kregiñ gant un toud nevez",
"keyboard_shortcuts.unfocus": "Difokus an dachenn testenn/klask",
"keyboard_shortcuts.up": "Pignat er roll",
"learn_more_link.got_it": "Mat eo",
"lightbox.close": "Serriñ",
"lightbox.next": "Da-heul",
"lightbox.previous": "A-raok",
"limited_account_hint.action": "Diskouez an aelad memes tra",
"limited_account_hint.action": "Diskouez ar profil memes tra",
"limited_account_hint.title": "Kuzhet eo bet ar profil-mañ gant an evezhierien eus {domain}.",
"link_preview.author": "Gant {name}",
"link_preview.more_from_author": "Muioc'h gant {name}",
"lists.add_member": "Ouzhpennañ",
"lists.add_to_list": "Ouzhpennañ d'al listenn",
"lists.create": "Krouiñ",
@ -359,13 +379,19 @@
"lists.done": "Graet",
"lists.edit": "Kemmañ al listenn",
"lists.list_name": "Anv al listenn",
"lists.new_list_name": "Anv nevez al listenn",
"lists.no_lists_yet": "Listenn ebet c'hoazh.",
"lists.replies_policy.followed": "Pep implijer.ez heuliet",
"lists.replies_policy.list": "Izili ar roll",
"lists.replies_policy.none": "Den ebet",
"lists.save": "Enrollañ",
"lists.search": "Klask",
"load_pending": "{count, plural, one {# dra nevez} other {# dra nevez}}",
"loading_indicator.label": "O kargañ…",
"media_gallery.hide": "Kuzhat",
"navigation_bar.about": "Diwar-benn",
"navigation_bar.account_settings": "Ger-tremen ha surentez",
"navigation_bar.administration": "Merañ",
"navigation_bar.automated_deletion": "Dilemel an embannadenn ent-emgefreek",
"navigation_bar.blocks": "Implijer·ezed·ien berzet",
"navigation_bar.bookmarks": "Sinedoù",
@ -374,11 +400,12 @@
"navigation_bar.favourites": "Muiañ-karet",
"navigation_bar.filters": "Gerioù kuzhet",
"navigation_bar.follow_requests": "Pedadoù heuliañ",
"navigation_bar.followed_tags": "Hashtagoù o heuliañ",
"navigation_bar.followed_tags": "Gerioù-klik o heuliañ",
"navigation_bar.follows_and_followers": "Heuliadennoù ha heulier·ezed·ien",
"navigation_bar.import_export": "Enporzhiañ hag ezporzhiañ",
"navigation_bar.lists": "Listennoù",
"navigation_bar.logout": "Digennaskañ",
"navigation_bar.moderation": "Habaskadur",
"navigation_bar.more": "Muioc'h",
"navigation_bar.mutes": "Implijer·ion·ezed kuzhet",
"navigation_bar.preferences": "Gwellvezioù",
@ -391,6 +418,8 @@
"notification.follow.name_and_others": "{name} <a>{count, plural, one {hag # den all} two {ha # zen all} few {ha # den all} many {ha # den all} other {ha # den all}}</a> zo o heuliañ ac'hanoc'h",
"notification.follow_request": "Gant {name} eo bet goulennet ho heuliañ",
"notification.label.reply": "Respont",
"notification.mention": "Meneg",
"notification.mentioned_you": "Gant {name} oc'h bet meneget",
"notification.moderation-warning.learn_more": "Gouzout hiroc'h",
"notification.own_poll": "Echu eo ho sontadeg",
"notification.reblog": "Gant {name} eo bet skignet ho toud",
@ -447,7 +476,7 @@
"onboarding.profile.display_name": "Anv diskouezet",
"onboarding.profile.display_name_hint": "Hoc'h anv klok pe hoc'h anv fentus…",
"onboarding.profile.note": "Berr-ha-berr",
"onboarding.profile.note_hint": "Gallout a rit @menegiñ tud all pe #hashtagoù…",
"onboarding.profile.note_hint": "Gallout a rit @menegiñ tud all pe #geri-klik…",
"onboarding.profile.save_and_continue": "Enrollañ ha kenderc'hel",
"onboarding.profile.upload_avatar": "Enporzhiañ ur skeudenn profil",
"password_confirmation.mismatching": "Disheñvel eo an daou c'her-termen-se",
@ -480,6 +509,7 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}eil",
"relative_time.today": "hiziv",
"remove_quote_hint.button_label": "Mat eo",
"reply_indicator.cancel": "Nullañ",
"reply_indicator.poll": "Sontadeg",
"report.block": "Stankañ",
@ -528,7 +558,7 @@
"search.placeholder": "Klask",
"search.quick_action.account_search": "Profiloù a glot gant {x}",
"search.quick_action.go_to_account": "Mont d'ar profil {x}",
"search.quick_action.go_to_hashtag": "Mont d'an hashtag {x}",
"search.quick_action.go_to_hashtag": "Mont d'ar ger-klik {x}",
"search.quick_action.open_url": "Digeriñ an URL e-barzh Mastodon",
"search.quick_action.status_search": "Embannadurioù a glot gant {x}",
"search.search_or_paste": "Klask pe pegañ un URL",
@ -541,7 +571,7 @@
"search_popout.user": "implijer·ez",
"search_results.accounts": "Profiloù",
"search_results.all": "Pep tra",
"search_results.hashtags": "Hashtagoù",
"search_results.hashtags": "Gerioù-klik",
"search_results.no_results": "Disoc'h ebet.",
"search_results.see_all": "Gwelet pep tra",
"search_results.statuses": "Toudoù",
@ -607,6 +637,7 @@
"subscribed_languages.save": "Enrollañ ar cheñchamantoù",
"subscribed_languages.target": "Cheñch ar yezhoù koumanantet evit {target}",
"tabs_bar.home": "Degemer",
"tabs_bar.menu": "Lañser",
"tabs_bar.notifications": "Kemennoù",
"tabs_bar.publish": "Embannadenn nevez",
"tabs_bar.search": "Klask",
@ -638,6 +669,8 @@
"video.hide": "Kuzhat ar video",
"video.pause": "Paouez",
"video.play": "Lenn",
"visibility_modal.privacy_label": "Gwelusted",
"visibility_modal.quote_followers": "Tud koumanantet hepken",
"visibility_modal.quote_public": "Pep den"
"visibility_modal.quote_public": "Pep den",
"visibility_modal.save": "Enrollañ"
}

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} m",
"relative_time.seconds": "{number} s",
"relative_time.today": "dnes",
"remove_quote_hint.button_label": "Chápu",
"remove_quote_hint.message": "Můžete to udělat z {icon} nabídky možností.",
"remove_quote_hint.title": "Chcete odstranit citovaný příspěvek?",
"reply_indicator.attachments": "{count, plural, one {{counter} příloha} few {{counter} přílohy} other {{counter} příloh}}",
"reply_indicator.cancel": "Zrušit",
"reply_indicator.poll": "Anketa",
@ -863,6 +866,7 @@
"status.block": "Blokovat @{name}",
"status.bookmark": "Přidat do záložek",
"status.cancel_reblog_private": "Zrušit boostnutí",
"status.cannot_quote": "Citování je na tomo příspěvku zakázáno",
"status.cannot_reblog": "Tento příspěvek nemůže být boostnutý",
"status.context.load_new_replies": "K dispozici jsou nové odpovědi",
"status.context.loading": "Hledání dalších odpovědí",
@ -988,6 +992,7 @@
"visibility_modal.header": "Viditelnost a interakce",
"visibility_modal.helper.direct_quoting": "Soukromé zmínky, které jsou vytvořeny na Mastodonu, nemohou být citovány ostatními.",
"visibility_modal.helper.privacy_editing": "Publikované příspěvky nemohou změnit svou viditelnost.",
"visibility_modal.helper.privacy_private_self_quote": "Citace vlastních soukromých příspěvků nelze zveřejnit.",
"visibility_modal.helper.private_quoting": "Příspěvky pouze pro sledující, které jsou vytvořeny na Mastodonu, nemohou být citovány ostatními.",
"visibility_modal.helper.unlisted_quoting": "Když vás lidé citují, jejich příspěvek bude v časové ose populárních příspěvků také skryt.",
"visibility_modal.instructions": "Nastavte, kdo bude moci interagovat s tímto příspěvkem. Tyto nastavení též můžete změnit pro všechny budoucí příspěvky v <link>Nastavení > Výchozí nastavení příspěvků</link>.",

View File

@ -768,6 +768,7 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "i dag",
"remove_quote_hint.button_label": "Forstået",
"reply_indicator.attachments": "{count, plural, one {# vedhæftning} other {# vedhæftninger}}",
"reply_indicator.cancel": "Afbryd",
"reply_indicator.poll": "Afstemning",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} Min.",
"relative_time.seconds": "{number} Sek.",
"relative_time.today": "heute",
"remove_quote_hint.button_label": "Verstanden",
"remove_quote_hint.message": "Klicke dafür im Beitrag auf „{icon} Mehr“.",
"remove_quote_hint.title": "Möchtest du aus dem zitierten Beitrag entfernt werden?",
"reply_indicator.attachments": "{count, plural, one {# Anhang} other {# Anhänge}}",
"reply_indicator.cancel": "Abbrechen",
"reply_indicator.poll": "Umfrage",

View File

@ -991,7 +991,7 @@
"visibility_modal.button_title": "Set visibility",
"visibility_modal.header": "Visibility and interaction",
"visibility_modal.helper.direct_quoting": "Private mentions authored on Mastodon can't be quoted by others.",
"visibility_modal.helper.privacy_editing": "Published posts cannot change their visibility.",
"visibility_modal.helper.privacy_editing": "Visibility can't be changed after a post is published.",
"visibility_modal.helper.privacy_private_self_quote": "Self-quotes of private posts cannot be made public.",
"visibility_modal.helper.private_quoting": "Follower-only posts authored on Mastodon can't be quoted by others.",
"visibility_modal.helper.unlisted_quoting": "When people quote you, their post will also be hidden from trending timelines.",

View File

@ -30,6 +30,8 @@
"account.edit_profile": "Redakti la profilon",
"account.enable_notifications": "Sciigu min kiam @{name} afiŝos",
"account.endorse": "Montri en profilo",
"account.familiar_followers_one": "Sekvita de {name1}",
"account.familiar_followers_two": "Sekvita de {name1} kaj {name2}",
"account.featured": "Montrita",
"account.featured.accounts": "Profiloj",
"account.featured.hashtags": "Kradvortoj",
@ -305,6 +307,7 @@
"emoji_button.search_results": "Serĉaj rezultoj",
"emoji_button.symbols": "Simboloj",
"emoji_button.travel": "Vojaĝoj kaj lokoj",
"empty_column.account_featured.me": "Vi ankoraŭ nenion prezentis. Ĉu vi sciis, ke vi povas prezenti viajn plej ofte uzatajn kradvortojn, kaj eĉ la kontojn de viaj amikoj sur via profilo?",
"empty_column.account_featured_other.unknown": "Ĉi tiu konto ankoraŭ ne montris ion ajn.",
"empty_column.account_hides_collections": "Ĉi tiu uzanto elektis ne disponebligi ĉi tiu informon",
"empty_column.account_suspended": "Konto suspendita",
@ -338,6 +341,7 @@
"explore.trending_links": "Novaĵoj",
"explore.trending_statuses": "Afiŝoj",
"explore.trending_tags": "Kradvortoj",
"featured_carousel.header": "{count, plural, one {Alpinglita afiŝo} other {Alpinglitaj afiŝoj}}",
"featured_carousel.next": "Antaŭen",
"featured_carousel.post": "Afiŝi",
"featured_carousel.previous": "Malantaŭen",
@ -751,6 +755,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "hodiaŭ",
"remove_quote_hint.button_label": "Komprenite",
"remove_quote_hint.message": "Vi povas fari tion el la menuo de opcioj {icon}.",
"remove_quote_hint.title": "Ĉu vi volas forigi vian cititan afiŝon?",
"reply_indicator.attachments": "{count, plural, one {# aldonaĵo} other {# aldonaĵoj}}",
"reply_indicator.cancel": "Nuligi",
"reply_indicator.poll": "Balotenketo",
@ -846,6 +853,7 @@
"status.block": "Bloki @{name}",
"status.bookmark": "Aldoni al la legosignoj",
"status.cancel_reblog_private": "Ne plu diskonigi",
"status.cannot_quote": "Citaĵoj estas malebligitaj en ĉi tiu afiŝo",
"status.cannot_reblog": "Ĉi tiun afiŝon ne eblas diskonigi",
"status.context.load_new_replies": "Disponeblaj novaj respondoj",
"status.context.loading": "Serĉante pliajn respondojn",
@ -971,6 +979,7 @@
"visibility_modal.helper.privacy_editing": "Publikigitaj afiŝoj ne povas ŝanĝi sian videblon.",
"visibility_modal.helper.private_quoting": "Afiŝoj nur por sekvantoj verkitaj ĉe Mastodon ne povas esti cititaj de aliaj.",
"visibility_modal.helper.unlisted_quoting": "Kiam homoj citas vin, ilia afiŝo ankaŭ estos kaŝita de tendencaj templinioj.",
"visibility_modal.privacy_label": "Videbleco",
"visibility_modal.quote_followers": "Nur sekvantoj",
"visibility_modal.quote_label": "Kiu povas citi",
"visibility_modal.quote_nobody": "Nur mi",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "hoy",
"remove_quote_hint.button_label": "Entendido",
"remove_quote_hint.message": "Podés hacerlo desde el menú de opciones {icon}.",
"remove_quote_hint.title": "¿Querés eliminar tu mensaje citado?",
"reply_indicator.attachments": "{count, plural,one {# adjunto} other {# adjuntos}}",
"reply_indicator.cancel": "Cancelar",
"reply_indicator.poll": "Encuesta",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} m",
"relative_time.seconds": "{number} s",
"relative_time.today": "hoy",
"remove_quote_hint.button_label": "Entendido",
"remove_quote_hint.message": "Puedes hacerlo desde el menú de opciones {icon}.",
"remove_quote_hint.title": "¿Quieres eliminar tu publicación citada?",
"reply_indicator.attachments": "{count, plural, one {# adjunto} other {# adjuntos}}",
"reply_indicator.cancel": "Cancelar",
"reply_indicator.poll": "Encuesta",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} m",
"relative_time.seconds": "{number} s",
"relative_time.today": "hoy",
"remove_quote_hint.button_label": "Entendido",
"remove_quote_hint.message": "Puedes hacerlo desde el menú de opciones {icon}.",
"remove_quote_hint.title": "¿Quieres eliminar tu publicación citada?",
"reply_indicator.attachments": "{count, plural, one {# adjunto} other {# adjuntos}}",
"reply_indicator.cancel": "Cancelar",
"reply_indicator.poll": "Encuesta",

View File

@ -863,6 +863,7 @@
"status.block": "Blokeeri @{name}",
"status.bookmark": "Järjehoidja",
"status.cancel_reblog_private": "Lõpeta jagamine",
"status.cannot_quote": "Selle postituse tsiteerimine pole lubatud",
"status.cannot_reblog": "Seda postitust ei saa jagada",
"status.context.load_new_replies": "Leidub uusi vastuseid",
"status.context.loading": "Kontrollin täiendavate vastuste olemasolu",
@ -988,9 +989,13 @@
"visibility_modal.header": "Nähtavus ja kasutus",
"visibility_modal.helper.direct_quoting": "Ainult mainituile mõeldud Mastodoni postitusi ei saa teiste poolt tsiteerida.",
"visibility_modal.helper.privacy_editing": "Avaldatud postitused ei saa muuta oma nähtavust.",
"visibility_modal.helper.privacy_private_self_quote": "Privaatsete postituste tsiteerimist oma enda poolt pole võimalik teha avalikuks.",
"visibility_modal.helper.private_quoting": "Ainult jälgijatele mõeldud Mastodoni postitusi ei saa teiste poolt tsiteerida.",
"visibility_modal.helper.unlisted_quoting": "Kui teised kasutajad sind tsiteerivad, siis nende postitused peidetakse ajajoonelt, mis näitavad populaarsust koguvaid postitusi.",
"visibility_modal.instructions": "Halda seda, kes võivad antud postitusega suhestuda. Lisaks võid kõikide tulevaste postituste seadistusi muuta valikust <link>Eelistused > Postituse vaikeseadistused</link>.",
"visibility_modal.privacy_label": "Nähtavus",
"visibility_modal.quote_followers": "Ainult jälgijad",
"visibility_modal.quote_label": "Kes võivad tsiteerida",
"visibility_modal.quote_nobody": "Ainult mina",
"visibility_modal.quote_public": "Kõik",
"visibility_modal.save": "Salvesta"

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} min",
"relative_time.seconds": "{number} s",
"relative_time.today": "tänään",
"remove_quote_hint.button_label": "Selvä",
"remove_quote_hint.message": "Voit tehdä sen {icon}-valikosta.",
"remove_quote_hint.title": "Haluatko poistaa lainatun julkaisusi?",
"reply_indicator.attachments": "{count, plural, one {# liite} other {# liitettä}}",
"reply_indicator.cancel": "Peruuta",
"reply_indicator.poll": "Äänestys",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "hoxe",
"remove_quote_hint.button_label": "Entendido",
"remove_quote_hint.message": "Pódelo facer desde o {icon} menú de opcións.",
"remove_quote_hint.title": "Queres eliminar a publicación citada?",
"reply_indicator.attachments": "{count, plural, one {# adxunto} other {# adxuntos}}",
"reply_indicator.cancel": "Desbotar",
"reply_indicator.poll": "Enquisa",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} דקות",
"relative_time.seconds": "{number} שניות",
"relative_time.today": "היום",
"remove_quote_hint.button_label": "הבנתי",
"remove_quote_hint.message": "ניתן לעשות זאת מתפריט האפשרויות {icon}",
"remove_quote_hint.title": "להסיר את ההודעה המצוטטת?",
"reply_indicator.attachments": "{count, plural,one {# קובץ מצורף}other {# קבצים מצורפים}}",
"reply_indicator.cancel": "ביטול",
"reply_indicator.poll": "משאל",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number}mín",
"relative_time.seconds": "{number}sek",
"relative_time.today": "í dag",
"remove_quote_hint.button_label": "Náði því",
"remove_quote_hint.message": "Þú getur gert það úr {icon} valmyndinni.",
"remove_quote_hint.title": "Viltu fjarlægja tilvitnuðu færsluna þína?",
"reply_indicator.attachments": "{count, plural, one {# viðhengi} other {# viðhengi}}",
"reply_indicator.cancel": "Hætta við",
"reply_indicator.poll": "Könnun",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "vandaag",
"remove_quote_hint.button_label": "Begrepen",
"remove_quote_hint.message": "Je kunt dit doen vanuit het {icon} optiesmenu.",
"remove_quote_hint.title": "Wil je jouw geciteerd bericht verwijderen?",
"reply_indicator.attachments": "{count, plural, one {# bijlage} other {# bijlagen}}",
"reply_indicator.cancel": "Annuleren",
"reply_indicator.poll": "Peiling",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} phút",
"relative_time.seconds": "{number}s",
"relative_time.today": "hôm nay",
"remove_quote_hint.button_label": "Đã hiểu",
"remove_quote_hint.message": "Bạn cũng có thể làm trong menu tùy chọn {icon}",
"remove_quote_hint.title": "Gỡ tút mà bạn đã trích dẫn?",
"reply_indicator.attachments": "{count, plural, other {# tập tin đính kèm}}",
"reply_indicator.cancel": "Hủy bỏ",
"reply_indicator.poll": "Vốt",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} 分钟前",
"relative_time.seconds": "{number} 秒前",
"relative_time.today": "今天",
"remove_quote_hint.button_label": "明白了",
"remove_quote_hint.message": "你可以通过 {icon} 选项菜单进行此操作。",
"remove_quote_hint.title": "是否需要删除你的引用嘟文?",
"reply_indicator.attachments": "{count, plural, other {# 个附件}}",
"reply_indicator.cancel": "取消",
"reply_indicator.poll": "投票",

View File

@ -768,6 +768,9 @@
"relative_time.minutes": "{number} 分鐘前",
"relative_time.seconds": "{number} 秒",
"relative_time.today": "今天",
"remove_quote_hint.button_label": "了解",
"remove_quote_hint.message": "您能自 {icon} 選單完成此操作。",
"remove_quote_hint.title": "是否想要移除您的引用嘟文?",
"reply_indicator.attachments": "{count, plural, other {# 個附加檔案}}",
"reply_indicator.cancel": "取消",
"reply_indicator.poll": "投票",

View File

@ -1,10 +0,0 @@
# frozen_string_literal: true
module AccessGrantExtension
extend ActiveSupport::Concern
included do
scope :expired, -> { where.not(expires_in: nil).where('created_at + MAKE_INTERVAL(secs => expires_in) < NOW()') }
scope :revoked, -> { where.not(revoked_at: nil).where(revoked_at: ...Time.now.utc) }
end
end

View File

@ -1,29 +0,0 @@
# frozen_string_literal: true
module AccessTokenExtension
extend ActiveSupport::Concern
included do
include Redisable
has_many :web_push_subscriptions, class_name: 'Web::PushSubscription', inverse_of: :access_token
after_commit :push_to_streaming_api
scope :expired, -> { where.not(expires_in: nil).where('created_at + MAKE_INTERVAL(secs => expires_in) < NOW()') }
scope :not_revoked, -> { where(revoked_at: nil) }
scope :revoked, -> { where.not(revoked_at: nil).where(revoked_at: ...Time.now.utc) }
end
def revoke(clock = Time)
update(revoked_at: clock.now.utc)
end
def update_last_used(request, clock = Time)
update(last_used_at: clock.now.utc, last_used_ip: request.remote_ip)
end
def push_to_streaming_api
redis.publish("timeline:access_token:#{id}", Oj.dump(event: :kill)) if revoked? || destroyed?
end
end

View File

@ -1,49 +0,0 @@
# frozen_string_literal: true
module ApplicationExtension
extend ActiveSupport::Concern
APP_NAME_LIMIT = 60
APP_REDIRECT_URI_LIMIT = 2_000
APP_WEBSITE_LIMIT = 2_000
included do
include Redisable
has_many :created_users, class_name: 'User', foreign_key: 'created_by_application_id', inverse_of: :created_by_application
validates :name, length: { maximum: APP_NAME_LIMIT }
validates :redirect_uri, length: { maximum: APP_REDIRECT_URI_LIMIT }
validates :website, url: true, length: { maximum: APP_WEBSITE_LIMIT }, if: :website?
# The relationship used between Applications and AccessTokens is using
# dependent: delete_all, which means the ActiveRecord callback in
# AccessTokenExtension is not run, so instead we manually announce to
# streaming that these tokens are being deleted.
before_destroy :close_streaming_sessions, prepend: true
end
def confirmation_redirect_uri
redirect_uri.lines.first.strip
end
def redirect_uris
# Doorkeeper stores the redirect_uri value as a newline delimeted list in
# the database:
redirect_uri.split
end
def close_streaming_sessions(resource_owner = nil)
# TODO: #28793 Combine into a single topic
payload = Oj.dump(event: :kill)
scope = access_tokens
scope = scope.where(resource_owner_id: resource_owner.id) unless resource_owner.nil?
scope.in_batches do |tokens|
redis.pipelined do |pipeline|
tokens.ids.each do |id|
pipeline.publish("timeline:access_token:#{id}", payload)
end
end
end
end
end

View File

@ -9,12 +9,12 @@ class Vacuum::AccessTokensVacuum
private
def vacuum_revoked_access_tokens!
Doorkeeper::AccessToken.expired.in_batches.delete_all
Doorkeeper::AccessToken.revoked.in_batches.delete_all
OAuth::AccessToken.expired.in_batches.delete_all
OAuth::AccessToken.revoked.in_batches.delete_all
end
def vacuum_revoked_access_grants!
Doorkeeper::AccessGrant.expired.in_batches.delete_all
Doorkeeper::AccessGrant.revoked.in_batches.delete_all
OAuth::AccessGrant.expired.in_batches.delete_all
OAuth::AccessGrant.revoked.in_batches.delete_all
end
end

7
app/models/oauth.rb Normal file
View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
module OAuth
def self.table_name_prefix
'oauth_'
end
end

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
class OAuth::AccessGrant < ApplicationRecord
include ::Doorkeeper::Orm::ActiveRecord::Mixins::AccessGrant
scope :expired, -> { where.not(expires_in: nil).where('created_at + MAKE_INTERVAL(secs => expires_in) < NOW()') }
scope :revoked, -> { where.not(revoked_at: nil).where(revoked_at: ...Time.now.utc) }
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
class OAuth::AccessToken < ApplicationRecord
include ::Doorkeeper::Orm::ActiveRecord::Mixins::AccessToken
include Redisable
has_many :web_push_subscriptions, class_name: 'Web::PushSubscription', inverse_of: :access_token, dependent: nil
scope :expired, -> { where.not(expires_in: nil).where('created_at + MAKE_INTERVAL(secs => expires_in) < NOW()') }
scope :not_revoked, -> { where(revoked_at: nil) }
scope :revoked, -> { where.not(revoked_at: nil).where(revoked_at: ...Time.now.utc) }
after_commit :push_to_streaming_api
def revoke(clock = Time)
update(revoked_at: clock.now.utc)
end
def update_last_used(request, clock = Time)
update(last_used_at: clock.now.utc, last_used_ip: request.remote_ip)
end
private
def push_to_streaming_api
redis.publish("timeline:access_token:#{id}", Oj.dump(event: :kill)) if revoked? || destroyed?
end
end

View File

@ -0,0 +1,44 @@
# frozen_string_literal: true
class OAuth::Application < ApplicationRecord
include ::Doorkeeper::Orm::ActiveRecord::Mixins::Application
APP_NAME_LIMIT = 60
APP_REDIRECT_URI_LIMIT = 2_000
APP_WEBSITE_LIMIT = 2_000
include Redisable
has_many :created_users, class_name: 'User', foreign_key: :created_by_application_id, inverse_of: :created_by_application, dependent: nil
validates :name, length: { maximum: APP_NAME_LIMIT }
validates :redirect_uri, length: { maximum: APP_REDIRECT_URI_LIMIT }
validates :website, url: true, length: { maximum: APP_WEBSITE_LIMIT }, if: :website?
before_destroy :close_streaming_sessions, prepend: true
def confirmation_redirect_uri
redirect_uri.lines.first.strip
end
def redirect_uris
# The redirect_uri value is stored as a newline delimited list
redirect_uri.split
end
# The association between `Application` and `AccessToken` uses a setting of
# `dependent: delete_all` which means the callbacks in `AccessToken` are not
# run. Instead, announce to streaming that these tokens are being deleted.
def close_streaming_sessions(resource_owner = nil)
payload = Oj.dump(event: :kill)
scope = access_tokens
scope = scope.where(resource_owner_id: resource_owner.id) unless resource_owner.nil?
scope.in_batches do |tokens|
redis.pipelined do |pipeline|
tokens.ids.each do |id|
pipeline.publish("timeline:access_token:#{id}", payload)
end
end
end
end
end

View File

@ -32,7 +32,7 @@ class Report < ApplicationRecord
rate_limit by: :account, family: :reports
belongs_to :account
belongs_to :application, class_name: 'Doorkeeper::Application', optional: true
belongs_to :application, class_name: 'OAuth::Application', optional: true
with_options class_name: 'Account' do
belongs_to :target_account

View File

@ -19,7 +19,7 @@ class SessionActivation < ApplicationRecord
include BrowserDetection
belongs_to :user, inverse_of: :session_activations
belongs_to :access_token, class_name: 'Doorkeeper::AccessToken', dependent: :destroy, optional: true
belongs_to :access_token, class_name: 'OAuth::AccessToken', dependent: :destroy, optional: true
belongs_to :web_push_subscription, class_name: 'Web::PushSubscription', dependent: :destroy, optional: true
delegate :token,
@ -61,12 +61,12 @@ class SessionActivation < ApplicationRecord
private
def assign_access_token
self.access_token = Doorkeeper::AccessToken.create!(access_token_attributes)
self.access_token = OAuth::AccessToken.create!(access_token_attributes)
end
def access_token_attributes
{
application_id: Doorkeeper::Application.find_by(superapp: true)&.id,
application_id: OAuth::Application.find_by(superapp: true)&.id,
resource_owner_id: user_id,
scopes: DEFAULT_SCOPES.join(' '),
expires_in: Doorkeeper.configuration.access_token_expires_in,

View File

@ -58,7 +58,7 @@ class Status < ApplicationRecord
update_index('statuses', :proper)
update_index('public_statuses', :proper)
belongs_to :application, class_name: 'Doorkeeper::Application', optional: true
belongs_to :application, class_name: 'OAuth::Application', optional: true
belongs_to :account, inverse_of: :statuses
belongs_to :in_reply_to_account, class_name: 'Account', optional: true

View File

@ -76,11 +76,11 @@ class User < ApplicationRecord
belongs_to :account, inverse_of: :user
belongs_to :invite, counter_cache: :uses, optional: true
belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true
belongs_to :created_by_application, class_name: 'OAuth::Application', optional: true
belongs_to :role, class_name: 'UserRole', optional: true
accepts_nested_attributes_for :account
has_many :applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: nil
has_many :applications, class_name: 'OAuth::Application', as: :owner, dependent: nil
has_many :backups, inverse_of: :user, dependent: nil
has_many :invites, inverse_of: :user, dependent: nil
has_many :login_activities, inverse_of: :user, dependent: :destroy
@ -273,7 +273,7 @@ class User < ApplicationRecord
end
def applications_last_used
Doorkeeper::AccessToken
OAuth::AccessToken
.where(resource_owner_id: id)
.where.not(last_used_at: nil)
.group(:application_id)
@ -284,7 +284,7 @@ class User < ApplicationRecord
def token_for_app(app)
return nil if app.nil? || app.owner != self
Doorkeeper::AccessToken.find_or_create_by(application_id: app.id, resource_owner_id: id) do |t|
OAuth::AccessToken.find_or_create_by(application_id: app.id, resource_owner_id: id) do |t|
t.scopes = app.scopes
t.expires_in = Doorkeeper.configuration.access_token_expires_in
t.use_refresh_token = Doorkeeper.configuration.refresh_token_enabled?
@ -338,9 +338,9 @@ class User < ApplicationRecord
end
def revoke_access!
Doorkeeper::AccessGrant.by_resource_owner(self).touch_all(:revoked_at)
OAuth::AccessGrant.by_resource_owner(self).touch_all(:revoked_at)
Doorkeeper::AccessToken.by_resource_owner(self).in_batches do |batch|
OAuth::AccessToken.by_resource_owner(self).in_batches do |batch|
batch.touch_all(:revoked_at)
Web::PushSubscription.where(access_token_id: batch).delete_all

View File

@ -18,7 +18,7 @@
class Web::PushSubscription < ApplicationRecord
belongs_to :user
belongs_to :access_token, class_name: 'Doorkeeper::AccessToken'
belongs_to :access_token, class_name: 'OAuth::AccessToken'
has_one :session_activation, foreign_key: 'web_push_subscription_id', inverse_of: :web_push_subscription, dependent: nil
@ -42,7 +42,7 @@ class Web::PushSubscription < ApplicationRecord
class << self
def unsubscribe_for(application_id, resource_owner)
access_token_ids = Doorkeeper::AccessToken.where(application_id: application_id, resource_owner_id: resource_owner.id).not_revoked.pluck(:id)
access_token_ids = OAuth::AccessToken.where(application_id: application_id, resource_owner_id: resource_owner.id).not_revoked.pluck(:id)
where(access_token_id: access_token_ids).delete_all
end
end

View File

@ -27,7 +27,7 @@ class AppSignUpService < BaseService
end
def create_access_token!
@access_token = Doorkeeper::AccessToken.create!(
@access_token = OAuth::AccessToken.create!(
application: @app,
resource_owner_id: @user.id,
scopes: @app.scopes,

View File

@ -27,7 +27,7 @@ class PostStatusService < BaseService
# @option [String] :scheduled_at
# @option [Hash] :poll Optional poll to attach
# @option [Enumerable] :media_ids Optional array of media IDs to attach
# @option [Doorkeeper::Application] :application
# @option [OAuth::Application] :application
# @option [String] :idempotency Optional idempotency key
# @option [Boolean] :with_rate_limit
# @option [Enumerable] :allowed_mentions Optional array of expected mentioned account IDs, raises `UnexpectedMentionsError` if unexpected accounts end up in mentions

View File

@ -21,7 +21,7 @@ class PublishScheduledStatusWorker
def options_with_objects(options)
options.tap do |options_hash|
options_hash[:application] = Doorkeeper::Application.find(options_hash.delete(:application_id)) if options[:application_id]
options_hash[:application] = OAuth::Application.find(options_hash.delete(:application_id)) if options[:application_id]
options_hash[:thread] = Status.find(options_hash.delete(:in_reply_to_id)) if options_hash[:in_reply_to_id]
end
end

View File

@ -20,7 +20,7 @@ class Scheduler::IpCleanupScheduler
SessionActivation.where(updated_at: ...IP_RETENTION_PERIOD.ago).in_batches.update_all(ip: nil)
User.where(current_sign_in_at: ...IP_RETENTION_PERIOD.ago).in_batches.update_all(sign_up_ip: nil)
LoginActivity.where(created_at: ...IP_RETENTION_PERIOD.ago).in_batches.destroy_all
Doorkeeper::AccessToken.where(last_used_at: ...IP_RETENTION_PERIOD.ago).in_batches.update_all(last_used_ip: nil)
OAuth::AccessToken.where(last_used_at: ...IP_RETENTION_PERIOD.ago).in_batches.update_all(last_used_ip: nil)
end
def clean_expired_ip_blocks!

View File

@ -117,9 +117,6 @@ module Mastodon
end
config.to_prepare do
Doorkeeper::Application.include ApplicationExtension
Doorkeeper::AccessGrant.include AccessGrantExtension
Doorkeeper::AccessToken.include AccessTokenExtension
Devise::FailureApp.include AbstractController::Callbacks
Devise::FailureApp.include Localized
end

View File

@ -4,6 +4,10 @@ Doorkeeper.configure do
# Change the ORM that doorkeeper will use (needs plugins)
orm :active_record
access_grant_class 'OAuth::AccessGrant'
access_token_class 'OAuth::AccessToken'
application_class 'OAuth::Application'
# This block will be called to check whether the resource owner is authenticated or not.
resource_owner_authenticator do
current_user || redirect_to(new_user_session_url)

View File

@ -63,6 +63,7 @@ br:
all: Pep tra
local: Lec'hel
remote: A-bell
title: Lec'hiadur
media_attachments: Restroù media stag
moderation:
active: Oberiant
@ -180,6 +181,7 @@ br:
name: Anv
registrations:
confirm: Kadarnaat
save: Enrollañ
status: Statud
follow_recommendations:
status: Statud
@ -260,6 +262,7 @@ br:
title: Disklêriadennoù
unresolved: Andiskoulmet
updated_at: Nevesaet
view_profile: Gwelet ar profil
roles:
categories:
devops: DevOps
@ -287,6 +290,7 @@ br:
danger_zone: Takad dañjer
discovery:
privacy: Buhez prevez
profile_directory: Kavlec'h ar profiloù
title: Dizoloadur
trends: Luskadoù
domain_blocks:
@ -310,6 +314,10 @@ br:
strikes:
actions:
delete_statuses: Dilamet eo bet toudoù %{target} gant %{name}
tags:
title: Gerioù-klik
terms_of_service:
save_draft: Enrollañ ar brouilhed
trends:
allow: Aotren
approved: Aprouet
@ -324,7 +332,7 @@ br:
dashboard:
tag_uses_measure: implijoù hollek
not_usable: N'haller ket en implijout
title: Hashtagoù diouzh ar c'hiz
title: Gerioù-klik diouzh ar c'hiz
warning_presets:
add_new: Ouzhpenniñ unan nevez
delete: Dilemel
@ -342,7 +350,7 @@ br:
none: ur c'hemenn diwall
new_trends:
new_trending_tags:
title: Hashtagoù diouzh ar c'hiz
title: Gerioù-klik diouzh ar c'hiz
appearance:
discovery: Dizoloadur
localization:
@ -350,6 +358,7 @@ br:
guide_link: https://crowdin.com/project/mastodon
application_mailer:
view: 'Sellet :'
view_profile: Gwelet ar profil
view_status: Gwelet ar c'hannad
auth:
delete_account: Dilemel ar gont
@ -396,6 +405,8 @@ br:
created_at: Deiziad
title_actions:
none: Diwall
edit_profile:
other: All
emoji_styles:
auto: Emgefreek
twemoji: Twemoji
@ -422,6 +433,8 @@ br:
other: "%{count} a gannadoù"
two: "%{count} gannad"
title: Siloù
new:
save: Enrollañ ar sil nevez
statuses:
index:
title: Toudoù silet
@ -547,7 +560,7 @@ br:
back: Distreiñ da vMastodon
development: Diorren
edit_profile: Kemmañ ar profil
featured_tags: Hashtagoù pennañ
featured_tags: Gerioù-klik pennañ
import: Enporzhiañ
import_and_export: Enporzhiañ hag ezporzhiañ
preferences: Gwellvezioù
@ -609,6 +622,9 @@ br:
edit_profile_title: Personelaat ho profil
feature_action: Gouzout hiroc'h
follow_action: Heuliañ
hashtags_title: Gerioù-klik diouzh ar c'hiz
hashtags_view_more: Gwelet muioc'h a c'herioù-klik diouzh ar c'hiz
share_title: Rannit ho kont Mastodon
sign_in_action: Kevreañ
subject: Donemat e Mastodon
title: Degemer mat e bourzh, %{name}!

View File

@ -1894,6 +1894,9 @@ cy:
self_vote: Nid oes modd i chi bleidleisio yn eich polau eich hun
too_few_options: rhaid cael mwy nag un eitem
too_many_options: ni all gynnwys mwy na %{max} eitem
vote: Pleidleisio
posting_defaults:
explanation: Bydd y gosodiadau hyn yn cael eu defnyddio fel rhagosodiadau pan fyddwch chi'n creu postiadau newydd, ond gallwch chi eu golygu fesul postiad o fewn y cyfansoddwr.
preferences:
other: Arall
posting_defaults: Rhagosodiadau postio

View File

@ -367,7 +367,7 @@ en:
title: Custom emojis
uncategorized: Uncategorized
unlist: Unlist
unlisted: Quiet public
unlisted: Unlisted
update_failed_msg: Could not update that emoji
updated_msg: Emoji successfully updated!
upload: Upload
@ -1923,7 +1923,7 @@ en:
private_long: Only show to followers
public: Public
public_long: Anyone on and off Mastodon
unlisted: Unlisted
unlisted: Quiet public
unlisted_long: Hidden from Mastodon search results, trending, and public timelines
statuses_cleanup:
enabled: Automatically delete old posts

View File

@ -2,6 +2,8 @@
br:
simple_form:
hints:
account:
note: 'Gallout a rit @menegiñ tud all pe #gerioù-klik.'
defaults:
avatar: WEBP, PNG, GIF pe JPG. Bihanoc'h eget %{size}. A vo izelaet betek %{dimensions}px
header: WEBP, PNG, GIF pe JPG. Bihanoc'h eget %{size}. A vo izelaet betek %{dimensions}px
@ -56,7 +58,7 @@ br:
username: Anv
whole_word: Ger a-bezh
featured_tag:
name: Hashtag
name: Ger-klik
invite:
comment: Evezhiadenn
invite_request:
@ -71,8 +73,8 @@ br:
hint: Titouroù ouzhpenn
text: Reolenn
tag:
name: Hashtag
trendable: Aotren an hashtag-mañ da zont war wel dindan tuadurioù
name: Ger-klik
trendable: Aotren ar ger-klik-mañ da zont war wel dindan tuadurioù
user:
role: Roll
time_zone: Gwerzhid eur

View File

@ -1,3 +1,3 @@
# frozen_string_literal: true
Doorkeeper::Application.create_with(name: 'Web', redirect_uri: Doorkeeper.configuration.native_redirect_uri, scopes: 'read write follow push').find_or_create_by(superapp: true)
OAuth::Application.create_with(name: 'Web', redirect_uri: Doorkeeper.configuration.native_redirect_uri, scopes: 'read write follow push').find_or_create_by(superapp: true)

View File

@ -134,12 +134,12 @@ namespace :tests do
exit(1)
end
unless Doorkeeper::Application.find(2)[:scopes] == 'write:accounts profile'
unless OAuth::Application.find(2)[:scopes] == 'write:accounts profile'
puts 'Application OAuth scopes not rewritten as expected'
exit(1)
end
unless Doorkeeper::Application.find(2).access_tokens.first[:scopes] == 'write:accounts profile'
unless OAuth::Application.find(2).access_tokens.first[:scopes] == 'write:accounts profile'
puts 'OAuth access token scopes not rewritten as expected'
exit(1)
end

View File

@ -5,7 +5,7 @@ require 'rails_helper'
RSpec.describe OAuth::AuthorizationsController do
render_views
let(:app) { Doorkeeper::Application.create!(name: 'test', redirect_uri: 'http://localhost/', scopes: 'read') }
let(:app) { OAuth::Application.create!(name: 'test', redirect_uri: 'http://localhost/', scopes: 'read') }
describe 'GET #new' do
subject do
@ -34,7 +34,7 @@ RSpec.describe OAuth::AuthorizationsController do
context 'when app is already authorized' do
before do
Doorkeeper::AccessToken.find_or_create_for(
OAuth::AccessToken.find_or_create_for(
application: app,
resource_owner: user.id,
scopes: app.scopes,

View File

@ -55,7 +55,7 @@ RSpec.describe OAuth::AuthorizedApplicationsController do
it 'revokes access tokens for the application and removes subscriptions and sends kill payload to streaming' do
post :destroy, params: { id: application.id }
expect(Doorkeeper::AccessToken.where(application: application).first.revoked_at)
expect(OAuth::AccessToken.where(application: application).first.revoked_at)
.to_not be_nil
expect(Web::PushSubscription.where(user: user).count)
.to eq(0)

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
Fabricator :access_grant, from: 'Doorkeeper::AccessGrant' do
Fabricator :access_grant, from: OAuth::AccessGrant do
application
resource_owner_id { Fabricate(:user).id }
expires_in 3_600

View File

@ -1,3 +1,3 @@
# frozen_string_literal: true
Fabricator :access_token, from: 'Doorkeeper::AccessToken'
Fabricator :access_token, from: OAuth::AccessToken

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
Fabricator(:application, from: Doorkeeper::Application) do
Fabricator(:application, from: OAuth::Application) do
name 'Example'
website 'http://example.com'
redirect_uri 'http://example.com/callback'

View File

@ -2,7 +2,7 @@
require 'rails_helper'
RSpec.describe Doorkeeper::AccessGrant do
RSpec.describe OAuth::AccessGrant do
describe 'Validations' do
subject { Fabricate :access_grant }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
RSpec.describe Doorkeeper::AccessToken do
RSpec.describe OAuth::AccessToken do
describe 'Associations' do
it { is_expected.to have_many(:web_push_subscriptions).class_name('Web::PushSubscription').inverse_of(:access_token) }
end

View File

@ -2,7 +2,7 @@
require 'rails_helper'
RSpec.describe Doorkeeper::Application do
RSpec.describe OAuth::Application do
describe 'Associations' do
it { is_expected.to have_many(:created_users).class_name('User').inverse_of(:created_by_application).with_foreign_key(:created_by_application_id) }
end

View File

@ -345,7 +345,7 @@ RSpec.describe User do
it 'creates and returns a persisted token' do
expect { user.token_for_app(app) }
.to change(Doorkeeper::AccessToken.where(resource_owner_id: user.id, application: app), :count).by(1)
.to change(OAuth::AccessToken.where(resource_owner_id: user.id, application: app), :count).by(1)
end
end
@ -355,7 +355,7 @@ RSpec.describe User do
it 'returns a persisted token' do
expect(user.token_for_app(app))
.to be_a(Doorkeeper::AccessToken)
.to be_a(OAuth::AccessToken)
.and eq(token)
end
end
@ -437,7 +437,7 @@ RSpec.describe User do
end
def remove_active_user_tokens
change { Doorkeeper::AccessToken.active_for(user).count }.to(0)
change { OAuth::AccessToken.active_for(user).count }.to(0)
end
def remove_user_web_subscriptions

View File

@ -31,7 +31,7 @@ RSpec.describe 'Apps' do
expect(response.content_type)
.to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
app = OAuth::Application.find_by(name: client_name)
expect(app).to be_present
expect(app.scopes.to_s).to eq scopes
@ -64,7 +64,7 @@ RSpec.describe 'Apps' do
expect(response).to have_http_status(200)
expect(response.content_type)
.to start_with('application/json')
expect(Doorkeeper::Application.find_by(name: client_name)).to be_present
expect(OAuth::Application.find_by(name: client_name)).to be_present
expect(response.parsed_body)
.to include(
@ -84,7 +84,7 @@ RSpec.describe 'Apps' do
expect(response.content_type)
.to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
app = OAuth::Application.find_by(name: client_name)
expect(app).to be_present
expect(app.scopes.to_s).to eq 'read'
@ -117,12 +117,12 @@ RSpec.describe 'Apps' do
expect(response).to have_http_status(200)
expect(response.content_type)
.to start_with('application/json')
expect(Doorkeeper::Application.find_by(name: client_name).scopes.to_s).to eq 'read'
expect(OAuth::Application.find_by(name: client_name).scopes.to_s).to eq 'read'
end
end
context 'with a too-long name' do
let(:client_name) { 'a' * Doorkeeper::Application::APP_NAME_LIMIT * 2 }
let(:client_name) { 'a' * OAuth::Application::APP_NAME_LIMIT * 2 }
it 'returns http unprocessable entity' do
subject
@ -134,7 +134,7 @@ RSpec.describe 'Apps' do
end
context 'with a too-long website' do
let(:website) { "https://foo.bar/#{'a' * Doorkeeper::Application::APP_WEBSITE_LIMIT * 2}" }
let(:website) { "https://foo.bar/#{'a' * OAuth::Application::APP_WEBSITE_LIMIT * 2}" }
it 'returns http unprocessable entity' do
subject
@ -146,7 +146,7 @@ RSpec.describe 'Apps' do
end
context 'with a too-long redirect_uri' do
let(:redirect_uris) { "https://app.example/#{'a' * Doorkeeper::Application::APP_REDIRECT_URI_LIMIT * 2}" }
let(:redirect_uris) { "https://app.example/#{'a' * OAuth::Application::APP_REDIRECT_URI_LIMIT * 2}" }
it 'returns http unprocessable entity' do
subject
@ -180,7 +180,7 @@ RSpec.describe 'Apps' do
expect(response.content_type)
.to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
app = OAuth::Application.find_by(name: client_name)
expect(app).to be_present
expect(app.redirect_uri).to eq redirect_uris
@ -204,7 +204,7 @@ RSpec.describe 'Apps' do
expect(response.content_type)
.to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
app = OAuth::Application.find_by(name: client_name)
expect(app).to be_present
expect(app.redirect_uri).to eq redirect_uris.join "\n"
@ -276,7 +276,7 @@ RSpec.describe 'Apps' do
expect(response.content_type)
.to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
app = OAuth::Application.find_by(name: client_name)
expect(app).to be_present
expect(app.website).to eq website

View File

@ -169,7 +169,7 @@ RSpec.describe 'Caching behavior' do
let(:alice) { Account.find_by(username: 'alice') }
let(:user) { User.find_by(email: 'user@host.example') }
let(:token) { Doorkeeper::AccessToken.find_by(resource_owner_id: user.id) }
let(:token) { OAuth::AccessToken.find_by(resource_owner_id: user.id) }
before_all do
alice = Fabricate(:account, username: 'alice')

View File

@ -25,7 +25,7 @@ RSpec.describe 'Settings / Exports' do
let(:params) do
{
doorkeeper_application: {
oauth_application: {
name: 'My New App',
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
website: 'http://google.com',
@ -36,13 +36,13 @@ RSpec.describe 'Settings / Exports' do
it 'supports passing scope values as string' do
expect { subject }
.to change(Doorkeeper::Application, :count).by(1)
.to change(OAuth::Application, :count).by(1)
expect(response)
.to redirect_to(settings_applications_path)
end
it 'gracefully handles invalid nested params' do
post settings_applications_path(doorkeeper_application: 'invalid')
post settings_applications_path(oauth_application: 'invalid')
expect(response)
.to have_http_status(400)
@ -53,7 +53,7 @@ RSpec.describe 'Settings / Exports' do
let(:application) { Fabricate :application, owner: user }
it 'gracefully handles invalid nested params' do
put settings_application_path(application.id, doorkeeper_application: 'invalid')
put settings_application_path(application.id, oauth_application: 'invalid')
expect(response)
.to have_http_status(400)

View File

@ -68,7 +68,7 @@ RSpec.describe 'Auth Passwords' do
end
def user_token_count
Doorkeeper::AccessToken
OAuth::AccessToken
.active_for(user)
.count
end

View File

@ -7,7 +7,7 @@ RSpec.describe 'Using OAuth from an external app' do
subject { visit "/oauth/authorize?#{params.to_query}" }
let(:client_app) { Doorkeeper::Application.create!(name: 'test', redirect_uri: about_url(host: Rails.application.config.x.local_domain), scopes: 'read') }
let(:client_app) { OAuth::Application.create!(name: 'test', redirect_uri: about_url(host: Rails.application.config.x.local_domain), scopes: 'read') }
let(:params) do
{ client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' }
end
@ -264,7 +264,7 @@ RSpec.describe 'Using OAuth from an external app' do
end
def user_has_grant_with_client_app?
Doorkeeper::AccessGrant
OAuth::AccessGrant
.exists?(
application: client_app,
resource_owner_id: user.id

View File

@ -34,7 +34,7 @@ RSpec.describe 'Settings applications page' do
fill_in_form
expect { submit_form }
.to change(Doorkeeper::Application, :count).by(1)
.to change(OAuth::Application, :count).by(1)
expect(page)
.to have_content(I18n.t('doorkeeper.applications.index.title'))
.and have_content('My new app')
@ -47,7 +47,7 @@ RSpec.describe 'Settings applications page' do
visit new_settings_application_path
expect { submit_form }
.to not_change(Doorkeeper::Application, :count)
.to not_change(OAuth::Application, :count)
expect(page)
.to have_content("can't be blank")
end
@ -60,9 +60,9 @@ RSpec.describe 'Settings applications page' do
fill_in I18n.t('activerecord.attributes.doorkeeper/application.redirect_uri'),
with: 'urn:ietf:wg:oauth:2.0:oob'
check 'read', id: :doorkeeper_application_scopes_read
check 'write', id: :doorkeeper_application_scopes_write
check 'follow', id: :doorkeeper_application_scopes_follow
check 'read', id: :oauth_application_scopes_read
check 'write', id: :oauth_application_scopes_write
check 'follow', id: :oauth_application_scopes_follow
end
def submit_form
@ -76,12 +76,12 @@ RSpec.describe 'Settings applications page' do
fill_in form_app_name_label,
with: 'My new app name with a new value'
check 'push', id: :doorkeeper_application_scopes_push
check 'push', id: :oauth_application_scopes_push
submit_form
expect(page)
.to have_content('My new app name with a new value')
.and have_checked_field('push', id: :doorkeeper_application_scopes_push)
.and have_checked_field('push', id: :oauth_application_scopes_push)
end
it 'does not update with wrong values' do
@ -110,7 +110,7 @@ RSpec.describe 'Settings applications page' do
visit settings_applications_path
expect { destroy_application }
.to change(Doorkeeper::Application, :count).by(-1)
.to change(OAuth::Application, :count).by(-1)
expect(page)
.to have_no_content(application.name)
expect(redis_pipeline_stub)