1111 <p >{{ t('General.currentMFA') }}: {{ getMFAMethodLabel(props.user?.mfa ?? '') }}</p >
1212 </el-card >
1313 <template v-if =" withMFA " >
14+ <el-alert v-if =" disableMfaBlocked" type =" warning" :closable =" false" class =" mfa-alert" >
15+ {{ t('General.disableMFAForbiddenBySSO') }}
16+ </el-alert >
1417 <div class =" buttons" >
1518 <el-button type =" primary" plain :loading =" submitLoading" @click =" resetTOTPSecret" >
1619 {{ tl('resetTOTPSecret') }}
1720 </el-button >
18- <el-button type =" danger" plain :loading =" submitLoading" @click =" deleteMFA" >
21+ <el-button
22+ type =" danger"
23+ plain
24+ :loading =" submitLoading"
25+ :disabled =" disableMfaBlocked || ssoConfigLoading"
26+ @click =" deleteMFA"
27+ >
1928 {{ tl('disableMFA') }}
2029 </el-button >
2130 </div >
4150
4251<script setup lang="ts">
4352import { deleteUserMfa , updateUserMfa } from ' @/api/function'
53+ import { getSSOBackend } from ' @/api/sso'
4454import { type User , UserMFA } from ' @/types/typeAlias'
4555
4656const props = defineProps <{
@@ -54,6 +64,12 @@ const { t, tl } = useI18nTl('General')
5464const { mfaOptions, isMFAEnabled, getMFAMethodLabel } = useMFAMethods ()
5565const withMFA = computed (() => isMFAEnabled (props .user .mfa ?? ' ' ))
5666const isSSOUser = computed (() => !! props .user ?.backend && props .user .backend !== ' local' )
67+ const ssoConfigLoading = ref (false )
68+ const ssoBackendConfig = ref <Record <string , any > | null >(null )
69+ const isSSOBackendMfaEnforced = computed (
70+ () => !! (ssoBackendConfig .value ?.force_mfa || ssoBackendConfig .value ?.enforce_mfa ),
71+ )
72+ const disableMfaBlocked = computed (() => isSSOUser .value && isSSOBackendMfaEnforced .value )
5773
5874const defaultMFA = mfaOptions [0 ].value
5975
@@ -69,12 +85,31 @@ const showDialog = computed({
6985watch (showDialog , async (value : boolean ) => {
7086 if (! value ) {
7187 initData ()
88+ return
7289 }
90+ await loadSSOBackendConfig ()
7391})
7492
7593const initData = () => {
7694 submitLoading .value = false
7795 selectedMFA .value = defaultMFA
96+ ssoConfigLoading .value = false
97+ ssoBackendConfig .value = null
98+ }
99+
100+ const loadSSOBackendConfig = async () => {
101+ if (! isSSOUser .value || ! props .user ?.backend ) {
102+ ssoBackendConfig .value = null
103+ return
104+ }
105+ try {
106+ ssoConfigLoading .value = true
107+ ssoBackendConfig .value = (await getSSOBackend (props .user .backend as any )) as Record <string , any >
108+ } catch (error ) {
109+ ssoBackendConfig .value = null
110+ } finally {
111+ ssoConfigLoading .value = false
112+ }
78113}
79114
80115const resetTOTPSecret = async () => {
@@ -122,6 +157,10 @@ const deleteMFA = async () => {
122157 if (! username ) {
123158 return
124159 }
160+ if (disableMfaBlocked .value ) {
161+ ElMessage .warning (t (' General.disableMFAForbiddenBySSO' ))
162+ return
163+ }
125164 await operationWarning (t (' General.confirmDisableMFA' ))
126165 submitLoading .value = true
127166 if (isSSOUser .value ) {
@@ -142,6 +181,9 @@ const deleteMFA = async () => {
142181
143182<style lang="scss">
144183.mfa-setting-dialog {
184+ .mfa-alert {
185+ margin-bottom : 12px ;
186+ }
145187 .buttons {
146188 margin-top : 12px ;
147189 }
0 commit comments