Skip to content

Commit 9f9c55a

Browse files
authored
fix(api-ApplicationPassword): Added all ApplicationPasswords API endpoints to API docs generation ZMS-136 (#645)
* List Application Passwords and Request ASP information endpoints added to API docs generation * fixes. Added Create new Application Password endpoint to API docs generation * Added Delete an Application Password api endpoint to API docs generation
1 parent b9e3f94 commit 9f9c55a

File tree

1 file changed

+187
-37
lines changed

1 file changed

+187
-37
lines changed

lib/api/asps.js

+187-37
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,70 @@ const tools = require('../tools');
1111
const roles = require('../roles');
1212
const util = require('util');
1313
const { sessSchema, sessIPSchema, booleanSchema } = require('../schemas');
14+
const { userId } = require('../schemas/request/general-schemas');
15+
const { successRes } = require('../schemas/response/general-schemas');
1416

1517
module.exports = (db, server, userHandler) => {
1618
const mobileconfigGetSignedConfig = util.promisify(mobileconfig.getSignedConfig.bind(mobileconfig));
1719

1820
server.get(
19-
'/users/:user/asps',
21+
{
22+
path: '/users/:user/asps',
23+
tags: ['ApplicationPasswords'],
24+
summary: 'List Application Passwords',
25+
validationObjs: {
26+
requestBody: {},
27+
queryParams: {
28+
showAll: booleanSchema.default(false).description('If not true then skips entries with a TTL set'),
29+
sess: sessSchema,
30+
ip: sessIPSchema
31+
},
32+
pathParams: { user: userId },
33+
response: {
34+
200: {
35+
description: 'Success',
36+
model: Joi.object({
37+
success: successRes,
38+
results: Joi.array()
39+
.items(
40+
Joi.object({
41+
id: Joi.string().required().description('ID of the Application Password'),
42+
description: Joi.string().required().description('Description'),
43+
scopes: Joi.array()
44+
.items(
45+
Joi.string()
46+
.required()
47+
.valid(...consts.SCOPES, '*')
48+
)
49+
.required()
50+
.description('Allowed scopes for the Application Password'),
51+
lastUse: Joi.object({
52+
time: Joi.date().required().description('Datestring of last use or false if password has not been used'),
53+
event: Joi.string().required().description('Event ID of the security log for the last authentication')
54+
})
55+
.required()
56+
.$_setFlag('objectName', 'LastUse')
57+
.description('Information about last use'),
58+
created: Joi.date().required().description('Datestring'),
59+
expires: Joi.date().required().description('Application password expires after the given date')
60+
}).$_setFlag('objectName', 'GetASPsResult')
61+
)
62+
.required()
63+
.description('Event listing')
64+
})
65+
}
66+
}
67+
}
68+
},
2069
tools.responseWrapper(async (req, res) => {
2170
res.charSet('utf-8');
2271

23-
const schema = Joi.object().keys({
24-
user: Joi.string().hex().lowercase().length(24).required(),
25-
showAll: booleanSchema.default(false),
26-
sess: sessSchema,
27-
ip: sessIPSchema
72+
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
73+
74+
const schema = Joi.object({
75+
...pathParams,
76+
...requestBody,
77+
...queryParams
2878
});
2979

3080
const result = schema.validate(req.params, {
@@ -130,15 +180,55 @@ module.exports = (db, server, userHandler) => {
130180
);
131181

132182
server.get(
133-
'/users/:user/asps/:asp',
183+
{
184+
path: '/users/:user/asps/:asp',
185+
tags: ['ApplicationPasswords'],
186+
summary: 'Request ASP information',
187+
validationObjs: {
188+
requestBody: {},
189+
queryParams: {
190+
sess: sessSchema,
191+
ip: sessIPSchema
192+
},
193+
pathParams: { user: userId, asp: Joi.string().hex().lowercase().length(24).required().description('ID of the Application Password') },
194+
response: {
195+
200: {
196+
description: 'Success',
197+
model: Joi.object({
198+
success: successRes,
199+
id: Joi.string().required().description('ID of the Application Password'),
200+
description: Joi.string().required().description('Description'),
201+
scopes: Joi.array()
202+
.items(
203+
Joi.string()
204+
.valid(...consts.SCOPES, '*')
205+
.required()
206+
)
207+
.required()
208+
.description('Allowed scopes for the Application Password'),
209+
lastUse: Joi.object({
210+
time: Joi.date().required().description('Datestring of last use or false if password has not been used'),
211+
event: Joi.string().required().description('Event ID of the security log for the last authentication')
212+
})
213+
.required()
214+
.$_setFlag('objectName', 'LastUse')
215+
.description('Information about last use'),
216+
created: Joi.date().required().description('Datestring'),
217+
expires: Joi.date().required().description('Application password expires after the given date')
218+
})
219+
}
220+
}
221+
}
222+
},
134223
tools.responseWrapper(async (req, res) => {
135224
res.charSet('utf-8');
136225

137-
const schema = Joi.object().keys({
138-
user: Joi.string().hex().lowercase().length(24).required(),
139-
asp: Joi.string().hex().lowercase().length(24).required(),
140-
sess: sessSchema,
141-
ip: sessIPSchema
226+
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
227+
228+
const schema = Joi.object({
229+
...pathParams,
230+
...requestBody,
231+
...queryParams
142232
});
143233

144234
const result = schema.validate(req.params, {
@@ -204,28 +294,74 @@ module.exports = (db, server, userHandler) => {
204294
);
205295

206296
server.post(
207-
'/users/:user/asps',
297+
{
298+
path: '/users/:user/asps',
299+
tags: ['ApplicationPasswords'],
300+
summary: 'Create new Application Password',
301+
validationObjs: {
302+
requestBody: {
303+
description: Joi.string().trim().max(255).required().description('Description for the Application Password entry'),
304+
scopes: Joi.array()
305+
.items(
306+
Joi.string()
307+
.valid(...consts.SCOPES, '*')
308+
.required()
309+
)
310+
.unique()
311+
.description(
312+
'List of scopes this Password applies to. Special scope "*" indicates that this password can be used for any scope except "master"'
313+
),
314+
address: Joi.string()
315+
.empty('')
316+
.email({ tlds: false })
317+
.description(
318+
'E-mail address to be used as the account address in mobileconfig file. Must be one of the listed identity addresses of the user. Defaults to the main address of the user'
319+
),
320+
password: Joi.string()
321+
.empty('')
322+
.pattern(/^[a-z]{16}$/, { name: 'password' })
323+
.description('Optional pregenerated password. Must be 16 characters, latin letters only.'),
324+
generateMobileconfig: booleanSchema
325+
.default(false)
326+
.description('If true then result contains a mobileconfig formatted file with account config'),
327+
ttl: Joi.number().empty([0, '']).description('TTL in seconds for this password. Every time password is used, TTL is reset to this value'),
328+
sess: sessSchema,
329+
ip: sessIPSchema
330+
},
331+
queryParams: {},
332+
pathParams: { user: userId },
333+
response: {
334+
200: {
335+
description: 'Success',
336+
model: Joi.object({
337+
success: successRes,
338+
id: Joi.string().required().description('ID of the Application Password'),
339+
password: Joi.string()
340+
.required()
341+
.description(
342+
'Application Specific Password. Generated password is whitespace agnostic, so it could be displayed to the client as "abcd efgh ijkl mnop" instead of "abcdefghijklmnop"'
343+
),
344+
mobileconfig: Joi.string()
345+
.required()
346+
.description(
347+
'Base64 encoded mobileconfig file. Generated profile file should be sent to the client with Content-Type value of application/x-apple-aspen-config.'
348+
),
349+
name: Joi.string().required().description('Account name'),
350+
address: Joi.string().required().description('Account address or the address specified in params of this endpoint')
351+
})
352+
}
353+
}
354+
}
355+
},
208356
tools.responseWrapper(async (req, res) => {
209357
res.charSet('utf-8');
210358

211-
const schema = Joi.object().keys({
212-
user: Joi.string().hex().lowercase().length(24).required(),
213-
description: Joi.string().trim().max(255).required(),
214-
scopes: Joi.array()
215-
.items(
216-
Joi.string()
217-
.valid(...consts.SCOPES, '*')
218-
.required()
219-
)
220-
.unique(),
221-
address: Joi.string().empty('').email({ tlds: false }),
222-
password: Joi.string()
223-
.empty('')
224-
.pattern(/^[a-z]{16}$/, { name: 'password' }),
225-
generateMobileconfig: booleanSchema.default(false),
226-
ttl: Joi.number().empty([0, '']),
227-
sess: sessSchema,
228-
ip: sessIPSchema
359+
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
360+
361+
const schema = Joi.object({
362+
...pathParams,
363+
...requestBody,
364+
...queryParams
229365
});
230366

231367
if (typeof req.params.scopes === 'string') {
@@ -432,15 +568,29 @@ module.exports = (db, server, userHandler) => {
432568
);
433569

434570
server.del(
435-
'/users/:user/asps/:asp',
571+
{
572+
path: '/users/:user/asps/:asp',
573+
tags: ['ApplicationPasswords'],
574+
summary: 'Delete an Application Password',
575+
validationObjs: {
576+
requestBody: {},
577+
queryParams: {
578+
sess: sessSchema,
579+
ip: sessIPSchema
580+
},
581+
pathParams: { user: userId, asp: Joi.string().hex().lowercase().length(24).required().description('ID of the Application Password') },
582+
response: { 200: { description: 'Success', model: Joi.object({ success: successRes }) } }
583+
}
584+
},
436585
tools.responseWrapper(async (req, res) => {
437586
res.charSet('utf-8');
438587

439-
const schema = Joi.object().keys({
440-
user: Joi.string().hex().lowercase().length(24).required(),
441-
asp: Joi.string().hex().lowercase().length(24).required(),
442-
sess: sessSchema,
443-
ip: sessIPSchema
588+
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
589+
590+
const schema = Joi.object({
591+
...pathParams,
592+
...requestBody,
593+
...queryParams
444594
});
445595

446596
const result = schema.validate(req.params, {

0 commit comments

Comments
 (0)