From 8a73cd5e81b53ec28f9fb05552cc123ad5fa9d52 Mon Sep 17 00:00:00 2001 From: Akarsh MR Date: Wed, 13 May 2026 06:44:15 +0000 Subject: [PATCH] FREEI-2880 SCIM token masking in directory add/edit form --- functions.inc/auth/modules/Scim.php | 11 +++-- views/directories.php | 72 +++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/functions.inc/auth/modules/Scim.php b/functions.inc/auth/modules/Scim.php index bcf12ef9..6ecd84ce 100644 --- a/functions.inc/auth/modules/Scim.php +++ b/functions.inc/auth/modules/Scim.php @@ -90,15 +90,20 @@ public static function getConfig($userman, $freepbx, $config) { 'title' => _("SCIM Token"), 'type' => 'raw', 'value' => sprintf( - ' + '
+ +
', $typeauth, - _("Refresh Token") + _("Refresh Token"), + _("Copy Token"), + _("Show Token"), + _("Hide Token") ), - 'help' => _("Use this token for SCIM provisioning"), + 'help' => _("Use this token for SCIM provisioning. The value is masked by default; use the Show/Hide and Copy buttons to view or copy it."), ), array('type' => 'fieldset_init', 'legend' => _("Operational Settings")), array( diff --git a/views/directories.php b/views/directories.php index 3d559aed..26be62a2 100644 --- a/views/directories.php +++ b/views/directories.php @@ -464,6 +464,78 @@ function rotateScimToken() { rotateScimToken(); }); + function copyScimTokenFallback(token) { + var $field = $("#scim-token"); + if (!$field.length) { + return false; + } + var originalType = $field.attr("type"); + $field.attr("type", "text"); + var node = $field[0]; + try { + node.focus(); + node.select(); + if (typeof node.setSelectionRange === "function") { + node.setSelectionRange(0, token.length); + } + } catch (e) {} + var copied = false; + try { + copied = document.execCommand("copy"); + } catch (e) { + copied = false; + } + $field.attr("type", originalType); + try { node.blur(); } catch (e) {} + return copied; + } + + $(document).on("click", "#scim-copy-token", function() { + var token = ($("#scim-token").val() || "").toString(); + if (!token) { + showScimMessage("", "danger"); + return; + } + if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") { + navigator.clipboard.writeText(token).then(function() { + showScimMessage("", "success"); + }).catch(function() { + if (copyScimTokenFallback(token)) { + showScimMessage("", "success"); + } else { + showScimMessage("", "danger"); + } + }); + return; + } + if (copyScimTokenFallback(token)) { + showScimMessage("", "success"); + } else { + showScimMessage("", "danger"); + } + }); + + $(document).on("click", "#scim-toggle-token", function() { + var $btn = $(this); + var $field = $("#scim-token"); + if (!$field.length) { + return; + } + var $label = $btn.find(".scim-toggle-label"); + var $icon = $btn.find("i"); + var showLabel = $btn.data("show-label"); + var hideLabel = $btn.data("hide-label"); + if ($field.attr("type") === "password") { + $field.attr("type", "text"); + $label.text(hideLabel); + $icon.removeClass("fa-eye").addClass("fa-eye-slash"); + } else { + $field.attr("type", "password"); + $label.text(showLabel); + $icon.removeClass("fa-eye-slash").addClass("fa-eye"); + } + }); + function generateScimToken() { var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var token = "";