From 1457bab4b1aa3bd78eb8f4d5476db65fc4e190a7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 28 Apr 2022 13:40:59 +0200 Subject: [PATCH] feat: event model ui init --- app/controllers/web/console.php | 4 +- app/views/console/webhooks/index.phtml | 125 +++++++++++++---- gulpfile.js | 1 + package-lock.json | 32 +++-- public/dist/scripts/app-all.js | 8 +- public/dist/scripts/app.js | 8 +- public/scripts/events.js | 178 +++++++++++++++++++++++++ 7 files changed, 305 insertions(+), 51 deletions(-) create mode 100644 public/scripts/events.js diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index 58bc905db..06fd839aa 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -162,9 +162,7 @@ App::get('/console/webhooks') $page = new View(__DIR__.'/../../views/console/webhooks/index.phtml'); - $page - ->setParam('events', Config::getParam('events', [])) - ; + $page->setParam('events', Config::getParam('events', [])); $layout ->setParam('title', APP_NAME.' - Webhooks') diff --git a/app/views/console/webhooks/index.phtml b/app/views/console/webhooks/index.phtml index 93bc72edd..54c9f6e76 100644 --- a/app/views/console/webhooks/index.phtml +++ b/app/views/console/webhooks/index.phtml @@ -1,8 +1,27 @@ getParam('events', [])); +$events = $this->getParam('events', []); + +foreach ($events as $name => $event) { + foreach ($event as $key => $value) { + if (!\str_starts_with($key, '$')) { + if (!($value['$resource'] ?? false)) { + $patterns[] = "{$name}.{$key}"; + } else { + foreach ($value as $key2 => $value2) { + if (!\str_starts_with($key2, '$')) { + if (!($value2['$resource'] ?? false)) { + $patterns[] = "{$key}.{$key2}"; + } + } + } + } + } + } +} ?> +

Home @@ -61,22 +80,46 @@ $events = array_keys($this->getParam('events', [])); -
- -
- $event): ?> -
- -   - +
+ + + + +
+ + +
Leave empty for wildcard access
+
+ + +
Leave empty for wildcard access
+
+
+ + +
+
@@ -99,7 +142,7 @@ $events = array_keys($this->getParam('events', [])); Learn more

- +
@@ -183,22 +226,46 @@ $events = array_keys($this->getParam('events', [])); -
- -
- $event): ?> -
- -   - +
+ + + + +
+ + +
Leave empty for wildcard access
+
+ + +
Leave empty for wildcard access
+
+
+ + +
+
@@ -221,7 +288,7 @@ $events = array_keys($this->getParam('events', [])); Learn more

