From bd6b518aae61608ddc2d82b43ccc283dc95b9c54 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期三, 11 三月 2026 13:59:33 +0800
Subject: [PATCH] #
---
src/main/webapp/static/js/detail/detail.js | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 176 insertions(+), 1 deletions(-)
diff --git a/src/main/webapp/static/js/detail/detail.js b/src/main/webapp/static/js/detail/detail.js
index 0e041d7..5a80ca2 100644
--- a/src/main/webapp/static/js/detail/detail.js
+++ b/src/main/webapp/static/js/detail/detail.js
@@ -19,6 +19,9 @@
mfaDialogMode: "enable",
mfaSetupLoading: false,
mfaSubmitting: false,
+ passkeyDialogVisible: false,
+ passkeyDialogMode: "register",
+ passkeySubmitting: false,
form: {
id: "",
roleName: "",
@@ -30,7 +33,12 @@
mfaEnabled: 0,
mfaEnabled$: "鍚�",
mfaBoundTime$: "",
- mfaMaskedSecret: ""
+ mfaMaskedSecret: "",
+ passkeyBound: false,
+ passkeyName: "",
+ passkeyBoundTime$: "",
+ passkeyLastUsedTime$: "",
+ passkeyTransports: ""
},
passwordForm: {
oldPassword: "",
@@ -45,6 +53,10 @@
secret: "",
qrCode: "",
otpAuth: ""
+ },
+ passkeyForm: {
+ name: "",
+ currentPassword: ""
},
rules: {
username: [
@@ -109,6 +121,11 @@
},
trigger: "blur"
}
+ ]
+ },
+ passkeyRules: {
+ currentPassword: [
+ { required: true, message: "璇疯緭鍏ュ綋鍓嶅瘑鐮�", trigger: "blur" }
]
}
};
@@ -314,6 +331,164 @@
}
});
},
+ openPasskeyRegisterDialog: function () {
+ if (!window.WCS_WEBAUTHN || !window.WCS_WEBAUTHN.isSupported()) {
+ this.$message.error(this.resolvePasskeyErrorMessage({ message: window.isSecureContext ? "not-supported" : "secure-context" }, "褰撳墠鐜涓嶆敮鎸侀�氳瀵嗛挜"));
+ return;
+ }
+ this.passkeyDialogMode = "register";
+ this.resetPasskeyDialogState();
+ this.passkeyDialogVisible = true;
+ },
+ openPasskeyRemoveDialog: function () {
+ this.passkeyDialogMode = "remove";
+ this.resetPasskeyDialogState();
+ this.passkeyDialogVisible = true;
+ },
+ closePasskeyDialog: function () {
+ this.passkeyDialogVisible = false;
+ this.resetPasskeyDialogState();
+ },
+ resetPasskeyDialogState: function () {
+ this.passkeySubmitting = false;
+ this.passkeyForm = {
+ name: "",
+ currentPassword: ""
+ };
+ if (this.$refs.passkeyForm) {
+ this.$refs.passkeyForm.clearValidate();
+ }
+ },
+ handlePasskeySubmit: function () {
+ var vm = this;
+ if (!vm.$refs.passkeyForm) {
+ return;
+ }
+ vm.$refs.passkeyForm.validate(function (valid) {
+ if (!valid) {
+ return false;
+ }
+ if (vm.passkeyDialogMode === "register") {
+ vm.submitPasskeyRegister();
+ } else {
+ vm.submitPasskeyRemove();
+ }
+ return true;
+ });
+ },
+ submitPasskeyRegister: function () {
+ var vm = this;
+ if (!window.WCS_WEBAUTHN || !window.WCS_WEBAUTHN.isSupported()) {
+ vm.$message.error(vm.resolvePasskeyErrorMessage({ message: window.isSecureContext ? "not-supported" : "secure-context" }, "褰撳墠鐜涓嶆敮鎸侀�氳瀵嗛挜"));
+ return;
+ }
+ vm.passkeySubmitting = true;
+ $.ajax({
+ url: baseUrl + "/user/passkey/register/options/auth",
+ headers: { token: localStorage.getItem("token") },
+ method: "POST",
+ success: function (res) {
+ if (handleForbidden(res)) {
+ return;
+ }
+ if (Number(res.code) !== 200) {
+ vm.passkeySubmitting = false;
+ vm.$message.error(res.msg || "閫氳瀵嗛挜閰嶇疆鍔犺浇澶辫触");
+ return;
+ }
+ vm.executePasskeyRegister(res.data || {});
+ },
+ error: function () {
+ vm.passkeySubmitting = false;
+ vm.$message.error("閫氳瀵嗛挜閰嶇疆鍔犺浇澶辫触");
+ }
+ });
+ },
+ executePasskeyRegister: function (optionsPayload) {
+ var vm = this;
+ window.WCS_WEBAUTHN.register(optionsPayload).then(function (credential) {
+ $.ajax({
+ url: baseUrl + "/user/passkey/register/finish/auth",
+ headers: { token: localStorage.getItem("token") },
+ data: {
+ ticket: optionsPayload.ticket,
+ currentPassword: hex_md5(vm.passkeyForm.currentPassword),
+ name: vm.passkeyForm.name,
+ credentialId: credential.credentialId,
+ clientDataJSON: credential.clientDataJSON,
+ authenticatorData: credential.authenticatorData,
+ publicKey: credential.publicKey,
+ publicKeyAlgorithm: credential.publicKeyAlgorithm,
+ transports: credential.transports
+ },
+ method: "POST",
+ success: function (res) {
+ if (handleForbidden(res)) {
+ return;
+ }
+ if (Number(res.code) !== 200) {
+ vm.$message.error(res.msg || "閫氳瀵嗛挜缁戝畾澶辫触");
+ return;
+ }
+ vm.$message.success("閫氳瀵嗛挜宸茬粦瀹�");
+ vm.closePasskeyDialog();
+ vm.loadDetail();
+ },
+ error: function () {
+ vm.$message.error("閫氳瀵嗛挜缁戝畾澶辫触");
+ },
+ complete: function () {
+ vm.passkeySubmitting = false;
+ }
+ });
+ }).catch(function (err) {
+ vm.passkeySubmitting = false;
+ vm.$message.error(vm.resolvePasskeyErrorMessage(err, "閫氳瀵嗛挜缁戝畾澶辫触"));
+ });
+ },
+ submitPasskeyRemove: function () {
+ var vm = this;
+ vm.passkeySubmitting = true;
+ $.ajax({
+ url: baseUrl + "/user/passkey/remove/auth",
+ headers: { token: localStorage.getItem("token") },
+ data: {
+ currentPassword: hex_md5(vm.passkeyForm.currentPassword)
+ },
+ method: "POST",
+ success: function (res) {
+ if (handleForbidden(res)) {
+ return;
+ }
+ if (Number(res.code) !== 200) {
+ vm.$message.error(res.msg || "閫氳瀵嗛挜瑙g粦澶辫触");
+ return;
+ }
+ vm.$message.success("閫氳瀵嗛挜宸茶В缁�");
+ vm.closePasskeyDialog();
+ vm.loadDetail();
+ },
+ error: function () {
+ vm.$message.error("閫氳瀵嗛挜瑙g粦澶辫触");
+ },
+ complete: function () {
+ vm.passkeySubmitting = false;
+ }
+ });
+ },
+ resolvePasskeyErrorMessage: function (err, fallback) {
+ var message = err && err.message ? String(err.message) : "";
+ if (message === "secure-context") {
+ return "閫氳瀵嗛挜浠呮敮鎸佸湪 HTTPS 鎴� localhost 鐜涓嬩娇鐢�";
+ }
+ if (message === "not-supported" || message === "extension-unsupported" || message === "public-key-missing") {
+ return "褰撳墠娴忚鍣ㄤ笉鏀寔閫氳瀵嗛挜锛岃浣跨敤鏈�鏂扮増 Chrome銆丒dge 鎴� Safari";
+ }
+ if (err && err.name === "NotAllowedError") {
+ return "宸插彇娑堥�氳瀵嗛挜鎿嶄綔鎴栭獙璇佽秴鏃�";
+ }
+ return fallback || "閫氳瀵嗛挜鎿嶄綔澶辫触";
+ },
copySecret: function () {
var vm = this;
var text = vm.mfaSetup.secret || "";
--
Gitblit v1.9.1