From 5a15373dcd76ed7371dbbee88104dd0c4384a889 Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Mon, 12 Nov 2018 04:59:16 +0000 Subject: [registration] add configurator for registration hooks --- server/.sequelizerc | 5 + server/api/configurator.js | 2 +- server/api/registrations.js | 59 +++++++++ .../20181008151633-create-registrationhook.js | 7 ++ server/models/registrationhook.js | 8 +- webapp/package-lock.json | 52 ++++---- webapp/package.json | 14 +-- webapp/src/components/RegistrationModule.vue | 137 +++++++++++++++++++++ webapp/src/components/RegistrationModuleDelete.vue | 63 ++++++++++ webapp/src/components/RegistrationModuleEdit.vue | 120 ++++++++++++++++++ webapp/src/config/dashboard.js | 2 + webapp/src/config/i18n.js | 2 + webapp/src/config/store.js | 2 + webapp/src/store/registration.js | 40 ++++++ 14 files changed, 478 insertions(+), 35 deletions(-) create mode 100644 server/.sequelizerc create mode 100644 webapp/src/components/RegistrationModule.vue create mode 100644 webapp/src/components/RegistrationModuleDelete.vue create mode 100644 webapp/src/components/RegistrationModuleEdit.vue create mode 100644 webapp/src/store/registration.js diff --git a/server/.sequelizerc b/server/.sequelizerc new file mode 100644 index 0000000..3a02529 --- /dev/null +++ b/server/.sequelizerc @@ -0,0 +1,5 @@ +const path = require('path'); + +module.exports = { + 'config': path.resolve('config', 'database.json') +} \ No newline at end of file diff --git a/server/api/configurator.js b/server/api/configurator.js index 3c5bab8..250471b 100644 --- a/server/api/configurator.js +++ b/server/api/configurator.js @@ -60,7 +60,7 @@ router.post(['/entries', '/entries/:id'], async (req, res) => { entry = await db.entry.findOne({ where: { id: req.params.id } }) if (entry) await entry.update(item) } else { - await db.entry.create(item) + entry = await db.entry.create(item) } if (entry) { res.send({ id: entry.id }) diff --git a/server/api/registrations.js b/server/api/registrations.js index eb9a7a0..928ee94 100644 --- a/server/api/registrations.js +++ b/server/api/registrations.js @@ -21,6 +21,65 @@ router.get('/', (req, res) => { }) }) +/* + * Returns all registration hooks sorted by sortValue. + * + * @return: List of registration hooks + */ +router.get('/hooks', (req, res) => { + db.registrationhook.findAll({ order: [ ['sortValue', 'ASC'] ], include: [{ model: db.group, as: 'groups', attributes: ['id'] }] }).then(hooks => { + res.send(hooks) + }) +}) + +// POST requests. + +/* + * Reorders the registration hooks based on an array of hook ids. + */ +router.post('/hookorder', async (req, res) => { + var idSortvalueMap = {} + req.body.ids.forEach((id, index) => { + idSortvalueMap[id] = index + }) + var hooks = await db.registrationhook.findAll() + var promises = [] + hooks.forEach(hook => { + promises.push(hook.update({ sortvalue: idSortvalueMap[hook.id] })) + }) + await Promise.all(promises) + res.end() +}) + +router.post(['/hooks', '/hooks/:id'], async (req, res) => { + var item = { + name: req.body.name, + description: req.body.description, + type: req.body.type, + script: req.body.script + } + var hook = null + if (req.params.id > 0) { + hook = await db.registrationhook.findOne({ where: { id: req.params.id } }) + if (hook) await hook.update(item) + } else { + var maxSortvalue = await db.registrationhook.max('sortvalue') + item.sortvalue = maxSortvalue ? maxSortvalue + 1 : 1 + hook = await db.registrationhook.create(item) + } + if (hook) { + hook.setGroups(req.body.groups) + res.send({ id: hook.id }) + } + res.end() +}) + +// DELETE requests. + +router.delete(['/hooks', '/hooks/:id'], (req, res) => { + db.registrationhook.destroy({ where: { id: req.params.id || req.body.ids } }).then(count => { res.send({ count }) }) +}) + module.exports.router = router // GET requests. diff --git a/server/migrations/20181008151633-create-registrationhook.js b/server/migrations/20181008151633-create-registrationhook.js index 59692c5..5914188 100644 --- a/server/migrations/20181008151633-create-registrationhook.js +++ b/server/migrations/20181008151633-create-registrationhook.js @@ -4,9 +4,16 @@ module.exports = { return queryInterface.createTable('registrationhooks', { id: { primaryKey: true, + autoIncrement: true, allowNull: false, type: Sequelize.INTEGER, }, + name: { + type: Sequelize.STRING + }, + description: { + type: Sequelize.STRING(2048) + }, sortvalue: Sequelize.INTEGER, type: Sequelize.STRING, script: { diff --git a/server/models/registrationhook.js b/server/models/registrationhook.js index 1e74288..0d1ea6e 100644 --- a/server/models/registrationhook.js +++ b/server/models/registrationhook.js @@ -7,11 +7,17 @@ module.exports = (sequelize, DataTypes) => { primaryKey: true, type: DataTypes.INTEGER }, + name: DataTypes.STRING, + description: DataTypes.STRING(2048), sortvalue: DataTypes.INTEGER, type: DataTypes.STRING, script: { allowNull: true, - type: DataTypes.BLOB + type: DataTypes.BLOB, + get() { + var blob = this.getDataValue('script') + return blob ? blob.toString() : ''; + } } }, { timestamps: false diff --git a/webapp/package-lock.json b/webapp/package-lock.json index d14d0c9..900a449 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -2221,9 +2221,9 @@ "dev": true }, "copy-webpack-plugin": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.2.tgz", - "integrity": "sha512-zmC33E8FFSq3AbflTvqvPvBo621H36Afsxlui91d+QyZxPIuXghfnTsa1CuqiAaCPgJoSUWfTFbKJnadZpKEbQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", + "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==", "dev": true, "requires": { "cacache": "^10.0.4", @@ -6503,13 +6503,13 @@ } }, "node-notifier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", - "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.3.0.tgz", + "integrity": "sha512-AhENzCSGZnZJgBARsUjnQ7DnZbzyP+HxlVXuD0xqAnvL8q+OqtSX7lGg9e8nHzwXkMMXNdVeqq4E2M3EUAqX6Q==", "dev": true, "requires": { "growly": "^1.3.0", - "semver": "^5.4.1", + "semver": "^5.5.0", "shellwords": "^0.1.1", "which": "^1.3.0" } @@ -7005,9 +7005,9 @@ "dev": true }, "portfinder": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", - "integrity": "sha512-syFcRIRzVI1BoEFOCaAiizwDolh1S1YXSodsVhncbhjzjZQulhczNRbqnUl9N31Q4dKGOXsNDqxC2BWBgSMqeQ==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.19.tgz", + "integrity": "sha512-23aeQKW9KgHe6citUrG3r9HjeX6vls0h713TAa+CwTKZwNIr/pD2ApaxYF4Um3ZZyq4ar+Siv3+fhoHaIwSOSw==", "dev": true, "requires": { "async": "^1.5.2", @@ -7017,7 +7017,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true } @@ -9969,9 +9969,9 @@ } }, "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, "send": { @@ -11046,9 +11046,9 @@ } }, "url-loader": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.1.tgz", - "integrity": "sha512-vugEeXjyYFBCUOpX+ZuaunbK3QXMKaQ3zUnRfIpRBlGkY7QizCnzyyn2ASfcxsvyU3ef+CJppVywnl3Kgf13Gg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", "dev": true, "requires": { "loader-utils": "^1.1.0", @@ -11057,9 +11057,9 @@ }, "dependencies": { "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", + "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -11323,9 +11323,9 @@ } }, "vue2-hammer": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vue2-hammer/-/vue2-hammer-1.0.6.tgz", - "integrity": "sha512-MfRDkMdQoEng/BRe7moIDbiMgcPqgclVD3WqNfnQ6JlKtTOyMV/X5Z8/IEySa8QGHDVDOp9fI3WmwEoKxnZQ3g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/vue2-hammer/-/vue2-hammer-1.0.7.tgz", + "integrity": "sha512-ClD5i3MEDhITE5Jmc1ZtTx6q8wJeymv13FWXlj9iDxORfajF0N4DT7j5Q4dIwEwT4lXzYtNh739cIUUCw5UjKA==", "requires": { "hammerjs": "^2.0.8" } @@ -11339,9 +11339,9 @@ } }, "vuetify": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-1.2.3.tgz", - "integrity": "sha512-ssMsLVwth62T4usPAFbn8yk69qqBDp4VWPmlY4XiYZ7aGMPoa/sQ08BlAeG8J81y+K60bY88FZ2gquQKlGqlsg==" + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-1.3.7.tgz", + "integrity": "sha512-EXKQggY+SPTBlmzmcFcNI6h/xdZLv6vr9VBcos8+kUumftIG7HDqqtFdRVNCco4EPrQgiG5sWDm5raM07NDvBg==" }, "vuex": { "version": "3.0.1", diff --git a/webapp/package.json b/webapp/package.json index a1a3ff9..bc4513b 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -16,9 +16,9 @@ "vue-i18n": "^7.8.1", "vue-router": "^3.0.1", "vue-touch": "^2.0.0-beta.4", - "vue2-hammer": "^1.0.6", + "vue2-hammer": "^1.0.7", "vuedraggable": "^2.16.0", - "vuetify": "^1.2.3", + "vuetify": "^1.3.7", "vuex": "^3.0.1" }, "devDependencies": { @@ -34,7 +34,7 @@ "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "chalk": "^2.0.1", - "copy-webpack-plugin": "^4.5.2", + "copy-webpack-plugin": "^4.6.0", "css-loader": "^0.28.0", "eslint": "^4.15.0", "eslint-config-standard": "^10.2.1", @@ -49,18 +49,18 @@ "file-loader": "^1.1.4", "friendly-errors-webpack-plugin": "^1.6.1", "html-webpack-plugin": "^2.30.1", - "node-notifier": "^5.1.2", + "node-notifier": "^5.3.0", "optimize-css-assets-webpack-plugin": "^3.2.0", "ora": "^1.2.0", - "portfinder": "^1.0.17", + "portfinder": "^1.0.19", "postcss-import": "^11.0.0", "postcss-loader": "^2.1.6", "postcss-url": "^7.2.1", "rimraf": "^2.6.0", - "semver": "^5.5.1", + "semver": "^5.6.0", "shelljs": "^0.7.6", "uglifyjs-webpack-plugin": "^1.3.0", - "url-loader": "^1.1.1", + "url-loader": "^1.1.2", "vue-loader": "^13.7.3", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.17", diff --git a/webapp/src/components/RegistrationModule.vue b/webapp/src/components/RegistrationModule.vue new file mode 100644 index 0000000..f9b857f --- /dev/null +++ b/webapp/src/components/RegistrationModule.vue @@ -0,0 +1,137 @@ + +{ + "en": { + "hooks": "Registration hooks", + "createHook": "Create hook" + }, + "de": { + "hooks": "Registrierungs Hooks ", + "createHook": "Hook erstellen" + } +} + + + + + + + + diff --git a/webapp/src/components/RegistrationModuleDelete.vue b/webapp/src/components/RegistrationModuleDelete.vue new file mode 100644 index 0000000..002e629 --- /dev/null +++ b/webapp/src/components/RegistrationModuleDelete.vue @@ -0,0 +1,63 @@ + +{ + "en": { + "title": "Delete this hook?" + }, + "de": { + "title": "Diesen Hook löschen?" + } +} + + + + + + + + diff --git a/webapp/src/components/RegistrationModuleEdit.vue b/webapp/src/components/RegistrationModuleEdit.vue new file mode 100644 index 0000000..cc4189d --- /dev/null +++ b/webapp/src/components/RegistrationModuleEdit.vue @@ -0,0 +1,120 @@ + +{ + "en": { + "name": "Name", + "description": "Description", + "type": "Script type", + "groups": "Groups", + "script": "Script", + "titleNew": "Create hook", + "titleExisting": "Edit hook" + }, + "de": { + "name": "Name", + "description": "Beschreibung", + "type": "Skript Art", + "groups": "Gruppen", + "script": "Script", + "titleNew": "Hook erstellen", + "titleExisting": "Hook bearbeiten" + } +} + + + + + + + + diff --git a/webapp/src/config/dashboard.js b/webapp/src/config/dashboard.js index 44c894f..a092cdc 100644 --- a/webapp/src/config/dashboard.js +++ b/webapp/src/config/dashboard.js @@ -1,11 +1,13 @@ import GroupModule from '@/components/GroupModule' import ConfiguratorModule from '@/components/ConfiguratorModule' +import RegistrationModule from '@/components/RegistrationModule' import BackendModule from '@/components/BackendModule' import PermissionModule from '@/components/PermissionModule' export default [ { path: 'groups', component: GroupModule, icon: 'category' }, { path: 'configurator', component: ConfiguratorModule, icon: 'list' }, + { path: 'registration', component: RegistrationModule, icon: 'assignment' }, { path: 'backends', component: BackendModule, icon: 'cloud' }, { path: 'permissions', component: PermissionModule, icon: 'lock_open' } ] diff --git a/webapp/src/config/i18n.js b/webapp/src/config/i18n.js index 91f8a79..818f57c 100644 --- a/webapp/src/config/i18n.js +++ b/webapp/src/config/i18n.js @@ -25,6 +25,7 @@ export default { '$dashboardModules': { 'GroupModule': 'Groups / Clients', 'ConfiguratorModule': 'iPXE Configurator', + 'RegistrationModule': 'Client Registration', 'BackendModule': 'External Backends', 'PermissionModule': 'Permission Manager' } @@ -55,6 +56,7 @@ export default { '$dashboardModules': { 'GroupModule': 'Gruppen / Clienten', 'ConfiguratorModule': 'iPXE Konfigurator', + 'RegistrationModule': 'Client Registrierung', 'BackendModule': 'Externe Backends', 'PermissionModule': 'Rechteverwaltung' } diff --git a/webapp/src/config/store.js b/webapp/src/config/store.js index ca6b01f..710a07b 100644 --- a/webapp/src/config/store.js +++ b/webapp/src/config/store.js @@ -1,11 +1,13 @@ import groups from '@/store/groups' import configurator from '@/store/configurator' +import registration from '@/store/registration' import backends from '@/store/backends' import permissions from '@/store/permissions' export default { groups, configurator, + registration, backends, permissions } diff --git a/webapp/src/store/registration.js b/webapp/src/store/registration.js new file mode 100644 index 0000000..388558d --- /dev/null +++ b/webapp/src/store/registration.js @@ -0,0 +1,40 @@ +import axios from 'axios' + +export default { + namespaced: true, + state: { + hooks: [], + groupList: [], + dialog: { + show: false, + type: null, + info: {} + } + }, + mutations: { + setHooks (state, hooks) { state.hooks = hooks }, + setGroupList (state, groupList) { state.groupList = groupList }, + setDialog (state, { show, type, info }) { + if (info !== undefined) state.dialog.info = info + if (type !== undefined) state.dialog.type = type + if (show !== undefined) state.dialog.show = show + } + }, + actions: { + loadHooks (context) { + axios.get('/api/registrations/hooks').then(result => { + context.commit('setHooks', result.data) + }) + }, + loadGroupList (context) { + axios.get('/api/groups/getList').then(result => { + context.commit('setGroupList', result.data) + }) + }, + setHooks (context, hooks) { + axios.post('/api/registrations/hookorder', { ids: hooks.map(x => x.id) }).then(result => { + context.commit('setHooks', hooks) + }) + } + } +} -- cgit v1.2.3-55-g7522