Skip to content

Commit 7291994

Browse files
committed
feat(utilisateurs): ajoute des nouvelles routes pour créer des utilisateurs
1 parent bf5b42c commit 7291994

File tree

6 files changed

+99
-12
lines changed

6 files changed

+99
-12
lines changed

server/controllers/userController.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ export const usersRouter = {
2020
}
2121

2222
return { status: constants.HTTP_STATUS_OK, response: user };
23+
},
24+
put: async ({ body }, { userId }) => {
25+
console.info('Update user', body);
26+
27+
const userToUpdate = await userRepository.findUnique(userId);
28+
if (!userToUpdate) {
29+
return { status: constants.HTTP_STATUS_NOT_FOUND };
30+
}
31+
32+
await userRepository.update(body, userId);
33+
return { status: constants.HTTP_STATUS_OK };
2334
}
2435
},
2536
'/users': {
@@ -34,6 +45,12 @@ export const usersRouter = {
3445
const users = await userRepository.findMany(findOptions);
3546

3647
return { status: constants.HTTP_STATUS_OK, response: users };
48+
},
49+
post: async ({ body }) => {
50+
console.info('Create user', body);
51+
52+
await userRepository.insert(body);
53+
return { status: constants.HTTP_STATUS_CREATED };
3754
}
3855
}
3956
} as const satisfies ProtectedSubRouter;

