Basic system autuomation, mail processing
This commit is contained in:
@@ -1103,7 +1103,8 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"title": "Permissions",
|
||||
"parameters": {},
|
||||
"entrypoint": "permissions",
|
||||
@@ -1200,5 +1201,385 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Automation scripts",
|
||||
"entrypoint": "automation_script",
|
||||
"path": "/automation/script",
|
||||
"authentication": [
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
|
||||
"struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation"
|
||||
]
|
||||
}
|
||||
],
|
||||
"apis": [
|
||||
{
|
||||
"name": "list",
|
||||
"method": "GET",
|
||||
"title": "List/read automation script",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "query",
|
||||
"required": false,
|
||||
"title": "Search query to match against automation script",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "resource",
|
||||
"required": false,
|
||||
"title": "Limit by resource (via trigger)",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "incDeleted",
|
||||
"required": false,
|
||||
"title": "Include deleted scripts",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"type": "uint",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"type": "uint",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "create",
|
||||
"method": "POST",
|
||||
"title": "Add new automation script",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "name",
|
||||
"title": "automation name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "sourceRef",
|
||||
"title": "Source URL",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"title": "Source code",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "runAs",
|
||||
"title": "Run as specific user",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"name": "timeout",
|
||||
"title": "Script timeout (in milliseconds)",
|
||||
"type": "uint"
|
||||
},
|
||||
{
|
||||
"name": "critical",
|
||||
"title": "Is it critical to run this script successfully",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "async",
|
||||
"title": "Will this script be ran asynchronously",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "triggers",
|
||||
"type": "automation.TriggerSet"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"method": "GET",
|
||||
"title": "Read automation script by ID",
|
||||
"path": "/{scriptID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "automation script ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "update",
|
||||
"method": "POST",
|
||||
"title": "Update automation script",
|
||||
"path": "/{scriptID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "Automation script ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "name",
|
||||
"title": "Script name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "sourceRef",
|
||||
"title": "Source URL",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"title": "Source code",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "runAs",
|
||||
"title": "Run script as specific user",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"name": "timeout",
|
||||
"title": "Run script in user-agent (browser)",
|
||||
"type": "uint"
|
||||
},
|
||||
{
|
||||
"name": "critical",
|
||||
"title": "Is it critical to run this script successfully",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "async",
|
||||
"title": "Will this script be ran asynchronously",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "triggers",
|
||||
"type": "automation.TriggerSet"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "delete",
|
||||
"method": "DELETE",
|
||||
"title": "Delete script",
|
||||
"path": "/{scriptID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "Script ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test",
|
||||
"method": "POST",
|
||||
"title": "Run source code in corredor. Used for testing",
|
||||
"path": "/test",
|
||||
"parameters": {
|
||||
"post": [
|
||||
{"name": "source", "type": "string", "title": "Script's source code"},
|
||||
{"name": "payload", "type": "json.RawMessage", "title": "Payload to be used"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Automation script triggers",
|
||||
"entrypoint": "automation_trigger",
|
||||
"path": "/automation/script/{scriptID}/trigger",
|
||||
"authentication": [
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "Script ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
"apis": [
|
||||
{
|
||||
"name": "list",
|
||||
"method": "GET",
|
||||
"title": "List/read automation script triggers",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "resource",
|
||||
"required": false,
|
||||
"title": "Only triggers of a specific resource",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"required": false,
|
||||
"title": "Only triggers of a specific event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "incDeleted",
|
||||
"required": false,
|
||||
"title": "Include deleted scripts",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"type": "uint",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"type": "uint",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "create",
|
||||
"method": "POST",
|
||||
"title": "Add new automation script trigger",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "resource",
|
||||
"title": "Resource",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"title": "Event",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "condition",
|
||||
"title": "Event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"method": "GET",
|
||||
"title": "Read automation script trigger by ID",
|
||||
"path": "/{triggerID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "triggerID",
|
||||
"required": true,
|
||||
"title": "Automation script trigger ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "update",
|
||||
"method": "POST",
|
||||
"title": "Update automation script trigger",
|
||||
"path": "/{triggerID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "triggerID",
|
||||
"required": true,
|
||||
"title": "Automation script trigger ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "resource",
|
||||
"title": "Resource",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"title": "Event",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "condition",
|
||||
"title": "Event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "delete",
|
||||
"method": "DELETE",
|
||||
"title": "Delete script",
|
||||
"path": "/{triggerID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "triggerID",
|
||||
"required": true,
|
||||
"title": "Automation script trigger ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
226
api/system/spec/automation_script.json
Normal file
226
api/system/spec/automation_script.json
Normal file
@@ -0,0 +1,226 @@
|
||||
{
|
||||
"Title": "Automation scripts",
|
||||
"Interface": "Automation_script",
|
||||
"Struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation"
|
||||
]
|
||||
}
|
||||
],
|
||||
"Parameters": null,
|
||||
"Protocol": "",
|
||||
"Authentication": [
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
"Path": "/automation/script",
|
||||
"APIs": [
|
||||
{
|
||||
"Name": "list",
|
||||
"Method": "GET",
|
||||
"Title": "List/read automation script",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "query",
|
||||
"required": false,
|
||||
"title": "Search query to match against automation script",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "resource",
|
||||
"required": false,
|
||||
"title": "Limit by resource (via trigger)",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "incDeleted",
|
||||
"required": false,
|
||||
"title": "Include deleted scripts",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)",
|
||||
"type": "uint"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)",
|
||||
"type": "uint"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "create",
|
||||
"Method": "POST",
|
||||
"Title": "Add new automation script",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "name",
|
||||
"title": "automation name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "sourceRef",
|
||||
"title": "Source URL",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"title": "Source code",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "runAs",
|
||||
"title": "Run as specific user",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"name": "timeout",
|
||||
"title": "Script timeout (in milliseconds)",
|
||||
"type": "uint"
|
||||
},
|
||||
{
|
||||
"name": "critical",
|
||||
"title": "Is it critical to run this script successfully",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "async",
|
||||
"title": "Will this script be ran asynchronously",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "triggers",
|
||||
"type": "automation.TriggerSet"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "read",
|
||||
"Method": "GET",
|
||||
"Title": "Read automation script by ID",
|
||||
"Path": "/{scriptID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "automation script ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "update",
|
||||
"Method": "POST",
|
||||
"Title": "Update automation script",
|
||||
"Path": "/{scriptID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "Automation script ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "name",
|
||||
"title": "Script name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "sourceRef",
|
||||
"title": "Source URL",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"title": "Source code",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "runAs",
|
||||
"title": "Run script as specific user",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"name": "timeout",
|
||||
"title": "Run script in user-agent (browser)",
|
||||
"type": "uint"
|
||||
},
|
||||
{
|
||||
"name": "critical",
|
||||
"title": "Is it critical to run this script successfully",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "async",
|
||||
"title": "Will this script be ran asynchronously",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "triggers",
|
||||
"type": "automation.TriggerSet"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "delete",
|
||||
"Method": "DELETE",
|
||||
"Title": "Delete script",
|
||||
"Path": "/{scriptID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "Script ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "test",
|
||||
"Method": "POST",
|
||||
"Title": "Run source code in corredor. Used for testing",
|
||||
"Path": "/test",
|
||||
"Parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "source",
|
||||
"title": "Script's source code",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"title": "Payload to be used",
|
||||
"type": "json.RawMessage"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
165
api/system/spec/automation_trigger.json
Normal file
165
api/system/spec/automation_trigger.json
Normal file
@@ -0,0 +1,165 @@
|
||||
{
|
||||
"Title": "Automation script triggers",
|
||||
"Interface": "Automation_trigger",
|
||||
"Struct": null,
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "scriptID",
|
||||
"required": true,
|
||||
"title": "Script ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Protocol": "",
|
||||
"Authentication": [
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
"Path": "/automation/script/{scriptID}/trigger",
|
||||
"APIs": [
|
||||
{
|
||||
"Name": "list",
|
||||
"Method": "GET",
|
||||
"Title": "List/read automation script triggers",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "resource",
|
||||
"required": false,
|
||||
"title": "Only triggers of a specific resource",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"required": false,
|
||||
"title": "Only triggers of a specific event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "incDeleted",
|
||||
"required": false,
|
||||
"title": "Include deleted scripts",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)",
|
||||
"type": "uint"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)",
|
||||
"type": "uint"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "create",
|
||||
"Method": "POST",
|
||||
"Title": "Add new automation script trigger",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "resource",
|
||||
"required": true,
|
||||
"title": "Resource",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"required": true,
|
||||
"title": "Event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "condition",
|
||||
"title": "Event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "read",
|
||||
"Method": "GET",
|
||||
"Title": "Read automation script trigger by ID",
|
||||
"Path": "/{triggerID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "triggerID",
|
||||
"required": true,
|
||||
"title": "Automation script trigger ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "update",
|
||||
"Method": "POST",
|
||||
"Title": "Update automation script trigger",
|
||||
"Path": "/{triggerID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "triggerID",
|
||||
"required": true,
|
||||
"title": "Automation script trigger ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "resource",
|
||||
"required": true,
|
||||
"title": "Resource",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"required": true,
|
||||
"title": "Event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "condition",
|
||||
"title": "Event",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "delete",
|
||||
"Method": "DELETE",
|
||||
"Title": "Delete script",
|
||||
"Path": "/{triggerID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "triggerID",
|
||||
"required": true,
|
||||
"title": "Automation script trigger ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -278,6 +278,229 @@
|
||||
|
||||
|
||||
|
||||
# Automation scripts
|
||||
|
||||
| Method | Endpoint | Purpose |
|
||||
| ------ | -------- | ------- |
|
||||
| `GET` | `/automation/script/` | List/read automation script |
|
||||
| `POST` | `/automation/script/` | Add new automation script |
|
||||
| `GET` | `/automation/script/{scriptID}` | Read automation script by ID |
|
||||
| `POST` | `/automation/script/{scriptID}` | Update automation script |
|
||||
| `DELETE` | `/automation/script/{scriptID}` | Delete script |
|
||||
| `POST` | `/automation/script/test` | Run source code in corredor. Used for testing |
|
||||
|
||||
## List/read automation script
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| query | string | GET | Search query to match against automation script | N/A | NO |
|
||||
| resource | string | GET | Limit by resource (via trigger) | N/A | NO |
|
||||
| incDeleted | bool | GET | Include deleted scripts | N/A | NO |
|
||||
| page | uint | GET | Page number (0 based) | N/A | NO |
|
||||
| perPage | uint | GET | Returned items per page (default 50) | N/A | NO |
|
||||
|
||||
## Add new automation script
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| name | string | POST | automation name | N/A | NO |
|
||||
| sourceRef | string | POST | Source URL | N/A | NO |
|
||||
| source | string | POST | Source code | N/A | NO |
|
||||
| runAs | uint64 | POST | Run as specific user | N/A | NO |
|
||||
| timeout | uint | POST | Script timeout (in milliseconds) | N/A | NO |
|
||||
| critical | bool | POST | Is it critical to run this script successfully | N/A | NO |
|
||||
| async | bool | POST | Will this script be ran asynchronously | N/A | NO |
|
||||
| enabled | bool | POST | | N/A | NO |
|
||||
| triggers | automation.TriggerSet | POST | | N/A | NO |
|
||||
|
||||
## Read automation script by ID
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| scriptID | uint64 | PATH | automation script ID | N/A | YES |
|
||||
|
||||
## Update automation script
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| scriptID | uint64 | PATH | Automation script ID | N/A | YES |
|
||||
| name | string | POST | Script name | N/A | NO |
|
||||
| sourceRef | string | POST | Source URL | N/A | NO |
|
||||
| source | string | POST | Source code | N/A | NO |
|
||||
| runAs | uint64 | POST | Run script as specific user | N/A | NO |
|
||||
| timeout | uint | POST | Run script in user-agent (browser) | N/A | NO |
|
||||
| critical | bool | POST | Is it critical to run this script successfully | N/A | NO |
|
||||
| async | bool | POST | Will this script be ran asynchronously | N/A | NO |
|
||||
| enabled | bool | POST | | N/A | NO |
|
||||
| triggers | automation.TriggerSet | POST | | N/A | NO |
|
||||
|
||||
## Delete script
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}` | HTTP/S | DELETE | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| scriptID | uint64 | PATH | Script ID | N/A | YES |
|
||||
|
||||
## Run source code in corredor. Used for testing
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/test` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| source | string | POST | Script's source code | N/A | NO |
|
||||
| payload | json.RawMessage | POST | Payload to be used | N/A | NO |
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
# Automation script triggers
|
||||
|
||||
| Method | Endpoint | Purpose |
|
||||
| ------ | -------- | ------- |
|
||||
| `GET` | `/automation/script/{scriptID}/trigger/` | List/read automation script triggers |
|
||||
| `POST` | `/automation/script/{scriptID}/trigger/` | Add new automation script trigger |
|
||||
| `GET` | `/automation/script/{scriptID}/trigger/{triggerID}` | Read automation script trigger by ID |
|
||||
| `POST` | `/automation/script/{scriptID}/trigger/{triggerID}` | Update automation script trigger |
|
||||
| `DELETE` | `/automation/script/{scriptID}/trigger/{triggerID}` | Delete script |
|
||||
|
||||
## List/read automation script triggers
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}/trigger/` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| resource | string | GET | Only triggers of a specific resource | N/A | NO |
|
||||
| event | string | GET | Only triggers of a specific event | N/A | NO |
|
||||
| incDeleted | bool | GET | Include deleted scripts | N/A | NO |
|
||||
| page | uint | GET | Page number (0 based) | N/A | NO |
|
||||
| perPage | uint | GET | Returned items per page (default 50) | N/A | NO |
|
||||
| scriptID | uint64 | PATH | Script ID | N/A | YES |
|
||||
|
||||
## Add new automation script trigger
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}/trigger/` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| resource | string | POST | Resource | N/A | YES |
|
||||
| event | string | POST | Event | N/A | YES |
|
||||
| condition | string | POST | Event | N/A | NO |
|
||||
| enabled | bool | POST | | N/A | NO |
|
||||
| scriptID | uint64 | PATH | Script ID | N/A | YES |
|
||||
|
||||
## Read automation script trigger by ID
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}/trigger/{triggerID}` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| triggerID | uint64 | PATH | Automation script trigger ID | N/A | YES |
|
||||
| scriptID | uint64 | PATH | Script ID | N/A | YES |
|
||||
|
||||
## Update automation script trigger
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}/trigger/{triggerID}` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| triggerID | uint64 | PATH | Automation script trigger ID | N/A | YES |
|
||||
| scriptID | uint64 | PATH | Script ID | N/A | YES |
|
||||
| resource | string | POST | Resource | N/A | YES |
|
||||
| event | string | POST | Event | N/A | YES |
|
||||
| condition | string | POST | Event | N/A | NO |
|
||||
| enabled | bool | POST | | N/A | NO |
|
||||
|
||||
## Delete script
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/automation/script/{scriptID}/trigger/{triggerID}` | HTTP/S | DELETE | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| triggerID | uint64 | PATH | Automation script trigger ID | N/A | YES |
|
||||
| scriptID | uint64 | PATH | Script ID | N/A | YES |
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
# Organisations
|
||||
|
||||
Organisations represent a top-level grouping entity. There may be many organisations defined in a single deployment.
|
||||
|
||||
198
pkg/automation/mail/condition.go
Normal file
198
pkg/automation/mail/condition.go
Normal file
@@ -0,0 +1,198 @@
|
||||
package mail
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/mail"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
)
|
||||
|
||||
// Trigger condition:
|
||||
// Matcher for mail headers
|
||||
|
||||
type (
|
||||
Condition struct {
|
||||
MatchAll bool `json:"matchAll"`
|
||||
Headers []HeaderMatcher `json:"headers"`
|
||||
}
|
||||
|
||||
HeaderMatcher struct {
|
||||
Name HMName `json:"name"`
|
||||
Op HMOp `json:"op"`
|
||||
Match string `json:"match"`
|
||||
|
||||
// Compiled regexp
|
||||
re *regexp.Regexp
|
||||
}
|
||||
|
||||
HMName string
|
||||
HMOp string
|
||||
|
||||
userExistanceVerifier func(string) bool
|
||||
)
|
||||
|
||||
const (
|
||||
HeaderMatchNameFrom HMName = "from"
|
||||
HeaderMatchNameTo = "to"
|
||||
HeaderMatchNameCC = "cc"
|
||||
HeaderMatchNameBCC = "bcc"
|
||||
HeaderMatchNameReplyTo = "reply-to"
|
||||
HeaderMatchNameSubject = "subject"
|
||||
|
||||
HMOpEqualCi HMOp = ""
|
||||
HMOpSuffixCi = "suffix-ci"
|
||||
HMOpPrefixCi = "prefix-ci"
|
||||
HMOpRegex = "regex"
|
||||
HMOpUser = "user"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnknownHeaderMatcherName = errors.New("unknown header matcher field")
|
||||
ErrUnknownHeaderMatcherOperator = errors.New("unknown header matcher operator")
|
||||
ErrInvalidHeaderMatcherValue = errors.New("invalid header matcher value")
|
||||
)
|
||||
|
||||
func (c *Condition) Prepare() (err error) {
|
||||
for i := range c.Headers {
|
||||
err = c.Headers[i].prepare()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// IsValid verifies if header matcher is valid
|
||||
func (m *HeaderMatcher) prepare() (err error) {
|
||||
switch m.Name {
|
||||
case HeaderMatchNameFrom,
|
||||
HeaderMatchNameTo,
|
||||
HeaderMatchNameCC,
|
||||
HeaderMatchNameBCC,
|
||||
HeaderMatchNameReplyTo,
|
||||
HeaderMatchNameSubject:
|
||||
// ok fields
|
||||
default:
|
||||
return ErrUnknownHeaderMatcherName
|
||||
}
|
||||
|
||||
switch m.Op {
|
||||
case HMOpRegex:
|
||||
// Try to compile given regex
|
||||
m.re, err = regexp.Compile(m.Match)
|
||||
if err != nil {
|
||||
return ErrInvalidHeaderMatcherValue
|
||||
}
|
||||
case HMOpUser:
|
||||
// When matching against existing user,
|
||||
// there should be no value set
|
||||
if m.Match != "" {
|
||||
return ErrInvalidHeaderMatcherValue
|
||||
}
|
||||
case HMOpEqualCi, HMOpSuffixCi, HMOpPrefixCi:
|
||||
// no special validation here
|
||||
m.Match = strings.ToLower(m.Match)
|
||||
default:
|
||||
return ErrUnknownHeaderMatcherOperator
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (n HMName) match(name string) bool {
|
||||
return string(n) == strings.ToLower(name)
|
||||
}
|
||||
|
||||
// IsMatch checks if header matcher matches against given headers
|
||||
func (m *HeaderMatcher) isMatch(header mail.Header, exists userExistanceVerifier, matchAll bool) (match bool) {
|
||||
var lcHeader string
|
||||
|
||||
for name, vv := range header {
|
||||
if !m.Name.match(name) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range vv {
|
||||
lcHeader = strings.ToLower(v)
|
||||
|
||||
switch m.Op {
|
||||
case HMOpEqualCi:
|
||||
match = m.Match == lcHeader
|
||||
// spew.Dump("doing simple string match", match, m, v)
|
||||
case HMOpSuffixCi:
|
||||
match = strings.HasSuffix(lcHeader, m.Match)
|
||||
case HMOpPrefixCi:
|
||||
match = strings.HasPrefix(lcHeader, m.Match)
|
||||
case HMOpRegex:
|
||||
match = m.re.MatchString(v)
|
||||
case HMOpUser:
|
||||
match = exists(v)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
if !match && matchAll {
|
||||
// fail in first non-match
|
||||
return false
|
||||
} else if match && !matchAll {
|
||||
// match in first
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match
|
||||
}
|
||||
|
||||
func (c *Condition) CheckHeader(header mail.Header, uev userExistanceVerifier) (match bool) {
|
||||
_ = c.Prepare()
|
||||
|
||||
// Pre-process & simplify header values: parse all addresses,
|
||||
// extract emails and toss away names, we do not need them
|
||||
for name := range header {
|
||||
for i, v := range header[name] {
|
||||
switch name {
|
||||
case "from",
|
||||
"to",
|
||||
"cc",
|
||||
"bcc",
|
||||
"reply-to":
|
||||
addr, _ := mail.ParseAddress(v)
|
||||
header[name][i] = addr.Address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range c.Headers {
|
||||
match = h.isMatch(header, uev, c.MatchAll)
|
||||
|
||||
if !match && c.MatchAll {
|
||||
// fail in first non-match
|
||||
return false
|
||||
} else if match && !c.MatchAll {
|
||||
// match in first
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return match
|
||||
}
|
||||
|
||||
func MakeChecker(headers types.MailMessageHeader, uev userExistanceVerifier) automation.TriggerConditionChecker {
|
||||
return func(c string) bool {
|
||||
var (
|
||||
tc = Condition{}
|
||||
)
|
||||
|
||||
if err := json.Unmarshal([]byte(c), &tc); err == nil {
|
||||
return tc.CheckHeader(headers.Raw, uev)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package service
|
||||
package mail
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -11,45 +11,45 @@ func Test_makeMailHeaderChecker(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mh types.MailMessageHeader
|
||||
tc TriggerCondition
|
||||
tc Condition
|
||||
expecting bool
|
||||
}{
|
||||
{
|
||||
name: "empty should not match",
|
||||
mh: types.MailMessageHeader{},
|
||||
tc: TriggerCondition{},
|
||||
tc: Condition{},
|
||||
},
|
||||
{
|
||||
name: "simple check",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"Subject": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{Headers: []TriggerConditionHeaderMatcher{{Name: "Subject", Match: "SIMPLE"}}},
|
||||
tc: Condition{Headers: []HeaderMatcher{{Name: HeaderMatchNameSubject, Match: "SIMPLE"}}},
|
||||
expecting: true,
|
||||
},
|
||||
{
|
||||
name: "simple check - no match",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"Subject": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{Headers: []TriggerConditionHeaderMatcher{{Name: "Subject", Match: "complex"}}},
|
||||
tc: Condition{Headers: []HeaderMatcher{{Name: HeaderMatchNameSubject, Match: "complex"}}},
|
||||
expecting: false,
|
||||
},
|
||||
{
|
||||
name: "simple check - no match",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"Subject": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{Headers: []TriggerConditionHeaderMatcher{{Name: "From", Match: "SIMPLE"}}},
|
||||
tc: Condition{Headers: []HeaderMatcher{{Name: HeaderMatchNameFrom, Match: "SIMPLE"}}},
|
||||
expecting: false,
|
||||
},
|
||||
{
|
||||
name: "simple check - name-case",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"SUBJECT": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{Headers: []TriggerConditionHeaderMatcher{{Name: "subject", Match: "SIMPLE"}}},
|
||||
tc: Condition{Headers: []HeaderMatcher{{Name: HeaderMatchNameSubject, Match: "SIMPLE"}}},
|
||||
expecting: true,
|
||||
},
|
||||
{
|
||||
name: "two matchers, one matches",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"Subject": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{
|
||||
Headers: []TriggerConditionHeaderMatcher{
|
||||
{Name: "Subject", Match: "SIMPLE"},
|
||||
{Name: "Subject", Match: "complex"},
|
||||
tc: Condition{
|
||||
Headers: []HeaderMatcher{
|
||||
{Name: HeaderMatchNameSubject, Match: "SIMPLE"},
|
||||
{Name: HeaderMatchNameSubject, Match: "complex"},
|
||||
},
|
||||
},
|
||||
expecting: true,
|
||||
@@ -57,11 +57,11 @@ func Test_makeMailHeaderChecker(t *testing.T) {
|
||||
{
|
||||
name: "two matchers, one matches, match-all=true",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"Subject": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{
|
||||
tc: Condition{
|
||||
MatchAll: true,
|
||||
Headers: []TriggerConditionHeaderMatcher{
|
||||
{Name: "Subject", Match: "SIMPLE"},
|
||||
{Name: "Subject", Match: "complex"},
|
||||
Headers: []HeaderMatcher{
|
||||
{Name: HeaderMatchNameSubject, Match: "SIMPLE"},
|
||||
{Name: HeaderMatchNameSubject, Match: "complex"},
|
||||
},
|
||||
},
|
||||
expecting: false,
|
||||
@@ -69,19 +69,23 @@ func Test_makeMailHeaderChecker(t *testing.T) {
|
||||
{
|
||||
name: "regex check",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"Subject": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{Headers: []TriggerConditionHeaderMatcher{{Name: "Subject", Match: "^S.+$", Op: "regex"}}},
|
||||
tc: Condition{Headers: []HeaderMatcher{{Name: HeaderMatchNameSubject, Match: "^S.+$", Op: HMOpRegex}}},
|
||||
expecting: true,
|
||||
},
|
||||
{
|
||||
name: "case-insensitive check",
|
||||
mh: types.MailMessageHeader{Raw: map[string][]string{"Subject": []string{"SIMPLE"}}},
|
||||
tc: TriggerCondition{Headers: []TriggerConditionHeaderMatcher{{Name: "Subject", Match: "simple", Op: "ci"}}},
|
||||
tc: Condition{Headers: []HeaderMatcher{{Name: HeaderMatchNameSubject, Match: "simple", Op: HMOpEqualCi}}},
|
||||
expecting: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
checker := (automationRunner{}).makeMailHeaderChecker(tt.mh)
|
||||
if err := tt.tc.Prepare(); err != nil {
|
||||
t.Errorf("unable to prepare header matcher: %v", err)
|
||||
}
|
||||
|
||||
checker := MakeChecker(tt.mh, nil)
|
||||
|
||||
j, _ := json.Marshal(tt.tc)
|
||||
if checker(string(j)) != tt.expecting {
|
||||
File diff suppressed because one or more lines are too long
48
system/db/schema/mysql/20190902080000.automation.up.sql
Normal file
48
system/db/schema/mysql/20190902080000.automation.up.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
CREATE TABLE IF NOT EXISTS sys_automation_script (
|
||||
`id` BIGINT(20) UNSIGNED NOT NULL,
|
||||
`rel_namespace` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'For compatibility only, not used',
|
||||
`name` VARCHAR(64) NOT NULL DEFAULT 'unnamed' COMMENT 'The name of the script',
|
||||
`source` TEXT NOT NULL COMMENT 'Source code for the script',
|
||||
`source_ref` VARCHAR(200) NOT NULL COMMENT 'Where is the script located (if remote)',
|
||||
`async` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'Do we run this script asynchronously?',
|
||||
`rel_runner` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Who is running the script? 0 for invoker',
|
||||
`run_in_ua` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'Run this script inside user-agent environment',
|
||||
`timeout` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Any explicit timeout set for this script (milliseconds)?',
|
||||
`critical` BOOLEAN NOT NULL DEFAULT TRUE COMMENT 'Is it critical that this script is executed successfully',
|
||||
`enabled` BOOLEAN NOT NULL DEFAULT TRUE COMMENT 'Is this script enabled?',
|
||||
|
||||
`created_by` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_by` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`updated_at` DATETIME NULL DEFAULT NULL,
|
||||
`deleted_by` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`deleted_at` DATETIME NULL DEFAULT NULL,
|
||||
|
||||
PRIMARY KEY (`id`)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_automation_trigger (
|
||||
`id` BIGINT(20) UNSIGNED NOT NULL,
|
||||
`rel_script` BIGINT(20) UNSIGNED NOT NULL COMMENT 'Script that is triggered',
|
||||
|
||||
`resource` VARCHAR(128) NOT NULL COMMENT 'Resource triggering the event',
|
||||
`event` VARCHAR(128) NOT NULL COMMENT 'Event triggered',
|
||||
`event_condition`
|
||||
TEXT NOT NULL COMMENT 'Trigger condition',
|
||||
`enabled` BOOLEAN NOT NULL DEFAULT TRUE COMMENT 'Trigger enabled?',
|
||||
|
||||
`weight` INT NOT NULL DEFAULT 0,
|
||||
|
||||
`created_by` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_by` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`updated_at` DATETIME NULL DEFAULT NULL,
|
||||
`deleted_by` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`deleted_at` DATETIME NULL DEFAULT NULL,
|
||||
|
||||
CONSTRAINT `fk_sys_automation_script` FOREIGN KEY (`rel_script`) REFERENCES `sys_automation_script` (`id`),
|
||||
|
||||
PRIMARY KEY (`id`)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
@@ -2,10 +2,6 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/mail"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -17,7 +13,9 @@ import (
|
||||
intAuth "github.com/cortezaproject/corteza-server/internal/auth"
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation"
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation/corredor"
|
||||
mailTrigger "github.com/cortezaproject/corteza-server/pkg/automation/mail"
|
||||
"github.com/cortezaproject/corteza-server/pkg/sentry"
|
||||
"github.com/cortezaproject/corteza-server/system/internal/repository"
|
||||
"github.com/cortezaproject/corteza-server/system/proto"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
)
|
||||
@@ -27,10 +25,15 @@ type (
|
||||
opt AutomationRunnerOpt
|
||||
logger *zap.Logger
|
||||
runner corredor.ScriptRunnerClient
|
||||
userFinder automationRunnerUserFinder
|
||||
scriptFinder automationScriptsFinder
|
||||
jwtEncoder intAuth.TokenEncoder
|
||||
}
|
||||
|
||||
automationRunnerUserFinder interface {
|
||||
FindByEmail(string) (*types.User, error)
|
||||
}
|
||||
|
||||
automationScriptsFinder interface {
|
||||
Watch(ctx context.Context)
|
||||
FindRunnableScripts(resource, event string, cc ...automation.TriggerConditionChecker) automation.ScriptSet
|
||||
@@ -41,27 +44,13 @@ type (
|
||||
ApiBaseURLMessaging string
|
||||
ApiBaseURLCompose string
|
||||
}
|
||||
|
||||
TriggerCondition struct {
|
||||
MatchAll bool `json:"matchAll"`
|
||||
Headers []TriggerConditionHeaderMatcher `json:"headers"`
|
||||
}
|
||||
|
||||
TriggerConditionHeaderMatcher struct {
|
||||
Name string `json:"name"`
|
||||
Match string `json:"match"`
|
||||
Op string `json:"op"`
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
AutomationResourceRecord = "compose:record"
|
||||
)
|
||||
|
||||
func AutomationRunner(opt AutomationRunnerOpt, f automationScriptsFinder, r corredor.ScriptRunnerClient) automationRunner {
|
||||
var svc = automationRunner{
|
||||
opt: opt,
|
||||
|
||||
userFinder: DefaultUser,
|
||||
scriptFinder: f,
|
||||
runner: r,
|
||||
|
||||
@@ -76,7 +65,7 @@ func (svc automationRunner) Watch(ctx context.Context) {
|
||||
svc.scriptFinder.Watch(ctx)
|
||||
}
|
||||
|
||||
func (svc automationRunner) OnReceivedMailMessage(ctx context.Context, mail *types.MailMessage) error {
|
||||
func (svc automationRunner) OnReceiveMailMessage(ctx context.Context, mail *types.MailMessage) error {
|
||||
return svc.findMailScripts(mail.Header).Walk(
|
||||
svc.makeMailScriptRunner(ctx, mail),
|
||||
)
|
||||
@@ -84,7 +73,12 @@ func (svc automationRunner) OnReceivedMailMessage(ctx context.Context, mail *typ
|
||||
|
||||
// Finds all scripts that can process email
|
||||
func (svc automationRunner) findMailScripts(headers types.MailMessageHeader) automation.ScriptSet {
|
||||
ss, _ := svc.scriptFinder.FindRunnableScripts("system:mail", "onReceived", svc.makeMailHeaderChecker(headers)).
|
||||
uev := func(email string) bool {
|
||||
u, err := svc.userFinder.FindByEmail(email)
|
||||
return u != nil && err == nil
|
||||
}
|
||||
|
||||
ss, _ := svc.scriptFinder.FindRunnableScripts("system:mail", "onReceive", mailTrigger.MakeChecker(headers, uev)).
|
||||
Filter(func(script *automation.Script) (bool, error) {
|
||||
// Filter out user-agent scripts
|
||||
return !script.RunInUA, nil
|
||||
@@ -93,22 +87,24 @@ func (svc automationRunner) findMailScripts(headers types.MailMessageHeader) aut
|
||||
return ss
|
||||
}
|
||||
|
||||
func (svc automationRunner) RecordScriptTester(ctx context.Context, source string, mail *types.MailMessage) (err error) {
|
||||
// Make record script runner and
|
||||
runner := svc.makeMailScriptRunner(ctx, mail)
|
||||
|
||||
return runner(&automation.Script{
|
||||
ID: 0,
|
||||
Name: "test",
|
||||
SourceRef: "test",
|
||||
Source: source,
|
||||
Async: false,
|
||||
RunAs: 0,
|
||||
RunInUA: false,
|
||||
Timeout: 0,
|
||||
Critical: true,
|
||||
Enabled: false,
|
||||
})
|
||||
func (svc automationRunner) RecordScriptTester(ctx context.Context, source string, payload interface{}) (err error) {
|
||||
// Make record script runner
|
||||
// @todo figure out how to convert payload to *types.MailMessage
|
||||
// runner := svc.makeMailScriptRunner(ctx, payload)
|
||||
//
|
||||
// return runner(&automation.Script{
|
||||
// ID: 0,
|
||||
// Name: "test",
|
||||
// SourceRef: "test",
|
||||
// Source: source,
|
||||
// Async: false,
|
||||
// RunAs: 0,
|
||||
// RunInUA: false,
|
||||
// Timeout: 0,
|
||||
// Critical: true,
|
||||
// Enabled: false,
|
||||
// })
|
||||
return repository.ErrNotImplemented
|
||||
}
|
||||
|
||||
// Runs record script
|
||||
@@ -194,64 +190,3 @@ func (svc automationRunner) getJWT(ctx context.Context, script *automation.Scrip
|
||||
|
||||
return svc.jwtEncoder.Encode(intAuth.GetIdentityFromContext(ctx))
|
||||
}
|
||||
|
||||
func (svc automationRunner) makeMailHeaderChecker(headers types.MailMessageHeader) automation.TriggerConditionChecker {
|
||||
return func(c string) bool {
|
||||
var (
|
||||
err error
|
||||
tc = TriggerCondition{}
|
||||
re *regexp.Regexp
|
||||
match bool
|
||||
)
|
||||
|
||||
if err := json.Unmarshal([]byte(c), &tc); err != nil {
|
||||
panic(err) // @todo replace with log
|
||||
return false
|
||||
}
|
||||
|
||||
for _, m := range tc.Headers {
|
||||
if m.Op == "regex" {
|
||||
if re, err = regexp.Compile(m.Match); err != nil {
|
||||
// Invalid re
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for name, vv := range headers.Raw {
|
||||
name = strings.ToLower(name)
|
||||
if strings.ToLower(m.Name) != name {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range vv {
|
||||
switch name {
|
||||
case "from",
|
||||
"to",
|
||||
"cc",
|
||||
"bcc",
|
||||
"reply-to":
|
||||
a, _ := mail.ParseAddress(v)
|
||||
v = a.Address
|
||||
}
|
||||
|
||||
switch m.Op {
|
||||
case "regex":
|
||||
match = re.MatchString(v)
|
||||
case "ci":
|
||||
match = strings.ToLower(v) == strings.ToLower(m.Match)
|
||||
default:
|
||||
match = v == m.Match
|
||||
}
|
||||
|
||||
if tc.MatchAll && !match {
|
||||
return false
|
||||
} else if !tc.MatchAll && match {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func AutomationScript(sm automationScriptManager) automationScript {
|
||||
return svc
|
||||
}
|
||||
|
||||
func (svc automationScript) FindByID(ctx context.Context, namespaceID, scriptID uint64) (*automation.Script, error) {
|
||||
func (svc automationScript) FindByID(ctx context.Context, scriptID uint64) (*automation.Script, error) {
|
||||
if s, err := svc.loadCombo(ctx, scriptID); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
@@ -133,7 +133,7 @@ func (svc automationScript) Update(ctx context.Context, mod *automation.Script)
|
||||
return svc.scriptManager.UpdateScript(ctx, s)
|
||||
}
|
||||
|
||||
func (svc automationScript) Delete(ctx context.Context, namespaceID, scriptID uint64) (err error) {
|
||||
func (svc automationScript) Delete(ctx context.Context, scriptID uint64) (err error) {
|
||||
if s, err := svc.loadCombo(ctx, scriptID); err != nil {
|
||||
return err
|
||||
} else if !svc.ac.CanDeleteAutomationScript(ctx, s) {
|
||||
|
||||
@@ -105,7 +105,7 @@ func (svc automationTrigger) isValid(ctx context.Context, s *automation.Script,
|
||||
}
|
||||
|
||||
switch t.Event {
|
||||
case "onReceived":
|
||||
case "onReceive":
|
||||
// @todo validate
|
||||
|
||||
default:
|
||||
|
||||
@@ -92,7 +92,7 @@ func Init(ctx context.Context, log *zap.Logger, c Config) (err error) {
|
||||
// handles script & trigger management & keeping runnables cripts in internal cache
|
||||
ias := automation.Service(automation.AutomationServiceConfig{
|
||||
Logger: DefaultLogger,
|
||||
DbTablePrefix: "system",
|
||||
DbTablePrefix: "sys",
|
||||
DB: repository.DB(ctx),
|
||||
TokenMaker: func(ctx context.Context, userID uint64) (jwt string, err error) {
|
||||
var u *types.User
|
||||
|
||||
180
system/rest/automation_script.go
Normal file
180
system/rest/automation_script.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/titpetric/factory/resputil"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rh"
|
||||
"github.com/cortezaproject/corteza-server/system/internal/service"
|
||||
"github.com/cortezaproject/corteza-server/system/rest/request"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
automationScriptPayload struct {
|
||||
*automation.Script
|
||||
|
||||
CanGrant bool `json:"canGrant"`
|
||||
CanUpdate bool `json:"canUpdate"`
|
||||
CanDelete bool `json:"canDelete"`
|
||||
CanSetRunner bool `json:"canSetRunner"`
|
||||
CanSetAsAsync bool `json:"canSetAsAsync"`
|
||||
CanSetAsCritical bool `json:"canAsCritical"`
|
||||
}
|
||||
|
||||
automationScriptSetPayload struct {
|
||||
Filter automation.ScriptFilter `json:"filter"`
|
||||
Set []*automationScriptPayload `json:"set"`
|
||||
}
|
||||
|
||||
automationScriptRunnablePayload struct {
|
||||
Set []*automationScriptRunnable `json:"set"`
|
||||
}
|
||||
|
||||
automationScriptRunnable struct {
|
||||
ScriptID uint64 `json:"scriptID,string"`
|
||||
Name string `json:"name"`
|
||||
Events map[string][]string `json:"events"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Async bool `json:"async"`
|
||||
}
|
||||
|
||||
AutomationScript struct {
|
||||
scripts automationScriptService
|
||||
runner automationScriptRunner
|
||||
ac automationScriptAccessController
|
||||
}
|
||||
|
||||
automationScriptService interface {
|
||||
FindByID(context.Context, uint64) (*automation.Script, error)
|
||||
Find(context.Context, automation.ScriptFilter) (automation.ScriptSet, automation.ScriptFilter, error)
|
||||
Create(context.Context, *automation.Script) error
|
||||
Update(context.Context, *automation.Script) error
|
||||
Delete(context.Context, uint64) error
|
||||
}
|
||||
|
||||
automationScriptRunner interface {
|
||||
RecordScriptTester(context.Context, string, interface{}) error
|
||||
}
|
||||
|
||||
automationScriptAccessController interface {
|
||||
CanGrant(context.Context) bool
|
||||
|
||||
CanUpdateAutomationScript(context.Context, *automation.Script) bool
|
||||
CanDeleteAutomationScript(context.Context, *automation.Script) bool
|
||||
}
|
||||
)
|
||||
|
||||
func (AutomationScript) New() *AutomationScript {
|
||||
return &AutomationScript{
|
||||
scripts: service.DefaultAutomationScriptManager,
|
||||
runner: service.DefaultAutomationRunner,
|
||||
ac: service.DefaultAccessControl,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) List(ctx context.Context, r *request.AutomationScriptList) (interface{}, error) {
|
||||
set, filter, err := ctrl.scripts.Find(ctx, automation.ScriptFilter{
|
||||
Query: r.Query,
|
||||
Resource: r.Resource,
|
||||
|
||||
IncDeleted: false,
|
||||
PageFilter: rh.Paging(r.Page, r.PerPage),
|
||||
})
|
||||
|
||||
return ctrl.makeFilterPayload(ctx, set, filter, err)
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) Create(ctx context.Context, r *request.AutomationScriptCreate) (interface{}, error) {
|
||||
var (
|
||||
script = &automation.Script{
|
||||
Name: r.Name,
|
||||
SourceRef: r.SourceRef,
|
||||
Source: r.Source,
|
||||
Async: r.Async,
|
||||
RunAs: r.RunAs,
|
||||
Timeout: r.Timeout,
|
||||
Critical: r.Critical,
|
||||
Enabled: r.Enabled,
|
||||
}
|
||||
)
|
||||
|
||||
script.AddTrigger(automation.STMS_FRESH, r.Triggers...)
|
||||
|
||||
return ctrl.makePayload(ctx, script, ctrl.scripts.Create(ctx, script))
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) Read(ctx context.Context, r *request.AutomationScriptRead) (interface{}, error) {
|
||||
script, err := ctrl.scripts.FindByID(ctx, r.ScriptID)
|
||||
return ctrl.makePayload(ctx, script, err)
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) Update(ctx context.Context, r *request.AutomationScriptUpdate) (interface{}, error) {
|
||||
mod := &automation.Script{
|
||||
ID: r.ScriptID,
|
||||
Name: r.Name,
|
||||
SourceRef: r.SourceRef,
|
||||
Source: r.Source,
|
||||
Async: r.Async,
|
||||
RunAs: r.RunAs,
|
||||
Timeout: r.Timeout,
|
||||
Critical: r.Critical,
|
||||
Enabled: r.Enabled,
|
||||
}
|
||||
|
||||
mod.AddTrigger(automation.STMS_UPDATE, r.Triggers...)
|
||||
|
||||
return ctrl.makePayload(ctx, mod, ctrl.scripts.Update(ctx, mod))
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) Delete(ctx context.Context, r *request.AutomationScriptDelete) (interface{}, error) {
|
||||
return resputil.OK(), ctrl.scripts.Delete(ctx, r.ScriptID)
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) Test(ctx context.Context, r *request.AutomationScriptTest) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
if err = ctrl.runner.RecordScriptTester(ctx, r.Source, r.Payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.Payload, err
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) makePayload(ctx context.Context, s *automation.Script, err error) (*automationScriptPayload, error) {
|
||||
if err != nil || s == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &automationScriptPayload{
|
||||
Script: s,
|
||||
|
||||
CanGrant: ctrl.ac.CanGrant(ctx),
|
||||
CanUpdate: ctrl.ac.CanUpdateAutomationScript(ctx, s),
|
||||
CanDelete: ctrl.ac.CanDeleteAutomationScript(ctx, s),
|
||||
|
||||
CanSetRunner: ctrl.ac.CanGrant(ctx),
|
||||
CanSetAsCritical: true,
|
||||
CanSetAsAsync: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ctrl AutomationScript) makeFilterPayload(ctx context.Context, nn automation.ScriptSet, f automation.ScriptFilter, err error) (*automationScriptSetPayload, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
modp := &automationScriptSetPayload{Filter: f, Set: make([]*automationScriptPayload, len(nn))}
|
||||
|
||||
for i := range nn {
|
||||
modp.Set[i], _ = ctrl.makePayload(ctx, nn[i], nil)
|
||||
}
|
||||
|
||||
return modp, nil
|
||||
}
|
||||
166
system/rest/automation_trigger.go
Normal file
166
system/rest/automation_trigger.go
Normal file
@@ -0,0 +1,166 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/titpetric/factory/resputil"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rh"
|
||||
"github.com/cortezaproject/corteza-server/system/internal/service"
|
||||
"github.com/cortezaproject/corteza-server/system/rest/request"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
automationTriggerPayload struct {
|
||||
*automation.Trigger
|
||||
|
||||
CanRun bool `json:"canRun"`
|
||||
}
|
||||
|
||||
automationTriggerSetPayload struct {
|
||||
Filter automation.TriggerFilter `json:"filter"`
|
||||
Set []*automationTriggerPayload `json:"set"`
|
||||
}
|
||||
|
||||
AutomationTrigger struct {
|
||||
triggers automationTriggerService
|
||||
scripts automationScriptFinderService
|
||||
|
||||
ac automationTriggerAccessController
|
||||
}
|
||||
|
||||
automationTriggerService interface {
|
||||
FindByID(context.Context, uint64) (*automation.Trigger, error)
|
||||
Find(context.Context, automation.TriggerFilter) (automation.TriggerSet, automation.TriggerFilter, error)
|
||||
Create(context.Context, *automation.Script, *automation.Trigger) error
|
||||
Update(context.Context, *automation.Script, *automation.Trigger) error
|
||||
Delete(context.Context, *automation.Script, *automation.Trigger) error
|
||||
}
|
||||
|
||||
automationScriptFinderService interface {
|
||||
FindByID(context.Context, uint64) (*automation.Script, error)
|
||||
}
|
||||
|
||||
automationTriggerAccessController interface {
|
||||
CanGrant(context.Context) bool
|
||||
|
||||
CanRunAutomationTrigger(context.Context, *automation.Trigger) bool
|
||||
}
|
||||
)
|
||||
|
||||
func (AutomationTrigger) New() *AutomationTrigger {
|
||||
return &AutomationTrigger{
|
||||
scripts: service.DefaultAutomationScriptManager,
|
||||
triggers: service.DefaultAutomationTriggerManager,
|
||||
ac: service.DefaultAccessControl,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) List(ctx context.Context, r *request.AutomationTriggerList) (interface{}, error) {
|
||||
set, filter, err := ctrl.triggers.Find(ctx, automation.TriggerFilter{
|
||||
Resource: r.Resource,
|
||||
Event: r.Event,
|
||||
ScriptID: r.ScriptID,
|
||||
|
||||
IncDeleted: false,
|
||||
PageFilter: rh.Paging(r.Page, r.PerPage),
|
||||
})
|
||||
|
||||
return ctrl.makeFilterPayload(ctx, set, filter, err)
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) Create(ctx context.Context, r *request.AutomationTriggerCreate) (interface{}, error) {
|
||||
s, _, err := ctrl.loadCombo(ctx, r.ScriptID, 0)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "can not create trigger")
|
||||
}
|
||||
|
||||
var (
|
||||
t = &automation.Trigger{
|
||||
Event: r.Event,
|
||||
Resource: r.Resource,
|
||||
Condition: r.Condition,
|
||||
ScriptID: s.ID,
|
||||
Enabled: r.Enabled,
|
||||
}
|
||||
)
|
||||
|
||||
return ctrl.makePayload(ctx, t, ctrl.triggers.Create(ctx, s, t))
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) Read(ctx context.Context, r *request.AutomationTriggerRead) (interface{}, error) {
|
||||
_, t, err := ctrl.loadCombo(ctx, r.ScriptID, 0)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "can not read trigger")
|
||||
}
|
||||
|
||||
return ctrl.makePayload(ctx, t, err)
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) Update(ctx context.Context, r *request.AutomationTriggerUpdate) (interface{}, error) {
|
||||
s, t, err := ctrl.loadCombo(ctx, r.ScriptID, r.TriggerID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "can not update trigger")
|
||||
}
|
||||
|
||||
t.Event = r.Event
|
||||
t.Resource = r.Resource
|
||||
t.Condition = r.Condition
|
||||
t.ScriptID = r.ScriptID
|
||||
t.Enabled = r.Enabled
|
||||
|
||||
return ctrl.makePayload(ctx, t, ctrl.triggers.Update(ctx, s, t))
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) Delete(ctx context.Context, r *request.AutomationTriggerDelete) (interface{}, error) {
|
||||
s, t, err := ctrl.loadCombo(ctx, r.ScriptID, r.TriggerID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "can not update trigger")
|
||||
}
|
||||
|
||||
return resputil.OK(), ctrl.triggers.Delete(ctx, s, t)
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) loadCombo(ctx context.Context, scriptID, triggerID uint64) (s *automation.Script, t *automation.Trigger, err error) {
|
||||
if triggerID > 0 {
|
||||
t, err = ctrl.triggers.FindByID(ctx, triggerID)
|
||||
return
|
||||
}
|
||||
|
||||
if scriptID > 0 {
|
||||
s, err = ctrl.scripts.FindByID(ctx, scriptID)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) makePayload(ctx context.Context, t *automation.Trigger, err error) (*automationTriggerPayload, error) {
|
||||
if err != nil || t == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &automationTriggerPayload{
|
||||
Trigger: t,
|
||||
|
||||
CanRun: ctrl.ac.CanRunAutomationTrigger(ctx, t),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ctrl AutomationTrigger) makeFilterPayload(ctx context.Context, nn automation.TriggerSet, f automation.TriggerFilter, err error) (*automationTriggerSetPayload, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
modp := &automationTriggerSetPayload{Filter: f, Set: make([]*automationTriggerPayload, len(nn))}
|
||||
|
||||
for i := range nn {
|
||||
modp.Set[i], _ = ctrl.makePayload(ctx, nn[i], nil)
|
||||
}
|
||||
|
||||
return modp, nil
|
||||
}
|
||||
185
system/rest/handlers/automation_script.go
Normal file
185
system/rest/handlers/automation_script.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package handlers
|
||||
|
||||
/*
|
||||
Hello! This file is auto-generated from `docs/src/spec.json`.
|
||||
|
||||
For development:
|
||||
In order to update the generated files, edit this file under the location,
|
||||
add your struct fields, imports, API definitions and whatever you want, and:
|
||||
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `automation_script.go`, `automation_script.util.go` or `automation_script_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `automation_script.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/titpetric/factory/resputil"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/logger"
|
||||
"github.com/cortezaproject/corteza-server/system/rest/request"
|
||||
)
|
||||
|
||||
// Internal API interface
|
||||
type AutomationScriptAPI interface {
|
||||
List(context.Context, *request.AutomationScriptList) (interface{}, error)
|
||||
Create(context.Context, *request.AutomationScriptCreate) (interface{}, error)
|
||||
Read(context.Context, *request.AutomationScriptRead) (interface{}, error)
|
||||
Update(context.Context, *request.AutomationScriptUpdate) (interface{}, error)
|
||||
Delete(context.Context, *request.AutomationScriptDelete) (interface{}, error)
|
||||
Test(context.Context, *request.AutomationScriptTest) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
type AutomationScript struct {
|
||||
List func(http.ResponseWriter, *http.Request)
|
||||
Create func(http.ResponseWriter, *http.Request)
|
||||
Read func(http.ResponseWriter, *http.Request)
|
||||
Update func(http.ResponseWriter, *http.Request)
|
||||
Delete func(http.ResponseWriter, *http.Request)
|
||||
Test func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
func NewAutomationScript(h AutomationScriptAPI) *AutomationScript {
|
||||
return &AutomationScript{
|
||||
List: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationScriptList()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationScript.List", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.List(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationScript.List", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationScript.List", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Create: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationScriptCreate()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationScript.Create", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Create(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationScript.Create", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationScript.Create", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Read: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationScriptRead()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationScript.Read", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Read(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationScript.Read", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationScript.Read", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Update: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationScriptUpdate()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationScript.Update", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Update(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationScript.Update", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationScript.Update", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Delete: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationScriptDelete()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationScript.Delete", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Delete(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationScript.Delete", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationScript.Delete", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Test: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationScriptTest()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationScript.Test", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Test(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationScript.Test", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationScript.Test", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (h AutomationScript) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middlewares...)
|
||||
r.Get("/automation/script/", h.List)
|
||||
r.Post("/automation/script/", h.Create)
|
||||
r.Get("/automation/script/{scriptID}", h.Read)
|
||||
r.Post("/automation/script/{scriptID}", h.Update)
|
||||
r.Delete("/automation/script/{scriptID}", h.Delete)
|
||||
r.Post("/automation/script/test", h.Test)
|
||||
})
|
||||
}
|
||||
162
system/rest/handlers/automation_trigger.go
Normal file
162
system/rest/handlers/automation_trigger.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package handlers
|
||||
|
||||
/*
|
||||
Hello! This file is auto-generated from `docs/src/spec.json`.
|
||||
|
||||
For development:
|
||||
In order to update the generated files, edit this file under the location,
|
||||
add your struct fields, imports, API definitions and whatever you want, and:
|
||||
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `automation_trigger.go`, `automation_trigger.util.go` or `automation_trigger_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `automation_trigger.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/titpetric/factory/resputil"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/logger"
|
||||
"github.com/cortezaproject/corteza-server/system/rest/request"
|
||||
)
|
||||
|
||||
// Internal API interface
|
||||
type AutomationTriggerAPI interface {
|
||||
List(context.Context, *request.AutomationTriggerList) (interface{}, error)
|
||||
Create(context.Context, *request.AutomationTriggerCreate) (interface{}, error)
|
||||
Read(context.Context, *request.AutomationTriggerRead) (interface{}, error)
|
||||
Update(context.Context, *request.AutomationTriggerUpdate) (interface{}, error)
|
||||
Delete(context.Context, *request.AutomationTriggerDelete) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
type AutomationTrigger struct {
|
||||
List func(http.ResponseWriter, *http.Request)
|
||||
Create func(http.ResponseWriter, *http.Request)
|
||||
Read func(http.ResponseWriter, *http.Request)
|
||||
Update func(http.ResponseWriter, *http.Request)
|
||||
Delete func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
func NewAutomationTrigger(h AutomationTriggerAPI) *AutomationTrigger {
|
||||
return &AutomationTrigger{
|
||||
List: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationTriggerList()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationTrigger.List", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.List(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationTrigger.List", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationTrigger.List", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Create: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationTriggerCreate()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationTrigger.Create", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Create(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationTrigger.Create", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationTrigger.Create", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Read: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationTriggerRead()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationTrigger.Read", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Read(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationTrigger.Read", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationTrigger.Read", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Update: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationTriggerUpdate()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationTrigger.Update", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Update(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationTrigger.Update", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationTrigger.Update", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Delete: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAutomationTriggerDelete()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("AutomationTrigger.Delete", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Delete(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("AutomationTrigger.Delete", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("AutomationTrigger.Delete", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (h AutomationTrigger) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middlewares...)
|
||||
r.Get("/automation/script/{scriptID}/trigger/", h.List)
|
||||
r.Post("/automation/script/{scriptID}/trigger/", h.Create)
|
||||
r.Get("/automation/script/{scriptID}/trigger/{triggerID}", h.Read)
|
||||
r.Post("/automation/script/{scriptID}/trigger/{triggerID}", h.Update)
|
||||
r.Delete("/automation/script/{scriptID}/trigger/{triggerID}", h.Delete)
|
||||
})
|
||||
}
|
||||
449
system/rest/request/automation_script.go
Normal file
449
system/rest/request/automation_script.go
Normal file
@@ -0,0 +1,449 @@
|
||||
package request
|
||||
|
||||
/*
|
||||
Hello! This file is auto-generated from `docs/src/spec.json`.
|
||||
|
||||
For development:
|
||||
In order to update the generated files, edit this file under the location,
|
||||
add your struct fields, imports, API definitions and whatever you want, and:
|
||||
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `automation_script.go`, `automation_script.util.go` or `automation_script_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `automation_script.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"encoding/json"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/automation"
|
||||
)
|
||||
|
||||
var _ = chi.URLParam
|
||||
var _ = multipart.FileHeader{}
|
||||
|
||||
// AutomationScript list request parameters
|
||||
type AutomationScriptList struct {
|
||||
Query string
|
||||
Resource string
|
||||
IncDeleted bool
|
||||
Page uint
|
||||
PerPage uint
|
||||
}
|
||||
|
||||
func NewAutomationScriptList() *AutomationScriptList {
|
||||
return &AutomationScriptList{}
|
||||
}
|
||||
|
||||
func (r AutomationScriptList) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["query"] = r.Query
|
||||
out["resource"] = r.Resource
|
||||
out["incDeleted"] = r.IncDeleted
|
||||
out["page"] = r.Page
|
||||
out["perPage"] = r.PerPage
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationScriptList) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := get["query"]; ok {
|
||||
r.Query = val
|
||||
}
|
||||
if val, ok := get["resource"]; ok {
|
||||
r.Resource = val
|
||||
}
|
||||
if val, ok := get["incDeleted"]; ok {
|
||||
r.IncDeleted = parseBool(val)
|
||||
}
|
||||
if val, ok := get["page"]; ok {
|
||||
r.Page = parseUint(val)
|
||||
}
|
||||
if val, ok := get["perPage"]; ok {
|
||||
r.PerPage = parseUint(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationScriptList()
|
||||
|
||||
// AutomationScript create request parameters
|
||||
type AutomationScriptCreate struct {
|
||||
Name string
|
||||
SourceRef string
|
||||
Source string
|
||||
RunAs uint64 `json:",string"`
|
||||
Timeout uint
|
||||
Critical bool
|
||||
Async bool
|
||||
Enabled bool
|
||||
Triggers automation.TriggerSet
|
||||
}
|
||||
|
||||
func NewAutomationScriptCreate() *AutomationScriptCreate {
|
||||
return &AutomationScriptCreate{}
|
||||
}
|
||||
|
||||
func (r AutomationScriptCreate) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["name"] = r.Name
|
||||
out["sourceRef"] = r.SourceRef
|
||||
out["source"] = r.Source
|
||||
out["runAs"] = r.RunAs
|
||||
out["timeout"] = r.Timeout
|
||||
out["critical"] = r.Critical
|
||||
out["async"] = r.Async
|
||||
out["enabled"] = r.Enabled
|
||||
out["triggers"] = r.Triggers
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationScriptCreate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := post["name"]; ok {
|
||||
r.Name = val
|
||||
}
|
||||
if val, ok := post["sourceRef"]; ok {
|
||||
r.SourceRef = val
|
||||
}
|
||||
if val, ok := post["source"]; ok {
|
||||
r.Source = val
|
||||
}
|
||||
if val, ok := post["runAs"]; ok {
|
||||
r.RunAs = parseUInt64(val)
|
||||
}
|
||||
if val, ok := post["timeout"]; ok {
|
||||
r.Timeout = parseUint(val)
|
||||
}
|
||||
if val, ok := post["critical"]; ok {
|
||||
r.Critical = parseBool(val)
|
||||
}
|
||||
if val, ok := post["async"]; ok {
|
||||
r.Async = parseBool(val)
|
||||
}
|
||||
if val, ok := post["enabled"]; ok {
|
||||
r.Enabled = parseBool(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationScriptCreate()
|
||||
|
||||
// AutomationScript read request parameters
|
||||
type AutomationScriptRead struct {
|
||||
ScriptID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewAutomationScriptRead() *AutomationScriptRead {
|
||||
return &AutomationScriptRead{}
|
||||
}
|
||||
|
||||
func (r AutomationScriptRead) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["scriptID"] = r.ScriptID
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationScriptRead) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationScriptRead()
|
||||
|
||||
// AutomationScript update request parameters
|
||||
type AutomationScriptUpdate struct {
|
||||
ScriptID uint64 `json:",string"`
|
||||
Name string
|
||||
SourceRef string
|
||||
Source string
|
||||
RunAs uint64 `json:",string"`
|
||||
Timeout uint
|
||||
Critical bool
|
||||
Async bool
|
||||
Enabled bool
|
||||
Triggers automation.TriggerSet
|
||||
}
|
||||
|
||||
func NewAutomationScriptUpdate() *AutomationScriptUpdate {
|
||||
return &AutomationScriptUpdate{}
|
||||
}
|
||||
|
||||
func (r AutomationScriptUpdate) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["scriptID"] = r.ScriptID
|
||||
out["name"] = r.Name
|
||||
out["sourceRef"] = r.SourceRef
|
||||
out["source"] = r.Source
|
||||
out["runAs"] = r.RunAs
|
||||
out["timeout"] = r.Timeout
|
||||
out["critical"] = r.Critical
|
||||
out["async"] = r.Async
|
||||
out["enabled"] = r.Enabled
|
||||
out["triggers"] = r.Triggers
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationScriptUpdate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
if val, ok := post["name"]; ok {
|
||||
r.Name = val
|
||||
}
|
||||
if val, ok := post["sourceRef"]; ok {
|
||||
r.SourceRef = val
|
||||
}
|
||||
if val, ok := post["source"]; ok {
|
||||
r.Source = val
|
||||
}
|
||||
if val, ok := post["runAs"]; ok {
|
||||
r.RunAs = parseUInt64(val)
|
||||
}
|
||||
if val, ok := post["timeout"]; ok {
|
||||
r.Timeout = parseUint(val)
|
||||
}
|
||||
if val, ok := post["critical"]; ok {
|
||||
r.Critical = parseBool(val)
|
||||
}
|
||||
if val, ok := post["async"]; ok {
|
||||
r.Async = parseBool(val)
|
||||
}
|
||||
if val, ok := post["enabled"]; ok {
|
||||
r.Enabled = parseBool(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationScriptUpdate()
|
||||
|
||||
// AutomationScript delete request parameters
|
||||
type AutomationScriptDelete struct {
|
||||
ScriptID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewAutomationScriptDelete() *AutomationScriptDelete {
|
||||
return &AutomationScriptDelete{}
|
||||
}
|
||||
|
||||
func (r AutomationScriptDelete) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["scriptID"] = r.ScriptID
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationScriptDelete) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationScriptDelete()
|
||||
|
||||
// AutomationScript test request parameters
|
||||
type AutomationScriptTest struct {
|
||||
Source string
|
||||
Payload json.RawMessage
|
||||
}
|
||||
|
||||
func NewAutomationScriptTest() *AutomationScriptTest {
|
||||
return &AutomationScriptTest{}
|
||||
}
|
||||
|
||||
func (r AutomationScriptTest) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["source"] = r.Source
|
||||
out["payload"] = r.Payload
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationScriptTest) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := post["source"]; ok {
|
||||
r.Source = val
|
||||
}
|
||||
if val, ok := post["payload"]; ok {
|
||||
r.Payload = json.RawMessage(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationScriptTest()
|
||||
360
system/rest/request/automation_trigger.go
Normal file
360
system/rest/request/automation_trigger.go
Normal file
@@ -0,0 +1,360 @@
|
||||
package request
|
||||
|
||||
/*
|
||||
Hello! This file is auto-generated from `docs/src/spec.json`.
|
||||
|
||||
For development:
|
||||
In order to update the generated files, edit this file under the location,
|
||||
add your struct fields, imports, API definitions and whatever you want, and:
|
||||
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `automation_trigger.go`, `automation_trigger.util.go` or `automation_trigger_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `automation_trigger.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"encoding/json"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var _ = chi.URLParam
|
||||
var _ = multipart.FileHeader{}
|
||||
|
||||
// AutomationTrigger list request parameters
|
||||
type AutomationTriggerList struct {
|
||||
Resource string
|
||||
Event string
|
||||
IncDeleted bool
|
||||
Page uint
|
||||
PerPage uint
|
||||
ScriptID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewAutomationTriggerList() *AutomationTriggerList {
|
||||
return &AutomationTriggerList{}
|
||||
}
|
||||
|
||||
func (r AutomationTriggerList) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["resource"] = r.Resource
|
||||
out["event"] = r.Event
|
||||
out["incDeleted"] = r.IncDeleted
|
||||
out["page"] = r.Page
|
||||
out["perPage"] = r.PerPage
|
||||
out["scriptID"] = r.ScriptID
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationTriggerList) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := get["resource"]; ok {
|
||||
r.Resource = val
|
||||
}
|
||||
if val, ok := get["event"]; ok {
|
||||
r.Event = val
|
||||
}
|
||||
if val, ok := get["incDeleted"]; ok {
|
||||
r.IncDeleted = parseBool(val)
|
||||
}
|
||||
if val, ok := get["page"]; ok {
|
||||
r.Page = parseUint(val)
|
||||
}
|
||||
if val, ok := get["perPage"]; ok {
|
||||
r.PerPage = parseUint(val)
|
||||
}
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationTriggerList()
|
||||
|
||||
// AutomationTrigger create request parameters
|
||||
type AutomationTriggerCreate struct {
|
||||
Resource string
|
||||
Event string
|
||||
Condition string
|
||||
Enabled bool
|
||||
ScriptID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewAutomationTriggerCreate() *AutomationTriggerCreate {
|
||||
return &AutomationTriggerCreate{}
|
||||
}
|
||||
|
||||
func (r AutomationTriggerCreate) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["resource"] = r.Resource
|
||||
out["event"] = r.Event
|
||||
out["condition"] = r.Condition
|
||||
out["enabled"] = r.Enabled
|
||||
out["scriptID"] = r.ScriptID
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationTriggerCreate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := post["resource"]; ok {
|
||||
r.Resource = val
|
||||
}
|
||||
if val, ok := post["event"]; ok {
|
||||
r.Event = val
|
||||
}
|
||||
if val, ok := post["condition"]; ok {
|
||||
r.Condition = val
|
||||
}
|
||||
if val, ok := post["enabled"]; ok {
|
||||
r.Enabled = parseBool(val)
|
||||
}
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationTriggerCreate()
|
||||
|
||||
// AutomationTrigger read request parameters
|
||||
type AutomationTriggerRead struct {
|
||||
TriggerID uint64 `json:",string"`
|
||||
ScriptID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewAutomationTriggerRead() *AutomationTriggerRead {
|
||||
return &AutomationTriggerRead{}
|
||||
}
|
||||
|
||||
func (r AutomationTriggerRead) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["triggerID"] = r.TriggerID
|
||||
out["scriptID"] = r.ScriptID
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationTriggerRead) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
r.TriggerID = parseUInt64(chi.URLParam(req, "triggerID"))
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationTriggerRead()
|
||||
|
||||
// AutomationTrigger update request parameters
|
||||
type AutomationTriggerUpdate struct {
|
||||
TriggerID uint64 `json:",string"`
|
||||
ScriptID uint64 `json:",string"`
|
||||
Resource string
|
||||
Event string
|
||||
Condition string
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
func NewAutomationTriggerUpdate() *AutomationTriggerUpdate {
|
||||
return &AutomationTriggerUpdate{}
|
||||
}
|
||||
|
||||
func (r AutomationTriggerUpdate) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["triggerID"] = r.TriggerID
|
||||
out["scriptID"] = r.ScriptID
|
||||
out["resource"] = r.Resource
|
||||
out["event"] = r.Event
|
||||
out["condition"] = r.Condition
|
||||
out["enabled"] = r.Enabled
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationTriggerUpdate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
r.TriggerID = parseUInt64(chi.URLParam(req, "triggerID"))
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
if val, ok := post["resource"]; ok {
|
||||
r.Resource = val
|
||||
}
|
||||
if val, ok := post["event"]; ok {
|
||||
r.Event = val
|
||||
}
|
||||
if val, ok := post["condition"]; ok {
|
||||
r.Condition = val
|
||||
}
|
||||
if val, ok := post["enabled"]; ok {
|
||||
r.Enabled = parseBool(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationTriggerUpdate()
|
||||
|
||||
// AutomationTrigger delete request parameters
|
||||
type AutomationTriggerDelete struct {
|
||||
TriggerID uint64 `json:",string"`
|
||||
ScriptID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewAutomationTriggerDelete() *AutomationTriggerDelete {
|
||||
return &AutomationTriggerDelete{}
|
||||
}
|
||||
|
||||
func (r AutomationTriggerDelete) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["triggerID"] = r.TriggerID
|
||||
out["scriptID"] = r.ScriptID
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *AutomationTriggerDelete) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
r.TriggerID = parseUInt64(chi.URLParam(req, "triggerID"))
|
||||
r.ScriptID = parseUInt64(chi.URLParam(req, "scriptID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAutomationTriggerDelete()
|
||||
@@ -25,5 +25,8 @@ func MountRoutes(r chi.Router) {
|
||||
handlers.NewPermissions(Permissions{}.New()).MountRoutes(r)
|
||||
handlers.NewApplication(Application{}.New()).MountRoutes(r)
|
||||
handlers.NewSettings(Settings{}.New()).MountRoutes(r)
|
||||
|
||||
handlers.NewAutomationScript(AutomationScript{}.New()).MountRoutes(r)
|
||||
handlers.NewAutomationTrigger(AutomationTrigger{}.New()).MountRoutes(r)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user