diff --git a/src/client/pages/Layout.tsx b/src/client/pages/Layout.tsx
index f9dc65d..3ada306 100644
--- a/src/client/pages/Layout.tsx
+++ b/src/client/pages/Layout.tsx
@@ -3,8 +3,23 @@ import { Outlet } from 'react-router-dom';
import { NavItem } from '../components/NavItem';
import { UserOutlined } from '@ant-design/icons';
import { Button, Dropdown } from 'antd';
+import { useUserStore } from '../store/user';
export const Layout: React.FC = React.memo(() => {
+ const workspaces = useUserStore((state) => {
+ const userInfo = state.info;
+ if (userInfo) {
+ return userInfo.workspaces.map((w) => ({
+ id: w.workspace.id,
+ name: w.workspace.name,
+ role: w.role,
+ current: userInfo.currentWorkspace.id === w.workspace.id,
+ }));
+ }
+
+ return [];
+ });
+
return (
@@ -24,6 +39,15 @@ export const Layout: React.FC = React.memo(() => {
placement="bottomRight"
menu={{
items: [
+ {
+ key: 'workspaces',
+ label: 'Workspaces',
+ children: workspaces.map((w) => ({
+ key: w.id,
+ label: `${w.name}${w.current ? '(current)' : ''}`,
+ disabled: w.current,
+ })),
+ },
{
key: 'logout',
label: 'Logout',
diff --git a/src/client/store/user.ts b/src/client/store/user.ts
index 89bfe87..59c78c9 100644
--- a/src/client/store/user.ts
+++ b/src/client/store/user.ts
@@ -25,7 +25,15 @@ export const useUserStore = create(() => ({
info: null,
}));
-export function setUserInfo(info: UserInfo) {
+export function setUserInfo(info: UserLoginInfo) {
+ if (!info.currentWorkspace && info.workspaces[0]) {
+ // Make sure currentWorkspace existed
+ info.currentWorkspace = {
+ id: info.workspaces[0].workspace.id,
+ name: info.workspaces[0].workspace.name,
+ };
+ }
+
useUserStore.setState({
info,
});
diff --git a/src/server/middleware/auth.ts b/src/server/middleware/auth.ts
index d8abeaf..1dae4aa 100644
--- a/src/server/middleware/auth.ts
+++ b/src/server/middleware/auth.ts
@@ -2,10 +2,12 @@ import { findUser } from '../model/user';
import passport from 'passport';
import { Handler } from 'express';
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt';
-import { nanoid } from 'nanoid';
import jwt from 'jsonwebtoken';
+import { hashUuid } from '../utils/common';
+import dayjs from 'dayjs';
-export const jwtSecret = process.env.JWT_SECRET || nanoid();
+export const jwtSecret =
+ process.env.JWT_SECRET || hashUuid(dayjs().format('YYYYMMDD'));
export const jwtIssuer = process.env.JWT_ISSUER || 'tianji.msgbyte.com';
export const jwtAudience = process.env.JWT_AUDIENCE || 'msgbyte.com';
diff --git a/src/server/model/user.ts b/src/server/model/user.ts
index 23e192c..34f99bc 100644
--- a/src/server/model/user.ts
+++ b/src/server/model/user.ts
@@ -55,7 +55,7 @@ export async function createAdminUser(username: string, password: string) {
);
}
- const user = await prisma.user.create({
+ let user = await prisma.user.create({
data: {
username,
password: await hashPassword(password),
@@ -77,13 +77,14 @@ export async function createAdminUser(username: string, password: string) {
});
if (user.workspaces[0]) {
- prisma.user.update({
+ user = await prisma.user.update({
where: {
id: user.id,
},
data: {
currentWorkspaceId: user.workspaces[0].workspace.id,
},
+ select: createUserSelect,
});
}
@@ -101,7 +102,7 @@ export async function createUser(username: string, password: string) {
throw new Error('User already exists');
}
- const user = await prisma.user.create({
+ let user = await prisma.user.create({
data: {
username,
password: await hashPassword(password),
@@ -123,13 +124,14 @@ export async function createUser(username: string, password: string) {
});
if (user.workspaces[0]) {
- prisma.user.update({
+ user = await prisma.user.update({
where: {
id: user.id,
},
data: {
currentWorkspaceId: user.workspaces[0].workspace.id,
},
+ select: createUserSelect,
});
}