tianji/src/server/trpc/routers/user.ts

138 lines
3.1 KiB
TypeScript
Raw Normal View History

import { protectProedure, publicProcedure, router } from '../trpc';
2023-10-16 14:34:01 +00:00
import { z } from 'zod';
import {
authUser,
authUserWithToken,
changeUserPassword,
2023-10-16 14:34:01 +00:00
createAdminUser,
createUser,
getUserCount,
} from '../../model/user';
import { jwtSign } from '../../middleware/auth';
import { TRPCError } from '@trpc/server';
2023-10-21 16:26:13 +00:00
import { env } from '../../utils/env';
import { userInfoSchema } from '../../model/_schema/index';
import { OPENAPI_TAG } from '../../utils/const';
2023-10-16 14:34:01 +00:00
export const userRouter = router({
login: publicProcedure
2023-10-21 16:26:13 +00:00
.meta({
openapi: { method: 'POST', path: '/login', tags: [OPENAPI_TAG.USER] },
})
2023-10-16 14:34:01 +00:00
.input(
z.object({
username: z.string(),
password: z.string(),
})
)
2023-10-21 16:26:13 +00:00
.output(
z.object({
info: userInfoSchema,
token: z.string(),
})
)
2023-10-16 14:34:01 +00:00
.mutation(async ({ input }) => {
const { username, password } = input;
const user = await authUser(username, password);
const token = jwtSign(user);
return { info: user, token };
}),
loginWithToken: publicProcedure
2023-10-21 16:26:13 +00:00
.meta({
openapi: {
method: 'POST',
path: '/loginWithToken',
tags: [OPENAPI_TAG.USER],
},
})
2023-10-16 14:34:01 +00:00
.input(
z.object({
token: z.string(),
})
)
2023-10-21 16:26:13 +00:00
.output(
z.object({
info: userInfoSchema,
token: z.string(),
})
)
2023-10-16 14:34:01 +00:00
.mutation(async ({ input }) => {
const { token } = input;
if (!token) {
throw new Error('Cannot get token');
}
try {
const user = await authUserWithToken(token);
const newToken = jwtSign(user);
return { info: user, token: newToken };
} catch (err) {
throw new TRPCError({ code: 'FORBIDDEN', message: 'Invalid token' });
}
}),
register: publicProcedure
2023-10-21 16:26:13 +00:00
.meta({
openapi: {
enabled: env.allowRegister,
method: 'POST',
path: '/register',
tags: [OPENAPI_TAG.USER],
},
})
2023-10-16 14:34:01 +00:00
.input(
z.object({
username: z.string(),
password: z.string(),
})
)
2023-10-21 16:26:13 +00:00
.output(
z.object({
info: userInfoSchema,
token: z.string(),
})
)
2023-10-16 14:34:01 +00:00
.mutation(async ({ input }) => {
2023-10-21 16:26:13 +00:00
if (!env.allowRegister) {
throw new TRPCError({
code: 'FORBIDDEN',
message: 'Not allow register',
});
}
2023-10-16 14:34:01 +00:00
const { username, password } = input;
const userCount = await getUserCount();
if (userCount === 0) {
const user = await createAdminUser(username, password);
const token = jwtSign(user);
return { info: user, token };
} else {
const user = await createUser(username, password);
const token = jwtSign(user);
return { info: user, token };
}
}),
changePassword: protectProedure
.input(
z.object({
oldPassword: z.string(),
newPassword: z.string(),
})
)
.mutation(async ({ input, ctx }) => {
const userId = ctx.user.id;
const { oldPassword, newPassword } = input;
return changeUserPassword(userId, oldPassword, newPassword);
}),
2023-10-16 14:34:01 +00:00
});