Skip to content

Commit

Permalink
Merge pull request #84 from CloudEcosystemDev/feat/add-template-versi…
Browse files Browse the repository at this point in the history
…oning

Added template versioning schema and endpoints
  • Loading branch information
jorgerusso committed Sep 19, 2023
2 parents c436543 + 4543490 commit 4835a24
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 87 deletions.
79 changes: 68 additions & 11 deletions services/template-repository/app/api/controllers/flowTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const log = require('../../config/logger'); // eslint-disable-line

// require our MongoDB-Model
const FlowTemplate = require('../../models/flowTemplate');
const TemplateVersion = require('../../models/templateVersion');

// Gets all flowTemplates
router.get('/', jsonParser, can(config.flowTemplateReadPermission), async (req, res) => {
Expand Down Expand Up @@ -170,16 +171,12 @@ router.patch('/:id', jsonParser, can(config.flowTemplateWritePermission), async

// Get the current template
const oldTemplate = await storage.getTemplateById(req.params.id, req.user);
const copyOldTemplate = JSON.parse(JSON.stringify(oldTemplate));

if (!oldTemplate) {
return res.status(404).send({ errors: [{ message: 'Template not found', code: 404 }] });
}

// TODO: Decide How to handle Template States when Updated (i.e. Published -> Draft and bump version if changed?)
/* if (oldTemplate.status !== 'draft') {
return res.status(409).send({ errors: [{ message: `Flow is not inactive. Current status: ${oldFlow.status}`, code: 409 }] });
} */

const updateTemplate = Object.assign(oldTemplate, updateData);
updateTemplate._id = updateTemplate.id;
delete updateTemplate.id;
Expand Down Expand Up @@ -213,6 +210,10 @@ router.patch('/:id', jsonParser, can(config.flowTemplateWritePermission), async
},
};

const templateVersion = { template: copyOldTemplate, templateId: oldTemplate._id };
const newTemplateVersion = new TemplateVersion(templateVersion);
await newTemplateVersion.save();

await publishQueue(ev);

res.status(200).send({ data: response, meta: {} });
Expand All @@ -221,6 +222,66 @@ router.patch('/:id', jsonParser, can(config.flowTemplateWritePermission), async
}
});

router.get('/:id/versions', jsonParser, can(config.flowTemplateReadPermission), async (req, res) => {
const templateId = req.params.id;

if (!mongoose.Types.ObjectId.isValid(templateId)) {
return res.status(400).send({ errors: [{ message: 'Invalid id', code: 400 }] });
}

const template = await storage.getTemplateById(templateId, req.user);

if (!template) {
return res.status(404).send({ errors: [{ message: 'Template not found', code: 404 }] });
}

// we skip the template object by default
let selectProjection = '-template';

if (req.query.verbose === 'true') {
selectProjection = '';
}
const versions = await storage.getTemplateVersionsByTemplateId(templateId, selectProjection);

const response = {
data: versions,
meta: {},
};

return res.status(200).send(response);
});

router.get('/:id/versions/:versionId', jsonParser, can(config.flowTemplateReadPermission), async (req, res) => {
const templateId = req.params.id;
const versionTemplateId = req.params.versionId;

if (!mongoose.Types.ObjectId.isValid(templateId)) {
return res.status(400).send({ errors: [{ message: 'Invalid id', code: 400 }] });
}
if (!mongoose.Types.ObjectId.isValid(versionTemplateId)) {
return res.status(400).send({ errors: [{ message: 'Invalid template version id', code: 400 }] });
}

const template = await storage.getTemplateById(templateId, req.user);

if (!template) {
return res.status(404).send({ errors: [{ message: 'Template not found', code: 404 }] });
}

const templateVersion = await storage.getTemplateVersionById(versionTemplateId);

if (!templateVersion) {
return res.status(404).send({ errors: [{ message: 'Template version not found', code: 404 }] });
}

const response = {
data: templateVersion,
meta: {},
};

return res.status(200).send(response);
});

