diff --git a/frontend/src/assets/svg/icon_qr_outlined.svg b/frontend/src/assets/svg/icon_qr_outlined.svg new file mode 100644 index 00000000..8fb87a4f --- /dev/null +++ b/frontend/src/assets/svg/icon_qr_outlined.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/src/assets/svg/logo_ldap.svg b/frontend/src/assets/svg/logo_ldap.svg index 57deedf2..bd13cd4a 100644 --- a/frontend/src/assets/svg/logo_ldap.svg +++ b/frontend/src/assets/svg/logo_ldap.svg @@ -1,4 +1,4 @@ - + @@ -6,7 +6,7 @@ - + diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 89ffb4c5..3c7bf281 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -741,7 +741,18 @@ "oidc_settings": "OIDC Settings", "metadata_url": "Metadata URL", "realm": "Realm", - "oidc_field_mapping_placeholder": "e.g., {\"account\": \"oidcAccount\", \"name\": \"oidcName\", \"email\": \"email\"}" + "oidc_field_mapping_placeholder": "e.g., {\"account\": \"oidcAccount\", \"name\": \"oidcName\", \"email\": \"email\"}", + "ldap_settings": "LDAP Settings", + "server_address": "Server Address", + "server_address_placeholder": "Example: ldap://ldap.example.com:389", + "bind_dn": "Bind DN", + "bind_dn_placeholder": "Example: cn=admin,dc=example,dc=com", + "bind_pwd": "Bind Password", + "ou": "User OU", + "ou_placeholder": "Example: ou=users,dc=example,dc=com", + "user_filter": "User Filter", + "user_filter_placeholder": "Example: uid", + "ldap_field_mapping_placeholder": "Example: {\"account\": \"ldapAccount\", \"name\": \"ldapName\", \"email\": \"mail\"}" }, "login": { "default_login": "Default", diff --git a/frontend/src/i18n/ko-KR.json b/frontend/src/i18n/ko-KR.json index 3c7fe3c8..92eb64b0 100644 --- a/frontend/src/i18n/ko-KR.json +++ b/frontend/src/i18n/ko-KR.json @@ -741,7 +741,18 @@ "oidc_settings": "OIDC 설정", "metadata_url": "메타데이터 URL", "realm": "영역", - "oidc_field_mapping_placeholder": "예: {\"account\": \"oidcAccount\", \"name\": \"oidcName\", \"email\": \"email\"}" + "oidc_field_mapping_placeholder": "예: {\"account\": \"oidcAccount\", \"name\": \"oidcName\", \"email\": \"email\"}", + "ldap_settings": "LDAP 설정", + "server_address": "서버 주소", + "server_address_placeholder": "예: ldap://ldap.example.com:389", + "bind_dn": "바인드 DN", + "bind_dn_placeholder": "예: cn=admin,dc=example,dc=com", + "bind_pwd": "바인드 비밀번호", + "ou": "사용자 OU", + "ou_placeholder": "예: ou=users,dc=example,dc=com", + "user_filter": "사용자 필터", + "user_filter_placeholder": "예: uid", + "ldap_field_mapping_placeholder": "예: {\"account\": \"ldapAccount\", \"name\": \"ldapName\", \"email\": \"mail\"}" }, "login": { "default_login": "기본값", diff --git a/frontend/src/i18n/zh-CN.json b/frontend/src/i18n/zh-CN.json index 7da8b245..8760e8a3 100644 --- a/frontend/src/i18n/zh-CN.json +++ b/frontend/src/i18n/zh-CN.json @@ -741,7 +741,18 @@ "oidc_settings": "OIDC 设置", "metadata_url": "元数据地址", "realm": "领域", - "oidc_field_mapping_placeholder": "例如:{'{'}\"account\": \"oidcAccount\", \"name\": \"oidcName\", \"email\": \"email\"{'}'}" + "oidc_field_mapping_placeholder": "例如:{'{'}\"account\": \"oidcAccount\", \"name\": \"oidcName\", \"email\": \"email\"{'}'}", + "ldap_settings": "LDAP 设置", + "server_address": "服务器地址", + "server_address_placeholder": "例如:ldap://ldap.example.com:389", + "bind_dn": "绑定 DN", + "bind_dn_placeholder": "例如:cn=admin,dc=example,dc=com", + "bind_pwd": "绑定密码", + "ou": "用户 OU", + "ou_placeholder": "例如:ou=users,dc=example,dc=com", + "user_filter": "用户过滤器", + "user_filter_placeholder": "例如:uid", + "ldap_field_mapping_placeholder": "例如:{'{'}\"account\": \"ldapAccount\", \"name\": \"ldapName\", \"email\": \"mail\"{'}'}" }, "login": { "default_login": "默认", diff --git a/frontend/src/views/login/index.vue b/frontend/src/views/login/index.vue index c0cd05ff..d40c0e45 100644 --- a/frontend/src/views/login/index.vue +++ b/frontend/src/views/login/index.vue @@ -28,42 +28,45 @@
-

{{ $t('common.login') }}

- - - - - - - - - - - +
+

{{ $t('common.login') }}

+ + + + + + + + + + + +
@@ -93,7 +96,9 @@ const loginForm = ref({ username: '', password: '', }) +const activeName = ref('simple') +// const isLdap = computed(() => activeName.value == 'ldap') const bg = computed(() => { return appearanceStore.getBg || (appearanceStore.isBlue ? loginImage : login_image) }) @@ -118,6 +123,9 @@ const submitForm = () => { } }) } +const switchTab = (name: string) => { + activeName.value = name || 'simple' +} diff --git a/frontend/src/views/login/xpack/QrcodeLdap.vue b/frontend/src/views/login/xpack/QrcodeLdap.vue new file mode 100644 index 00000000..32146371 --- /dev/null +++ b/frontend/src/views/login/xpack/QrcodeLdap.vue @@ -0,0 +1,185 @@ + + + + diff --git a/frontend/src/views/system/authentication/LdapEditor.vue b/frontend/src/views/system/authentication/LdapEditor.vue index cf4e0713..6e08ed15 100644 --- a/frontend/src/views/system/authentication/LdapEditor.vue +++ b/frontend/src/views/system/authentication/LdapEditor.vue @@ -7,23 +7,16 @@ import { request } from '@/utils/request' const { t } = useI18n() const dialogVisible = ref(false) const loadingInstance = ref | null>(null) -const mappingTips = ref(t('system.for_example')) const ldapForm = ref() -interface LdapForm { - addr?: string - dn?: string - pwd?: string - ou?: string - filter?: string - mapping?: string -} + +const id = ref(null) const state = reactive({ - form: reactive({ - addr: '', - dn: '', - pwd: '', + form: reactive({ + server_address: '', + bind_dn: '', + bind_pwd: '', ou: '', - filter: '', + user_filter: '', mapping: '', }), }) @@ -35,13 +28,14 @@ const validateMapping = (rule, value, callback) => { } try { JSON.parse(value) - } catch (e) { - callback(new Error(t('system.in_json_format'))) + } catch (e: any) { + console.error(e) + callback(new Error(t('authentication.in_json_format'))) } callback() } const rule = reactive({ - addr: [ + server_address: [ { required: true, message: t('common.require'), @@ -54,14 +48,14 @@ const rule = reactive({ trigger: 'blur', }, ], - dn: [ + bind_dn: [ { required: true, message: t('common.require'), trigger: ['blur', 'change'], }, ], - pwd: [ + bind_pwd: [ { required: true, message: t('common.require'), @@ -75,7 +69,7 @@ const rule = reactive({ trigger: ['blur', 'change'], }, ], - filter: [ + user_filter: [ { required: true, message: t('common.require'), @@ -84,26 +78,27 @@ const rule = reactive({ ], mapping: [ { - required: true, + required: false, message: t('common.require'), trigger: ['blur', 'change'], }, - { required: true, validator: validateMapping, trigger: 'blur' }, + { required: false, validator: validateMapping, trigger: 'blur' }, ], }) const edit = () => { showLoading() request - .get('/setting/authentication/info/ldap') + .get('/system/authentication/3') .then((res) => { - const resData = res as Partial - ;(Object.keys(resData) as (keyof LdapForm)[]).forEach((key) => { - const value = resData[key] - if (value !== undefined) { - state.form[key] = value as any - } - }) + if (!res?.config) { + return + } + id.value = res.id + const data = JSON.parse(res.config) + for (const key in data) { + state.form[key] = data[key] as any + } }) .finally(() => { closeLoading() @@ -117,7 +112,15 @@ const submitForm = async (formEl: FormInstance | undefined) => { await formEl.validate((valid) => { if (valid) { const param = { ...state.form } - const method = request.post('/setting/authentication/save/ldap', param) + const data = { + id: 3, + type: 3, + config: JSON.stringify(param), + name: 'ldap', + } + const method = id.value + ? request.put('/system/authentication', data) + : request.post('/system/authentication', data) showLoading() method .then((res) => { @@ -138,6 +141,7 @@ const submitForm = async (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => { if (!formEl) return formEl.resetFields() + id.value = null dialogVisible.value = false } @@ -155,16 +159,21 @@ const closeLoading = () => { } const validate = () => { - const url = '/setting/authentication/validate/ldap' - const data = state.form + const url = '/system/authentication/status' + const config_data = state.form + const data = { + type: 3, + name: 'ldap', + config: JSON.stringify(config_data), + } showLoading() request - .post(url, data) + .patch(url, data) .then((res) => { - if (res === 'true') { - ElMessage.success(t('commons.test_connect') + t('report.last_status_success')) + if (res) { + ElMessage.success(t('ds.connection_success')) } else { - ElMessage.error(t('commons.test_connect') + t('report.last_status_fail') + ': ' + res.data) + ElMessage.error(t('ds.connection_failed')) } }) .finally(() => { @@ -181,7 +190,7 @@ defineExpose({