Drop support for global user merges

Global user merges are currently not supported due to various issues,
and the UserMerge extension is unmaintained and waiting for
undeployment[0]. To partially unblock that, this patch drops all code
required for global user merges (which have been disabled on Wikimedia
wikis anyways for years).

The user merge log formatter is kept, as it is required to not break the
existing log entries. Similarly the hook handler for the DeleteAccount
hook (from UserMerge) is kept, as policy still technically requires that
all extensions support UserMerge while it is deployed on Wikimedia
wikis.

[0]: https://phabricator.wikimedia.org/T216089

Bug: T216089
Change-Id: I3860d3d644e58ced703a466aaea3433d8c0eb9fc
这个提交包含在:
Taavi Väänänen 2021-12-11 14:32:15 +02:00
父节点 585abd609a
当前提交 e8c0ead8d1
找不到此签名对应的密钥
GPG 密钥 ID: EF242F709F912FBE
共有 11 个文件被更改,包括 4 次插入827 次删除

查看文件

@ -14,7 +14,6 @@ $cfg['directory_list'] = array_merge(
'../../extensions/Renameuser',
'../../extensions/SecurePoll',
'../../extensions/TitleBlacklist',
'../../extensions/UserMerge',
]
);
@ -29,7 +28,6 @@ $cfg['exclude_analysis_directory_list'] = array_merge(
'../../extensions/Renameuser',
'../../extensions/SecurePoll',
'../../extensions/TitleBlacklist',
'../../extensions/UserMerge',
]
);

查看文件

