Skip to content

Commit 78f69e7

Browse files
committed
Require admin authorization for POST /users
1 parent c832b28 commit 78f69e7

File tree

2 files changed

+102
-12
lines changed

2 files changed

+102
-12
lines changed

sci-log-db/src/__tests__/acceptance/user.controller.acceptance.ts

+96-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ describe('UserController', () => {
2424
2525
firstName: 'Example',
2626
lastName: 'User',
27-
roles: [],
27+
roles: [] as string[],
28+
};
29+
30+
const adminUserData = {
31+
32+
firstName: 'Example',
33+
lastName: 'User',
34+
roles: ['admin'],
2835
};
2936

3037
const userDataReturned = {
@@ -54,8 +61,18 @@ describe('UserController', () => {
5461
});
5562

5663
it('creates new user when POST /users is invoked', async () => {
57-
const res = await client
64+
const newUser = await createAUser(adminUserData);
65+
66+
let res = await client
67+
.post('/users/login')
68+
.send({principal: newUser.email, password: userPassword})
69+
.expect(200);
70+
71+
const token = res.body.token;
72+
73+
res = await client
5874
.post('/users')
75+
.set('Authorization', 'Bearer ' + token)
5976
.send({...userData, password: userPassword})
6077
.expect(200);
6178

@@ -70,20 +87,66 @@ describe('UserController', () => {
7087
it('creates a new user with the given id', async () => {
7188
// This test verifies the scenario described in our docs, see
7289
// https://loopback.io/doc/en/lb4/Authentication-Tutorial.html
73-
const res = await client.post('/users').send({
74-
id: '5dd6acee242760334f6aef65',
75-
...userData,
76-
password: userPassword,
77-
});
90+
const newUser = await createAUser(adminUserData);
91+
92+
let res = await client
93+
.post('/users/login')
94+
.send({principal: newUser.email, password: userPassword})
95+
.expect(200);
96+
97+
const token = res.body.token;
98+
99+
res = await client
100+
.post('/users')
101+
.set('Authorization', 'Bearer ' + token)
102+
.send({
103+
id: '5dd6acee242760334f6aef65',
104+
...userData,
105+
password: userPassword,
106+
});
78107
expect(res.body).to.deepEqual({
79108
id: '5dd6acee242760334f6aef65',
80109
...userDataReturned,
81110
});
82111
});
83112

113+
it('throws 403 Forbidden for POST /users when not authenticated as admin', async () => {
114+
const newUser = await createAUser(userData); // non-admin user
115+
116+
let res = await client
117+
.post('/users/login')
118+
.send({principal: newUser.email, password: userPassword})
119+
.expect(200);
120+
121+
const token = res.body.token;
122+
123+
res = await client
124+
.post('/users')
125+
.set('Authorization', 'Bearer ' + token)
126+
.send({
127+
128+
username: 'test',
129+
password: 'p4ssw0rd',
130+
firstName: 'Example',
131+
lastName: 'User',
132+
})
133+
.expect(403);
134+
});
135+
84136
it('throws error for POST /users with a missing email', async () => {
85-
const res = await client
137+
const newUser = await createAUser(adminUserData);
138+
139+
let res = await client
140+
.post('/users/login')
141+
.send({principal: newUser.email, password: userPassword})
142+
.expect(200);
143+
144+
const token = res.body.token;
145+
expect(token).to.not.be.empty();
146+
147+
res = await client
86148
.post('/users')
149+
.set('Authorization', 'Bearer ' + token)
87150
.send({
88151
password: 'p4ssw0rd',
89152
firstName: 'Example',
@@ -98,8 +161,18 @@ describe('UserController', () => {
98161
});
99162

100163
it('throws error for POST /users with an invalid email', async () => {
101-
const res = await client
164+
const newUser = await createAUser(adminUserData);
165+
166+
let res = await client
167+
.post('/users/login')
168+
.send({principal: newUser.email, password: userPassword})
169+
.expect(200);
170+
171+
const token = res.body.token;
172+
173+
res = await client
102174
.post('/users')
175+
.set('Authorization', 'Bearer ' + token)
103176
.send({
104177
email: 'test@loop&back.io',
105178
password: 'p4ssw0rd',
@@ -137,12 +210,23 @@ describe('UserController', () => {
137210
});
138211

139212
it('throws error for POST /users with an existing email', async () => {
213+
const newUser = await createAUser(adminUserData);
214+
215+
let res = await client
216+
.post('/users/login')
217+
.send({principal: newUser.email, password: userPassword})
218+
.expect(200);
219+
220+
const token = res.body.token;
221+
140222
await client
141223
.post('/users')
224+
.set('Authorization', 'Bearer ' + token)
142225
.send({...userData, password: userPassword})
143226
.expect(200);
144-
const res = await client
227+
res = await client
145228
.post('/users')
229+
.set('Authorization', 'Bearer ' + token)
146230
.send({...userData, password: userPassword})
147231
.expect(409);
148232

@@ -261,9 +345,9 @@ describe('UserController', () => {
261345
await app.migrateSchema();
262346
}
263347

264-
async function createAUser() {
348+
async function createAUser(newUserData = userData) {
265349
const encryptedPassword = await passwordHasher.hashPassword(userPassword);
266-
const newUser = await userRepo.create(userData);
350+
const newUser = await userRepo.create(newUserData);
267351
// MongoDB returns an id object we need to convert to string
268352
newUser.id = newUser.id.toString();
269353

sci-log-db/src/controllers/user.controller.ts

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export class UserController {
5656
) {}
5757

5858
@post('/users', {
59+
security: OPERATION_SECURITY_SPEC,
5960
responses: {
6061
'200': {
6162
description: 'User',
@@ -69,6 +70,11 @@ export class UserController {
6970
},
7071
},
7172
})
73+
@authenticate('jwt')
74+
@authorize({
75+
allowedRoles: ['admin'],
76+
voters: [basicAuthorization],
77+
})
7278
async create(
7379
@requestBody({
7480
content: {

0 commit comments

Comments
 (0)