feat: chat password auth (#3318)

This commit is contained in:
shaohuzhang1 2025-06-19 20:02:52 +08:00 committed by GitHub
parent 7aa73e7110
commit 4e170c6ed7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 100 additions and 44 deletions

View File

@ -45,7 +45,7 @@ class ChatAnonymousUserToken(AuthBaseHandle):
if application_setting_model is not None:
application_setting = QuerySet(application_setting_model).filter(application_id=application_id).first()
if application_setting.authentication:
if 'password' != chat_user_token.authentication.auth_type:
if 'password' != application_setting.authentication_value.get('type', ''):
raise AppAuthenticationFailed(1002, _('Authentication information is incorrect'))
return None, ChatAuth(
current_role_list=[RoleConstants.CHAT_ANONYMOUS_USER],

View File

@ -59,6 +59,20 @@ const anonymousAuthentication: (
) => Promise<Result<any>> = (assessToken, loading) => {
return post('/auth/anonymous', { access_token: assessToken }, {}, loading)
}
/**
*
* @param assessToken
* @param password
* @param loading
* @returns
*/
const passwordAuthentication: (
assessToken: string,
password: string,
loading?: Ref<boolean>,
) => Promise<Result<any>> = (assessToken, password, loading) => {
return post('auth/password', { access_token: assessToken, password: password }, {}, loading)
}
/**
*
* @param loading
@ -161,4 +175,5 @@ export default {
getQrSource,
ldapLogin,
getAuthSetting,
passwordAuthentication,
}

View File

@ -74,6 +74,12 @@ const useChatUserStore = defineStore('chat-user', {
return this.token
})
},
passwordAuthentication(password: string) {
return ChatAPI.passwordAuthentication(this.accessToken as string, password).then((ok) => {
this.setToken(ok.data)
return this.token
})
},
login(request: LoginRequest, loading?: Ref<boolean>) {
return ChatAPI.login(this.accessToken as string, request, loading).then((ok) => {
this.setToken(ok.data.token)

View File

@ -40,7 +40,7 @@
class="mb-16"
:class="form.authentication_value.type === 'password' ? 'active' : ''"
>
<el-radio value="replace" size="large">
<el-radio value="password" size="large">
<p class="mb-4 lighter">
{{ $t('views.applicationOverview.appInfo.LimitDialog.authenticationValue') }}
</p>

View File

@ -1,53 +1,31 @@
<template>
<el-dialog
:modelValue="show"
modal-class="positioned-mask"
width="300"
:title="$t('chat.passwordValidator.title')"
custom-class="no-close-button"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
top="25vh"
center
:modal="true"
>
<el-form ref="FormRef" :model="form" @submit.prevent="validator">
<el-form-item prop="value" :rules="rules.value">
<el-input show-password v-model="form.value" />
</el-form-item>
<el-button class="w-full mt-8" type="primary" @click="validator" :loading="loading">
{{ $t('common.confirm') }}</el-button
>
</el-form>
</el-dialog>
<el-form ref="FormRef" :model="form" @submit.prevent="validator">
<el-form-item prop="value" :rules="rules.password">
<el-input show-password v-model="form.password" />
</el-form-item>
<el-button class="w-full mt-8" type="primary" @click="validator" :loading="loading">
{{ $t('common.confirm') }}</el-button
>
</el-form>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import useStore from '@/stores'
import { t } from '@/locales'
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const FormRef = ref()
const {
params: { accessToken }
} = route as any
const { application } = useStore()
const { chatUser } = useStore()
const props = defineProps<{ applicationProfile: any; modelValue: boolean }>()
const loading = ref<boolean>(false)
const show = computed(() => {
if (props.applicationProfile) {
if (props.modelValue) {
return false
}
return props.applicationProfile.authentication
}
return false
})
const router = useRouter()
const emit = defineEmits(['update:modelValue'])
const auth = () => {
return application.asyncAppAuthentication(accessToken, loading, form.value).then(() => {
emit('update:modelValue', true)
return chatUser.passwordAuthentication(form.value.password).then((ok) => {
router.push({ name: 'chat', params: { accessToken: chatUser.accessToken } })
})
}
const validator_auth = (rule: any, value: string, callback: any) => {
@ -64,12 +42,11 @@ const validator = () => {
}
const rules = {
value: [{ required: true, validator: validator_auth, trigger: 'manual' }]
password: [{ required: true, validator: validator_auth, trigger: 'manual' }],
}
const form = ref({
type: 'password',
value: ''
password: '',
})
</script>
<style lang="scss">

View File

@ -0,0 +1,50 @@
<template>
<div>
<el-form ref="FormRef" :model="form" @submit.prevent="validator">
<el-form-item prop="value" :rules="rules.value">
<el-input show-password v-model="form.value" />
</el-form-item>
<el-button class="w-full mt-8" type="primary" @click="validator" :loading="loading">
{{ $t('common.confirm') }}</el-button
>
</el-form>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import useStore from '@/stores'
import { t } from '@/locales'
const route = useRoute()
const FormRef = ref()
const {
params: { accessToken },
} = route as any
const { application } = useStore()
const loading = ref<boolean>(false)
const auth = () => {
return application.asyncAppAuthentication(accessToken, loading, form.value).then(() => {})
}
const validator_auth = (rule: any, value: string, callback: any) => {
if (value === '') {
callback(new Error(t('chat.passwordValidator.errorMessage1')))
} else {
auth().catch(() => {
callback(new Error(t('chat.passwordValidator.errorMessage2')))
})
}
}
const validator = () => {
FormRef.value.validate()
}
const rules = {
value: [{ required: true, validator: validator_auth, trigger: 'manual' }],
}
const form = ref({
type: 'password',
value: '',
})
</script>
<style lang="scss" scoped></style>

View File

@ -1,6 +1,13 @@
<template>
<UserLoginLayout v-if="!loading" v-loading="loading">
<LoginContainer :subTitle="theme.themeInfo?.slogan || $t('theme.defaultSlogan')">
<LoginContainer
v-if="chatUser.chat_profile?.authentication_type == 'password'"
:subTitle="theme.themeInfo?.slogan || $t('theme.defaultSlogan')"
>
<PasswordAuth></PasswordAuth>
</LoginContainer>
<LoginContainer v-else :subTitle="theme.themeInfo?.slogan || $t('theme.defaultSlogan')">
<h2 class="mb-24" v-if="!showQrCodeTab">
{{ loginMode == 'LOCAL' ? $t('views.login.title') : loginMode }}
</h2>
@ -139,6 +146,7 @@ import useStore from '@/stores'
import { useI18n } from 'vue-i18n'
import QrCodeTab from '@/views/login/scanCompinents/QrCodeTab.vue'
import { MsgConfirm, MsgError } from '@/utils/message.ts'
import PasswordAuth from '@/views/chat/auth/component/password.vue'
import useUserStore from '@/stores/modules/user.ts'
const router = useRouter()