arrest
Version:
OpenAPI v3 compliant REST framework for Node.js, with support for MongoDB and JSON-Schema
121 lines • 4.98 kB
JavaScript
import { API } from '../../api.js';
import { addConstraint, patchToMongo } from '../util.js';
import { MongoOperation } from './base.js';
export class PatchMongoOperation extends MongoOperation {
constructor(resource, path, method, id = 'patch') {
super(resource, path, method, id);
}
getCustomInfo() {
return {
summary: `Patch a ${this.resource.info.name}`,
parameters: [
{
$ref: '#/components/parameters/id',
},
],
requestBody: {
description: `The updated ${this.resource.info.name}, minus the unique identifier and the metatadata`,
content: {
'application/json': {
schema: {
type: 'array',
items: {
oneOf: [
{
type: 'object',
required: ['op', 'path', 'value'],
additionalProperties: false,
properties: {
op: { enum: ['add', 'replace', 'test'] },
path: { type: 'string', minLength: 1 },
value: {},
},
},
{
type: 'object',
required: ['op', 'from', 'path'],
additionalProperties: false,
properties: {
op: { enum: ['move'] },
from: { type: 'string', minLength: 1 },
path: { type: 'string', minLength: 1 },
},
},
{
type: 'object',
required: ['op', 'path'],
additionalProperties: false,
properties: {
op: { enum: ['remove'] },
path: { type: 'string', minLength: 1 },
},
},
],
},
},
},
},
required: true,
},
responses: {
'200': {
description: `${this.resource.info.name} successfully updated`,
content: {
'application/json': {
schema: this.responseSchema,
},
},
},
'404': {
$ref: '#/components/responses/notFound',
},
},
};
}
async prepareQuery(job) {
job = await super.prepareQuery(job);
job.query = addConstraint(job.query, this.getItemQuery(job.req.params.id));
const patch = job.req.body;
if (job.req.ability) {
const dottedPath = (path) => path
.split('/')
.slice(1)
.filter((i) => i !== '-' && isNaN(parseInt(i)))
.join('.');
for (let p of patch) {
if (!this.checkAbilityForPath(job.req.ability, dottedPath(p.path)) ||
(p['from'] && !this.checkAbilityForPath(job.req.ability, dottedPath(p['from'])))) {
API.fireError(403, 'insufficient privileges', p);
}
}
}
const update = patchToMongo(patch, this.resource.info.escapeProperties);
if (update.query) {
job.query = addConstraint(job.query, update.query);
}
job.doc = update.doc;
return job;
}
async prepareOpts(job) {
job.opts = { returnDocument: 'after' };
return job;
}
async runOperation(job) {
let result = await job.coll.findOneAndUpdate(job.query, job.doc, job.opts);
if (!result.ok || !result.value) {
job.req.logger.error('update failed', result);
API.fireError(404, 'not_found');
}
job.data = result.value;
return job;
}
async redactResult(job) {
job = await super.redactResult(job);
if (this.resource.info.id !== '_id') {
delete job.data['_id'];
}
delete job.data._metadata;
return job;
}
}
//# sourceMappingURL=patch.js.map