diff --git a/src/api/sso.ts b/src/api/sso.ts index 0ec458bd2..909bf2da8 100644 --- a/src/api/sso.ts +++ b/src/api/sso.ts @@ -12,8 +12,8 @@ export const getSSOList = (): Promise => { } export const postSSOLogin = ( - backend: 'ldap' | 'saml', - emqxDashboardSsoLdapLogin: PostSsoLoginBackendBody, + backend: 'ldap' | 'saml' | 'tongauth', + emqxDashboardSsoLdapLogin?: PostSsoLoginBackendBody, ): Promise => { return http.post(`/sso/login/${backend}`, emqxDashboardSsoLdapLogin) } diff --git a/src/assets/img/tongauth.png b/src/assets/img/tongauth.png new file mode 100644 index 000000000..009c6edeb Binary files /dev/null and b/src/assets/img/tongauth.png differ diff --git a/src/hooks/SSO/useSSO.ts b/src/hooks/SSO/useSSO.ts index cf5236c28..bf3e39dd8 100644 --- a/src/hooks/SSO/useSSO.ts +++ b/src/hooks/SSO/useSSO.ts @@ -7,12 +7,15 @@ import { PostSsoLoginBackend200, } from '@/types/schemas/dashboardSingleSignOn.schemas' import { ComputedRef, Ref, computed, reactive, ref } from 'vue' +import useI18nTl from '../useI18nTl' export const useSSOBackendsLabel = (): { getBackendLabel: (backend: string) => string } => { + const { tl } = useI18nTl('General') const backendsLabelMap: Map = new Map([ [DashboardSsoBackendStatusBackend.ldap, 'LDAP'], [DashboardSsoBackendStatusBackend.saml, 'SAML 2.0'], [DashboardSsoBackendStatusBackend.oidc, 'OIDC'], + [DashboardSsoBackendStatusBackend.tongauth, tl('tongtech')], ]) const getBackendLabel = (backend: string): string => backendsLabelMap.get(backend) || '' @@ -36,6 +39,9 @@ export default function useSSO(): { enabledSSOList: Ref> ldapRecord: SsoLogin hasSSOEnabled: ComputedRef + tongTechLoginUrl: string + tongTechBackend: Ref<'tongauth'> + isTongTechAuthEnabled: ComputedRef ldapLogin: () => Promise getEnabledSSO: () => Promise } { @@ -49,6 +55,8 @@ export default function useSSO(): { }) const currentLoginBackend = ref('local') + const getLoginUrl = (backend: string) => `${API_BASE_URL}/sso/login/${backend}` + const samlLoginUrl = `${API_BASE_URL}/sso/login/${DashboardSsoBackendStatusBackend.saml}` const samlBackend = ref(DashboardSamlBackend.saml) @@ -57,6 +65,12 @@ export default function useSSO(): { const hasSSOEnabled = computed(() => enabledSSOList.value.length > 0) + const tongTechLoginUrl = getLoginUrl(DashboardSsoBackendStatusBackend.tongauth) + const tongTechBackend = ref(DashboardSsoBackendStatusBackend.tongauth) + const isTongTechAuthEnabled = computed(() => + enabledSSOList.value.includes(DashboardSsoBackendStatusBackend.tongauth), + ) + const getEnabledSSO = async () => { try { enabledSSOList.value = await getSSORunning() @@ -88,6 +102,9 @@ export default function useSSO(): { enabledSSOList, ldapRecord, hasSSOEnabled, + tongTechLoginUrl, + tongTechBackend, + isTongTechAuthEnabled, ldapLogin, getEnabledSSO, } diff --git a/src/hooks/SSO/useSSODetail.ts b/src/hooks/SSO/useSSODetail.ts index 7241d4068..e20eac941 100644 --- a/src/hooks/SSO/useSSODetail.ts +++ b/src/hooks/SSO/useSSODetail.ts @@ -52,11 +52,20 @@ export default (): { fallback_methods: ['RS256'], client_jwks: 'none', }) + const createRawTongTechForm = (): any => ({ + enable: true, + backend: DashboardSsoBackendStatusBackend.tongauth, + dashboard_addr: location.origin + location.pathname.slice(0, -1), + auth_server_addr: 'http://168.1.15.162:9000', + client_id: 'tongmmp_yunjian_oauth2', + client_secret: 'b2c3d4e5-f678-9c0a-1b2f-4567890abcde', + }) const formCreatorMap: Map any> = new Map([ [DashboardSsoBackendStatusBackend.ldap, createRawLDAPForm], [DashboardSsoBackendStatusBackend.saml, createRawSAMLForm], [DashboardSsoBackendStatusBackend.oidc, createRawOIDCForm], + [DashboardSsoBackendStatusBackend.tongauth, createRawTongTechForm], ]) const createRawForm = (backend: string) => { const func = formCreatorMap.get(backend) diff --git a/src/i18n/Base.js b/src/i18n/Base.js index c9a3b11b0..3e03fc5bd 100644 --- a/src/i18n/Base.js +++ b/src/i18n/Base.js @@ -703,4 +703,16 @@ export default { zh: '', en: ' ', }, + tongTechAuthGuidance: { + zh: '请在配置文件中,{add}或启用东方通单点登录,并重启服务', + en: 'Please {add} or enable TongTech Auth in the configuration file and restart the service', + }, + tongTechAuthConfigComment: { + zh: '东方通单点登录配置参数,请确保参数在 dashboard > sso 层级下', + en: 'TongTech SSO configuration parameters, please ensure the parameters are under the dashboard > sso hierarchy', + }, + jumping: { + zh: '跳转中...', + en: 'Jumping...', + }, } diff --git a/src/i18n/General.js b/src/i18n/General.js index c85d10fb8..972ea1b7c 100644 --- a/src/i18n/General.js +++ b/src/i18n/General.js @@ -263,6 +263,10 @@ export default { zh: '启用 {backend} SSO', en: 'Enable {backend} SSO', }, + tongtech: { + zh: '东方通', + en: 'TongTech', + }, baseDN: { zh: '基本 DN', en: 'Base DN', @@ -355,6 +359,14 @@ export default { zh: '备用方法', en: 'Fallback Methods', }, + authServerAddr: { + zh: '认证服务器地址', + en: 'Auth Server Address', + }, + authServerAddrDesc: { + zh: '东方通认证服务器的基本 URL。示例:http://168.1.15.162:9000', + en: 'The Base URL of the TongAuth Server. Example: http://168.1.15.162:9000', + }, JWK: { zh: 'JSON Web 密钥', en: 'JSON Web Key (JWK)', diff --git a/src/types/schemas/dashboardSingleSignOn.schemas.ts b/src/types/schemas/dashboardSingleSignOn.schemas.ts index 3a3bfbf5f..b095a9ae7 100644 --- a/src/types/schemas/dashboardSingleSignOn.schemas.ts +++ b/src/types/schemas/dashboardSingleSignOn.schemas.ts @@ -1,3 +1,55 @@ +export type GetSsoTongauthCallback404Code = + typeof GetSsoTongauthCallback404Code[keyof typeof GetSsoTongauthCallback404Code] + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const GetSsoTongauthCallback404Code = { + BACKEND_NOT_FOUND: 'BACKEND_NOT_FOUND', +} as const + +export type GetSsoTongauthCallback404 = { + code?: GetSsoTongauthCallback404Code + message?: string +} + +export type GetSsoTongauthCallback401Code = + typeof GetSsoTongauthCallback401Code[keyof typeof GetSsoTongauthCallback401Code] + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const GetSsoTongauthCallback401Code = { + BAD_USERNAME_OR_PWD: 'BAD_USERNAME_OR_PWD', +} as const + +export type GetSsoTongauthCallback401 = { + code?: GetSsoTongauthCallback401Code + message?: string +} + +export type GetSsoTongauthCallback400Code = + typeof GetSsoTongauthCallback400Code[keyof typeof GetSsoTongauthCallback400Code] + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const GetSsoTongauthCallback400Code = { + BAD_REQUEST: 'BAD_REQUEST', +} as const + +export type GetSsoTongauthCallback400 = { + code?: GetSsoTongauthCallback400Code + message?: string +} + +export type GetSsoTongauthCallback302Code = + typeof GetSsoTongauthCallback302Code[keyof typeof GetSsoTongauthCallback302Code] + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const GetSsoTongauthCallback302Code = { + REDIRECT: 'REDIRECT', +} as const + +export type GetSsoTongauthCallback302 = { + code?: GetSsoTongauthCallback302Code + message?: string +} + export type DeleteSsoBackend404Code = typeof DeleteSsoBackend404Code[keyof typeof DeleteSsoBackend404Code] @@ -23,9 +75,9 @@ export type PutSsoBackend404 = { message?: string } -export type PutSsoBackend200 = SsoOidc | DashboardSaml | SsoLdap +export type PutSsoBackend200 = DashboardTongauth | DashboardSaml | SsoOidc | SsoLdap -export type PutSsoBackendBody = SsoOidc | DashboardSaml | SsoLdap +export type PutSsoBackendBody = DashboardTongauth | DashboardSaml | SsoOidc | SsoLdap export type GetSsoBackend404Code = typeof GetSsoBackend404Code[keyof typeof GetSsoBackend404Code] @@ -39,15 +91,16 @@ export type GetSsoBackend404 = { message?: string } -export type GetSsoBackend200 = SsoOidc | DashboardSaml | SsoLdap +export type GetSsoBackend200 = DashboardTongauth | DashboardSaml | SsoOidc | SsoLdap export type GetSsoRunning200Item = typeof GetSsoRunning200Item[keyof typeof GetSsoRunning200Item] // eslint-disable-next-line @typescript-eslint/no-redeclare export const GetSsoRunning200Item = { ldap: 'ldap', - saml: 'saml', oidc: 'oidc', + saml: 'saml', + tongauth: 'tongauth', } as const export type PostSsoLoginBackend404Code = @@ -109,7 +162,7 @@ export type PostSsoLoginBackend200 = { license?: PostSsoLoginBackend200License } -export type PostSsoLoginBackendBody = SsoLogin | DashboardLogin | SsoLogin +export type PostSsoLoginBackendBody = DashboardLogin | DashboardLogin | SsoLogin | SsoLogin export type GetSsoSamlMetadata404Code = typeof GetSsoSamlMetadata404Code[keyof typeof GetSsoSamlMetadata404Code] @@ -301,6 +354,20 @@ export const SsoLdapBackend = { ldap: 'ldap', } as const +export interface SsoLdap { + enable?: boolean + backend: SsoLdapBackend + query_timeout?: string + server: string + pool_size?: number + username: string + password?: string + base_dn: string + filter?: string + request_timeout?: string + ssl?: LdapSsl +} + export type SsoClientFileJwksType = typeof SsoClientFileJwksType[keyof typeof SsoClientFileJwksType] // eslint-disable-next-line @typescript-eslint/no-redeclare @@ -370,18 +437,21 @@ export interface LdapSsl { server_name_indication?: LdapSslServerNameIndication } -export interface SsoLdap { +export type DashboardTongauthBackend = + typeof DashboardTongauthBackend[keyof typeof DashboardTongauthBackend] + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const DashboardTongauthBackend = { + tongauth: 'tongauth', +} as const + +export interface DashboardTongauth { enable?: boolean - backend: SsoLdapBackend - query_timeout?: string - server: string - pool_size?: number - username: string - password?: string - base_dn: string - filter?: string - request_timeout?: string - ssl?: LdapSsl + backend: DashboardTongauthBackend + dashboard_addr?: string + auth_server_addr?: string + client_id?: string + client_secret?: string } export type DashboardSamlBackend = typeof DashboardSamlBackend[keyof typeof DashboardSamlBackend] @@ -405,7 +475,7 @@ export type DashboardLoginBackend = typeof DashboardLoginBackend[keyof typeof Da // eslint-disable-next-line @typescript-eslint/no-redeclare export const DashboardLoginBackend = { - saml: 'saml', + tongauth: 'tongauth', } as const export interface DashboardLogin { @@ -418,8 +488,9 @@ export type DashboardSsoBackendStatusBackend = // eslint-disable-next-line @typescript-eslint/no-redeclare export const DashboardSsoBackendStatusBackend = { ldap: 'ldap', - saml: 'saml', oidc: 'oidc', + saml: 'saml', + tongauth: 'tongauth', } as const export interface DashboardSsoBackendStatus { diff --git a/src/views/Base/Login.vue b/src/views/Base/Login.vue index 5791106a0..166b625f8 100644 --- a/src/views/Base/Login.vue +++ b/src/views/Base/Login.vue @@ -1,6 +1,8 @@ + +