[TikiWiki-commits] [Git][tikiwiki/tiki][master] [NEW] 2FA: Allow site admins to reset or disable 2FA per user
"Merci Jacob \(@mercihabam\) via TikiWiki-cvs" <[email protected]>
| Newsgroups | gmane.comp.cms.tiki.cvs |
|---|---|
| Message-ID | <68f8eb7be6c88_2c7511381602a@gitlab-sidekiq-low-urgency-cpu-bound-v2-65cbf47f7b-2rjjr.mail> |
Merci Jacob pushed to branch master at Tiki Wiki CMS Groupware / Tiki
Commits:
a7ba8b44 by Merci Jacob at 2025-10-22T14:23:11+00:00
[NEW] 2FA: Allow site admins to reset or disable 2FA per user
---
* add js only when the pref is enabled
* fix linter
* reset user 2FA on "reset button" click, and show proper feedback
* [NEW] 2FA: Allow site admins to reset or disable 2FA per user
See merge request tikiwiki/tiki!8723
- - - - -
6 changed files:
- lib/core/Services/User/Controller.php
- path_js_importmap_generator.php
- + src/js/jquery-tiki/tiki-admin_2fa.js
- templates/tiki-adminusers.tpl
- themes/base_files/scss/_element-plus-tiki.scss
- tiki-adminusers.php
Changes:
=====================================
lib/core/Services/User/Controller.php
=====================================
@@ -1340,4 +1340,45 @@ class Services_User_Controller
TikiLib::lib('tiki')->set_user_preference($user, 'trk_items_column_pref', $columns);
return tr('Your column preference for tracker "%0" is saved.', $tracker_name);
}
+
+ public function actionReset2FA($input)
+ {
+ Services_Exception_Denied::checkGlobal('admin_users');
+
+ $user = $input->user->text();
+ if (empty($user)) {
+ throw new Services_Exception(tra('No user was specified'));
+ }
+
+ TikiLib::lib('user')->update_2_factor_secret($user, '');
+ return ['success' => true, 'message' => tra('2FA secret reset successfully')];
+ }
+
+ public function actionToggle2FA($input)
+ {
+ Services_Exception_Denied::checkGlobal('admin_users');
+
+ $user = $input->user->text();
+ if (empty($user)) {
+ throw new Services_Exception(tra('No user was specified'));
+ }
+
+ $tikilib = TikiLib::lib('tiki');
+
+ $usersDisabled2FA = $tikilib->get_preference('twoFactorAuthExcludedUsers', expectArray: true);
+ $usersEnabled2FA = $tikilib->get_preference('twoFactorAuthIncludedUsers', expectArray: true);
+
+ if ($input->enable->bool()) {
+ $usersEnabled2FA = array_unique(array_merge($usersEnabled2FA, [$user]));
+ $usersDisabled2FA = array_diff($usersDisabled2FA, [$user]);
+ } else {
+ $usersDisabled2FA = array_unique(array_merge($usersDisabled2FA, [$user]));
+ $usersEnabled2FA = array_diff($usersEnabled2FA, [$user]);
+ }
+
+ $tikilib->set_preference('twoFactorAuthExcludedUsers', $usersDisabled2FA);
+ $tikilib->set_preference('twoFactorAuthIncludedUsers', $usersEnabled2FA);
+
+ return ['success' => true];
+ }
}
=====================================
path_js_importmap_generator.php
=====================================
@@ -67,6 +67,7 @@ function generateJsImportmapScripts(bool $useBaseUrl = false)
"@jquery-tiki/tiki-svgedit_draw" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/tiki-svgedit_draw.js",
"@jquery-tiki/tiki-handle_svgedit" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/tiki-handle_svgedit.js",
"@jquery-tiki/tiki-admin_menu_options" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/tiki-admin_menu_options.js",
+ "@jquery-tiki/tiki-admin_2fa" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/tiki-admin_2fa.js",
"@jquery-tiki/tiki-edit_structure" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/tiki-edit_structure.js",
"@jquery-tiki/wikiplugin-trackercalendar" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/wikiplugin-trackercalendar.js",
"@jquery-tiki/fullcalendar_to_pdf" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/fullcalendar_to_pdf.js",
=====================================
src/js/jquery-tiki/tiki-admin_2fa.js
=====================================
@@ -0,0 +1,41 @@
+$("#force2FA").on("change", function () {
+ $.tikiModal(tr("Saving..."));
+ $.post($.service("user", "toggle2FA"), { enable: $(this).is(":checked"), user: $(this).data("user") })
+ .done(function () {
+ showMessage(tr("Settings saved"), "success");
+ })
+ .fail(function () {
+ showMessage(tr("Failed to save settings"), "error");
+ })
+ .always(function () {
+ $.tikiModal();
+ });
+});
+
+$("#reset2FA").on("click", function () {
+ $.openModal({
+ title: tr("Reset 2FA"),
+ content: tr("Are you sure you want to reset Two Factor Authentication method for this user? They will need to set it up again."),
+ buttons: [
+ {
+ text: tr("Reset"),
+ type: "danger",
+ onClick: function () {
+ $.closeModal();
+ $.tikiModal(tr("Resetting..."));
+ $.post($.service("user", "reset2FA"), { user: $("#reset2FA").data("user") })
+ .done(function () {
+ showMessage(tr("2FA has been reset"), "success");
+ $("#reset2FA").prop("disabled", true);
+ })
+ .fail(function () {
+ showMessage(tr("Failed to reset 2FA"), "error");
+ })
+ .always(function () {
+ $.tikiModal();
+ });
+ },
+ },
+ ],
+ });
+});
=====================================
templates/tiki-adminusers.tpl
=====================================
@@ -598,6 +598,23 @@
</div>
{/if}
+ {if $prefs.twoFactorAuth eq 'y'}
+ <div class="mb-3 row">
+ <label class="col-sm-3 col-md-2 col-form-label" for="force2FA">{tr}2FA{/tr}</label>
+ <div class="form-check form-switch col-sm-7 col-md-6">
+ <input class="form-check-input" type="checkbox" role="switch" id="force2FA" data-user="{$userinfo.login}" {if $force2FA}checked{/if}>
+ <small class="form-text text-muted">{tr}Enable/Disable Two Factor Authentication for this user.{/tr}</small>
+ </div>
+ </div>
+ <div class="mb-3 row">
+ <div class="col-sm-3 col-md-2"></div>
+ <div class="col-sm-7 col-md-6">
+ <button type="button" class="btn btn-secondary w-100" id="reset2FA" {if not $userinfo.twoFactorSecret}disabled{/if} data-user="{$userinfo.login}">{tr}Reset 2FA{/tr}</button>
+ <small class="form-text text-muted">{tr}This will require the user to reset up 2FA the next time they log in.{/tr}</small>
+ </div>
+ </div>
+ {/if}
+
<div class="mb-3 row">
<div class="col-sm-9 offset-sm-3 col-md-10 offset-md-2">
{if isset($userinfo.userId) && $userinfo.userId}
=====================================
themes/base_files/scss/_element-plus-tiki.scss
=====================================
@@ -18,4 +18,8 @@ el-select, el-autocomplete, el-input {
el-autocomplete ~ .search_mod_magnifier {
margin-top: unset !important;
-}
\ No newline at end of file
+}
+
+.el-message {
+ z-index: 9999 !important;
+}
=====================================
tiki-adminusers.php
=====================================
@@ -582,6 +582,10 @@ if (isset($_REQUEST['user']) and $_REQUEST['user']) {
}
}
+ if ($prefs['twoFactorAuth'] == 'y') {
+ $smarty->assign('force2FA', $userlib->forceTwoFactorAuth($userinfo['login']));
+ }
+
if ($prefs['email_due'] > 0) {
$userinfo['daysSinceEmailConfirm'] = floor(($userlib->now - $userinfo['email_confirm']) / (60 * 60 * 24));
}
@@ -668,6 +672,12 @@ if (count($errors) > 0) {
Feedback::error(['mes' => $errors]);
}
+$headerlib = TikiLib::lib('header');
+
+if ($prefs['twoFactorAuth'] == 'y') {
+ $headerlib->add_js_module("import '@jquery-tiki/tiki-admin_2fa';");
+}
+
$smarty->assign_by_ref('all_groups', $all_groups);
$smarty->assign('userinfo', $userinfo);
$smarty->assign('userId', $_REQUEST['user']);
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/a7ba8b442d65a4f0a1f7e76c5cd44766064c3e91
--
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/a7ba8b442d65a4f0a1f7e76c5cd44766064c3e91
You're receiving this email because of your account on gitlab.com.
_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs