diff --git a/cmd/agent/mise.toml b/cmd/agent/mise.toml index 627b3b5b..2f323200 100644 --- a/cmd/agent/mise.toml +++ b/cmd/agent/mise.toml @@ -1,5 +1,8 @@ +[task_config] +dir = "{{cwd}}" + [tasks.start] alias = "dev" description = "Start server" -run = "go run main.go" +run = "go run cmd/agent/main.go" depends = ["//:go-install"] diff --git a/mise.toml b/mise.toml index c514aff0..298e7173 100644 --- a/mise.toml +++ b/mise.toml @@ -29,6 +29,7 @@ description = "Start development environment" depends = [ "//agent:dev", "//cmd/agent:start", + "//packages/web:dev", ] [tasks.setup] diff --git a/packages/api/src/modules/auth/service.ts b/packages/api/src/modules/auth/service.ts deleted file mode 100644 index b8e91f3b..00000000 --- a/packages/api/src/modules/auth/service.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { db } from '@memoh/db' -import { users, settings } from '@memoh/db/schema' -import { eq } from 'drizzle-orm' - -/** - * 验证用户凭据 - * 优先检查是否为 ROOT 用户,否则查询数据库 - */ -export const validateUser = async (username: string, password: string) => { - // 检查是否为 ROOT 用户 - const rootUser = process.env.ROOT_USER - const rootPassword = process.env.ROOT_USER_PASSWORD - - let userId: string | null = null - - if (rootUser && rootPassword && username === rootUser) { - if (password === rootPassword) { - // 检查 root 用户是否存在于数据库中 - const [existingUser] = await db - .select() - .from(users) - .where(eq(users.username, rootUser)) - - userId = existingUser?.id - - if (!existingUser) { - // 为 root 用户创建数据库记录 - // 使用占位符密码哈希,因为实际密码在环境变量中 - - const [newUser] = await db - .insert(users) - .values({ - username: rootUser, - passwordHash: 'ENV_BASED_AUTH', // 占位符,实际使用环境变量验证 - role: 'admin', - displayName: 'Root User', - email: null, - avatarUrl: null, - isActive: true, - }) - .onConflictDoNothing() // 避免并发创建导致的冲突 - .returning({ - id: users.id, - }) - - userId = newUser.id - } - - // 检查 root 用户的 settings 是否存在,不存在则创建 - const [existingSettings] = await db - .select() - .from(settings) - .where(eq(settings.userId, userId)) - - if (!existingSettings) { - // 为 root 用户创建默认 settings - await db - .insert(settings) - .values({ - userId: userId, - defaultChatModel: null, - defaultEmbeddingModel: null, - defaultSummaryModel: null, - maxContextLoadTime: 60, - language: 'Same as user input', - }) - .onConflictDoNothing() // 避免并发创建导致的冲突 - } - - // 返回 ROOT 用户信息 - return { - id: userId, - username: rootUser, - role: 'admin' as const, - displayName: 'Root User', - } - } - return null - } - - // 查询数据库中的用户(使用 username 而不是 id) - const [user] = await db - .select() - .from(users) - .where(eq(users.username, username)) - - if (!user) { - return null - } - - // 验证密码 (这里使用简单的 Bun.password.verify) - const isValid = await Bun.password.verify(password, user.passwordHash) - - if (!isValid) { - return null - } - - // 检查账户是否激活 - if (!user.isActive) { - return null - } - - // 更新最后登录时间 - await db - .update(users) - .set({ - lastLoginAt: new Date(), - }) - .where(eq(users.id, user.id)) - - return { - id: user.id, - username: user.username, - role: user.role, - displayName: user.displayName || user.username, - email: user.email, - } -} - diff --git a/packages/api/src/modules/user/index.ts b/packages/api/src/modules/user/index.ts deleted file mode 100644 index 02ab1488..00000000 --- a/packages/api/src/modules/user/index.ts +++ /dev/null @@ -1,182 +0,0 @@ -import Elysia from 'elysia' -import { adminMiddleware } from '../../middlewares' -import { - GetUserByIdModel, - CreateUserModel, - UpdateUserModel, - DeleteUserModel, - UpdatePasswordModel, -} from './model' -import { - getUsers, - getUserById, - createUser, - updateUser, - deleteUser, - updateUserPassword, -} from './service' - -export const userModule = new Elysia({ - prefix: '/user', -}) - // 使用管理员中间件保护所有路由 - .use(adminMiddleware) - // Get all users - .get('/', async ({ query }) => { - try { - const page = parseInt(query.page as string) || 1 - const limit = parseInt(query.limit as string) || 10 - const sortBy = query.sortBy as string || 'createdAt' - const sortOrder = (query.sortOrder as string) || 'desc' - - const result = await getUsers({ - page, - limit, - sortBy, - sortOrder: sortOrder as 'asc' | 'desc', - }) - - return { - success: true, - ...result, - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch users', - } - } - }) - // Get user by ID - .get('/:id', async ({ params, set }) => { - try { - const { id } = params - const user = await getUserById(id) - - if (!user) { - set.status = 404 - return { - success: false, - error: 'User not found', - } - } - - return { - success: true, - data: user, - } - } catch (error) { - set.status = 500 - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch user', - } - } - }, GetUserByIdModel) - // Create new user - .post('/', async ({ body, set }) => { - try { - const newUser = await createUser(body) - set.status = 201 - return { - success: true, - data: newUser, - } - } catch (error) { - if (error instanceof Error && ( - error.message.includes('already exists') - )) { - set.status = 409 - } else { - set.status = 500 - } - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to create user', - } - } - }, CreateUserModel) - // Update user - .put('/:id', async ({ params, body, set }) => { - try { - const { id } = params - const updatedUser = await updateUser(id, body) - - if (!updatedUser) { - set.status = 404 - return { - success: false, - error: 'User not found', - } - } - - return { - success: true, - data: updatedUser, - } - } catch (error) { - if (error instanceof Error && error.message.includes('already exists')) { - set.status = 409 - } else { - set.status = 500 - } - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update user', - } - } - }, UpdateUserModel) - // Delete user - .delete('/:id', async ({ params, set }) => { - try { - const { id } = params - const deletedUser = await deleteUser(id) - - if (!deletedUser) { - set.status = 404 - return { - success: false, - error: 'User not found', - } - } - - return { - success: true, - data: deletedUser, - } - } catch (error) { - set.status = 500 - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to delete user', - } - } - }, DeleteUserModel) - // Update user password - .patch('/:id/password', async ({ params, body, set }) => { - try { - const { id } = params - const updatedUser = await updateUserPassword(id, body.password) - - if (!updatedUser) { - set.status = 404 - return { - success: false, - error: 'User not found', - } - } - - return { - success: true, - data: updatedUser, - message: 'Password updated successfully', - } - } catch (error) { - set.status = 500 - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update password', - } - } - }, UpdatePasswordModel) - diff --git a/packages/web/mise.toml b/packages/web/mise.toml new file mode 100644 index 00000000..82fe917e --- /dev/null +++ b/packages/web/mise.toml @@ -0,0 +1,14 @@ +[tasks.dev] +alias = "dev" +description = "Start web development server" +run = "pnpm dev" +depends = ["//:pnpm-install"] + +[tasks.build] +description = "Build web" +run = "pnpm build" +depends = ["//:pnpm-install"] + +[tasks.start] +description = "Start web" +run = "pnpm start" \ No newline at end of file