// Gets a template by id
router.get('/:id', jsonParser, can(config.flowTemplateReadPermission), async (req, res) => {
const templateId = req.params.id;
Expand Down Expand Up @@ -255,13 +316,9 @@ router.delete('/:id', can(config.flowTemplateWritePermission), jsonParser, async
return res.status(404).send({ errors: [{ message: 'Template not found', code: 404 }] });
}

/* TODO: Decide if published templates can be directly deleted. If this section is not needed, the first check for "oldTemplate"
// May not be needed also, because of the check when calling to storage.deleteTemplate()
if (oldTemplate.status !== 'draft') {
return res.status(409).send({ errors: [{ message: `Flow is not inactive. Current status: ${oldFlow.status}`, code: 409 }] });
} */

const response = await storage.deleteTemplate(templateId, req.user);
// we delete the versions of this template
await storage.deleteTemplateVersions(templateId);

if (!response) {
res.status(404).send({ errors: [{ message: 'Template not found', code: 404 }] });
Expand Down
43 changes: 43 additions & 0 deletions services/template-repository/app/api/controllers/mongo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const mongoose = require('mongoose');
const config = require('../../config/index.js');
const log = require('../../config/logger');
const FlowTemplate = require('../../models/flowTemplate');
const TemplateVersion = require('../../models/templateVersion');

const format = (template) => {
const newTemplate = template;
Expand Down Expand Up @@ -119,6 +120,34 @@ const getTemplateById = (flowTemplateId, user) => new Promise((resolve) => {
});
});

const getTemplateVersionById = (templateVersionId) => new Promise((resolve) => {
const qry = { _id: new mongoose.Types.ObjectId(templateVersionId) };
TemplateVersion.findOne(qry).lean()
.then((doc) => {
const templateVersion = format(doc);
resolve(templateVersion);
})
.catch((err) => {
log.error(err);
});
});

// eslint-disable-next-line max-len
const getTemplateVersionsByTemplateId = (templateId, selectProjection) => new Promise((resolve, reject) => {
const qry = { templateId: new mongoose.Types.ObjectId(templateId) };
TemplateVersion.find(qry, selectProjection).sort({ _id: -1 }).lean().then((doc) => {
const templateVersions = doc;
for (let i = 0; i < templateVersions.length; i += 1) {
templateVersions[i] = format(templateVersions[i]);
}
resolve(templateVersions);
})
.catch((err) => {
reject();
log.error(err);
});
});

const addTemplate = (storeTemplate) => new Promise((resolve) => {
storeTemplate.save()
.then((doc) => {
Expand Down Expand Up @@ -190,6 +219,17 @@ const deleteTemplate = (flowTemplateId, user) => new Promise((resolve) => {
});
});

const deleteTemplateVersions = (templateId) => new Promise((resolve) => {
const qry = { templateId: new mongoose.Types.ObjectId(templateId) };
TemplateVersion.deleteMany(qry)
.then((response) => {
resolve(response);
})
.catch((err) => {
log.error(err);
});
});

const anonymise = (userId) => new Promise((resolve) => {
FlowTemplate.update(
{ 'owners.id': userId },
Expand Down Expand Up @@ -231,4 +271,7 @@ module.exports = {
anonymise,
getOrphanedTemplates,
format,
getTemplateVersionById,
getTemplateVersionsByTemplateId,
deleteTemplateVersions,
};
16 changes: 16 additions & 0 deletions services/template-repository/app/models/schemas/templateVersion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const mongoose = require('mongoose');
const TemplateSchema = require('./flowTemplate').flowTemplate;

const Schema = mongoose.Schema;

const clonedTemplate = TemplateSchema.clone().set('_id', false);

const templateVersion = new Schema(
{
templateId: { type: mongoose.Types.ObjectId, required: true, index: true },
template: clonedTemplate,
},
{ collection: 'templateVersions', timestamps: true },
);

module.exports.templateVersion = templateVersion;
6 changes: 6 additions & 0 deletions services/template-repository/app/models/templateVersion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const mongoose = require('mongoose');

const TemplateVersion = require('./schemas/templateVersion').templateVersion;

// Compile model from schema
module.exports = mongoose.model('TemplateVersion', TemplateVersion);
Loading

0 comments on commit 4835a24

Please sign in to comment.