diff --git a/frontend/desktop/src/__tests__/api/e2e/namespace/invite.test.ts b/frontend/desktop/src/__tests__/api/e2e/namespace/invite.test.ts index 65e765b1ef2..8a2800cfdc0 100644 --- a/frontend/desktop/src/__tests__/api/e2e/namespace/invite.test.ts +++ b/frontend/desktop/src/__tests__/api/e2e/namespace/invite.test.ts @@ -130,8 +130,8 @@ describe('invite member', () => { role }); console.log(res); - console.log(ns) - console.log(payload1) + console.log(ns); + console.log(payload1); expect(res.code).toBe(200); setAuth(token2); const res2 = await verifyInviteRequest({ action: reciveAction.Accepte, ns_uid }); diff --git a/frontend/desktop/src/api/auth.ts b/frontend/desktop/src/api/auth.ts index 3248e6ab987..ef8659256d5 100644 --- a/frontend/desktop/src/api/auth.ts +++ b/frontend/desktop/src/api/auth.ts @@ -6,7 +6,9 @@ import { AxiosHeaders, AxiosHeaderValue, type AxiosInstance } from 'axios'; import useSessionStore from '@/stores/session'; export const _getRegionToken = (request: AxiosInstance) => () => - request.post>('/api/auth/regionToken'); + request.post>( + '/api/auth/regionToken' + ); export const getRegionToken = _getRegionToken(request); export const _passwordExistRequest = (request: AxiosInstance) => (data: { user: string }) => diff --git a/frontend/desktop/src/api/namespace.ts b/frontend/desktop/src/api/namespace.ts index 4e904578469..1722827f836 100644 --- a/frontend/desktop/src/api/namespace.ts +++ b/frontend/desktop/src/api/namespace.ts @@ -53,9 +53,12 @@ export const _teamDetailsRequest = (request: AxiosInstance) => (ns_uid: string) export const _reciveMessageRequest = (request: AxiosInstance) => () => request.post>('/api/auth/namespace/recive'); export const _switchRequest = (request: AxiosInstance) => (ns_uid: string) => - request.post>('/api/auth/namespace/switch', { - ns_uid - }); + request.post>( + '/api/auth/namespace/switch', + { + ns_uid + } + ); // 提供给prod/dev环境使用 export const abdicateRequest = _abdicateRequest(request); export const createRequest = _createRequest(request); diff --git a/frontend/desktop/src/components/account/index.tsx b/frontend/desktop/src/components/account/index.tsx index 68d025693ba..43f34841eea 100644 --- a/frontend/desktop/src/components/account/index.tsx +++ b/frontend/desktop/src/components/account/index.tsx @@ -34,6 +34,7 @@ import { CopyIcon, DownloadIcon, LogoutIcon, RightArrowIcon } from '@sealos/ui'; import { ImageFallBackUrl } from '@/stores/config'; import { jwtDecode } from 'jwt-decode'; import { AccessTokenPayload } from '@/types/token'; +import { sessionConfig } from '@/utils/sessionConfig'; const NsMenu = () => { const { t } = useTranslation(); @@ -46,21 +47,9 @@ const NsMenu = () => { mutationFn: switchRequest, async onSuccess(data) { if (data.code === 200 && !!data.data) { - setToken(data.data.token); - const payload = jwtDecode(data.data.token); - if (session) { - setSession({ - ...session, - user: { - ...session.user, - nsid: payload.workspaceId, - ns_uid: payload.workspaceUid - }, - kubeconfig: data.data.kubeconfig - }); - } else { - throw Error('session in invalid'); - } + await sessionConfig(data.data); + } else { + throw Error('session in invalid'); } } }); diff --git a/frontend/desktop/src/components/signin/auth/usePassword.tsx b/frontend/desktop/src/components/signin/auth/usePassword.tsx index facc72764ef..4fcd7ea164c 100644 --- a/frontend/desktop/src/components/signin/auth/usePassword.tsx +++ b/frontend/desktop/src/components/signin/auth/usePassword.tsx @@ -8,6 +8,7 @@ import { useState } from 'react'; import { useForm } from 'react-hook-form'; import { jwtDecode } from 'jwt-decode'; import { AccessTokenPayload } from '@/types/token'; +import { sessionConfig } from '@/utils/sessionConfig'; export default function usePassword({ showError @@ -53,25 +54,7 @@ export default function usePassword({ inviterId }); if (!!result?.data) { - const regionUserToken = result.data.token; - setToken(regionUserToken); - const infoData = await UserInfo(); - const payload = jwtDecode(regionUserToken); - setSession({ - token: regionUserToken, - user: { - k8s_username: payload.userCrName, - name: infoData.data?.info.nickname || '', - avatar: infoData.data?.info.avatarUri || '', - nsid: payload.workspaceId, - ns_uid: payload.workspaceUid, - userCrUid: payload.userCrUid, - userUid: payload.userUid, - userId: payload.userId - }, - // @ts-ignore - kubeconfig: result.data.kubeconfig - }); + await sessionConfig(result.data); await router.replace('/'); } return; diff --git a/frontend/desktop/src/components/signin/auth/useSms.tsx b/frontend/desktop/src/components/signin/auth/useSms.tsx index 90054ded19e..d1fa03e9aa4 100644 --- a/frontend/desktop/src/components/signin/auth/useSms.tsx +++ b/frontend/desktop/src/components/signin/auth/useSms.tsx @@ -19,6 +19,7 @@ import { getRegionToken, UserInfo } from '@/api/auth'; import { jwtDecode } from 'jwt-decode'; import { uploadConvertData } from '@/api/platform'; import { AccessTokenPayload } from '@/types/token'; +import { sessionConfig } from '@/utils/sessionConfig'; export default function useSms({ showError @@ -61,24 +62,7 @@ export default function useSms({ setToken(globalToken); const regionTokenRes = await getRegionToken(); if (regionTokenRes?.data) { - const regionUserToken = regionTokenRes.data.token; - setToken(regionUserToken); - const infoData = await UserInfo(); - const payload = jwtDecode(regionUserToken); - setSession({ - token: regionUserToken, - user: { - k8s_username: payload.userCrName, - name: infoData.data?.info.nickname || '', - avatar: infoData.data?.info.avatarUri || '', - nsid: payload.workspaceId, - ns_uid: payload.workspaceUid, - userCrUid: payload.userCrUid, - userId: payload.userId, - userUid: payload.userUid - }, - kubeconfig: regionTokenRes.data.kubeconfig - }); + await sessionConfig(regionTokenRes.data); uploadConvertData([3]).then( (res) => { console.log(res); diff --git a/frontend/desktop/src/pages/api/auth/namespace/switch.ts b/frontend/desktop/src/pages/api/auth/namespace/switch.ts index d6e3e8eee5c..3140e4ad190 100644 --- a/frontend/desktop/src/pages/api/auth/namespace/switch.ts +++ b/frontend/desktop/src/pages/api/auth/namespace/switch.ts @@ -5,7 +5,7 @@ import { getUserKubeconfig } from '@/services/backend/kubernetes/admin'; import { switchKubeconfigNamespace } from '@/services/backend/kubernetes/user'; import { validate } from 'uuid'; import { JoinStatus } from 'prisma/region/generated/client'; -import { generateAccessToken, verifyAccessToken } from '@/services/backend/auth'; +import { generateAccessToken, generateAppToken, verifyAccessToken } from '@/services/backend/auth'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { @@ -26,19 +26,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) userCr: true } }); - const curWorkspaceItem = queryResults.find( - (item) => item.workspace.uid === payload.workspaceUid - ); - if (!curWorkspaceItem) - return jsonRes(res, { code: 403, message: 'You are not in this workspace' }); const newWorkspaceItem = queryResults.find((item) => item.workspace.uid === ns_uid); if (!newWorkspaceItem) return jsonRes(res, { code: 403, message: 'You are not in this workspace' }); const oldKcRaw = await getUserKubeconfig(payload.userCrUid, payload.userCrName); if (!oldKcRaw) return jsonRes(res, { code: 404, message: 'The kubeconfig is not found' }); const kubeconfig = switchKubeconfigNamespace(oldKcRaw, newWorkspaceItem.workspace.id); - - const token = generateAccessToken({ + const jwtPayload = { workspaceUid: newWorkspaceItem.workspaceUid, workspaceId: newWorkspaceItem.workspace.id, regionUid: payload.regionUid, @@ -46,10 +40,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) userCrName: payload.userCrName, userId: payload.userId, userUid: payload.userUid - }); + }; + const token = generateAccessToken(jwtPayload); + const appToken = generateAppToken(jwtPayload); const data = { token, - kubeconfig + kubeconfig, + appToken }; return jsonRes(res, { data, diff --git a/frontend/desktop/src/pages/callback.tsx b/frontend/desktop/src/pages/callback.tsx index 00507239387..4654c3d03c9 100644 --- a/frontend/desktop/src/pages/callback.tsx +++ b/frontend/desktop/src/pages/callback.tsx @@ -10,6 +10,7 @@ import { jwtDecode } from 'jwt-decode'; import { isString } from 'lodash'; import { getRegionToken, UserInfo } from '@/api/auth'; import { AccessTokenPayload } from '@/types/token'; +import { sessionConfig } from '@/utils/sessionConfig'; const Callback: NextPage = () => { const router = useRouter(); @@ -70,24 +71,7 @@ const Callback: NextPage = () => { setToken(token); const regionTokenRes = await getRegionToken(); if (regionTokenRes?.data) { - const regionUserToken = regionTokenRes.data.token; - setToken(regionUserToken); - const infoData = await UserInfo(); - const payload = jwtDecode(regionUserToken); - setSession({ - token: regionUserToken, - user: { - k8s_username: payload.userCrName, - name: infoData.data?.info.nickname || '', - avatar: infoData.data?.info.avatarUri || '', - nsid: payload.workspaceId, - ns_uid: payload.workspaceUid, - userCrUid: payload.userCrUid, - userUid: payload.userUid, - userId: payload.userId - }, - kubeconfig: regionTokenRes.data.kubeconfig - }); + await sessionConfig(regionTokenRes.data); uploadConvertData([3]).then( (res) => { console.log(res); diff --git a/frontend/desktop/src/pages/switchRegion.tsx b/frontend/desktop/src/pages/switchRegion.tsx index 21ec1f077cd..1701d7fbd48 100644 --- a/frontend/desktop/src/pages/switchRegion.tsx +++ b/frontend/desktop/src/pages/switchRegion.tsx @@ -8,6 +8,7 @@ import { getRegionToken, UserInfo } from '@/api/auth'; import { isString } from 'lodash'; import { jwtDecode } from 'jwt-decode'; import { AccessTokenPayload } from '@/types/token'; +import { sessionConfig } from '@/utils/sessionConfig'; const Callback: NextPage = () => { const router = useRouter(); @@ -28,32 +29,7 @@ const Callback: NextPage = () => { setToken(globalToken); const regionTokenRes = await getRegionToken(); if (regionTokenRes?.data) { - const regionUserToken = regionTokenRes.data.token; - setToken(regionUserToken); - const infoData = await UserInfo(); - const payload = jwtDecode(regionUserToken); - setSession({ - token: regionUserToken, - user: { - k8s_username: payload.userCrName, - name: infoData.data?.info.nickname || '', - avatar: infoData.data?.info.avatarUri || '', - nsid: payload.workspaceId, - ns_uid: payload.workspaceUid, - userCrUid: payload.userCrUid, - userId: payload.userId, - userUid: payload.userUid - }, - kubeconfig: regionTokenRes.data.kubeconfig - }); - uploadConvertData([3]).then( - (res) => { - console.log(res); - }, - (err) => { - console.log(err); - } - ); + await sessionConfig(regionTokenRes.data); await router.replace('/'); return; } else { diff --git a/frontend/desktop/src/services/backend/auth.ts b/frontend/desktop/src/services/backend/auth.ts index bc3f65e23ae..1aa9da5b873 100644 --- a/frontend/desktop/src/services/backend/auth.ts +++ b/frontend/desktop/src/services/backend/auth.ts @@ -6,6 +6,7 @@ import { getRegionUid } from '@/services/enable'; const jwtSecret = (process.env.JWT_SECRET as string) || '123456789'; const regionJwtSecret = process.env.JWT_SECRET_REGION || '123456789'; +const appJwtSecret = process.env.JWT_SECRET_APP || '123456789'; const verifyToken = async (header: IncomingHttpHeaders) => { try { if (!header?.authorization) { @@ -60,6 +61,7 @@ export const verifyJWT = (token?: string, secret? }); export const generateAccessToken = (props: AccessTokenPayload) => sign(props, jwtSecret, { expiresIn: '7d' }); - +export const generateAppToken = (props: AccessTokenPayload) => + sign(props, appJwtSecret, { expiresIn: '7d' }); export const generateAuthenticationToken = (props: AuthenticationTokenPayload) => sign(props, regionJwtSecret, { expiresIn: '60000' }); diff --git a/frontend/desktop/src/services/backend/regionAuth.ts b/frontend/desktop/src/services/backend/regionAuth.ts index 5b53d034e14..8cb18d5842b 100644 --- a/frontend/desktop/src/services/backend/regionAuth.ts +++ b/frontend/desktop/src/services/backend/regionAuth.ts @@ -6,7 +6,7 @@ import { customAlphabet } from 'nanoid'; import { retrySerially } from '@/utils/tools'; import { AccessTokenPayload } from '@/types/token'; import { JoinStatus, Role } from 'prisma/region/generated/client'; -import { generateAccessToken } from '@/services/backend/auth'; +import { generateAccessToken, generateAppToken } from '@/services/backend/auth'; const LetterBytes = 'abcdefghijklmnopqrstuvwxyz0123456789'; const HostnameLength = 8; @@ -35,6 +35,7 @@ export async function getRegionToken({ }): Promise<{ kubeconfig: string; token: string; + appToken: string; }> { const region = await globalPrisma.region.findUnique({ where: { @@ -141,28 +142,7 @@ export async function getRegionToken({ return { kubeconfig, - token: generateAccessToken(payload) + token: generateAccessToken(payload), + appToken: generateAppToken(payload) }; } - -export function verifyK8sUser({ - workspaceUid, - userCrUid -}: { - workspaceUid: string; - userCrUid: string; -}) { - return prisma.userWorkspace - .findUnique({ - where: { - workspaceUid_userCrUid: { - userCrUid, - workspaceUid - } - } - }) - .then( - (result) => !!result, - () => false - ); -} diff --git a/frontend/desktop/src/utils/sessionConfig.ts b/frontend/desktop/src/utils/sessionConfig.ts new file mode 100644 index 00000000000..94080153ffa --- /dev/null +++ b/frontend/desktop/src/utils/sessionConfig.ts @@ -0,0 +1,33 @@ +import { UserInfo } from '@/api/auth'; +import { jwtDecode } from 'jwt-decode'; +import { AccessTokenPayload } from '@/types/token'; +import useSessionStore from '@/stores/session'; + +export const sessionConfig = async ({ + token, + kubeconfig, + appToken +}: { + token: string; + kubeconfig: string; + appToken: string; +}) => { + const store = useSessionStore.getState(); + store.setToken(token); + const infoData = await UserInfo(); + const payload = jwtDecode(token); + store.setSession({ + token: appToken, + user: { + k8s_username: payload.userCrName, + name: infoData.data?.info.nickname || '', + avatar: infoData.data?.info.avatarUri || '', + nsid: payload.workspaceId, + ns_uid: payload.workspaceUid, + userCrUid: payload.userCrUid, + userId: payload.userId, + userUid: payload.userUid + }, + kubeconfig + }); +}; diff --git a/frontend/packages/client-sdk/src/master.ts b/frontend/packages/client-sdk/src/master.ts index 43b7744b926..fdb21ab1024 100644 --- a/frontend/packages/client-sdk/src/master.ts +++ b/frontend/packages/client-sdk/src/master.ts @@ -60,6 +60,7 @@ class MasterSDK { avatar: session.user.avatar, nsid: session.user.nsid }, + token: session.token, kubeconfig: session.kubeconfig }; } diff --git a/frontend/packages/client-sdk/src/types/user.d.ts b/frontend/packages/client-sdk/src/types/user.d.ts index b93a6040d8f..625e708b150 100644 --- a/frontend/packages/client-sdk/src/types/user.d.ts +++ b/frontend/packages/client-sdk/src/types/user.d.ts @@ -18,9 +18,7 @@ export type KubeConfig = string; export type Session = { token: string; // jwt token - // 提供一些简单的信息 user: UserInfo; - // 帮忙导出用的 kubeconfig: KubeConfig; }; @@ -39,7 +37,7 @@ export type UserInfoV1 = Readonly<{ }>; export type SessionV1 = { - token?: OAuthToken; + token?: string; user: UserInfoV1; kubeconfig: KubeConfig; }; diff --git a/frontend/providers/adminer/src/stores/session.ts b/frontend/providers/adminer/src/stores/session.ts index 839abd5efbf..61a3f7987ac 100644 --- a/frontend/providers/adminer/src/stores/session.ts +++ b/frontend/providers/adminer/src/stores/session.ts @@ -1,9 +1,9 @@ -import type { Session } from '@/interfaces/session'; import { sessionKey } from '@/interfaces/session'; import { create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; import { immer } from 'zustand/middleware/immer'; import * as yaml from 'js-yaml'; +import { SessionV1 as Session } from 'sealos-desktop-sdk'; type SessionState = { session: Session;