feat(auth): create routes to change locale and set initial locale

This commit is contained in:
Nicolas Meienberger 2023-05-06 13:22:17 +02:00 committed by Nicolas Meienberger
parent ce2ff2672c
commit 8744f22e76
5 changed files with 42 additions and 3 deletions

View file

@ -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 = {

View file

@ -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)));

View file

@ -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 })),

View file

@ -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;
};
}

View file

@ -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' });