From 4fa9ef414e59d497a97823c6fabfea153a90d41d Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Thu, 19 Sep 2024 15:12:47 +0100 Subject: [PATCH 1/4] Record who deployed flow that triggered auto snapshot part of #4413 --- forge/db/controllers/ProjectSnapshot.js | 8 ++++++- .../migrations/20240920-01-add-flow-user.js | 21 +++++++++++++++++++ forge/db/models/StorageFlow.js | 3 ++- forge/routes/storage/index.js | 6 ++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 forge/db/migrations/20240920-01-add-flow-user.js diff --git a/forge/db/controllers/ProjectSnapshot.js b/forge/db/controllers/ProjectSnapshot.js index f34306cf65..50fc1fdebc 100644 --- a/forge/db/controllers/ProjectSnapshot.js +++ b/forge/db/controllers/ProjectSnapshot.js @@ -321,7 +321,13 @@ const instanceAutoSnapshotUtils = { // 2. log the snapshot creation in audit log // 3. delete older auto snapshots if the limit is reached (10) // do NOT delete any snapshots that are currently in use by an target (instance/device/device group) - const user = meta?.user || { id: null } // if no user is available, use `null` (system user) + const currentFlow = await app.db.models.StorageFlow.byProject(project.id) + let flowUser = null + if (currentFlow.UserId !== null) { + flowUser = currentFlow.UserId + } + const user = meta?.user || { id: flowUser } // if no user is available, use `null` (system user) + // 1. create a snapshot from the instance const snapShot = await app.db.controllers.ProjectSnapshot.createSnapshot( diff --git a/forge/db/migrations/20240920-01-add-flow-user.js b/forge/db/migrations/20240920-01-add-flow-user.js new file mode 100644 index 0000000000..9d09c33e09 --- /dev/null +++ b/forge/db/migrations/20240920-01-add-flow-user.js @@ -0,0 +1,21 @@ +/** + * Add User to StorageFlows table + */ +const { DataTypes } = require('sequelize') + +module.exports = { + up: async (context) => { + await context.addColumn('StorageFlows', 'UserId', { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + references: { model: 'Users', key: 'id'}, + // CHECK ME + onDelete: 'SET NULL', + // CHECK ME + onUpdate: 'CASCADE' + }) + }, + down: async (context) => { + } +} \ No newline at end of file diff --git a/forge/db/models/StorageFlow.js b/forge/db/models/StorageFlow.js index ff024f66ac..2ab5771c54 100644 --- a/forge/db/models/StorageFlow.js +++ b/forge/db/models/StorageFlow.js @@ -15,6 +15,7 @@ module.exports = { }, associations: function (M) { this.belongsTo(M.Project) + this.belongsTo(M.User) }, finders: function (M) { return { @@ -22,7 +23,7 @@ module.exports = { byProject: async (project) => { return this.findOne({ where: { ProjectId: project }, - attributes: ['id', 'flow', 'updatedAt'] + attributes: ['id', 'flow', 'updatedAt', 'UserId'] }) } } diff --git a/forge/routes/storage/index.js b/forge/routes/storage/index.js index c369aeae75..69a0e5c2df 100644 --- a/forge/routes/storage/index.js +++ b/forge/routes/storage/index.js @@ -25,14 +25,20 @@ module.exports = async function (app) { app.post('/:projectId/flows', async (request, response) => { const id = request.params.projectId + let UserId = null + if (request.headers['ff-user']) { + UserId = app.db.models.User.decodeHashid(request.headers['ff-user'])[0] + } // Check if the project exists first let flow = await app.db.models.StorageFlow.byProject(id) if (flow) { flow.flow = JSON.stringify(request.body) + flow.UserId = UserId await flow.save() } else { flow = await app.db.models.StorageFlow.create({ flow: JSON.stringify(request.body), + UserId, ProjectId: id }) From c5f823f581047306a9f7286bc2cfbd2946af0cd9 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Thu, 19 Sep 2024 15:15:34 +0100 Subject: [PATCH 2/4] fix lint --- forge/db/controllers/ProjectSnapshot.js | 1 - forge/db/migrations/20240920-01-add-flow-user.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/forge/db/controllers/ProjectSnapshot.js b/forge/db/controllers/ProjectSnapshot.js index 50fc1fdebc..fa7fd028fa 100644 --- a/forge/db/controllers/ProjectSnapshot.js +++ b/forge/db/controllers/ProjectSnapshot.js @@ -327,7 +327,6 @@ const instanceAutoSnapshotUtils = { flowUser = currentFlow.UserId } const user = meta?.user || { id: flowUser } // if no user is available, use `null` (system user) - // 1. create a snapshot from the instance const snapShot = await app.db.controllers.ProjectSnapshot.createSnapshot( diff --git a/forge/db/migrations/20240920-01-add-flow-user.js b/forge/db/migrations/20240920-01-add-flow-user.js index 9d09c33e09..09299ba514 100644 --- a/forge/db/migrations/20240920-01-add-flow-user.js +++ b/forge/db/migrations/20240920-01-add-flow-user.js @@ -9,7 +9,7 @@ module.exports = { type: DataTypes.INTEGER, allowNull: true, defaultValue: null, - references: { model: 'Users', key: 'id'}, + references: { model: 'Users', key: 'id' }, // CHECK ME onDelete: 'SET NULL', // CHECK ME @@ -18,4 +18,4 @@ module.exports = { }, down: async (context) => { } -} \ No newline at end of file +} From aac359cf0b985c896c0d075b77ea1379679f22da Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Fri, 20 Sep 2024 13:18:17 +0100 Subject: [PATCH 3/4] rename migration --- ...{20240920-01-add-flow-user.js => 20240920-02-add-flow-user.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename forge/db/migrations/{20240920-01-add-flow-user.js => 20240920-02-add-flow-user.js} (100%) diff --git a/forge/db/migrations/20240920-01-add-flow-user.js b/forge/db/migrations/20240920-02-add-flow-user.js similarity index 100% rename from forge/db/migrations/20240920-01-add-flow-user.js rename to forge/db/migrations/20240920-02-add-flow-user.js From 2ea880707e8634d936a1ee2dcaa8b9ae690f30a1 Mon Sep 17 00:00:00 2001 From: Ben Hardill Date: Fri, 20 Sep 2024 15:59:41 +0100 Subject: [PATCH 4/4] Add tests --- test/unit/forge/routes/storage/index_spec.js | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/unit/forge/routes/storage/index_spec.js b/test/unit/forge/routes/storage/index_spec.js index 1e61988ef5..516a1beec9 100644 --- a/test/unit/forge/routes/storage/index_spec.js +++ b/test/unit/forge/routes/storage/index_spec.js @@ -147,6 +147,31 @@ describe('Storage API', function () { const flow = response.json() should(flow).eqls(newFlow) }) + + it('Save Flow with user', async function () { + const newFlow = [{ id: '1', type: 'tab', label: 'tab1', disabled: false, info: '' }] + const flowURL = `/storage/${project.id}/flows` + await app.inject({ + method: 'POST', + url: flowURL, + headers: { + authorization: `Bearer ${tokens.token}`, + 'ff-user': app.adminUser.hashid + }, + payload: newFlow + }) + const response = await app.inject({ + method: 'GET', + url: flowURL, + headers: { + authorization: `Bearer ${tokens.token}` + } + }) + const flow = response.json() + should(flow).eqls(newFlow) + const dbFlow = await app.db.models.StorageFlow.byProject(project.id) + dbFlow.should.have.property('UserId', app.adminUser.id) + }) }) describe('/credentials', function () {