From ee93c650d9d0f09a442e5e1c1ce1d90db4cb5e02 Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Thu, 25 Jan 2024 14:51:46 +0100 Subject: [PATCH 01/19] bump packages --- client/package.json | 2 +- server/package.json | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/client/package.json b/client/package.json index 010d7a08..6f73767e 100644 --- a/client/package.json +++ b/client/package.json @@ -14,7 +14,7 @@ "dependencies": { "core-js": "~3.34.0", "vue": "~2.7.15", - "axios": "~1.6.2", + "axios": "~1.6.6", "es6-promise": "~4.2.8", "vuelidate": "~0.7.7", "vue-router": "~3.5.4", diff --git a/server/package.json b/server/package.json index 5a6be612..9cca1046 100644 --- a/server/package.json +++ b/server/package.json @@ -17,8 +17,8 @@ "clean": "rimraf dist" }, "dependencies": { - "core-js": "~3.34.0", - "axios": "~1.6.2", + "core-js": "~3.35.1", + "axios": "~1.6.6", "cors": "~2.8.5", "bcrypt": "~5.1.0", "cheerio": "~1.0.0-rc.12", @@ -33,17 +33,17 @@ "modern-passport-http": "~0.3.0", "passport-jwt": "~4.0.1", "@outlinewiki/passport-azure-ad-oauth2": "~0.1.0", - "mysql2": "~3.6.5", + "mysql2": "~3.8.0", "ajv": "~6.12.6", "ajv-error-parser": "~1.0.7", "lodash": "~4.17.21", "bluebird": "~3.7.2", - "node-jq": "~4.2.2", - "moment": "~2.29.4", + "node-jq": "~4.3.0", + "moment": "~2.30.1", "yaml": "~2.3.4", "cert-info":"~1.5.1", "thenby":"~1.3.4", - "mssql":"~10.0.1", + "mssql":"~10.0.2", "mongodb":"~6.3.0", "pg":"~8.11.3", "ip":"1.1.8", @@ -54,18 +54,18 @@ "ldapjs": "~3.0.7", "read-last-lines": "~1.8.0", "swagger-ui-express": "~5.0.0", - "nodemailer": "~6.9.7", + "nodemailer": "~6.9.8", "cron-parser": "~4.9.0" }, "devDependencies": { - "@babel/core": "7.23.6", + "@babel/core": "7.23.7", "@babel/cli": "~7.23.4", "@babel/node": "~7.22.19", "@babel/eslint-parser": "7.23.3", - "nodemon": "~3.0.2", + "nodemon": "~3.0.3", "rifraf": "~2.0.3", "npm-run-all": "*", - "dotenv": "~16.3.1", + "dotenv": "~16.4.1", "eslint": "~8.56.0" }, "eslintConfig": { From e9855c23648c107ea833a02119cb6c2dcd90c772 Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 13:48:00 +0100 Subject: [PATCH 02/19] fix ldap and mail attr --- client/src/views/Ldap.vue | 5 +++++ client/src/views/Login.vue | 15 ++++++++------- server/src/controllers/login.controller.js | 2 +- server/src/db/create_schema_and_tables.sql | 10 +++++++++- server/src/lib/ldap-authentication.js | 17 ++++++++++++++++- server/src/models/ldap.model.js | 1 + server/src/models/schema.model.js | 13 ++++++++----- 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/client/src/views/Ldap.vue b/client/src/views/Ldap.vue index 2397d59a..4e3a1db4 100644 --- a/client/src/views/Ldap.vue +++ b/client/src/views/Ldap.vue @@ -25,6 +25,7 @@ + @@ -79,6 +80,7 @@ groups_search_base: "", group_class: "", group_member_attribute: "", + mail_attribute: "", group_member_user_attribute: "", cert:"", ca_bundle:"", @@ -150,6 +152,9 @@ groups_attribute:{ required }, + mail_attribute:{ + required + }, cert:{ requiredIf:requiredIf(function(ldap){ return ldap.enable_tls && !ldap.ignore_certs diff --git a/client/src/views/Login.vue b/client/src/views/Login.vue index 74c883b5..35d0b33d 100644 --- a/client/src/views/Login.vue +++ b/client/src/views/Login.vue @@ -15,7 +15,7 @@ @@ -45,6 +45,7 @@ username: "", password: "" }, + baseUrl:"/", azureAdEnabled:false, azureGroupfilter:"", azureGraphUrl:"https://graph.microsoft.com" @@ -53,7 +54,7 @@ methods: { getSettings(azuretoken){ var ref=this - axios.get(`${process.env.BASE_URL}api/v1/auth/settings`) + axios.get(`${ref.baseUrl}api/v1/auth/settings`) .then((result)=>{ if(result.data?.status=='success'){ this.azureAdEnabled=!!result.data.data.output.azureAdEnabled @@ -100,7 +101,7 @@ console.log("Groups have been filtered") } // No more nextLink, you have all the groups - axios.post(`${process.env.BASE_URL}api/v1/auth/azureadoauth2/login`, { azuretoken, groups:allGroups }) + axios.post(`${ref.baseUrl}api/v1/auth/azureadoauth2/login`, { azuretoken, groups:allGroups }) .then((result) => { if (result.data.token) { TokenStorage.storeToken(result.data.token); @@ -121,14 +122,14 @@ }); }, login() { - + var ref=this if (!this.$v.user.$invalid) { console.log("Logging in") - var basicAuth = 'Basic ' + btoa(this.user.username + ':' + this.user.password); + var basicAuth = 'Basic ' + new Buffer(this.user.username + ':' + this.user.password).toString('base64') var postconfig={ headers:{'Authorization':basicAuth} } - axios.post(`${process.env.BASE_URL}api/v1/auth/login`,{},postconfig) + axios.post(`${ref.baseUrl}api/v1/auth/login`,{},postconfig) .then((result)=>{ if(result.data.token){ console.log("Login success, storing tokens") @@ -158,7 +159,7 @@ }, mounted(){ - + this.baseUrl = process.env.BASE_URL if(this.$route.query.azuretoken){ this.loading=true this.getSettings(this.$route.query.azuretoken) diff --git a/server/src/controllers/login.controller.js b/server/src/controllers/login.controller.js index 6550bfad..545156f2 100644 --- a/server/src/controllers/login.controller.js +++ b/server/src/controllers/login.controller.js @@ -83,7 +83,7 @@ exports.basic = async function(req, res,next) { } // send the tokens to the requester // if admin role, you can override the expirydays (for accesstoken only) - if(req.query.expiryDays && user?.roles?.includes("admin") && !isNan(req.query.expiryDays)){ + if(req.query.expiryDays && user?.roles?.includes("admin") && !isNaN(req.query.expiryDays)){ return res.json(userToJwt(user,`${req.query.expiryDays}D`)) } return res.json(userToJwt(user)); diff --git a/server/src/db/create_schema_and_tables.sql b/server/src/db/create_schema_and_tables.sql index b086117b..cdece659 100644 --- a/server/src/db/create_schema_and_tables.sql +++ b/server/src/db/create_schema_and_tables.sql @@ -13,6 +13,7 @@ CREATE TABLE `users`( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, `group_id` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_AnsibleForms_users_natural_key` (`username`), @@ -54,6 +55,13 @@ CREATE TABLE `ldap` ( `bind_user_pw` text DEFAULT NULL, `search_base` varchar(250) DEFAULT NULL, `username_attribute` varchar(250) DEFAULT NULL, + `groups_search_base` varchar(250) DEFAULT NULL, + `groups_attribute` varchar(250) DEFAULT NULL, + `group_class` varchar(250) DEFAULT NULL, + `group_member_attribute` varchar(250) DEFAULT NULL, + `group_member_user_attribute` varchar(250) DEFAULT NULL, + `is_advanced` tinyint(4) DEFAULT NULL, + `mail_attribute` varchar(250) DEFAULT NULL, `enable` tinyint(4) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `awx`; @@ -117,7 +125,7 @@ CREATE TABLE `azuread` ( INSERT INTO AnsibleForms.azuread(client_id,secret_id,enable) VALUES('','',0); INSERT INTO AnsibleForms.groups(name) VALUES('admins'); INSERT INTO AnsibleForms.awx(uri,token,username,password) VALUES('','','',''); -INSERT INTO AnsibleForms.users(username,password,group_id) VALUES('admin','$2b$10$Z/W0HXNBk2aLR4yVLkq5L..C8tXg.G.o1vkFr8D2lw8JSgWRCNiCa',1); +INSERT INTO AnsibleForms.users(username,password,email,group_id) VALUES('admin','$2b$10$Z/W0HXNBk2aLR4yVLkq5L..C8tXg.G.o1vkFr8D2lw8JSgWRCNiCa','',1); INSERT INTO AnsibleForms.ldap(server,port,ignore_certs,enable_tls,cert,ca_bundle,bind_user_dn,bind_user_pw,search_base,username_attribute,enable) VALUES('',389,1,0,'','','','','','sAMAccountName',0); INSERT INTO AnsibleForms.settings(mail_server,mail_port,mail_secure,mail_username,mail_password,mail_from,url) VALUES('',25,0,'','','',''); SET FOREIGN_KEY_CHECKS=1; diff --git a/server/src/lib/ldap-authentication.js b/server/src/lib/ldap-authentication.js index d2c26dd9..0775fff3 100644 --- a/server/src/lib/ldap-authentication.js +++ b/server/src/lib/ldap-authentication.js @@ -4,6 +4,20 @@ const ldap = require('ldapjs') // convert a SearchResultEntry object in ldapjs 3.0 // to a user object to maintain backward compatibility +// added by Mirko for 5.0.1 => ΓΌ in results +function unescapeLdapResult(ldapResult) { + // Regular expression to match the escaped sequences + const regex = /\\([0-9a-fA-F]{2})\\([0-9a-fA-F]{2})/g; + + // Replace each escaped sequence with its Unicode character + return ldapResult.replace(regex, (match, p1, p2) => { + // Convert the hex codes to a Buffer + const bytes = Buffer.from([parseInt(p1, 16), parseInt(p2, 16)]); + // Convert the Buffer to a UTF-8 String + return bytes.toString('utf8'); + }); +} + function _searchResultToUser(pojo) { assert(pojo.type == 'SearchResultEntry') let user = { dn: pojo.objectName } @@ -85,7 +99,7 @@ async function _searchUser( let searchOptions = { filter: filter, scope: 'sub', - attributes: attributes, + attributes: attributes } if (attributes) { searchOptions.attributes = attributes @@ -212,6 +226,7 @@ async function authenticateWithAdmin( ) } var userDn = user.dn + userDn = unescapeLdapResult(userDn) let ldapUserClient try { ldapUserClient = await _ldapBind(userDn, userPassword, starttls, ldapOpts) diff --git a/server/src/models/ldap.model.js b/server/src/models/ldap.model.js index 42a9da68..14749b40 100644 --- a/server/src/models/ldap.model.js +++ b/server/src/models/ldap.model.js @@ -24,6 +24,7 @@ var Ldap=function(ldap){ this.group_class = (ldap.is_advanced)?ldap.group_class:"" this.group_member_attribute = (ldap.is_advanced)?ldap.group_member_attribute:"" this.group_member_user_attribute = (ldap.is_advanced)?ldap.group_member_user_attribute:"" + this.mail_attribute = ldap.mail_attribute }; Ldap.update = function (record) { logger.info(`Updating ldap ${record.server}`) diff --git a/server/src/models/schema.model.js b/server/src/models/schema.model.js index 5f4e827d..c3fecd66 100644 --- a/server/src/models/schema.model.js +++ b/server/src/models/schema.model.js @@ -266,12 +266,15 @@ function patchAll(){ tablePromises.push(setUtf8mb4CharacterSet("jobs","approval","longtext")) // allow emoticon or utf16 character tablePromises.push(setUtf8mb4CharacterSet("job_output","output","longtext")) // allow emoticon or utf16 character // patches to db for v4.0.20 - tablePromises.push(addColumn("ldap","groups_search_base","varchar(255)",true,"NULL")) // add column to have groups search base - tablePromises.push(addColumn("ldap","groups_attribute","varchar(255)",false,"'memberOf'")) // add column to have groups attribute - tablePromises.push(addColumn("ldap","group_class","varchar(255)",true,"NULL")) // add column to have group class - tablePromises.push(addColumn("ldap","group_member_attribute","varchar(255)",true,"NULL")) // add column to have group member attribute - tablePromises.push(addColumn("ldap","group_member_user_attribute","varchar(255)",true,"NULL")) // add column to have group member user attribute + tablePromises.push(addColumn("ldap","groups_search_base","varchar(250)",true,"NULL")) // add column to have groups search base + tablePromises.push(addColumn("ldap","groups_attribute","varchar(250)",false,"'memberOf'")) // add column to have groups attribute + tablePromises.push(addColumn("ldap","group_class","varchar(250)",true,"NULL")) // add column to have group class + tablePromises.push(addColumn("ldap","group_member_attribute","varchar(250)",true,"NULL")) // add column to have group member attribute + tablePromises.push(addColumn("ldap","group_member_user_attribute","varchar(250)",true,"NULL")) // add column to have group member user attribute tablePromises.push(addColumn("ldap","is_advanced","tinyint(4)",true,"0")) // is advanced config + // patches to db for v5.0.1 + tablePromises.push(addColumn("ldap","mail_attribute","varchar(250)",true,"NULL")) // add column to have mail attribute + tablePromises.push(addColumn("users","email","varchar(250)",true,"NULL")) // add column to have email buffer = fs.readFileSync(`${__dirname}/../db/create_settings_table.sql`) sql = buffer.toString() tablePromises.push(addTable("settings",sql)) // add settings table From 29d52a803c5c2e98784e42b2f516afc122ed897c Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 13:48:24 +0100 Subject: [PATCH 03/19] versions --- CHANGELOG.md | 10 ++++++++++ client/package.json | 2 +- server/package.json | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc0268d4..de18cf99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- login expiryDays didn't work +- fixed non-ascii codes in ldap +- fixed approvals, broken since 4.0.19 + +### Added +- add a form-reload route +- added mail attribute ldap + ## [5.0.0] - 2024-01-25 ### Added diff --git a/client/package.json b/client/package.json index 6f73767e..6fb97836 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "ansible_forms_vue", - "version": "5.0.0", + "version": "5.0.1", "private": true, "scripts": { "serve": "vue-cli-service serve", diff --git a/server/package.json b/server/package.json index 9cca1046..ed13fb22 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "ansible_forms", - "version": "5.0.0", + "version": "5.0.1", "repository": { "type": "git", "url": "git://github.com/ansibleguy76/ansibleforms.git" From 9d5d8d450ac0bd93cd81a4f94980bac1a77c9ce9 Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 14:05:28 +0100 Subject: [PATCH 04/19] dotenv --- client/vue.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/vue.config.js b/client/vue.config.js index dbfd4d46..690c9ccd 100644 --- a/client/vue.config.js +++ b/client/vue.config.js @@ -3,6 +3,7 @@ /** * @type {import('@vue/cli-service').ProjectOptions} */ + require("dotenv").config() const configureAPI = require('./../server/src/configure') const appConfig = require('./../server/config/app.config') From d15359604e4b4e40d152624cd7a274cfa756464d Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 14:06:05 +0100 Subject: [PATCH 05/19] fix form reload --- client/src/components/Form.vue | 103 +++++++++++++++++--------------- client/src/views/FormReload.vue | 20 +++++++ 2 files changed, 74 insertions(+), 49 deletions(-) create mode 100644 client/src/views/FormReload.vue diff --git a/client/src/components/Form.vue b/client/src/components/Form.vue index 810425ff..d6197632 100644 --- a/client/src/components/Form.vue +++ b/client/src/components/Form.vue @@ -1839,58 +1839,63 @@ generateJsonOutput(filedata={}){ var ref=this var formdata={} - this.currentForm.fields.forEach((item, i) => { - // this.checkDependencies(item) // hide field based on dependency - if(this.visibility[item.name] && !item.noOutput){ - var fieldmodel = [].concat(item.model || []) - var outputObject = item.outputObject || item.type=="expression" || item.type=="file" || item.type=="table" || false - var outputValue = undefined - // if uploaded file info, use that - if(item.name in filedata){ - outputValue=filedata[item.name] - // else just use the formdata - }else{ - // deep clone, otherwise weird effects - outputValue = Helpers.deepClone(this.form[item.name]) - } - // if no model is given, we assign to the root - if(!outputObject){ // do we need to flatten output ? - outputValue=this.getFieldValue(outputValue,item.valueColumn || "",true) - } - if(fieldmodel.length==0){ - // deep clone = otherwise weird effects - formdata[item.name]=Helpers.deepClone(outputValue) - }else{ - fieldmodel.forEach((f)=>{ - // convert fieldmodel for actual object - // svm.lif.name => svm["lif"].name = formvalue - // using reduce, which is a recursive function - f.split(/\s*\.\s*/).reduce((master,obj, level,arr) => { - // if last - - if (level === (arr.length - 1)){ - // the last piece we assign the value to - if(master[obj]===undefined){ - master[obj]=outputValue - }else{ - master[obj]=Lodash.merge(master[obj],outputValue) - } - - }else{ - // initialize first time to object - if(master[obj]===undefined){ - master[obj]={} - } - } - // return the result for next reduce iteration - return master[obj] + try{ + this.currentForm.fields.forEach((item, i) => { + // this.checkDependencies(item) // hide field based on dependency + if(this.visibility[item.name] && !item.noOutput){ + var fieldmodel = [].concat(item.model || []) + var outputObject = item.outputObject || item.type=="expression" || item.type=="file" || item.type=="table" || false + var outputValue = undefined + // if uploaded file info, use that + if(item.name in filedata){ + outputValue=filedata[item.name] + // else just use the formdata + }else{ + // deep clone, otherwise weird effects + outputValue = Helpers.deepClone(this.form[item.name]) + } + // if no model is given, we assign to the root + if(!outputObject){ // do we need to flatten output ? + outputValue=this.getFieldValue(outputValue,item.valueColumn || "",true) + } + if(fieldmodel.length==0){ + // deep clone = otherwise weird effects + formdata[item.name]=Helpers.deepClone(outputValue) + }else{ + fieldmodel.forEach((f)=>{ + // convert fieldmodel for actual object + // svm.lif.name => svm["lif"].name = formvalue + // using reduce, which is a recursive function + f.split(/\s*\.\s*/).reduce((master,obj, level,arr) => { + // if last + + if (level === (arr.length - 1)){ + // the last piece we assign the value to + if(master[obj]===undefined){ + master[obj]=outputValue + }else{ + master[obj]=Lodash.merge(master[obj],outputValue) + } + + }else{ + // initialize first time to object + if(master[obj]===undefined){ + master[obj]={} + } + } + // return the result for next reduce iteration + return master[obj] - },formdata); - }) + },formdata); + }) + } } - } - }); + }); + }catch(err){ + console.log(err) + ref.$toast.error("Failed to generate json output.\r\nContact the developer.\r\n" + (err.message || err.toString())) + } // update main data Vue.set(this,"formdata",formdata) }, diff --git a/client/src/views/FormReload.vue b/client/src/views/FormReload.vue new file mode 100644 index 00000000..6181d9ed --- /dev/null +++ b/client/src/views/FormReload.vue @@ -0,0 +1,20 @@ + + + From 479444b212316a73025cf563366e8321eee0da40 Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 14:06:24 +0100 Subject: [PATCH 06/19] form reload --- client/src/router.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/router.js b/client/src/router.js index d9cdf4be..3dba4521 100644 --- a/client/src/router.js +++ b/client/src/router.js @@ -2,6 +2,7 @@ import Vue from 'vue' import Router from 'vue-router' import Forms from './views/Forms.vue' import Form from './views/Form.vue' +import FormReload from './views/FormReload.vue' import Login from './views/Login.vue' import ErrorVue from './views/Error.vue' import Schema from './views/Schema.vue' @@ -60,6 +61,10 @@ export default new Router({ name:"Form", component:Form }, + { + path: '/form-reload', + component:FormReload + }, { path:"/login", name:"Login", From 2bd3e8033f2406933a6a51d6eff8d66bd9d51dcd Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 14:07:14 +0100 Subject: [PATCH 07/19] fix approvals --- server/src/models/job.model.js | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/server/src/models/job.model.js b/server/src/models/job.model.js index f9f764c7..2e309d30 100644 --- a/server/src/models/job.model.js +++ b/server/src/models/job.model.js @@ -871,16 +871,7 @@ Ansible.launch=async (ev,credentials,jobid,counter,approval,approved=false)=>{ }else{ counter++ } - if(approval){ - if(!approved){ - await Job.sendApprovalNotification(approval,ev,jobid) - await Job.printJobOutput(`APPROVE [${playbook}] ${'*'.repeat(69-playbook.length)}`,"stdout",jobid,++counter) - await Job.update({status:"approve",approval:JSON.stringify(approval),end:moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')},jobid) - return true - }else{ - logger.notice("Continuing ansible " + playbook + " it has been approved") - } - } + // we make a copy, we don't want to mutate the original var extravars={...ev} // ansible can have multiple inventories @@ -907,7 +898,16 @@ Ansible.launch=async (ev,credentials,jobid,counter,approval,approved=false)=>{ var keepExtravars = extravars?.__keepExtravars__ || false var diff = extravars?.__diff__ || false var ansibleCredentials = extravars?.__ansibleCredentials__ || "" - + if(approval){ + if(!approved){ + await Job.sendApprovalNotification(approval,ev,jobid) + await Job.printJobOutput(`APPROVE [${playbook}] ${'*'.repeat(69-playbook.length)}`,"stdout",jobid,++counter) + await Job.update({status:"approve",approval:JSON.stringify(approval),end:moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')},jobid) + return true + }else{ + logger.notice("Continuing ansible " + playbook + " it has been approved") + } + } // merge credentials now extravars = {...extravars,...credentials} // convert to string for the command @@ -997,16 +997,7 @@ Awx.launch = async function (ev,credentials,jobid,counter,approval,approved=fals }else{ counter++ } - if(approval){ - if(!approved){ - await Job.sendApprovalNotification(approval,ev,jobid) - await Job.printJobOutput(`APPROVE [${template}] ${'*'.repeat(69-template.length)}`,"stdout",jobid,++counter) - await Job.update({status:"approve",approval:JSON.stringify(approval),end:moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')},jobid) - return true - }else{ - logger.notice("Continuing awx " + template + " it has been approved") - } - } + // we make a copy, we don't mutate the original var extravars={...ev} @@ -1021,7 +1012,16 @@ Awx.launch = async function (ev,credentials,jobid,counter,approval,approved=fals var diff = extravars?.__diff__ || false var template = extravars?.__template__ var awxCredentials = extravars?.__awxCredentials__ || [] - + if(approval){ + if(!approved){ + await Job.sendApprovalNotification(approval,ev,jobid) + await Job.printJobOutput(`APPROVE [${template}] ${'*'.repeat(69-template.length)}`,"stdout",jobid,++counter) + await Job.update({status:"approve",approval:JSON.stringify(approval),end:moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')},jobid) + return true + }else{ + logger.notice("Continuing awx " + template + " it has been approved") + } + } try{ const jobTemplate = await Awx.findJobTemplateByName(template) logger.debug("Found jobtemplate, id = " + jobTemplate.id) From d43cc60575e73908f5971e5a8856f986d56398e0 Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 14:07:25 +0100 Subject: [PATCH 08/19] version bump --- server/src/swagger.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/swagger.json b/server/src/swagger.json index c2ade4a7..44e723ea 100644 --- a/server/src/swagger.json +++ b/server/src/swagger.json @@ -2,7 +2,7 @@ "swagger": "2.0", "info": { "description": "This is the swagger interface for AnsibleForms.\r\nUse the `/auth/login` api with basic authentication to obtain a JWT token.\r\nThen use the access token, prefixed with the word '**Bearer**' to use all other api's.\r\nNote that the access token is limited in time. You can then either login again and get a new set of tokens or use the `/token` api and the refresh token to obtain a new set (preferred).", - "version": "5.0.0", + "version": "5.0.1", "title": "AnsibleForms", "contact": { "email": "info@ansibleforms.com" From 253cc74d6b62e9f33d60f73243a7160321036593 Mon Sep 17 00:00:00 2001 From: Mirko Van Colen Date: Fri, 9 Feb 2024 14:07:47 +0100 Subject: [PATCH 09/19] add email --- client/src/views/Users.vue | 6 ++++++ server/src/lib/common.js | 1 + server/src/models/user.model.js | 7 +++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/client/src/views/Users.vue b/client/src/views/Users.vue index 3f2db4c0..832f434d 100644 --- a/client/src/views/Users.vue +++ b/client/src/views/Users.vue @@ -38,6 +38,7 @@