server/repositories/userRepository.test.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@ import { userRepository } from './userRepository';
77
test("impossible d'avoir 2 utilisateurs avec le même email", async () => {
88
const email = '[email protected]';
99

10-
await kysely.insertInto('users').values(genUser({ email })).execute();
11-
await kysely
12-
.insertInto('users')
13-
.values(genUser({ email: '[email protected]' }))
14-
.execute();
10+
await userRepository.insert(genUser({ email }));
11+
await userRepository.insert(genUser({ email: '[email protected]' }));
1512

1613
await expect(async () =>
1714
kysely
@@ -31,8 +28,8 @@ test("peut modifier le nom et le prénom d'un utilisateur", async () => {
3128
const user1 = genUser();
3229
const user2 = genUser();
3330

34-
await kysely.insertInto('users').values(user1).execute();
35-
await kysely.insertInto('users').values(user2).execute();
31+
await userRepository.insert(user1);
32+
await userRepository.insert(user2);
3633

3734
const newName = 'fullName';
3835

@@ -57,12 +54,12 @@ test("peut modifier le nom et le prénom d'un utilisateur", async () => {
5754
.selectAll()
5855
.where('email', '=', user2.email)
5956
.executeTakeFirst();
60-
expect(user2InDb).toMatchObject(user2);
57+
expect(user2InDb).toMatchObject({ ...user2, name: '-' });
6158
});
6259
test('peut ajouter et supprimer un logged secret', async () => {
6360
const user1 = genUser();
6461

65-
await kysely.insertInto('users').values(user1).execute();
62+
await userRepository.insert(user1);
6663

6764
const newSecret = uuidv4();
6865

server/repositories/userRepository.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ const findMany = async (findOptions: FindUserOptions): Promise<User[]> => {
5959
return users.map((_: User) => User.parse(_));
6060
};
6161

62+
const insert = async (
63+
user: Omit<KyselyUser, 'id' | 'loggedSecrets' | 'name'>
64+
): Promise<void> => {
65+
await kysely
66+
.insertInto('users')
67+
.values({ ...user, name: '-' })
68+
.execute();
69+
};
70+
6271
const update = async (
6372
partialUser: Partial<Omit<KyselyUser, 'id' | 'loggedSecrets'>>,
6473
id: User['id']
@@ -98,6 +107,7 @@ export const userRepository = {
98107
findOne,
99108
findMany,
100109
update,
110+
insert,
101111
addLoggedSecret,
102112
deleteLoggedSecret
103113
};

server/routers/test/user.router.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { COOKIE_MAESTRO_ACCESS_TOKEN } from 'maestro-shared/constants';
55
import { Region } from 'maestro-shared/referential/Region';
66
import { User } from 'maestro-shared/schema/User/User';
77
import {
8+
AdminFixture,
9+
genUser,
810
NationalCoordinator,
911
RegionalCoordinator,
1012
Sampler1Fixture,
@@ -130,4 +132,52 @@ describe('User router', () => {
130132
);
131133
});
132134
});
135+
136+
describe('POST /', () => {
137+
const testRoute = () => `/api/users`;
138+
139+
test('should fail if the user is not administrator', async () => {
140+
await request(app)
141+
.post(testRoute())
142+
.use(tokenProvider(NationalCoordinator))
143+
.send(genUser())
144+
.expect(constants.HTTP_STATUS_FORBIDDEN);
145+
});
146+
147+
test('should create an user', async () => {
148+
await request(app)
149+
.post(testRoute())
150+
.send(genUser())
151+
.use(tokenProvider(AdminFixture))
152+
.expect(constants.HTTP_STATUS_CREATED);
153+
});
154+
});
155+
156+
describe('PUT /{userId}', () => {
157+
const testRoute = (userId: string) => `/api/users/${userId}`;
158+
159+
test('should fail if the user is not administrator', async () => {
160+
await request(app)
161+
.put(testRoute(NationalCoordinator.id))
162+
.send({ role: 'Sampler' })
163+
.use(tokenProvider(NationalCoordinator))
164+
.expect(constants.HTTP_STATUS_FORBIDDEN);
165+
});
166+
167+
test('should fail if the updated user is unknown', async () => {
168+
await request(app)
169+
.put(testRoute('55555555-5555-5555-5555-555555555550'))
170+
.send({ role: 'Sampler' })
171+
.use(tokenProvider(AdminFixture))
172+
.expect(constants.HTTP_STATUS_NOT_FOUND);
173+
});
174+
175+
test('should update an user', async () => {
176+
await request(app)
177+
.put(testRoute(NationalCoordinator.id))
178+
.send({ role: 'Sampler' })
179+
.use(tokenProvider(AdminFixture))
180+
.expect(constants.HTTP_STATUS_OK);
181+
});
182+
});
133183
});

shared/routes/users.routes.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import z from 'zod';
22
import { FindUserOptions } from '../schema/User/FindUserOptions';
3-
import { User } from '../schema/User/User';
3+
import { User, UserToCreate, UserToUpdate } from '../schema/User/User';
44
import { SubRoutes } from './routes';
55

66
export const usersRoutes = {
@@ -10,6 +10,11 @@ export const usersRoutes = {
1010
response: z.array(User),
1111
query: FindUserOptions,
1212
permissions: 'NONE'
13+
},
14+
post: {
15+
response: z.void(),
16+
permissions: ['administrationMaestro'],
17+
body: UserToCreate
1318
}
1419
},
1520
'/users/:userId': {
@@ -19,6 +24,11 @@ export const usersRoutes = {
1924
get: {
2025
response: User,
2126
permissions: 'NONE'
27+
},
28+
put: {
29+
response: z.void(),
30+
permissions: ['administrationMaestro'],
31+
body: UserToUpdate
2232
}
2333
}
2434
} as const satisfies SubRoutes<'/users'>;

shared/schema/User/User.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ import {
1313

1414
const BaseUser = z.object({
1515
id: z.guid(),
16-
email: z.string().email(),
16+
email: z.email(),
1717
name: z.string(),
1818
programmingPlanKinds: z.array(ProgrammingPlanKind),
1919
role: UserRole,
20-
region: Region.nullish()
20+
region: Region.nullable()
2121
});
2222

2323
export const User = BaseUser.superRefine((user, ctx) => {
@@ -33,6 +33,9 @@ export const User = BaseUser.superRefine((user, ctx) => {
3333
}
3434
});
3535

36+
export const UserToCreate = User.omit({ id: true, name: true });
37+
export const UserToUpdate = User.omit({ name: true }).partial();
38+
3639
export const Sampler = BaseUser.pick({
3740
id: true,
3841
name: true

0 commit comments

Comments
 (0)