UNPKG

@flowfuse/flowfuse

Version:

An open source low-code development platform

254 lines (246 loc) • 8.64 kB
/** * Project Template api routes * * - /api/v1/templates * * @namespace templates * @memberof forge.routes.api */ module.exports = async function (app) { /** * Get a list of all templates * @name /api/v1/templates/:id * @static * @memberof forge.routes.api.templates */ app.get('/', { preHandler: app.needsPermission('template:list'), schema: { summary: 'Get a list of all templates', tags: ['Templates'], query: { $ref: 'PaginationParams' }, response: { 200: { type: 'object', properties: { meta: { $ref: 'PaginationMeta' }, count: { type: 'number' }, templates: { type: 'array', items: { $ref: 'TemplateSummary' } } } }, '4xx': { $ref: 'APIError' } } } }, async (request, reply) => { const paginationOptions = app.getPaginationOptions(request) const templates = await app.db.models.ProjectTemplate.getAll(paginationOptions) templates.templates = templates.templates.map(s => app.db.views.ProjectTemplate.templateSummary(s)) reply.send(templates) }) /** * Get the details of a template * @name /api/v1/templates/:id * @static * @memberof forge.routes.api.templates */ app.get('/:templateId', { preHandler: app.needsPermission('template:read'), schema: { summary: 'Get a template', tags: ['Templates'], params: { type: 'object', properties: { templateId: { type: 'string' } } }, response: { 200: { $ref: 'Template' }, '4xx': { $ref: 'APIError' } } } }, async (request, reply) => { const template = await app.db.models.ProjectTemplate.byId(request.params.templateId) if (template) { const result = app.db.views.ProjectTemplate.template(template) if (result.settings?.env) { result.settings.env = result.settings.env.map(env => { if (env.hidden) { env.value = '' } return env }) } reply.send(result) } else { reply.code(404).send({ code: 'not_found', error: 'Not Found' }) } }) /** * Create a template * @name /api/v1/templates * @static * @memberof forge.routes.api.templates */ app.post('/', { preHandler: app.needsPermission('template:create'), schema: { summary: 'Create a template - admin-only', tags: ['Templates'], body: { type: 'object', required: ['name', 'settings', 'policy'], properties: { name: { type: 'string' }, active: { type: 'boolean' }, description: { type: 'string' }, settings: { type: 'object' }, policy: { type: 'object' } } }, response: { 200: { $ref: 'TemplateSummary' }, '4xx': { $ref: 'APIError' } } } }, async (request, reply) => { // Currently only admins can create a template try { const templateSettings = app.db.controllers.ProjectTemplate.validateSettings(request.body.settings) const templateProperties = { name: request.body.name, active: request.body.active !== undefined ? request.body.active : undefined, description: request.body.description || '', settings: templateSettings, policy: request.body.policy } const template = await app.db.models.ProjectTemplate.create(templateProperties) template.setOwner(request.session.User) await template.save() const response = app.db.views.ProjectTemplate.templateSummary(template) reply.send(response) } catch (err) { let responseMessage if (err.errors) { responseMessage = err.errors.map(err => err.message).join(',') } else { responseMessage = err.toString() } reply.code(400).send({ code: 'unexpected_error', error: responseMessage }) } }) /** * Delete a template * @name /api/v1/templates * @static * @memberof forge.routes.api.templates */ app.delete('/:templateId', { preHandler: app.needsPermission('template:delete'), schema: { summary: 'Delete a template - admin-only', tags: ['Templates'], params: { type: 'object', properties: { templateId: { type: 'string' } } }, response: { 200: { $ref: 'APIStatus' }, '4xx': { $ref: 'APIError' } } } }, async (request, reply) => { const template = await app.db.models.ProjectTemplate.byId(request.params.templateId) // The `beforeDestroy` hook of the ProjectTemplate model ensures // we don't delete an in-use template try { await template.destroy() reply.send({ status: 'okay' }) } catch (err) { reply.code(400).send({ code: 'unexpected_error', error: err.toString() }) } }) /** * Update a template * @name /api/v1/templates * @static * @memberof forge.routes.api.templates */ app.put('/:templateId', { preHandler: app.needsPermission('template:edit'), schema: { summary: 'Update a template - admin-only', tags: ['Templates'], params: { type: 'object', properties: { templateId: { type: 'string' } } }, body: { type: 'object', required: ['name', 'settings', 'policy'], properties: { name: { type: 'string' }, active: { type: 'boolean' }, description: { type: 'string' }, settings: { type: 'object' }, policy: { type: 'object' } } }, response: { 200: { $ref: 'TemplateSummary' }, '4xx': { $ref: 'APIError' } } } }, async (request, reply) => { const templateSettings = app.db.controllers.ProjectTemplate.validateSettings(request.body.settings) const template = await app.db.models.ProjectTemplate.byId(request.params.templateId) template.name = request.body.name template.description = request.body.description template.active = request.body.active !== undefined ? request.body.active : undefined if (templateSettings.httpNodeAuth?.pass) { if (templateSettings.httpNodeAuth.pass === true) { // Copy over the existing value (if there is one) if (template.settings.httpNodeAuth?.pass) { templateSettings.httpNodeAuth.pass = template.settings.httpNodeAuth.pass } } } templateSettings.env = templateSettings.env.map((env, key) => { if (env.hidden === true && env.value === '') { // we need to re-map the hidden value so it won't get overwritten const existingVar = template.settings.env.find(currentEnv => currentEnv.name === env.name) if (existingVar) { env.value = existingVar.value } } return env }) template.settings = templateSettings template.policy = request.body.policy await template.save() const response = app.db.views.ProjectTemplate.templateSummary(template) reply.send(response) }) }