Skip to content

Commit

Permalink
fix(api-ApplicationPassword): Added all ApplicationPasswords API endp…
Browse files Browse the repository at this point in the history
…oints 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
  • Loading branch information
NickOvt authored Mar 18, 2024
1 parent b9e3f94 commit 9f9c55a
Showing 1 changed file with 187 additions and 37 deletions.
224 changes: 187 additions & 37 deletions lib/api/asps.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,70 @@ const tools = require('../tools');
const roles = require('../roles');
const util = require('util');
const { sessSchema, sessIPSchema, booleanSchema } = require('../schemas');
const { userId } = require('../schemas/request/general-schemas');
const { successRes } = require('../schemas/response/general-schemas');

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

server.get(
'/users/:user/asps',
{
path: '/users/:user/asps',
tags: ['ApplicationPasswords'],
summary: 'List Application Passwords',
validationObjs: {
requestBody: {},
queryParams: {
showAll: booleanSchema.default(false).description('If not true then skips entries with a TTL set'),
sess: sessSchema,
ip: sessIPSchema
},
pathParams: { user: userId },
response: {
200: {
description: 'Success',
model: Joi.object({
success: successRes,
results: Joi.array()
.items(
Joi.object({
id: Joi.string().required().description('ID of the Application Password'),
description: Joi.string().required().description('Description'),
scopes: Joi.array()
.items(
Joi.string()
.required()
.valid(...consts.SCOPES, '*')
)
.required()
.description('Allowed scopes for the Application Password'),
lastUse: Joi.object({
time: Joi.date().required().description('Datestring of last use or false if password has not been used'),
event: Joi.string().required().description('Event ID of the security log for the last authentication')
})
.required()
.$_setFlag('objectName', 'LastUse')
.description('Information about last use'),
created: Joi.date().required().description('Datestring'),
expires: Joi.date().required().description('Application password expires after the given date')
}).$_setFlag('objectName', 'GetASPsResult')
)
.required()
.description('Event listing')
})
}
}
}
},
tools.responseWrapper(async (req, res) => {
res.charSet('utf-8');

const schema = Joi.object().keys({
user: Joi.string().hex().lowercase().length(24).required(),
showAll: booleanSchema.default(false),
sess: sessSchema,
ip: sessIPSchema
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;

const schema = Joi.object({
...pathParams,
...requestBody,
...queryParams
});

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

server.get(
'/users/:user/asps/:asp',
{
path: '/users/:user/asps/:asp',
tags: ['ApplicationPasswords'],
summary: 'Request ASP information',
validationObjs: {
requestBody: {},
queryParams: {
sess: sessSchema,
ip: sessIPSchema
},
pathParams: { user: userId, asp: Joi.string().hex().lowercase().length(24).required().description('ID of the Application Password') },
response: {
200: {
description: 'Success',
model: Joi.object({
success: successRes,
id: Joi.string().required().description('ID of the Application Password'),
description: Joi.string().required().description('Description'),
scopes: Joi.array()
.items(
Joi.string()
.valid(...consts.SCOPES, '*')
.required()
)
.required()
.description('Allowed scopes for the Application Password'),
lastUse: Joi.object({
time: Joi.date().required().description('Datestring of last use or false if password has not been used'),
event: Joi.string().required().description('Event ID of the security log for the last authentication')
})
.required()
.$_setFlag('objectName', 'LastUse')
.description('Information about last use'),
created: Joi.date().required().description('Datestring'),
expires: Joi.date().required().description('Application password expires after the given date')
})
}
}
}
},
tools.responseWrapper(async (req, res) => {
res.charSet('utf-8');

const schema = Joi.object().keys({
user: Joi.string().hex().lowercase().length(24).required(),
asp: Joi.string().hex().lowercase().length(24).required(),
sess: sessSchema,
ip: sessIPSchema
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;

const schema = Joi.object({
...pathParams,
...requestBody,
...queryParams
});

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

server.post(
'/users/:user/asps',
{
path: '/users/:user/asps',
tags: ['ApplicationPasswords'],
summary: 'Create new Application Password',
validationObjs: {
requestBody: {
description: Joi.string().trim().max(255).required().description('Description for the Application Password entry'),
scopes: Joi.array()
.items(
Joi.string()
.valid(...consts.SCOPES, '*')
.required()
)
.unique()
.description(
'List of scopes this Password applies to. Special scope "*" indicates that this password can be used for any scope except "master"'
),
address: Joi.string()
.empty('')
.email({ tlds: false })
.description(
'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'
),
password: Joi.string()
.empty('')
.pattern(/^[a-z]{16}$/, { name: 'password' })
.description('Optional pregenerated password. Must be 16 characters, latin letters only.'),
generateMobileconfig: booleanSchema
.default(false)
.description('If true then result contains a mobileconfig formatted file with account config'),
ttl: Joi.number().empty([0, '']).description('TTL in seconds for this password. Every time password is used, TTL is reset to this value'),
sess: sessSchema,
ip: sessIPSchema
},
queryParams: {},
pathParams: { user: userId },
response: {
200: {
description: 'Success',
model: Joi.object({
success: successRes,
id: Joi.string().required().description('ID of the Application Password'),
password: Joi.string()
.required()
.description(
'Application Specific Password. Generated password is whitespace agnostic, so it could be displayed to the client as "abcd efgh ijkl mnop" instead of "abcdefghijklmnop"'
),
mobileconfig: Joi.string()
.required()
.description(
'Base64 encoded mobileconfig file. Generated profile file should be sent to the client with Content-Type value of application/x-apple-aspen-config.'
),
name: Joi.string().required().description('Account name'),
address: Joi.string().required().description('Account address or the address specified in params of this endpoint')
})
}
}
}
},
tools.responseWrapper(async (req, res) => {
res.charSet('utf-8');

const schema = Joi.object().keys({
user: Joi.string().hex().lowercase().length(24).required(),
description: Joi.string().trim().max(255).required(),
scopes: Joi.array()
.items(
Joi.string()
.valid(...consts.SCOPES, '*')
.required()
)
.unique(),
address: Joi.string().empty('').email({ tlds: false }),
password: Joi.string()
.empty('')
.pattern(/^[a-z]{16}$/, { name: 'password' }),
generateMobileconfig: booleanSchema.default(false),
ttl: Joi.number().empty([0, '']),
sess: sessSchema,
ip: sessIPSchema
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;

const schema = Joi.object({
...pathParams,
...requestBody,
...queryParams
});

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

server.del(
'/users/:user/asps/:asp',
{
path: '/users/:user/asps/:asp',
tags: ['ApplicationPasswords'],
summary: 'Delete an Application Password',
validationObjs: {
requestBody: {},
queryParams: {
sess: sessSchema,
ip: sessIPSchema
},
pathParams: { user: userId, asp: Joi.string().hex().lowercase().length(24).required().description('ID of the Application Password') },
response: { 200: { description: 'Success', model: Joi.object({ success: successRes }) } }
}
},
tools.responseWrapper(async (req, res) => {
res.charSet('utf-8');

const schema = Joi.object().keys({
user: Joi.string().hex().lowercase().length(24).required(),
asp: Joi.string().hex().lowercase().length(24).required(),
sess: sessSchema,
ip: sessIPSchema
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;

const schema = Joi.object({
...pathParams,
...requestBody,
...queryParams
});

const result = schema.validate(req.params, {
Expand Down

0 comments on commit 9f9c55a

Please sign in to comment.