@ -21,7 +21,6 @@ $specialPageAliases['en'] = [
'MultiLock' => [ 'MultiLock' ],
'GlobalRenameUser' => [ 'GlobalRenameUser' ],
'GlobalRenameProgress' => [ 'GlobalRenameProgress' ],
'GlobalUserMerge' => [ 'GlobalUserMerge' ],
'GlobalRenameRequest' => [ 'GlobalRenameRequest' ],
'GlobalRenameQueue' => [ 'GlobalRenameQueue' ],
'SulRenameWarning' => [ 'SulRenameWarning' ],
@ -45,7 +44,6 @@ $specialPageAliases['ar'] = [
'MultiLock' => [ 'قفل_متعدد' ],
'GlobalRenameUser' => [ 'إعادة_تسمية_مستخدم_عامة' ],
'GlobalRenameProgress' => [ 'تطور_إعادة_تسمية_عامة' ],
'GlobalUserMerge' => [ 'دمج_مستخدم_عام' ],
'GlobalRenameRequest' => [ 'طلب_إعادة_تسمية_عام' ],
'GlobalRenameQueue' => [ 'طابور|_إعادة_تسمية_عام' ],
'SulRenameWarning' => [ 'تحذير_إعادة_تسمية_إس_يو_إل' ],
@ -101,7 +99,6 @@ $specialPageAliases['bn'] = [
'MultiLock' => [ 'বহুবাধা' ],
'GlobalRenameUser' => [ 'বৈশ্বিক_ব্যবহারকারী_নামান্তর', 'বৈশ্বিক_ব্যবহারকারী_পুনঃনামকরণ' ],
'GlobalRenameProgress' => [ 'বৈশ্বিক_নামান্তরের_অগ্রগতি' ],
'GlobalUserMerge' => [ 'বৈশ্বিক_ব্যবহারকারী_একত্রীকরণ' ],
'GlobalRenameRequest' => [ 'বৈশ্বিক_নামান্তরের_অনুরোধ' ],
'GlobalRenameQueue' => [ 'বৈশ্বিক_নামান্তরের_সারি' ],
'SulRenameWarning' => [ 'SUL_নামান্তরের_সতর্কবার্তা' ],
@ -127,7 +124,6 @@ $specialPageAliases['bgn'] = [
'MultiLock' => [ 'چینکه_قُلپی' ],
'GlobalRenameUser' => [ ارمرزوکی_نامی_سراسرین_تغیر' ],
'GlobalRenameProgress' => [ 'سراسرین_نامی_تغیری_پیشرپت' ],
'GlobalUserMerge' => [ 'سراسرین_کارمرزوکی_ادغام' ],
'GlobalRenameRequest' => [ 'درخواست_په_سراسرین_کامرزوکی_ادغاما' ],
'GlobalRenameQueue' => [ 'سراسرین_نامی_سپ_ئی_تغیر' ],
'SulRenameWarning' => [ 'سراسرین_نامی_تغیر_ئی_هشدار' ],
@ -198,7 +194,6 @@ $specialPageAliases['cs'] = [
'MultiLock' => [ 'Hromadné_zamknutí' ],
'GlobalRenameUser' => [ 'Globální_přejmenování_uživatele' ],
'GlobalRenameProgress' => [ 'Průběh_globálního_přejmenování' ],
'GlobalUserMerge' => [ 'Sloučení_globálního_uživatele' ],
'GlobalRenameRequest' => [ 'Žádost_o_globální_přejmenování' ],
'GlobalRenameQueue' => [ 'Fronta_globálních_přejmenování' ],
];
@ -214,7 +209,6 @@ $specialPageAliases['de'] = [
'MultiLock' => [ 'Mehrfachsperre' ],
'GlobalRenameUser' => [ 'Globale_Benutzerumbenennung' ],
'GlobalRenameProgress' => [ 'Globaler_Umbenennungsfortschritt' ],
'GlobalUserMerge' => [ 'Globale_Benutzerzusammenführung' ],
'GlobalRenameRequest' => [ 'Globale_Umbenennungsanfrage' ],
'GlobalRenameQueue' => [ 'Globale_Umbenennungs-Warteschlange' ],
'SulRenameWarning' => [ 'SUL-Umbenennungswarnung' ],
@ -295,7 +289,6 @@ $specialPageAliases['fa'] = [
'MultiLock' => [ 'چندقفلی' ],
'GlobalRenameUser' => [ 'تغییر_سراسری_نام_کاربر' ],
'GlobalRenameProgress' => [ 'پیشرفت_تغییر_نام_سراسری' ],
'GlobalUserMerge' => [ 'ادغام_کاربر_سراسری' ],
'GlobalRenameRequest' => [ 'درخواست_ادغام_کاربر_سراسری' ],
'GlobalRenameQueue' => [ 'صف_تغییر_نام_سراسری' ],
'SulRenameWarning' => [ 'هشدار_تغییر_نام_سراسری' ],
@ -367,7 +360,6 @@ $specialPageAliases['he'] = [
'MultiLock' => [ 'נעילה_מרובה' ],
'GlobalRenameUser' => [ ינוי_שם_משתמש_גלובלי' ],
'GlobalRenameProgress' => [ 'התקדמות_שינוי_שם_משתמש_גלובלי' ],
'GlobalUserMerge' => [ יזוג_חשבון_גלובלי' ],
'GlobalRenameRequest' => [ 'בקשת_שינוי_שם_גלובלית' ],
'GlobalRenameQueue' => [ ור_שינויי_שם_גלובלי' ],
'SulRenameWarning' => [ 'אזהרה_שינוי_שם_של_SUL' ],
@ -473,7 +465,6 @@ $specialPageAliases['ja'] = [
'MultiLock' => [ '複数利用者ロック' ],
'GlobalRenameUser' => [ 'グローバル利用者名変更', 'グローバル改名', 'グローバル利用者名の変更' ],
'GlobalRenameProgress' => [ 'グローバル利用者名変更状況', 'グローバル利用者名変更の進捗' ],
'GlobalUserMerge' => [ 'グローバル利用者統合' ],
'GlobalRenameRequest' => [ 'グローバル利用者名変更依頼', 'グローバル利用者アカウントの改名依頼' ],
'GlobalRenameQueue' => [ 'グローバル利用者名変更依頼待ち', 'グローバル利用者名変更依頼の対応待ち' ],
];
@ -500,7 +491,6 @@ $specialPageAliases['ko'] = [
'MultiLock' => [ '다중잠금' ],
'GlobalRenameUser' => [ '전역사용자이름바꾸기' ],
'GlobalRenameProgress' => [ '전역이름바꾸기진행' ],
'GlobalUserMerge' => [ '전역사용자병합' ],
'GlobalRenameRequest' => [ '전역이름바꾸기요청' ],
];
@ -541,7 +531,6 @@ $specialPageAliases['lb'] = [
'MultiLock' => [ 'Méifach_Spär' ],
'GlobalRenameUser' => [ 'Global_Benotzerëmbenennung' ],
'GlobalRenameProgress' => [ 'Progrès_vun_der_globaler_Ëmbenennung' ],
'GlobalUserMerge' => [ 'Global_Benotzer_Fusioun' ],
'GlobalRenameRequest' => [ 'Global_Ufro_fir_Benotzer_ëmzebenennen' ],
'GlobalRenameQueue' => [ 'Lëscht_vun_de_globalen_Ëmbenennungen_déi_am_Gaang_sinn' ],
'SulRenameWarning' => [ 'Warnung_bei_der_SUL_Ëmbenennung' ],
@ -558,7 +547,6 @@ $specialPageAliases['lrc'] = [
'MultiLock' => [ 'چأن_قولفە' ],
'GlobalRenameUser' => [ 'د_نۊ_نوم_نیائن_جأھوٙنی_کاریار' ],
'GlobalRenameProgress' => [ 'پیشکئرد_د_نوٙ_نوٙم_نیائن_کاریار' ],
'GlobalUserMerge' => [ 'سأریأک_کاری_جأھوٙنی_کاریار' ],
'GlobalRenameRequest' => [ است_د_نۊ_نوٙم_نیائن_جأھوٙنی' ],
'GlobalRenameQueue' => [ 'گئی_بأنی_د_نۊ_نوٙم_نیائن_جأھوٙنی' ],
'SulRenameWarning' => [ 'ھشدار_تأک_کاری_د_نۊ_نوٙم_نیائن' ],
@ -578,7 +566,6 @@ $specialPageAliases['mg'] = [
'GlobalUsers' => [ 'Mpikambana_maneran-tsehatra', 'MpikambanaManerantsehatra' ],
'GlobalRenameUser' => [ 'Fanovan\'anaram-pikambana_maneran-tsehatra' ],
'GlobalRenameProgress' => [ 'Fandrosoan\'ny_fiovan\'anarana_maneran-tsehatra' ],
'GlobalUserMerge' => [ 'Fampitsoniham-pikambana_maneran-tsehatra' ],
];
/** Minangkabau (Baso Minangkabau) */
@ -601,7 +588,6 @@ $specialPageAliases['mk'] = [
'MultiLock' => [ 'ПовеќекратноЗаклучување' ],
'GlobalRenameUser' => [ 'ГлобалноПреименувањеКорисник' ],
'GlobalRenameProgress' => [ 'ГлобалноПреименувањеНапредок' ],
'GlobalUserMerge' => [ 'ГлобалноСпојувањеКорисник' ],
'GlobalRenameRequest' => [ 'ГлобалноСпојувањеБарање' ],
'GlobalRenameQueue' => [ 'РедицаГлобалноПреименување' ],
'SulRenameWarning' => [ редупредувањеПреименувањеSUL' ],
@ -662,7 +648,6 @@ $specialPageAliases['nb'] = [
'WikiSets' => [ 'Wikisett', 'Rediger_wikisett' ],
'GlobalUsers' => [ 'Globale_brukere' ],
'GlobalRenameUser' => [ 'Gi_en_bruker_nytt_navn_globalt' ],
'GlobalUserMerge' => [ 'Global_brukersammenslåing' ],
'GlobalRenameRequest' => [ 'Forespørsel_om_global_brukernavnendring' ],
'UsersWhoWillBeRenamed' => [ 'Brukere_som_vil_endre_navn' ],
];
@ -689,7 +674,6 @@ $specialPageAliases['nl'] = [
'MultiLock' => [ 'MeervoudigAfsluiten' ],
'GlobalRenameUser' => [ 'GlobaalGebruikerhernoemen' ],
'GlobalRenameProgress' => [ 'VoortgangGlobaalHernoemen' ],
'GlobalUserMerge' => [ 'GlobaalGebruikerSamenvoegen' ],
'GlobalRenameRequest' => [ 'GlobaalHernoemingsverzoek' ],
'GlobalRenameQueue' => [ 'WachtrijGlobaalHernoemen' ],
'SulRenameWarning' => [ 'SulHernoemingswaarschuwing' ],
@ -830,7 +814,6 @@ $specialPageAliases['sr-ec'] = [
'MultiLock' => [ 'Вишеструкоакључавање' ],
'GlobalRenameUser' => [ 'Глобално_преименовањеорисника' ],
'GlobalRenameProgress' => [ 'Напредак_глобалног_преименовања' ],
'GlobalUserMerge' => [ 'Глобално_спајањеорисника' ],
'GlobalRenameRequest' => [ 'Глобални_захтев_за_преименовање' ],
'GlobalRenameQueue' => [ 'Глобални_ред_за_преименовање' ],
'SulRenameWarning' => [ 'Упозорење_о_преименовању' ],
@ -849,7 +832,6 @@ $specialPageAliases['sr-el'] = [
'MultiLock' => [ 'Višestruko_zaključavanje' ],
'GlobalRenameUser' => [ 'Globalno_preimenovanje_korisnika' ],
'GlobalRenameProgress' => [ 'Napredak_globalnog_preimenovanja' ],
'GlobalUserMerge' => [ 'Globalno_spajanje_korisnika' ],
'GlobalRenameRequest' => [ 'Globalni_zahtev_za_preimenovanje' ],
'GlobalRenameQueue' => [ 'Globalni_red_za_preimenovanje' ],
'SulRenameWarning' => [ 'Upozorenje_o_preimenovanju' ],
@ -871,7 +853,6 @@ $specialPageAliases['sv'] = [
'GlobalUsers' => [ 'Globala_användare' ],
'GlobalRenameUser' => [ 'Globalt_användarnamnsbyte' ],
'GlobalRenameProgress' => [ 'Globalt_namnbytesförlopp' ],
'GlobalUserMerge' => [ 'Global_användarsammanslagning' ],
];
/** Swahili (Kiswahili) */
@ -926,7 +907,6 @@ $specialPageAliases['ur'] = [
'MultiLock' => [ 'متعدد_قفل' ],
'GlobalRenameUser' => [ المی_تبدیلی_صارف_نام' ],
'GlobalRenameProgress' => [ 'پیشرفت_عالمی_تبدیلی_نام' ],
'GlobalUserMerge' => [ 'ضم_عالمی_صارف' ],
'GlobalRenameRequest' => [ 'درخواست_تبدیلی_عالمی_نام' ],
'GlobalRenameQueue' => [ 'قطار_عالمی_تبدیلی_نام' ],
'SulRenameWarning' => [ 'انتباہالمی_تبدیلی_نام' ],
@ -952,7 +932,6 @@ $specialPageAliases['vi'] = [
'MultiLock' => [ 'Khóa_tài_khoản_toàn_cục' ],
'GlobalRenameUser' => [ 'Đổi_tên_thành_viên_toàn_cục', 'Đổi_tên_người_dùng_toàn_cục' ],
'GlobalRenameProgress' => [ 'Tiến_độ_đổi_tên_toàn_cục' ],
'GlobalUserMerge' => [ 'Hợp_nhất_người_dùng_toàn_cục', 'Hợp_nhất_thành_viên_toàn_cục' ],
'GlobalRenameRequest' => [ 'Yêu_cầu_đổi_tên_toàn_cục' ],
'GlobalRenameQueue' => [ 'Hàng_đợi_đổi_tên_toàn_cục' ],
'SulRenameWarning' => [ 'Cảnh_báo_đổi_tên_tài_khoản_hợp_nhất' ],
@ -974,7 +953,6 @@ $specialPageAliases['zh-hans'] = [
'MultiLock' => [ '批量锁定' ],
'GlobalRenameUser' => [ '全域重命名用户' ],
'GlobalRenameProgress' => [ '全域重命名状态' ],
'GlobalUserMerge' => [ '全域用户合并' ],
'GlobalRenameRequest' => [ '全域重命名申请' ],
'GlobalRenameQueue' => [ '全域重命名队列' ],
'SulRenameWarning' => [ 'SUL重命名警告' ],
@ -992,7 +970,6 @@ $specialPageAliases['zh-hant'] = [
'MultiLock' => [ '批次鎖定' ],
'GlobalRenameUser' => [ '全域重新命名使用者' ],
'GlobalRenameProgress' => [ '全域重新命名進度' ],
'GlobalUserMerge' => [ '全域使用者合併', '全域用户合併' ],
'GlobalRenameRequest' => [ '全域重命名申請' ],
'GlobalRenameQueue' => [ '全域重命名佇列' ],
'UsersWhoWillBeRenamed' => [ '將被重命名的使用者' ],

查看文件

@ -62,8 +62,7 @@
"centralauth-oversight",
"globalgrouppermissions",
"globalgroupmembership",
"centralauth-rename",
"centralauth-usermerge"
"centralauth-rename"
],
"SessionProviders": {
"CentralAuthSessionProvider": {
@ -183,18 +182,11 @@
"UserNameUtils",
"CentralAuth.CentralAuthUIService"
]
},
"GlobalUserMerge": {
"class": "MediaWiki\\Extension\\CentralAuth\\Special\\SpecialGlobalUserMerge",
"services": [
"UserNameUtils"
]
}
},
"JobClasses": {
"crosswikiSuppressUser": "CentralAuthSuppressUserJob",
"LocalRenameUserJob": "MediaWiki\\Extension\\CentralAuth\\GlobalRename\\LocalRenameJob\\LocalRenameUserJob",
"LocalUserMergeJob": "MediaWiki\\Extension\\CentralAuth\\GlobalRename\\LocalRenameJob\\LocalUserMergeJob",
"LocalPageMoveJob": "MediaWiki\\Extension\\CentralAuth\\GlobalRename\\LocalRenameJob\\LocalPageMoveJob",
"CentralAuthCreateLocalAccountJob": "CentralAuthCreateLocalAccountJob",
"CentralAuthUnattachUserJob": "CentralAuthUnattachUserJob"
@ -457,8 +449,7 @@
"mediawiki.util"
],
"messages": [
"centralauth-rename-confirm",
"centralauth-usermerge-confirm"
"centralauth-rename-confirm"
]
},
"ext.centralauth.ForeignApi": {
@ -757,10 +748,6 @@
"description": "Don't allow new unattached accounts to be created",
"value": false
},
"CentralAuthEnableUserMerge": {
"description": "Whether to enable the global user merge tool This only controls the availability of the special page, and does not prevent LocalUserMergeJobs from running on the given wiki.",
"value": false
},
"CentralAuthEnableUsersWhoWillBeRenamed": {
"description": "Feature flag for Special:UsersWhoWillBeRenamed",
"value": false

查看文件

@ -37,7 +37,6 @@
"action-centralauth-oversight": "suppress or hide global account",
"action-centralauth-rename": "rename global accounts",
"action-centralauth-unmerge": "unmerge global accounts",
"action-centralauth-usermerge": "globally merge multiple users",
"action-globalgroupmembership": "edit membership to global groups",
"action-globalgrouppermissions": "manage global groups",
"centralauth": "Global account manager",
@ -395,21 +394,6 @@
"centralauth-seconds-ago": "$1 {{PLURAL:$1|second|seconds}} ago",
"centralauth-state-mismatch": "Error: An edit conflict for this user was detected. Please verify your change and try again.",
"centralauth-token-mismatch": "Sorry, we could not process your form submission due to a loss of session data.",
"centralauth-usermerge-already": "There is already a global rename or merge in progress for $1.",
"centralauth-usermerge-confirm": "Do you really want to globally merge these users?",
"centralauth-usermerge-disabled": "The global user merge tool is disabled.",
"centralauth-usermerge-form-adduser": "Add user",
"centralauth-usermerge-form-deleteuser": "Remove user",
"centralauth-usermerge-form-newuser": "Final username",
"centralauth-usermerge-form-reason": "Reason",
"centralauth-usermerge-form-usernames": "Current usernames",
"centralauth-usermerge-invalid": "There is no global account with the name \"$1\".",
"centralauth-usermerge-noself": "You cannot merge accounts with yourself.",
"centralauth-usermerge-notinstalled": "The UserMerge extension is not installed.",
"centralauth-usermerge-nousers": "At least two valid global user accounts must be provided.",
"centralauth-usermerge-queued": "Merges for $1 into $2 have been queued.\n\nView the progress at [[Special:GlobalRenameProgress/$3]].",
"centralauth-usermerge-ratelimited": "As a security measure, you are only allowed to globally merge a user once per minute. Please try again after one minute.",
"centralauth-usermerge-toomany": "Only $1 {{PLURAL:$1|user|users}} can be merged at once.",
"centralauth-uwbr-editcount": "Edit count",
"centralauth-uwbr-intro": "This page lists users registered with this wiki who will be renamed.",
"centralauth-uwbr-name": "User name",
@ -499,8 +483,6 @@
"globalrenamerequest-username-label": "Current username:",
"globalrenameuser": "Rename global user",
"globalrenameuser-legend": "Rename global user",
"globalusermerge": "Merge global user",
"globalusermerge-legend": "Merge global user",
"globalusers": "Global accounts list",
"grant-createlocalaccount": "Forcibly create a local account for a global account",
"grant-setglobalaccountstatus": "Manage global account status",
@ -539,7 +521,6 @@
"right-centralauth-oversight": "Suppress or hide global account",
"right-centralauth-rename": "Rename global accounts",
"right-centralauth-unmerge": "Unmerge global account",
"right-centralauth-usermerge": "Globally merge multiple users",
"right-globalgroupmembership": "Edit membership to global groups",
"right-globalgrouppermissions": "Manage global groups",
"sessionprovider-centralauthsessionprovider": "central cookie-based sessions",

查看文件

@ -59,7 +59,6 @@
"action-centralauth-oversight": "{{doc-action|centralauth-oversight}}",
"action-centralauth-rename": "{{doc-action|centralauth-rename}}",
"action-centralauth-unmerge": "{{doc-action|centralauth-unmerge}}",
"action-centralauth-usermerge": "{{doc-action|centralauth-usermerge}}",
"action-globalgroupmembership": "{{doc-action|globalgroupmembership}}",
"action-globalgrouppermissions": "{{doc-action|globalgrouppermissions}}",
"centralauth": "{{doc-special|CentralAuth}}",
@ -372,7 +371,7 @@
"centralauth-rename-antispoofconflicts2": "Error message shown if the username conflicts in AntiSpoof either because of similarity or the target used to be someone else's username. $1 is a comma-separated list of conflicting usernames. $2 is number of conflicting usernames - for use with PLURAL.",
"centralauth-rename-badusername": "Error message if the new username is not valid.",
"centralauth-rename-cannotself": "Error message if the user tries renaming themselves.",
"centralauth-rename-confirm": "Confirmation text asking whether the global account should really be renamed.\n\nSee also:\n* {{msg-mw|Centralauth-usermerge-confirm}}",
"centralauth-rename-confirm": "Confirmation text asking whether the global account should really be renamed.",
"centralauth-rename-conflict-hidden": "Text displayed instead of the username if the user has been hidden",
"centralauth-rename-deny": "Confirm text asking whether the global rename request should really be denied.",
"centralauth-rename-desc": "{{desc|name=Renameuser for CentralAuth|url=https://www.mediawiki.org/wiki/Extension:CentralAuth}}\nSee also:\n* {{msg-mw|Centralauth-antispoof-desc}}",
@ -417,21 +416,6 @@
"centralauth-seconds-ago": "Parameters:\n* $1 - number of seconds\n{{Related|Centralauth-ago}}",
"centralauth-state-mismatch": "Error message when another admin has updated the user, and an edit conflict was detected.\n\nSee also:\n* {{msg-mw|Centralauth-token-mismatch}}\n* {{msg-mw|Centralauth-admin-bad-input}}",
"centralauth-token-mismatch": "Used as error message.\n\nSee also:\n* {{msg-mw|Centralauth-state-mismatch}}\n* {{msg-mw|Centralauth-admin-bad-input}}\n{{Identical|Loss of session data}}",
"centralauth-usermerge-already": "Error message if a user is already being globally renamed or merged.\n\nParmaeters:\n* $1 - the user's username",
"centralauth-usermerge-confirm": "Confirmation message displayed in a JavaScript alert before the form is submitted.\n\nSee also:\n* {{msg-mw|Centralauth-rename-confirm}}",
"centralauth-usermerge-disabled": "Error message shown if the special page is disabled through $wgCentralAuthEnableUserMerge",
"centralauth-usermerge-form-adduser": "Label on button that when clicked adds a new form field to input a username into.\n{{Identical|Add user}}",
"centralauth-usermerge-form-deleteuser": "Label on button that when clicked removes the associated form field.\n{{Identical|Remove user}}",
"centralauth-usermerge-form-newuser": "Label for form field",
"centralauth-usermerge-form-reason": "Label for form field.\n{{Identical|Reason}}",
"centralauth-usermerge-form-usernames": "Label for form field",
"centralauth-usermerge-invalid": "Error message shown if the user enters invalid input. Parameters:\n* $1 - the invalid input",
"centralauth-usermerge-noself": "Error message shown if a user tries merging accounts with themselves.",
"centralauth-usermerge-notinstalled": "Error message shown if Extension:UserMerge is not installed",
"centralauth-usermerge-nousers": "Error message shown if a user does not provide two or more users to merge.",
"centralauth-usermerge-queued": "Message shown after successfully submitting the form. Parameters:\n* $1 - a comma-separated list of users who are being merged into\n* $2 - a link to the final username's [[Special:CentralAuth]] page\n* $3 - the raw final username",
"centralauth-usermerge-ratelimited": "Error message shown when a user hits the rate limit of one global merge per minute.",
"centralauth-usermerge-toomany": "Error message shown when a user tries to merge more than the maximum number of users.\n\nParameters:\n* $1 - the maximum number of users that can be merged",
"centralauth-uwbr-editcount": "Heading for column in table",
"centralauth-uwbr-intro": "Text above table which lists users who will be renamed.",
"centralauth-uwbr-name": "Heading for column in table\n{{Identical|Username}}",
@ -521,8 +505,6 @@
"globalrenamerequest-username-label": "Form field label.",
"globalrenameuser": "{{doc-special|GlobalRenameUser}}",
"globalrenameuser-legend": "Label for fieldset around the form on Special:GlobalRenameUser",
"globalusermerge": "Name of special page",
"globalusermerge-legend": "Legend of fieldset surrounding the form",
"globalusers": "{{doc-special|GlobalUsers}}\nSee example: [[w:Special:GlobalUsers]] and [[w:Special:SpecialPages]]",
"grant-createlocalaccount": "Name for grant \"createlocalaccount\".\n{{Related|Grant}}",
"grant-setglobalaccountstatus": "Name for grant \"setglobalaccountstatus\".\n{{Related|Grant}}",
@ -561,7 +543,6 @@
"right-centralauth-oversight": "{{doc-right|centralauth-oversight}}",
"right-centralauth-rename": "{{doc-right|centralauth-rename}}",
"right-centralauth-unmerge": "{{doc-right|centralauth-unmerge}}\nThis is the opposite of merging a local (unlinked) account to a global account. It doesn't imply the complete disgregation of the global account, as even a single local account can be unmerged.",
"right-centralauth-usermerge": "{{doc-right|centralauth-usermerge}}",
"right-globalgroupmembership": "{{doc-right|globalgroupmembership}}",
"right-globalgrouppermissions": "{{doc-right|globalgrouppermissions}}",
"sessionprovider-centralauthsessionprovider": "Description of the sessions provided by the CentralAuthSessionProvider class, which use HTTP cookies. Should be phrased to make sense when added to a message such as {{msg-mw|cannotloginnow-text}}.",

查看文件

@ -1,213 +0,0 @@
<?php
namespace MediaWiki\Extension\CentralAuth\GlobalRename;
use CentralAuthUser;
use Hooks;
use MediaWiki\Extension\CentralAuth\GlobalRename\LocalRenameJob\LocalUserMergeJob;
use MediaWiki\Logger\LoggerFactory;
use Status;
use Title;
use User;
/**
* Merge a global user
*
* @license GPL-2.0-or-later
* @author Marius Hoch < hoo@online.de >
* @author Kunal Mehta < legoktm@gmail.com >
*/
class GlobalUserMerge {
/**
* @var User
*/
private $performingUser;
/**
* @var CentralAuthUser[]
*/
private $oldCAUsers;
/**
* @var CentralAuthUser
*/
private $newCAUser;
/**
* @var GlobalRenameUserStatus
*/
private $renameuserStatus;
/**
* @var callable
*/
private $jobQueueGroupGenerator;
/**
* @var GlobalUserMergeDatabaseUpdates
*/
private $databaseUpdates;
/**
* @var GlobalUserMergeLogger
*/
private $logger;
/**
* @var array
*/
private $session;
/**
* @param User $performingUser
* @param CentralAuthUser[] $oldCAUsers
* @param CentralAuthUser $newCAUser
* @param GlobalRenameUserStatus $renameuserStatus
* @param callable $jobQueueGroupGenerator Callable for getting a job queue group for a given wiki
* @param GlobalUserMergeDatabaseUpdates $databaseUpdates
* @param GlobalUserMergeLogger $logger
* @param array $session
*/
public function __construct(
User $performingUser,
array $oldCAUsers,
CentralAuthUser $newCAUser,
GlobalRenameUserStatus $renameuserStatus,
callable $jobQueueGroupGenerator,
GlobalUserMergeDatabaseUpdates $databaseUpdates,
GlobalUserMergeLogger $logger,
array $session
) {
$this->performingUser = $performingUser;
$this->oldCAUsers = $oldCAUsers;
$this->newCAUser = $newCAUser;
$this->renameuserStatus = $renameuserStatus;
$this->jobQueueGroupGenerator = $jobQueueGroupGenerator;
$this->databaseUpdates = $databaseUpdates;
$this->logger = $logger;
$this->session = $session;
}
private function addLogEntry( $reason ) {
$this->logger->log(
$this->oldCAUsers,
$this->newCAUser->getName(),
$reason
);
}
private function clearCaches() {
foreach ( $this->oldCAUsers as $oldCAUser ) {
$oldCAUser->quickInvalidateCache();
}
$this->newCAUser->quickInvalidateCache();
}
public function merge( $reason ) {
$wikis = [];
foreach ( $this->oldCAUsers as $oldCAUser ) {
$oldWikis = $oldCAUser->listAttached();
foreach ( $oldWikis as $wiki ) {
$wikis[$wiki][] = $oldCAUser->getName();
}
}
$status = $this->setRenameStatuses( $wikis );
if ( !$status->isOK() ) {
return $status;
}
// Now that we know all users are locked, update globaluser & localuser tables
foreach ( $this->oldCAUsers as $oldCAUser ) {
$oldName = $oldCAUser->getName();
$oldId = $oldCAUser->getId();
$newName = $this->newCAUser->getName();
$newId = $this->newCAUser->getId();
$logger = LoggerFactory::getInstance( 'CentralAuthUserMerge' );
$logger->info( "Merged '{oldname}' into '{newname}'", [
'oldname' => $oldName,
'oldid' => $oldId,
'newname' => $newName,
'newid' => $newId,
'attached' => $oldCAUser->listAttached(),
] );
$this->databaseUpdates->merge( $oldName, $newName, $newId );
$this->databaseUpdates->mergeGlobalUserGroups( $oldId, $newId );
$this->databaseUpdates->mergeRenameUserQueue( $oldId, $newId );
$oldCAUser->removeAntiSpoof();
Hooks::run( 'CentralAuthGlobalUserMerged',
[ $oldName, $newName, $oldId, $newId ] );
}
$this->clearCaches();
// If job insertion fails, an exception will cause rollback of all DBs.
// The job will block on reading renameuser_status until this commits due to it using
// a locking read and the pending update from setRenameStatuses() above. If we end up
// rolling back, then the job will abort because the status will not be 'queued'.
$this->injectJobs( $wikis );
$this->addLogEntry( $reason );
return Status::newGood();
}
/**
* @param array $wikis
*
* @return Status
*/
private function setRenameStatuses( array $wikis ) {
$rows = [];
foreach ( $wikis as $wiki => $users ) {
foreach ( $users as $user ) {
// @TODO: This shouldn't know about these column names
$rows[] = [
'ru_wiki' => $wiki,
'ru_oldname' => $user,
'ru_newname' => $this->newCAUser->getName(),
'ru_status' => 'queued'
];
}
}
$success = $this->renameuserStatus->setStatuses( $rows );
if ( !$success ) {
// Race condition: Another admin already started the rename!
return Status::newFatal( 'centralauth-rename-alreadyinprogress', $this->newCAUser->getName() );
}
return Status::newGood();
}
/**
* Submits the jobs
*
* @param array $wikis
*/
private function injectJobs( array $wikis ) {
foreach ( $wikis as $wiki => $users ) {
$job = $this->getJob( $users );
call_user_func( $this->jobQueueGroupGenerator, $wiki )->push( $job );
}
}
/**
* @param array $users
*
* @return LocalUserMergeJob
*/
private function getJob( array $users ) {
return new LocalUserMergeJob(
Title::newFromText( 'Global merge job' ),
[
'to' => $this->newCAUser->getName(),
'renamer' => $this->performingUser->getName(),
'from' => $users,
'session' => $this->session,
]
);
}
}

查看文件

@ -1,137 +0,0 @@
<?php
namespace MediaWiki\Extension\CentralAuth\GlobalRename;
use CentralAuthServices;
use CentralAuthUser;
use Wikimedia\Rdbms\IDatabase;
/**
* Update the rows in the CentralAuth tables during a user merge
*
* @license GPL-2.0-or-later
* @author Marius Hoch < hoo@online.de >
*/
class GlobalUserMergeDatabaseUpdates {
/** @var IDatabase */
private $dbw;
public function __construct() {
// TODO inject this
$this->dbw = CentralAuthServices::getDatabaseManager()->getCentralDB( DB_PRIMARY );
}
/**
* Merge a global user's rows into
* another global user's ones.
*
* @param string $oldname Old global username
* @param string $newname New global username
* @param int|null $newId New global user ID
*/
public function merge( $oldname, $newname, $newId = null ) {
$dbw = $this->dbw;
$dbw->startAtomic( __METHOD__ );
// Delete the old user's globaluser row
$dbw->delete(
'globaluser',
[ 'gu_name' => $oldname ],
__METHOD__
);
// Move localuser rows to the new name
// if there is no row already there
// Note that in some cases, an account
// may not exist at the new name on
// that wiki yet.
$dbw->update(
'localuser',
[
'lu_name' => $newname,
'lu_global_id' => $newId
],
[ 'lu_name' => $oldname ],
__METHOD__,
[ 'IGNORE' ]
);
// Get the list of wikis with local accounts attached to the global account
$attachedWikis = $dbw->selectFieldValues(
'localuser',
'lu_wiki',
[ 'lu_name' => $newname ],
__METHOD__
);
// For each attached account, update the lu_local_id field
$user = CentralAuthUser::newFromId( $newId );
foreach ( $attachedWikis as $wiki ) {
$localId = $user->getLocalId( $wiki );
// Note that $localId will be null in case there is no local account with new name
// on that wiki yet
$dbw->update(
'localuser',
[ 'lu_local_id' => $localId ],
[
'lu_name' => $newname,
'lu_wiki' => $wiki
],
__METHOD__
);
}
// Delete the ones that are duplicates,
// we'll use the existing rows
$dbw->delete(
'localuser',
[ 'lu_name' => $oldname ],
__METHOD__
);
$dbw->endAtomic( __METHOD__ );
}
/**
* Updates renameuser_queue table if enabled
* @param int $fromId
* @param int $toId
*/
public function mergeRenameUserQueue( $fromId, $toId ) {
global $wgCentralAuthEnableGlobalRenameRequest;
if ( !$wgCentralAuthEnableGlobalRenameRequest ) {
return;
}
$this->dbw->update(
'renameuser_queue',
[ 'rq_performer' => $toId ],
[ 'rq_performer' => $fromId ],
__METHOD__
);
}
/**
* Updates global_user_groups table
* @param int $fromId
* @param int $toId
*/
public function mergeGlobalUserGroups( $fromId, $toId ) {
$dbw = $this->dbw;
$dbw->startAtomic( __METHOD__ );
$dbw->update(
'global_user_groups',
[ 'gug_user' => $toId ],
[ 'gug_user' => $fromId ],
__METHOD__,
[ 'IGNORE' ]
);
// Delete any duplicates left over
$dbw->delete(
'global_user_groups',
[ 'gug_user' => $fromId ],
__METHOD__
);
$dbw->endAtomic( __METHOD__ );
}
}

查看文件

@ -1,56 +0,0 @@
<?php
namespace MediaWiki\Extension\CentralAuth\GlobalRename;
use CentralAuthUser;
use ManualLogEntry;
use Title;
use User;
/**
* Log a global merge into the local log
*
* @license GPL-2.0-or-later
* @author Kunal Mehta
*/
class GlobalUserMergeLogger {
/**
* @var User
*/
private $performingUser;
/**
* @param User $performingUser
*/
public function __construct( User $performingUser ) {
$this->performingUser = $performingUser;
}
/**
* @param CentralAuthUser[] $oldNames
* @param string $newName
* @param string $reason
*/
public function log( array $oldNames, $newName, $reason ) {
$logEntry = new ManualLogEntry( 'gblrename', 'merge' );
$logEntry->setPerformer( $this->performingUser );
$logEntry->setTarget(
Title::makeTitleSafe( NS_SPECIAL, 'CentralAuth/' . $newName )
);
$imploded = implode( '|',
array_map( static function ( CentralAuthUser $user ) {
return $user->getName();
}, $oldNames )
);
$logEntry->setComment( $reason );
$logEntry->setParameters( [
'4::olduser' => $imploded,
'5::newuser' => $newName,
] );
$logid = $logEntry->insert();
$logEntry->publish( $logid );
}
}

查看文件

@ -1,99 +0,0 @@
<?php
namespace MediaWiki\Extension\CentralAuth\GlobalRename\LocalRenameJob;
use CentralAuthUser;
use CentralAuthUtils;
use Exception;
use ExtensionRegistry;
use MediaWiki\MediaWikiServices;
use MergeUser;
use RuntimeException;
use Status;
use Title;
use User;
use UserMergeLogger;
/**
* Job class to merge a user locally
* This is intended to be run on each wiki individually
*/
class LocalUserMergeJob extends LocalRenameJob {
public function __construct( Title $title, array $params ) {
$this->command = 'LocalUserMergeJob';
parent::__construct( $title, $params );
}
public function doRun( $fnameTrxOwner ) {
if ( !ExtensionRegistry::getInstance()->isLoaded( 'UserMerge' ) ) {
throw new Exception( 'Extension:UserMerge is not installed' );
}
$from = $this->params['from'];
$to = $this->params['to'];
$this->updateStatus( 'inprogress' );
// Make the status update visible to all other transactions immediately
$factory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
$factory->commitPrimaryChanges( $fnameTrxOwner );
$toUser = $this->maybeCreateNewUser( $to );
if ( $toUser instanceof Status ) {
$factory->rollbackPrimaryChanges( $fnameTrxOwner );
$this->updateStatus( 'failed' );
// Make the status update visible to all other transactions immediately
$factory->commitPrimaryChanges( $fnameTrxOwner );
throw new RuntimeException( "autoCreateUser failed for '{$to}': " .
$toUser->getWikiText( false, false, 'en' ) );
}
$renamingUser = $this->getRenameUser();
foreach ( $from as $olduser ) {
// Merge the users in order
$um = new MergeUser(
User::newFromName( $olduser ),
$toUser,
new UserMergeLogger(),
MergeUser::USE_MULTI_COMMIT
);
$um->merge( $renamingUser, $fnameTrxOwner );
$um->delete( $renamingUser, 'wfMessage' );
}
$this->done();
return true;
}
protected function done() {
parent::done();
foreach ( $this->params['from'] as $from ) {
$caOld = CentralAuthUser::getInstanceByName( $from );
$caOld->quickInvalidateCache();
}
}
/**
* It's possible that the final global user doesn't
* have an account here yet. So let's create one, and
* then merge into it.
*
* @param string $newName
* @return User|Status Returns status on failure
*/
private function maybeCreateNewUser( $newName ) {
$user = User::newFromName( $newName );
if ( $user->getId() ) {
// User already exists, nothing to do.
return $user;
}
$status = Status::wrap( CentralAuthUtils::autoCreateUser( $user ) );
if ( !$status->isGood() ) {
return $status;
}
return $user;
}
}

查看文件

@ -1,238 +0,0 @@
<?php
namespace MediaWiki\Extension\CentralAuth\Special;
use CentralAuthUser;
use ErrorPageError;
use ExtensionRegistry;
use FormSpecialPage;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameUserStatus;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalUserMerge;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalUserMergeDatabaseUpdates;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalUserMergeLogger;
use MediaWiki\User\UserNameUtils;
use ObjectCache;
use SpecialPage;
use Status;
use User;
class SpecialGlobalUserMerge extends FormSpecialPage {
/**
* Maximum number of users that can be
* merged at once
*/
private const MAX_USERS_TO_MERGE = 5;
/**
* @var CentralAuthUser[]
*/
private $oldCAUsers = [];
/**
* @var string
*/
private $newUsername;
/** @var UserNameUtils */
private $userNameUtils;
public function __construct( UserNameUtils $userNameUtils ) {
parent::__construct( 'GlobalUserMerge', 'centralauth-usermerge' );
$this->userNameUtils = $userNameUtils;
}
public function doesWrites() {
return true;
}
public function execute( $par ) {
$this->addHelpLink( 'Extension:CentralAuth' );
if ( !ExtensionRegistry::getInstance()->isLoaded( 'UserMerge' ) ) {
$this->setHeaders();
throw new ErrorPageError( 'error', 'centralauth-usermerge-notinstalled' );
}
if ( !$this->getConfig()->get( 'CentralAuthEnableUserMerge' ) ) {
$this->setHeaders();
throw new ErrorPageError( 'error', 'centralauth-usermerge-disabled' );
}
$this->getOutput()->addModules( 'ext.centralauth.globalrenameuser' );
parent::execute( $par );
}
/**
* @return array[]
*/
protected function getFormFields() {
return [
'finaluser' => [
'id' => 'mw-globalusermerge-usernames',
'name' => 'newuser',
'label-message' => 'centralauth-usermerge-form-newuser',
'type' => 'text',
'required' => true,
'validation-callback' => [ $this, 'validateUsername' ],
],
'usernames' => [
'id' => 'mw-globalusermerge-usernames',
'name' => 'usernames',
'label-message' => 'centralauth-usermerge-form-usernames',
'type' => 'cloner',
'format' => 'table',
'create-button-message' => 'centralauth-usermerge-form-adduser',
'delete-button-message' => 'centralauth-usermerge-form-deleteuser',
'fields' => [
'name' => [
'type' => 'text',
'validation-callback' => [ $this, 'validateUsername' ],
],
],
],
'reason' => [
'id' => 'mw-globalusermerge-reason',
'name' => 'reason',
'label-message' => 'centralauth-usermerge-form-reason',
'type' => 'text',
],
];
}
/**
* @param string|null $name
* @return string|bool
*/
public function validateUsername( $name ) {
if ( $name === null || $name === '' ) {
// blank cloner field, bypass.
return true;
}
$name = $this->userNameUtils->getCanonical( $name, UserNameUtils::RIGOR_USABLE );
if ( !$name ) {
return $this->msg( 'centralauth-usermerge-invalid', $name )->escaped();
}
if ( $name === $this->getUser()->getName() ) {
return $this->msg( 'centralauth-usermerge-noself' )->escaped();
}
$caUser = CentralAuthUser::getPrimaryInstanceByName( $name );
if ( !$caUser->exists() ) {
return $this->msg( 'centralauth-usermerge-invalid', $name )->escaped();
}
if ( $caUser->renameInProgress() ) {
return $this->msg( 'centralauth-usermerge-already', $name )->escaped();
}
return true;
}
/**
* Implement a rudimentary rate limiting system,
* we can't use User::pingLImiter() because stewards
* have the "noratelimit" userright
*
* Hardcoded to allow 1 merge per 60 seconds
*
* @return bool true if we should let the user proceed
*/
private function checkRateLimit() {
$cache = ObjectCache::getLocalClusterInstance();
$key = 'centralauth:usermerge:' . md5( $this->getUser()->getName() );
$found = $cache->get( $key );
if ( $found === false ) {
$cache->set( $key, true, 60 );
return true;
} else {
return false;
}
}
/**
* @param array $data
* @return Status
*/
public function onSubmit( array $data ) {
$newUser = User::newFromName( $data['finaluser'], 'creatable' );
if ( !$newUser ) {
return Status::newFatal( 'centralauth-usermerge-invalid' );
}
if ( !$this->checkRateLimit() ) {
return Status::newFatal( 'centralauth-usermerge-ratelimited' );
}
foreach ( $data['usernames'] as $field ) {
if ( trim( $field['name'] ) !== '' ) {
$name = $this->userNameUtils->getCanonical( $field['name'] );
if ( $name === $newUser->getName() ) {
// The new user is also specified as one of the targets,
// DWIM and ignore it
continue;
}
$caUser = CentralAuthUser::getPrimaryInstanceByName( $name );
$this->oldCAUsers[] = $caUser;
}
}
if ( !$this->oldCAUsers ) {
return Status::newFatal( 'centralauth-usermerge-nousers' );
}
if ( count( $this->oldCAUsers ) > self::MAX_USERS_TO_MERGE ) {
return Status::newFatal( $this->msg( 'centralauth-usermerge-toomany' )
->numParams( self::MAX_USERS_TO_MERGE ) );
}
$this->newUsername = $newUser->getName();
$globalUserMerge = new GlobalUserMerge(
$this->getUser(),
$this->oldCAUsers,
CentralAuthUser::getInstance( $newUser ),
new GlobalRenameUserStatus( $newUser->getName() ),
'JobQueueGroup::singleton',
new GlobalUserMergeDatabaseUpdates(),
new GlobalUserMergeLogger( $this->getUser() ),
$this->getContext()->exportSession()
);
$status = $globalUserMerge->merge( $data['reason'] );
return $status;
}
/**
* Get a HTML link to this user's Special:CentralAuth page
*
* @param string $name
* @return string raw HTML
*/
public function getLocalizedCentralAuthLink( $name ) {
return $this->getLinkRenderer()->makeKnownLink(
SpecialPage::getTitleFor( 'CentralAuth', $name ),
$name
);
}
public function onSuccess() {
$lang = $this->getLanguage();
$globalUsers = array_map( function ( CentralAuthUser $user ) {
return $this->getLocalizedCentralAuthLink( $user->getName() );
}, $this->oldCAUsers );
$userList = $lang->commaList( $globalUsers );
$msg = $this->msg( 'centralauth-usermerge-queued' )
->rawParams(
$userList,
$this->getLocalizedCentralAuthLink( $this->newUsername )
)->params( $this->newUsername )->parse();
$this->getOutput()->addHTML( $msg );
}
protected function getGroupName() {
return 'users';
}
}

查看文件

@ -3,10 +3,6 @@ $( function () {
mw.util.$content.find( 'form' ).first().on( 'submit', function () {
// TODO: Convert this to OOUI.
// eslint-disable-next-line no-alert
return confirm( mw.msg(
mw.config.get( 'wgCanonicalSpecialPageName' ) === 'GlobalUserMerge' ?
'centralauth-usermerge-confirm' :
'centralauth-rename-confirm'
) );
return confirm( mw.msg( 'centralauth-rename-confirm' ) );
} );
} );