- +
diff --git a/gulpfile.js b/gulpfile.js index 781f7bad4..8bd41ece4 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -34,6 +34,7 @@ const configApp = { 'public/scripts/filters.js', 'public/scripts/app.js', 'public/scripts/upload-modal.js', + 'public/scripts/events.js', 'public/scripts/views/service.js', diff --git a/package-lock.json b/package-lock.json index e3f483af6..999afa76a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2950,6 +2950,15 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "node_modules/meow/node_modules/trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -4601,18 +4610,6 @@ "xtend": "~4.0.1" } }, - "node_modules/trim-newlines": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -7490,6 +7487,12 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true } } }, @@ -8837,11 +8840,6 @@ } } }, - "trim-newlines": { - "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", diff --git a/public/dist/scripts/app-all.js b/public/dist/scripts/app-all.js index 10fd74576..7b438114e 100644 --- a/public/dist/scripts/app-all.js +++ b/public/dist/scripts/app-all.js @@ -3748,7 +3748,13 @@ let write=formData.get('write');if(write){write=JSON.parse(write);} if(this.getFile(id)){this.updateFile(id,{name:file.name,completed:false,failed:false,cancelled:false,error:"",});}else{this.addFile({id:id,name:file.name,progress:0,completed:false,failed:false,cancelled:false,error:"",});} target.reset();try{const response=await sdk.storage.createFile(bucketId,fileId,file,read,write,(progress)=>{this.updateFile(id,{id:progress.$id,progress:Math.round(progress.progress),error:"",});id=progress.$id;const file=this.getFile(id)??{};if(file.cancelled===true){throw'USER_CANCELLED';}});const existingFile=this.getFile(id)??{};if(existingFile.cancelled){this.updateFile(id,{id:response.$id,name:response.name,failed:false,});id=response.$id;throw'USER_CANCELLED'}else{this.updateFile(id,{id:response.$id,name:response.name,progress:100,completed:true,failed:false,});id=response.$id;} document.dispatchEvent(new CustomEvent('storage.createFile'));}catch(error){if(error==='USER_CANCELLED'){await sdk.storage.deleteFile(bucketId,id);this.updateFile(id,{cancelled:false,failed:true,});this.removeFile(id);}else{this.updateFile(id,{id:id,failed:true,error:error.message??error});} -document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();} +document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){document.addEventListener('alpine:init',()=>{Alpine.data('events',()=>({events:[],selected:null,action:null,type:null,subType:null,resource:null,resourceName:'',subResource:null,subResourceName:'',hasResource:false,hasSubResource:false,attribute:null,hasAttribute:false,attributes:[],setEvent(){this.hasResource=this.hasSubResource=this.hasAttribute=this.action=false;if(!event)return;let[type,action]=this.selected.split('.');switch(type){case'users':if(action==='update'){this.hasAttribute=true;this.attributes=['email','name','password','status','prefs']} +this.hasResource=true;this.type=type;this.resourceName='User ID';break;case'collections':this.hasResource=true;this.type=type;this.resourceName='Collection ID';break;case'teams':this.hasResource=true;this.type=type;this.resourceName='Team ID';break;case'buckets':this.hasResource=true;this.type=type;this.resourceName='Bucket ID';break;case'functions':this.hasResource=true;this.type=type;this.resourceName='Function ID';break;case'sessions':this.hasResource=this.hasSubResource=true;this.type='users';this.subType=type;this.resourceName='User ID';this.subResourceName='Session ID';break;case'verification':this.hasResource=this.hasSubResource=true;this.type='users';this.subType=type;this.resourceName='User ID';this.subResourceName='Verification ID';break;case'recovery':this.hasResource=this.hasSubResource=true;this.type='users';this.subType=type;this.resourceName='User ID';this.subResourceName='Recovery ID';break;case'documents':this.hasResource=this.hasSubResource=true;this.type='collections';this.subType=type;this.resourceName='Collection ID';this.subResourceName='Document ID';break;case'attributes':this.hasResource=this.hasSubResource=true;this.type='collections';this.subType=type;this.resourceName='Collection ID';this.subResourceName='Attribute ID';break;case'indexes':this.hasResource=this.hasSubResource=true;this.type='collections';this.subType=type;this.resourceName='Collection ID';this.subResourceName='Index ID';break;case'files':this.hasResource=this.hasSubResource=true;this.type='buckets';this.subType=type;this.resourceName='Bucket ID';this.subResourceName='File ID';break;case'memberships':if(action==='update'){this.hasAttribute=true;this.attributes=['status']} +this.hasResource=this.hasSubResource=true;this.type='teams';this.subType=type;this.resourceName='Team ID';this.subResourceName='Membership ID';break;case'executions':this.hasResource=this.hasSubResource=true;this.type='functions';this.subType=type;this.resourceName='Function ID';this.subResourceName='Execution ID';break;case'deployments':this.hasResource=this.hasSubResource=true;this.type='functions';this.subType=type;this.resourceName='Function ID';this.subResourceName='Deployment ID';break;default:this.hasResource=true;this.hasSubResource=true;break;} +this.action=action;},addEvent(){let event=`${this.type}.${this.resource ? this.resource : '*'}`;if(this.hasSubResource){event+=`.${this.subType}.${this.subResource ? this.subResource : '*'}`;} +if(this.action){event+=`.${this.action}`;} +if(this.attribute){event+=`.${this.attribute}`;} +this.events.push(event);this.status=[];this.hasResource=this.hasSubResource=this.hasAttribute=false;this.type=this.subType=this.subResource=this.resource=this.attribute=this.selected=this.action=null;},removeEvent(index){this.events.splice(index,1);}}));});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();} throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},6000);};},redirect:function(url){return function(router){if(url==="/console"){window.location=url;return;} router.change(url||"/");};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];} return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];} diff --git a/public/dist/scripts/app.js b/public/dist/scripts/app.js index 7240e243c..8576a3a61 100644 --- a/public/dist/scripts/app.js +++ b/public/dist/scripts/app.js @@ -695,7 +695,13 @@ let write=formData.get('write');if(write){write=JSON.parse(write);} if(this.getFile(id)){this.updateFile(id,{name:file.name,completed:false,failed:false,cancelled:false,error:"",});}else{this.addFile({id:id,name:file.name,progress:0,completed:false,failed:false,cancelled:false,error:"",});} target.reset();try{const response=await sdk.storage.createFile(bucketId,fileId,file,read,write,(progress)=>{this.updateFile(id,{id:progress.$id,progress:Math.round(progress.progress),error:"",});id=progress.$id;const file=this.getFile(id)??{};if(file.cancelled===true){throw'USER_CANCELLED';}});const existingFile=this.getFile(id)??{};if(existingFile.cancelled){this.updateFile(id,{id:response.$id,name:response.name,failed:false,});id=response.$id;throw'USER_CANCELLED'}else{this.updateFile(id,{id:response.$id,name:response.name,progress:100,completed:true,failed:false,});id=response.$id;} document.dispatchEvent(new CustomEvent('storage.createFile'));}catch(error){if(error==='USER_CANCELLED'){await sdk.storage.deleteFile(bucketId,id);this.updateFile(id,{cancelled:false,failed:true,});this.removeFile(id);}else{this.updateFile(id,{id:id,failed:true,error:error.message??error});} -document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();} +document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){document.addEventListener('alpine:init',()=>{Alpine.data('events',()=>({events:[],selected:null,action:null,type:null,subType:null,resource:null,resourceName:'',subResource:null,subResourceName:'',hasResource:false,hasSubResource:false,attribute:null,hasAttribute:false,attributes:[],setEvent(){this.hasResource=this.hasSubResource=this.hasAttribute=this.action=false;if(!event)return;let[type,action]=this.selected.split('.');switch(type){case'users':if(action==='update'){this.hasAttribute=true;this.attributes=['email','name','password','status','prefs']} +this.hasResource=true;this.type=type;this.resourceName='User ID';break;case'collections':this.hasResource=true;this.type=type;this.resourceName='Collection ID';break;case'teams':this.hasResource=true;this.type=type;this.resourceName='Team ID';break;case'buckets':this.hasResource=true;this.type=type;this.resourceName='Bucket ID';break;case'functions':this.hasResource=true;this.type=type;this.resourceName='Function ID';break;case'sessions':this.hasResource=this.hasSubResource=true;this.type='users';this.subType=type;this.resourceName='User ID';this.subResourceName='Session ID';break;case'verification':this.hasResource=this.hasSubResource=true;this.type='users';this.subType=type;this.resourceName='User ID';this.subResourceName='Verification ID';break;case'recovery':this.hasResource=this.hasSubResource=true;this.type='users';this.subType=type;this.resourceName='User ID';this.subResourceName='Recovery ID';break;case'documents':this.hasResource=this.hasSubResource=true;this.type='collections';this.subType=type;this.resourceName='Collection ID';this.subResourceName='Document ID';break;case'attributes':this.hasResource=this.hasSubResource=true;this.type='collections';this.subType=type;this.resourceName='Collection ID';this.subResourceName='Attribute ID';break;case'indexes':this.hasResource=this.hasSubResource=true;this.type='collections';this.subType=type;this.resourceName='Collection ID';this.subResourceName='Index ID';break;case'files':this.hasResource=this.hasSubResource=true;this.type='buckets';this.subType=type;this.resourceName='Bucket ID';this.subResourceName='File ID';break;case'memberships':if(action==='update'){this.hasAttribute=true;this.attributes=['status']} +this.hasResource=this.hasSubResource=true;this.type='teams';this.subType=type;this.resourceName='Team ID';this.subResourceName='Membership ID';break;case'executions':this.hasResource=this.hasSubResource=true;this.type='functions';this.subType=type;this.resourceName='Function ID';this.subResourceName='Execution ID';break;case'deployments':this.hasResource=this.hasSubResource=true;this.type='functions';this.subType=type;this.resourceName='Function ID';this.subResourceName='Deployment ID';break;default:this.hasResource=true;this.hasSubResource=true;break;} +this.action=action;},addEvent(){let event=`${this.type}.${this.resource ? this.resource : '*'}`;if(this.hasSubResource){event+=`.${this.subType}.${this.subResource ? this.subResource : '*'}`;} +if(this.action){event+=`.${this.action}`;} +if(this.attribute){event+=`.${this.attribute}`;} +this.events.push(event);this.status=[];this.hasResource=this.hasSubResource=this.hasAttribute=false;this.type=this.subType=this.subResource=this.resource=this.attribute=this.selected=this.action=null;},removeEvent(index){this.events.splice(index,1);}}));});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();} throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},6000);};},redirect:function(url){return function(router){if(url==="/console"){window.location=url;return;} router.change(url||"/");};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];} return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];} diff --git a/public/scripts/events.js b/public/scripts/events.js new file mode 100644 index 000000000..b95a895d3 --- /dev/null +++ b/public/scripts/events.js @@ -0,0 +1,178 @@ +(function (window) { + document.addEventListener('alpine:init', () => { + Alpine.data('events', () => ({ + events: [], + selected: null, + action: null, + type: null, + subType: null, + resource: null, + resourceName: '', + subResource: null, + subResourceName: '', + hasResource: false, + hasSubResource: false, + attribute: null, + hasAttribute: false, + attributes: [], + setEvent() { + this.hasResource = this.hasSubResource = this.hasAttribute = this.action = false; + + if (!event) return; + + let [type, action] = this.selected.split('.'); + + switch (type) { + case 'users': + if (action === 'update') { + this.hasAttribute = true; + this.attributes = ['email', 'name', 'password', 'status', 'prefs'] + } + this.hasResource = true; + this.type = type; + this.resourceName = 'User ID'; + break; + + case 'collections': + this.hasResource = true; + this.type = type; + this.resourceName = 'Collection ID'; + break; + + case 'teams': + this.hasResource = true; + this.type = type; + this.resourceName = 'Team ID'; + break; + + case 'buckets': + this.hasResource = true; + this.type = type; + this.resourceName = 'Bucket ID'; + break; + + case 'functions': + this.hasResource = true; + this.type = type; + this.resourceName = 'Function ID'; + break; + + case 'sessions': + this.hasResource = this.hasSubResource = true; + this.type = 'users'; + this.subType = type; + this.resourceName = 'User ID'; + this.subResourceName = 'Session ID'; + break; + + case 'verification': + this.hasResource = this.hasSubResource = true; + this.type = 'users'; + this.subType = type; + this.resourceName = 'User ID'; + this.subResourceName = 'Verification ID'; + break; + + case 'recovery': + this.hasResource = this.hasSubResource = true; + this.type = 'users'; + this.subType = type; + this.resourceName = 'User ID'; + this.subResourceName = 'Recovery ID'; + break; + + case 'documents': + this.hasResource = this.hasSubResource = true; + this.type = 'collections'; + this.subType = type; + this.resourceName = 'Collection ID'; + this.subResourceName = 'Document ID'; + break; + + case 'attributes': + this.hasResource = this.hasSubResource = true; + this.type = 'collections'; + this.subType = type; + this.resourceName = 'Collection ID'; + this.subResourceName = 'Attribute ID'; + break; + + case 'indexes': + this.hasResource = this.hasSubResource = true; + this.type = 'collections'; + this.subType = type; + this.resourceName = 'Collection ID'; + this.subResourceName = 'Index ID'; + break; + + case 'files': + this.hasResource = this.hasSubResource = true; + this.type = 'buckets'; + this.subType = type; + this.resourceName = 'Bucket ID'; + this.subResourceName = 'File ID'; + break; + + case 'memberships': + if (action === 'update') { + this.hasAttribute = true; + this.attributes = ['status'] + } + this.hasResource = this.hasSubResource = true; + this.type = 'teams'; + this.subType = type; + this.resourceName = 'Team ID'; + this.subResourceName = 'Membership ID'; + break; + + case 'executions': + this.hasResource = this.hasSubResource = true; + this.type = 'functions'; + this.subType = type; + this.resourceName = 'Function ID'; + this.subResourceName = 'Execution ID'; + break; + + case 'deployments': + this.hasResource = this.hasSubResource = true; + this.type = 'functions'; + this.subType = type; + this.resourceName = 'Function ID'; + this.subResourceName = 'Deployment ID'; + break; + + default: + this.hasResource = true; + this.hasSubResource = true; + + break; + } + this.action = action; + }, + addEvent() { + let event = `${this.type}.${this.resource ? this.resource : '*'}`; + + if (this.hasSubResource) { + event += `.${this.subType}.${this.subResource ? this.subResource : '*'}`; + } + + if (this.action) { + event += `.${this.action}`; + } + + if (this.attribute) { + event += `.${this.attribute}`; + } + + this.events.push(event); + + this.status = []; + this.hasResource = this.hasSubResource = this.hasAttribute = false; + this.type = this.subType = this.subResource = this.resource = this.attribute = this.selected = this.action = null; + }, + removeEvent(index) { + this.events.splice(index, 1); + } + })); + }); +})(window); \ No newline at end of file