import { jwt, key, fields, parameters } from './lib.mjs' const common = { tags: ['API keys'], security: [jwt, key], } const local = { params: { key: { in: 'path', name: 'key', required: true, description: "The API key's UUID (the part you use as username)", schema: { example: 'c00475bd-3002-4baa-80ad-0145cd6a646c', type: 'string', }, }, }, errors: { accountStatusLacking: 'The account is in a status that does not allow this action (eg: it is not active or disabled).', insufficientAccessLevel: 'The credentials used to make this API call are insufficient for this operation.', }, response: { status: { 401: { description: '**Unauthorized - Authentication failed**\n\n' + 'Status code `401` indicates that the request could not be authenticated.' + 'This typically means that authentication failed.
\n' + '**Note:** _There is no response body for a `401` status code_.', }, 403: { description: '**Forbidden - Permissions problem**\n\n' + 'Status code `403` indicates that the request was forbidden.
' + 'The return body will have an `error` field which can hold:\n\n', content: { 'application/json': { schema: { type: 'object', properties: { result: fields.result, error: { ...fields.error, example: 'accountStatusLacking', }, }, }, }, }, }, 404: { description: '**Resource not found - The API key could not be found**\n\n' + 'Status code `404` indicates that the resource could not be found.
' + 'The return body will have an `error` field which can hold:\n\n' + '- `apikeyNotFound` : The API key could not be found, probably ' + 'because it does not or no longer exists' + '', content: { 'application/json': { schema: { type: 'object', properties: { result: fields.result, error: { ...fields.error, example: 'apikeyNotFound', }, }, }, }, }, }, 500: { description: '**Server error - API call failed**\n\n' + 'Status code `500` indicates that the request could not be handled ' + 'due to an unforseen error.', }, }, body: { withSecret: { description: 'Object holding the data of the created API key', type: 'object', properties: { expiresAt: { description: 'UTC Timestamp in ISO 8601 format.', type: 'string', example: '2022-12-18T18:14:30.460Z', }, key: { description: 'The _key_ part of the API key serves as the username', type: 'string', example: 'c00475bd-3002-4baa-80ad-0145cd6a646c', }, level: fields.level, name: fields.name, secret: { description: ` The _secret_ part of the API key serves as the password. It is only revealed in the response of the API key creation.`, type: 'string', example: '56b74b5dc2da7a4f37b3c9a6172e840cf4912dc37cbc55c87485f2e0abf59245', }, userId: { description: `The unique ID of the user who owns this resource.`, type: 'number', example: 4, }, }, }, }, }, } local.response.body.regular = { ...local.response.body.withSecret, properties: { ...local.response.body.withSecret.properties }, } delete local.response.body.regular.properties.secret const errorExamples = (errs) => errs.map((err) => `\n - \`${err}\` : ${local.errors[err]}`).join(' ') // Schemas export const schemas = { apikey: local.response.body.withSecret } // Paths export const paths = {} // Create API key paths['/apikeys/{auth}'] = { post: { ...common, summary: 'Create a new API key', description: 'Creates a new API key and returns it. ' + 'requires a `name`, `level`, and `expiresIn` field in the POST body.', parameters: [parameters.auth], requestBody: { required: true, content: { 'application/json': { schema: { type: 'object', properties: { expiresIn: { description: ` mber of seconds the API key will remain valid before expiring. n never be higher than the \`apikeys.maxExpirySeconds\` configuration setting.`, type: 'number', example: 3600, }, level: fields.level, name: fields.name, }, }, }, }, }, responses: { 201: { description: '**Success - API key created**\n\n' + 'Status code `201` indicates that the resource was created successfully.', content: { 'application/json': { schema: { type: 'object', properties: { result: fields.result, apikey: local.response.body.withSecret, }, }, }, }, }, 400: { description: '**Client error - Invalid request**\n\n' + 'Status code `400` indicates that the request was invalid.
' + 'The return body will have an `error` field which can hold:\n\n' + '- `postBodyMissing` : The POST request did not have a body\n' + '- `nameMissing` : The `name` field was missing from the request body\n' + '- `levelMissing` : The `level` field was missing from the request body\n' + '- `expiresInMissing` : The `expiresIn` field was missing from the request body\n' + '- `levelNotNumeric` : The `level` field in the request body was a number\n' + '- `invalidLevel` : The `level` field in the request body was not a valid permission level\n' + '- `expiresInNotNumeric` : The `expiresIn` field in the request body was not a number\n' + '- `expiresIsHigherThanMaximum` : The `expiresIn` field in the request body is higher than allowed by the `apikeys.maxExpirySeconds` configuration.' + '- `keyLevelExceedsRoleLevel` : The `level` field in the request body is higher than the `level` of the user creating the key. Which is not allowed.' + '', content: { 'application/json': { schema: { type: 'object', properties: { result: fields.result, error: { ...fields.error, example: 'levelMissing', }, }, }, }, }, }, 500: { description: '**Server error - API call failed**\n\n' + 'Status code `500` indicates that the request could not be handled due to an unforseen error.
' + 'The return body will have an `error` field which can hold:\n\n' + '- `createApikeyFailed` : The API key could not be created\n' + '', content: { 'application/json': { schema: { type: 'object', properties: { result: fields.result, error: { ...fields.error, example: 'createApikeyFailed', }, }, }, }, }, }, }, }, } // Get/Remove API key paths['/apikeys/{key}/{auth}'] = { // Get API key get: { ...common, summary: 'Retrieve an API key', description: 'Retrieves information about the API key `key`.', parameters: [parameters.auth, local.params.key], responses: { 200: { description: '**Success - API key returned**\n\n' + 'Status code `200` indicates that the resource was returned successfully.', content: { 'application/json': { schema: { type: 'object', properties: { result: { ...fields.result, example: 'success', }, apikey: local.response.body.regular, }, }, }, }, }, 401: local.response.status['401'], 403: { ...local.response.status['403'], description: local.response.status['403'].description + errorExamples(['accountStatusLacking', 'insufficientAccessLevel']), }, 404: local.response.status['404'], 500: local.response.status['500'], }, }, // Remove API key delete: { ...common, summary: 'Remove an API key', description: 'Removes the API key `key`.', parameters: [parameters.auth, local.params.key], responses: { 204: { description: '**Success - API key removed**\n\n' + 'Status code `204` indicates that the resource was removed successfully.' + '
**Note:** _There is no response body for a `204` status code_.', }, 401: local.response.status['401'], 403: { ...local.response.status['403'], description: local.response.status['403'].description + errorExamples(['accountStatusLacking', 'insufficientAccessLevel']), }, 404: local.response.status['404'], 500: local.response.status['500'], }, }, } // Get current API key paths['/whoami/key'] = { get: { tags: ['Whoami', ...common.tags], security: [key], summary: 'Retrieve the API key used in the request', description: 'Retrieves information about the API key that ' + 'was used to authenticate the request.\n\n' + '**Note:** _See `GET /whoami/jwt` for the JWT equivalent._', responses: { 200: { description: '**Success - API key returned**\n\n' + 'Status code `200` indicates that the resource was returned successfully.', content: { 'application/json': { schema: { type: 'object', properties: { result: { ...fields.result, example: 'success', }, apikey: local.response.body.regular, }, }, }, }, }, 401: local.response.status['401'], 403: { ...local.response.status['403'], description: local.response.status['403'].description + errorExamples(['accountStatusLacking', 'insufficientAccessLevel']), }, 500: local.response.status['500'], }, }, }