feat(auth): create routes to change locale and set initial locale
This commit is contained in:
parent
ce2ff2672c
commit
8744f22e76
5 changed files with 42 additions and 3 deletions
|
@ -1,8 +1,10 @@
|
|||
import { inferAsyncReturnType } from '@trpc/server';
|
||||
import { CreateNextContextOptions } from '@trpc/server/adapters/next';
|
||||
import { Locale } from '@/shared/internationalization/locales';
|
||||
|
||||
type Session = {
|
||||
userId?: number;
|
||||
locale?: Locale;
|
||||
};
|
||||
|
||||
type CreateContextOptions = {
|
||||
|
|
|
@ -40,7 +40,7 @@ export class AuthQueries {
|
|||
*/
|
||||
public async getUserDtoById(id: number) {
|
||||
const users = await this.db
|
||||
.select({ id: userTable.id, username: userTable.username, totpEnabled: userTable.totpEnabled })
|
||||
.select({ id: userTable.id, username: userTable.username, totpEnabled: userTable.totpEnabled, locale: userTable.locale })
|
||||
.from(userTable)
|
||||
.where(eq(userTable.id, Number(id)));
|
||||
|
||||
|
|
|
@ -8,9 +8,12 @@ const AuthService = new AuthServiceClass(db);
|
|||
export const authRouter = router({
|
||||
login: publicProcedure.input(z.object({ username: z.string(), password: z.string() })).mutation(async ({ input, ctx }) => AuthService.login({ ...input }, ctx.req)),
|
||||
logout: protectedProcedure.mutation(async ({ ctx }) => AuthServiceClass.logout(ctx.req)),
|
||||
register: publicProcedure.input(z.object({ username: z.string(), password: z.string() })).mutation(async ({ input, ctx }) => AuthService.register({ ...input }, ctx.req)),
|
||||
register: publicProcedure.input(z.object({ username: z.string(), password: z.string(), locale: z.string() })).mutation(async ({ input, ctx }) => AuthService.register({ ...input }, ctx.req)),
|
||||
me: publicProcedure.query(async ({ ctx }) => AuthService.me(ctx.req.session?.userId)),
|
||||
isConfigured: publicProcedure.query(async () => AuthService.isConfigured()),
|
||||
changeLocale: protectedProcedure
|
||||
.input(z.object({ locale: z.string() }))
|
||||
.mutation(async ({ input, ctx }) => AuthService.changeLocale({ userId: Number(ctx.req.session.userId), locale: input.locale })),
|
||||
// Password
|
||||
checkPasswordChangeRequest: publicProcedure.query(AuthServiceClass.checkPasswordChangeRequest),
|
||||
changeOperatorPassword: publicProcedure.input(z.object({ newPassword: z.string() })).mutation(({ input }) => AuthService.changeOperatorPassword({ newPassword: input.newPassword })),
|
||||
|
|
|
@ -9,10 +9,12 @@ import { getConfig } from '../../core/TipiConfig';
|
|||
import TipiCache from '../../core/TipiCache';
|
||||
import { fileExists, unlinkFile } from '../../common/fs.helpers';
|
||||
import { decrypt, encrypt } from '../../utils/encryption';
|
||||
import { Locales, getLocaleFromString } from '@/shared/internationalization/locales';
|
||||
|
||||
type UsernamePasswordInput = {
|
||||
username: string;
|
||||
password: string;
|
||||
locale?: string;
|
||||
};
|
||||
|
||||
export class AuthServiceClass {
|
||||
|
@ -225,7 +227,7 @@ export class AuthServiceClass {
|
|||
|
||||
const hash = await argon2.hash(password);
|
||||
|
||||
const newUser = await this.queries.createUser({ username: email, password: hash, operator: true });
|
||||
const newUser = await this.queries.createUser({ username: email, password: hash, operator: true, locale: getLocaleFromString(input.locale) });
|
||||
|
||||
if (!newUser) {
|
||||
throw new Error('Error creating user');
|
||||
|
@ -384,4 +386,31 @@ export class AuthServiceClass {
|
|||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a userId and a locale, change the user's locale
|
||||
*
|
||||
* @param {object} params - An object containing the user ID and the new locale
|
||||
* @param {string} params.locale - The new locale
|
||||
* @param {number} params.userId - The user ID
|
||||
*/
|
||||
public changeLocale = async (params: { locale: string; userId: number }) => {
|
||||
const { locale, userId } = params;
|
||||
|
||||
const isLocaleValid = Locales.includes(locale);
|
||||
|
||||
if (!isLocaleValid) {
|
||||
throw new Error('Invalid locale');
|
||||
}
|
||||
|
||||
const user = await this.queries.getUserById(userId);
|
||||
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
|
||||
await this.queries.updateUser(user.id, { locale });
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { typeToFlattenedError, ZodError } from 'zod';
|
|||
import { type Context } from './context';
|
||||
import { AuthQueries } from './queries/auth/auth.queries';
|
||||
import { db } from './db';
|
||||
import { Locale } from '@/shared/internationalization/locales';
|
||||
|
||||
const authQueries = new AuthQueries(db);
|
||||
|
||||
|
@ -56,6 +57,10 @@ const isAuthed = t.middleware(async ({ ctx, next }) => {
|
|||
|
||||
const user = await authQueries.getUserById(userId);
|
||||
|
||||
if (user?.locale) {
|
||||
ctx.req.session.locale = user.locale as Locale;
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
ctx.req.session.destroy(() => {});
|
||||
throw new TRPCError({ code: 'UNAUTHORIZED', message: 'You need to be logged in to perform this action' });
|
||||
|
|
Loading…
Add table
Reference in a new issue