adapt-authoring-auth-local 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/LocalAuthModule.js +2 -37
- package/lib/PasswordUtils.js +1 -1
- package/lib/utils/compare.js +1 -1
- package/lib/utils/getRandomHex.js +2 -2
- package/package.json +2 -2
- package/routes.json +234 -0
- package/tests/LocalAuthModule.spec.js +11 -93
- package/lib/apidefs.js +0 -195
package/lib/LocalAuthModule.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import _ from 'lodash'
|
|
2
2
|
import { AbstractAuthModule } from 'adapt-authoring-auth'
|
|
3
|
-
import apidefs from './apidefs.js'
|
|
4
3
|
import { compare, getRandomHex, validate } from './utils.js'
|
|
5
4
|
import { formatDistanceToNowStrict as toNow } from 'date-fns'
|
|
6
5
|
import PasswordUtils from './PasswordUtils.js'
|
|
@@ -20,52 +19,18 @@ class LocalAuthModule extends AbstractAuthModule {
|
|
|
20
19
|
|
|
21
20
|
/** @override */
|
|
22
21
|
async setValues () {
|
|
22
|
+
await super.setValues()
|
|
23
23
|
/** @ignore */ this.userSchema = 'localauthuser'
|
|
24
|
-
/** @ignore */ this.type = 'local'
|
|
25
|
-
/** @ignore */ this.routes = [
|
|
26
|
-
{
|
|
27
|
-
route: '/invite',
|
|
28
|
-
handlers: { post: this.inviteHandler.bind(this) },
|
|
29
|
-
meta: apidefs.invite
|
|
30
|
-
}, {
|
|
31
|
-
route: '/registersuper',
|
|
32
|
-
internal: true,
|
|
33
|
-
handlers: { post: this.registerSuperHandler.bind(this) },
|
|
34
|
-
meta: apidefs.registersuper
|
|
35
|
-
}, {
|
|
36
|
-
route: '/changepass',
|
|
37
|
-
handlers: { post: this.changePasswordHandler.bind(this) },
|
|
38
|
-
meta: apidefs.changepass
|
|
39
|
-
}, {
|
|
40
|
-
route: '/forgotpass',
|
|
41
|
-
handlers: { post: this.forgotPasswordHandler.bind(this) },
|
|
42
|
-
meta: apidefs.forgotpass
|
|
43
|
-
}, {
|
|
44
|
-
route: '/validatepass',
|
|
45
|
-
handlers: { post: this.validatePasswordHandler.bind(this) },
|
|
46
|
-
meta: apidefs.validatepass
|
|
47
|
-
}
|
|
48
|
-
]
|
|
49
24
|
}
|
|
50
25
|
|
|
51
26
|
/** @override */
|
|
52
27
|
async init () {
|
|
53
28
|
await super.init()
|
|
54
|
-
this.secureRoute('/invite', 'post', ['register:users'])
|
|
55
|
-
this.secureRoute('/validatepass', 'post', ['read:me'])
|
|
56
|
-
this.unsecureRoute('/registersuper', 'post')
|
|
57
|
-
this.unsecureRoute('/changepass', 'post')
|
|
58
|
-
this.unsecureRoute('/forgotpass', 'post')
|
|
59
|
-
// add API metadata
|
|
60
|
-
this.router.routes.find(r => r.route === '/').meta = apidefs.root
|
|
61
|
-
this.router.routes.find(r => r.route === '/register').meta = apidefs.register
|
|
62
|
-
|
|
63
|
-
const users = await this.app.waitForModule('users')
|
|
64
29
|
/**
|
|
65
30
|
* Local reference to the current UsersModule instance for convenience
|
|
66
31
|
* @type {UsersModule}
|
|
67
32
|
*/
|
|
68
|
-
this.users = users
|
|
33
|
+
this.users = await this.app.waitForModule('users')
|
|
69
34
|
}
|
|
70
35
|
|
|
71
36
|
/** @override */
|
package/lib/PasswordUtils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { App } from 'adapt-authoring-core'
|
|
2
2
|
import bcrypt from 'bcryptjs'
|
|
3
3
|
import { compare, getRandomHex, validate } from './utils.js'
|
|
4
|
-
import { promisify } from 'util'
|
|
4
|
+
import { promisify } from 'node:util'
|
|
5
5
|
|
|
6
6
|
/** @ignore */ const passwordResetsCollectionName = 'passwordresets'
|
|
7
7
|
/**
|
package/lib/utils/compare.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adapt-authoring-auth-local",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Module which implements username/password (local) authentication",
|
|
5
5
|
"homepage": "https://github.com/adapt-security/adapt-authoring-auth-local",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"adapt-authoring-mailer": "^1.0.2",
|
|
23
23
|
"adapt-authoring-mongodb": "^3.0.0",
|
|
24
24
|
"adapt-authoring-roles": "^1.1.3",
|
|
25
|
-
"adapt-authoring-server": "^2.
|
|
25
|
+
"adapt-authoring-server": "^2.1.0",
|
|
26
26
|
"adapt-authoring-users": "^1.0.2"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
package/routes.json
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "local",
|
|
3
|
+
"routes": [
|
|
4
|
+
{
|
|
5
|
+
"route": "/",
|
|
6
|
+
"override": true,
|
|
7
|
+
"handlers": { "post": "authenticateHandler" },
|
|
8
|
+
"meta": {
|
|
9
|
+
"post": {
|
|
10
|
+
"summary": "Authenticate with the API",
|
|
11
|
+
"requestBody": {
|
|
12
|
+
"content": {
|
|
13
|
+
"application/json": {
|
|
14
|
+
"schema": {
|
|
15
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"email": { "type": "string", "required": true },
|
|
19
|
+
"password": { "type": "string", "required": true },
|
|
20
|
+
"persistSession": { "type": "boolean" }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"responses": { "204": {} }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"route": "/register",
|
|
32
|
+
"override": true,
|
|
33
|
+
"handlers": { "post": "registerHandler" },
|
|
34
|
+
"meta": {
|
|
35
|
+
"post": {
|
|
36
|
+
"summary": "Register a new user",
|
|
37
|
+
"requestBody": {
|
|
38
|
+
"content": {
|
|
39
|
+
"application/json": {
|
|
40
|
+
"schema": {
|
|
41
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"email": { "type": "string", "required": true },
|
|
45
|
+
"firstName": { "type": "string", "required": true },
|
|
46
|
+
"lastName": { "type": "string", "required": true },
|
|
47
|
+
"password": { "type": "string", "required": true },
|
|
48
|
+
"roles": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": { "type": "string" }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"responses": {
|
|
58
|
+
"200": {
|
|
59
|
+
"content": {
|
|
60
|
+
"application/json": {
|
|
61
|
+
"schema": { "$ref": "#components/schemas/localauthuser" }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"route": "/invite",
|
|
71
|
+
"handlers": { "post": "inviteHandler" },
|
|
72
|
+
"permissions": { "post": ["register:users"] },
|
|
73
|
+
"meta": {
|
|
74
|
+
"post": {
|
|
75
|
+
"summary": "Invite a new user",
|
|
76
|
+
"requestBody": {
|
|
77
|
+
"content": {
|
|
78
|
+
"application/json": {
|
|
79
|
+
"schema": {
|
|
80
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
81
|
+
"type": "object",
|
|
82
|
+
"properties": {
|
|
83
|
+
"email": { "type": "string" }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"responses": { "204": {} }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"route": "/registersuper",
|
|
95
|
+
"internal": true,
|
|
96
|
+
"handlers": { "post": "registerSuperHandler" },
|
|
97
|
+
"permissions": { "post": null },
|
|
98
|
+
"meta": {
|
|
99
|
+
"post": {
|
|
100
|
+
"summary": "Register a new super user",
|
|
101
|
+
"description": "Only one user can be registered in this way, and if a super user already exists the request will fail.",
|
|
102
|
+
"requestBody": {
|
|
103
|
+
"content": {
|
|
104
|
+
"application/json": {
|
|
105
|
+
"schema": {
|
|
106
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
107
|
+
"type": "object",
|
|
108
|
+
"properties": {
|
|
109
|
+
"email": { "type": "string", "required": true },
|
|
110
|
+
"password": { "type": "string", "required": true }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"responses": {
|
|
117
|
+
"200": {
|
|
118
|
+
"content": {
|
|
119
|
+
"application/json": {
|
|
120
|
+
"schema": { "$ref": "#components/schemas/localauthuser" }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"route": "/changepass",
|
|
130
|
+
"handlers": { "post": "changePasswordHandler" },
|
|
131
|
+
"permissions": { "post": null },
|
|
132
|
+
"meta": {
|
|
133
|
+
"post": {
|
|
134
|
+
"summary": "Change the password of a user",
|
|
135
|
+
"description": "Can be used with or without authentication. If authenticated, an email/password combination will be acepted. If unauthenticated, a valid reset token and password must be specified.",
|
|
136
|
+
"requestBody": {
|
|
137
|
+
"content": {
|
|
138
|
+
"application/json": {
|
|
139
|
+
"schema": {
|
|
140
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
141
|
+
"type": "object",
|
|
142
|
+
"properties": {
|
|
143
|
+
"email": { "type": "string" },
|
|
144
|
+
"password": { "type": "string" },
|
|
145
|
+
"token": { "type": "string" }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"responses": { "204": {} }
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"route": "/forgotpass",
|
|
157
|
+
"handlers": { "post": "forgotPasswordHandler" },
|
|
158
|
+
"permissions": { "post": null },
|
|
159
|
+
"meta": {
|
|
160
|
+
"post": {
|
|
161
|
+
"summary": "Trigger a password reset",
|
|
162
|
+
"description": "Generates a password reset and emails this to the user with instructions on updating their password.",
|
|
163
|
+
"requestBody": {
|
|
164
|
+
"content": {
|
|
165
|
+
"application/json": {
|
|
166
|
+
"schema": {
|
|
167
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
168
|
+
"type": "object",
|
|
169
|
+
"properties": {
|
|
170
|
+
"email": { "type": "string" }
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"responses": {
|
|
177
|
+
"200": {
|
|
178
|
+
"content": {
|
|
179
|
+
"application/json": {
|
|
180
|
+
"schema": {
|
|
181
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"message": { "type": "string" }
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"route": "/validatepass",
|
|
196
|
+
"handlers": { "post": "validatePasswordHandler" },
|
|
197
|
+
"permissions": { "post": ["read:me"] },
|
|
198
|
+
"meta": {
|
|
199
|
+
"post": {
|
|
200
|
+
"summary": "Validate password",
|
|
201
|
+
"description": "Checks that a password passes the required complexity specified in the application's configuration settings.",
|
|
202
|
+
"requestBody": {
|
|
203
|
+
"content": {
|
|
204
|
+
"application/json": {
|
|
205
|
+
"schema": {
|
|
206
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
207
|
+
"type": "object",
|
|
208
|
+
"properties": {
|
|
209
|
+
"password": { "type": "string", "required": true }
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
"responses": {
|
|
216
|
+
"200": {
|
|
217
|
+
"content": {
|
|
218
|
+
"application/json": {
|
|
219
|
+
"schema": {
|
|
220
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
221
|
+
"type": "object",
|
|
222
|
+
"properties": {
|
|
223
|
+
"message": { "type": "string" }
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
}
|
|
@@ -122,6 +122,12 @@ mock.module('adapt-authoring-auth', {
|
|
|
122
122
|
|
|
123
123
|
getConfig (key) { return authlocalConfig[key] }
|
|
124
124
|
|
|
125
|
+
async setValues () {
|
|
126
|
+
this.type = undefined
|
|
127
|
+
this.routes = undefined
|
|
128
|
+
this.userSchema = 'user'
|
|
129
|
+
}
|
|
130
|
+
|
|
125
131
|
async init () {}
|
|
126
132
|
|
|
127
133
|
async register (data) { return { _id: 'new-user-id', ...data } }
|
|
@@ -215,111 +221,23 @@ describe('LocalAuthModule', () => {
|
|
|
215
221
|
assert.equal(instance.userSchema, 'localauthuser')
|
|
216
222
|
})
|
|
217
223
|
|
|
218
|
-
it('should
|
|
219
|
-
const instance = new LocalAuthModule()
|
|
220
|
-
await instance.setValues()
|
|
221
|
-
assert.equal(instance.type, 'local')
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
it('should define 5 routes', async () => {
|
|
225
|
-
const instance = new LocalAuthModule()
|
|
226
|
-
await instance.setValues()
|
|
227
|
-
assert.equal(instance.routes.length, 5)
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
it('should include the expected route paths', async () => {
|
|
231
|
-
const instance = new LocalAuthModule()
|
|
232
|
-
await instance.setValues()
|
|
233
|
-
const paths = instance.routes.map(r => r.route)
|
|
234
|
-
assert.deepEqual(paths, ['/invite', '/registersuper', '/changepass', '/forgotpass', '/validatepass'])
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
it('should mark registersuper as internal', async () => {
|
|
224
|
+
it('should call super.setValues()', async () => {
|
|
238
225
|
const instance = new LocalAuthModule()
|
|
239
226
|
await instance.setValues()
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
it('should define post handlers for all routes', async () => {
|
|
245
|
-
const instance = new LocalAuthModule()
|
|
246
|
-
await instance.setValues()
|
|
247
|
-
for (const route of instance.routes) {
|
|
248
|
-
assert.equal(typeof route.handlers.post, 'function')
|
|
249
|
-
}
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
it('should define meta for all routes', async () => {
|
|
253
|
-
const instance = new LocalAuthModule()
|
|
254
|
-
await instance.setValues()
|
|
255
|
-
for (const route of instance.routes) {
|
|
256
|
-
assert.ok(route.meta)
|
|
257
|
-
}
|
|
227
|
+
// super.setValues() initialises type and routes to undefined;
|
|
228
|
+
// in production, loadRouteConfig fills them from routes.json
|
|
229
|
+
assert.equal(instance.type, undefined)
|
|
230
|
+
assert.equal(instance.routes, undefined)
|
|
258
231
|
})
|
|
259
232
|
})
|
|
260
233
|
|
|
261
234
|
describe('#init()', () => {
|
|
262
|
-
it('should secure the invite route', async () => {
|
|
263
|
-
const instance = new LocalAuthModule()
|
|
264
|
-
instance.app = mockApp
|
|
265
|
-
instance.router = { routes: [{ route: '/', meta: null }, { route: '/register', meta: null }] }
|
|
266
|
-
await instance.setValues()
|
|
267
|
-
await instance.init()
|
|
268
|
-
assert.ok(secureRouteCalls.some(c => c[0] === '/invite' && c[1] === 'post'))
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
it('should secure the validatepass route with read:me permission', async () => {
|
|
272
|
-
const instance = new LocalAuthModule()
|
|
273
|
-
instance.app = mockApp
|
|
274
|
-
instance.router = { routes: [{ route: '/', meta: null }, { route: '/register', meta: null }] }
|
|
275
|
-
await instance.setValues()
|
|
276
|
-
await instance.init()
|
|
277
|
-
const call = secureRouteCalls.find(c => c[0] === '/validatepass')
|
|
278
|
-
assert.ok(call)
|
|
279
|
-
assert.deepEqual(call[2], ['read:me'])
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
it('should secure the invite route with register:users permission', async () => {
|
|
283
|
-
const instance = new LocalAuthModule()
|
|
284
|
-
instance.app = mockApp
|
|
285
|
-
instance.router = { routes: [{ route: '/', meta: null }, { route: '/register', meta: null }] }
|
|
286
|
-
await instance.setValues()
|
|
287
|
-
await instance.init()
|
|
288
|
-
const call = secureRouteCalls.find(c => c[0] === '/invite')
|
|
289
|
-
assert.ok(call)
|
|
290
|
-
assert.deepEqual(call[2], ['register:users'])
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
it('should unsecure registersuper, changepass, and forgotpass routes', async () => {
|
|
294
|
-
const instance = new LocalAuthModule()
|
|
295
|
-
instance.app = mockApp
|
|
296
|
-
instance.router = { routes: [{ route: '/', meta: null }, { route: '/register', meta: null }] }
|
|
297
|
-
await instance.setValues()
|
|
298
|
-
await instance.init()
|
|
299
|
-
const unsecuredPaths = unsecureRouteCalls.map(c => c[0])
|
|
300
|
-
assert.ok(unsecuredPaths.includes('/registersuper'))
|
|
301
|
-
assert.ok(unsecuredPaths.includes('/changepass'))
|
|
302
|
-
assert.ok(unsecuredPaths.includes('/forgotpass'))
|
|
303
|
-
})
|
|
304
|
-
|
|
305
235
|
it('should set the users property', async () => {
|
|
306
236
|
const instance = new LocalAuthModule()
|
|
307
237
|
instance.app = mockApp
|
|
308
|
-
instance.router = { routes: [{ route: '/', meta: null }, { route: '/register', meta: null }] }
|
|
309
|
-
await instance.setValues()
|
|
310
238
|
await instance.init()
|
|
311
239
|
assert.equal(instance.users, mockUsers)
|
|
312
240
|
})
|
|
313
|
-
|
|
314
|
-
it('should set meta on root and register routes', async () => {
|
|
315
|
-
const instance = new LocalAuthModule()
|
|
316
|
-
instance.app = mockApp
|
|
317
|
-
instance.router = { routes: [{ route: '/', meta: null }, { route: '/register', meta: null }] }
|
|
318
|
-
await instance.setValues()
|
|
319
|
-
await instance.init()
|
|
320
|
-
assert.ok(instance.router.routes.find(r => r.route === '/').meta)
|
|
321
|
-
assert.ok(instance.router.routes.find(r => r.route === '/register').meta)
|
|
322
|
-
})
|
|
323
241
|
})
|
|
324
242
|
|
|
325
243
|
describe('#authenticate()', () => {
|
package/lib/apidefs.js
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
changepass: {
|
|
3
|
-
post: {
|
|
4
|
-
summary: 'Change the password of a user',
|
|
5
|
-
description: 'Can be used with or without authentication. If authenticated, an email/password combination will be acepted. If unauthenticated, a valid reset token and password must be specified.',
|
|
6
|
-
requestBody: {
|
|
7
|
-
content: {
|
|
8
|
-
'application/json': {
|
|
9
|
-
schema: {
|
|
10
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
11
|
-
type: 'object',
|
|
12
|
-
properties: {
|
|
13
|
-
email: { type: 'string' },
|
|
14
|
-
password: { type: 'string' },
|
|
15
|
-
token: { type: 'string' }
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
responses: { 204: {} }
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
forgotpass: {
|
|
25
|
-
post: {
|
|
26
|
-
summary: 'Trigger a password reset',
|
|
27
|
-
description: 'Generates a password reset and emails this to the user with instructions on updating their password.',
|
|
28
|
-
requestBody: {
|
|
29
|
-
content: {
|
|
30
|
-
'application/json': {
|
|
31
|
-
schema: {
|
|
32
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
33
|
-
type: 'object',
|
|
34
|
-
properties: {
|
|
35
|
-
email: { type: 'string' }
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
responses: {
|
|
42
|
-
200: {
|
|
43
|
-
content: {
|
|
44
|
-
'application/json': {
|
|
45
|
-
schema: {
|
|
46
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
47
|
-
type: 'object',
|
|
48
|
-
properties: {
|
|
49
|
-
message: { type: 'string' }
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
invite: {
|
|
59
|
-
post: {
|
|
60
|
-
summary: 'Invite a new user',
|
|
61
|
-
requestBody: {
|
|
62
|
-
content: {
|
|
63
|
-
'application/json': {
|
|
64
|
-
schema: {
|
|
65
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
66
|
-
type: 'object',
|
|
67
|
-
properties: {
|
|
68
|
-
email: { type: 'string' }
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
responses: { 204: {} }
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
register: {
|
|
78
|
-
post: {
|
|
79
|
-
summary: 'Register a new user',
|
|
80
|
-
requestBody: {
|
|
81
|
-
content: {
|
|
82
|
-
'application/json': {
|
|
83
|
-
schema: {
|
|
84
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
85
|
-
type: 'object',
|
|
86
|
-
properties: {
|
|
87
|
-
email: { type: 'string', required: true },
|
|
88
|
-
firstName: { type: 'string', required: true },
|
|
89
|
-
lastName: { type: 'string', required: true },
|
|
90
|
-
password: { type: 'string', required: true },
|
|
91
|
-
roles: {
|
|
92
|
-
type: 'array',
|
|
93
|
-
items: { type: 'string' }
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
responses: {
|
|
101
|
-
200: {
|
|
102
|
-
content: {
|
|
103
|
-
'application/json': {
|
|
104
|
-
schema: { $ref: '#components/schemas/localauthuser' }
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
registersuper: {
|
|
112
|
-
post: {
|
|
113
|
-
summary: 'Register a new super user',
|
|
114
|
-
description: 'Only one user can be registered in this way, and if a super user already exists the request will fail.',
|
|
115
|
-
requestBody: {
|
|
116
|
-
content: {
|
|
117
|
-
'application/json': {
|
|
118
|
-
schema: {
|
|
119
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
120
|
-
type: 'object',
|
|
121
|
-
properties: {
|
|
122
|
-
email: { type: 'string', required: true },
|
|
123
|
-
password: { type: 'string', required: true }
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
responses: {
|
|
130
|
-
200: {
|
|
131
|
-
content: {
|
|
132
|
-
'application/json': {
|
|
133
|
-
schema: { $ref: '#components/schemas/localauthuser' }
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
root: {
|
|
141
|
-
post: {
|
|
142
|
-
summary: 'Authenticate with the API',
|
|
143
|
-
requestBody: {
|
|
144
|
-
content: {
|
|
145
|
-
'application/json': {
|
|
146
|
-
schema: {
|
|
147
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
148
|
-
type: 'object',
|
|
149
|
-
properties: {
|
|
150
|
-
email: { type: 'string', required: true },
|
|
151
|
-
password: { type: 'string', required: true },
|
|
152
|
-
persistSession: { type: 'boolean' }
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
responses: { 204: {} }
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
validatepass: {
|
|
162
|
-
post: {
|
|
163
|
-
summary: 'Validate password',
|
|
164
|
-
description: 'Checks that a password passes the required complexity specified in the application\'s configuration settings.',
|
|
165
|
-
requestBody: {
|
|
166
|
-
content: {
|
|
167
|
-
'application/json': {
|
|
168
|
-
schema: {
|
|
169
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
170
|
-
type: 'object',
|
|
171
|
-
properties: {
|
|
172
|
-
password: { type: 'string', required: true }
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
responses: {
|
|
179
|
-
200: {
|
|
180
|
-
content: {
|
|
181
|
-
'application/json': {
|
|
182
|
-
schema: {
|
|
183
|
-
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
184
|
-
type: 'object',
|
|
185
|
-
properties: {
|
|
186
|
-
message: { type: 'string' }
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|