mirror of
https://github.com/labring/sealos.git
synced 2026-09-24 15:46:19 +08:00
feat(desktop): add appToken for providers & fix ssr error (#4566)
This commit is contained in:
@@ -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 });
|
||||
|
||||
@@ -6,7 +6,9 @@ import { AxiosHeaders, AxiosHeaderValue, type AxiosInstance } from 'axios';
|
||||
import useSessionStore from '@/stores/session';
|
||||
|
||||
export const _getRegionToken = (request: AxiosInstance) => () =>
|
||||
request.post<any, ApiResp<{ token: string; kubeconfig: string }>>('/api/auth/regionToken');
|
||||
request.post<any, ApiResp<{ token: string; kubeconfig: string; appToken: string }>>(
|
||||
'/api/auth/regionToken'
|
||||
);
|
||||
|
||||
export const getRegionToken = _getRegionToken(request);
|
||||
export const _passwordExistRequest = (request: AxiosInstance) => (data: { user: string }) =>
|
||||
|
||||
@@ -53,9 +53,12 @@ export const _teamDetailsRequest = (request: AxiosInstance) => (ns_uid: string)
|
||||
export const _reciveMessageRequest = (request: AxiosInstance) => () =>
|
||||
request.post<any, ApiResp<{ messages: teamMessageDto[] }>>('/api/auth/namespace/recive');
|
||||
export const _switchRequest = (request: AxiosInstance) => (ns_uid: string) =>
|
||||
request.post<any, ApiResp<{ token: string; kubeconfig: string }>>('/api/auth/namespace/switch', {
|
||||
ns_uid
|
||||
});
|
||||
request.post<any, ApiResp<{ token: string; kubeconfig: string; appToken: string }>>(
|
||||
'/api/auth/namespace/switch',
|
||||
{
|
||||
ns_uid
|
||||
}
|
||||
);
|
||||
// 提供给prod/dev环境使用
|
||||
export const abdicateRequest = _abdicateRequest(request);
|
||||
export const createRequest = _createRequest(request);
|
||||
|
||||
@@ -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<AccessTokenPayload>(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');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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<AccessTokenPayload>(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;
|
||||
|
||||
@@ -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<AccessTokenPayload>(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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<AccessTokenPayload>(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);
|
||||
|
||||
@@ -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<AccessTokenPayload>(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 {
|
||||
|
||||
@@ -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 <T extends Object>(header: IncomingHttpHeaders) => {
|
||||
try {
|
||||
if (!header?.authorization) {
|
||||
@@ -60,6 +61,7 @@ export const verifyJWT = <T extends Object = JWTPayload>(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' });
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<AccessTokenPayload>(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
|
||||
});
|
||||
};
|
||||
@@ -60,6 +60,7 @@ class MasterSDK {
|
||||
avatar: session.user.avatar,
|
||||
nsid: session.user.nsid
|
||||
},
|
||||
token: session.token,
|
||||
kubeconfig: session.kubeconfig
|
||||
};
|
||||
}
|
||||
|
||||
+1
-3
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user