Skip to content

Commit 9dfc082

Browse files
authored
feat: support automation templates (baserow#4944)
* Add template for automation
1 parent 1064912 commit 9dfc082

22 files changed

Lines changed: 527 additions & 229 deletions

File tree

backend/src/baserow/contrib/automation/api/nodes/views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
from baserow.contrib.automation.workflows.exceptions import (
7373
AutomationWorkflowDoesNotExist,
7474
)
75+
from baserow.contrib.automation.workflows.handler import AutomationWorkflowHandler
7576
from baserow.contrib.automation.workflows.service import AutomationWorkflowService
7677

7778
AUTOMATION_NODES_TAG = "Automation nodes"
@@ -175,7 +176,7 @@ def post(self, request, data: Dict, workflow_id: int):
175176
}
176177
)
177178
def get(self, request, workflow_id: int):
178-
workflow = AutomationWorkflowService().get_workflow(request.user, workflow_id)
179+
workflow = AutomationWorkflowHandler().get_workflow(workflow_id)
179180

180181
nodes = AutomationNodeService().get_nodes(request.user, workflow)
181182

backend/src/baserow/contrib/automation/apps.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,20 @@ def ready(self):
145145

146146
action_scope_registry.register(WorkflowActionScopeType())
147147

148+
from baserow.core.registries import permission_manager_type_registry
149+
150+
from .permission_manager import AllowIfTemplatePermissionManagerType
151+
152+
prev_manager = permission_manager_type_registry.get(
153+
AllowIfTemplatePermissionManagerType.type
154+
)
155+
permission_manager_type_registry.unregister(
156+
AllowIfTemplatePermissionManagerType.type
157+
)
158+
permission_manager_type_registry.register(
159+
AllowIfTemplatePermissionManagerType(prev_manager)
160+
)
161+
148162
automation_node_type_registry.register(LocalBaserowCreateRowNodeType())
149163
automation_node_type_registry.register(LocalBaserowUpdateRowNodeType())
150164
automation_node_type_registry.register(LocalBaserowDeleteRowNodeType())
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from django.contrib.auth import get_user_model
2+
3+
from baserow.contrib.automation.nodes.operations import ListAutomationNodeOperationType
4+
from baserow.contrib.automation.operations import ListAutomationWorkflowsOperationType
5+
from baserow.core.permission_manager import (
6+
AllowIfTemplatePermissionManagerType as CoreAllowIfTemplatePermissionManagerType,
7+
)
8+
from baserow.core.registries import PermissionManagerType
9+
10+
User = get_user_model()
11+
12+
13+
class AllowIfTemplatePermissionManagerType(CoreAllowIfTemplatePermissionManagerType):
14+
"""
15+
Allows read operation on templates.
16+
"""
17+
18+
AUTOMATION_OPERATION_ALLOWED_ON_TEMPLATES = [
19+
ListAutomationWorkflowsOperationType.type,
20+
ListAutomationNodeOperationType.type,
21+
]
22+
23+
@property
24+
def OPERATION_ALLOWED_ON_TEMPLATES(self):
25+
return (
26+
self.prev_manager_type.OPERATION_ALLOWED_ON_TEMPLATES
27+
+ self.AUTOMATION_OPERATION_ALLOWED_ON_TEMPLATES
28+
)
29+
30+
def __init__(self, prev_manager_type: PermissionManagerType):
31+
self.prev_manager_type = prev_manager_type

backend/src/baserow/contrib/integrations/core/integration_types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class SerializedDict(IntegrationDict):
1616

1717
serializer_field_names = ["host", "port", "use_tls", "username", "password"]
1818
allowed_fields = ["host", "port", "use_tls", "username", "password"]
19-
sensitive_fields = ["username", "password"]
19+
sensitive_fields = ["host", "port", "use_tls", "username", "password"]
2020

2121
request_serializer_field_names = ["host", "port", "use_tls", "username", "password"]
2222
request_serializer_field_overrides = {}

backend/tests/baserow/contrib/integrations/core/test_smtp_integration_type.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,9 @@ def test_smtp_integration_export_serialized_exclude_sensitive(data_fixture):
233233
expected_serialized = {
234234
"id": AnyInt(),
235235
"type": "smtp",
236-
"host": "smtp.example.com",
237-
"port": 587,
238-
"use_tls": True,
236+
"host": None,
237+
"port": None,
238+
"use_tls": None,
239239
"username": None,
240240
"password": None,
241241
"name": "",

backend/tests/baserow/core/test_basic_permissions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@ def test_get_permissions(data_fixture):
519519
"dashboard.data_source.read",
520520
"dashboard.list_data_sources",
521521
"dashboard.data_source.dispatch",
522+
"automation.list_workflows",
523+
"automation.workflow.list_nodes",
522524
],
523525
"workspace_template_ids": [],
524526
},
@@ -575,6 +577,8 @@ def test_get_permissions(data_fixture):
575577
"dashboard.data_source.read",
576578
"dashboard.list_data_sources",
577579
"dashboard.data_source.dispatch",
580+
"automation.list_workflows",
581+
"automation.workflow.list_nodes",
578582
],
579583
"workspace_template_ids": [],
580584
},
@@ -648,6 +652,8 @@ def test_get_permissions(data_fixture):
648652
"dashboard.data_source.read",
649653
"dashboard.list_data_sources",
650654
"dashboard.data_source.dispatch",
655+
"automation.list_workflows",
656+
"automation.workflow.list_nodes",
651657
],
652658
"workspace_template_ids": [],
653659
},
@@ -704,6 +710,8 @@ def test_get_permissions(data_fixture):
704710
"dashboard.data_source.read",
705711
"dashboard.list_data_sources",
706712
"dashboard.data_source.dispatch",
713+
"automation.list_workflows",
714+
"automation.workflow.list_nodes",
707715
],
708716
"workspace_template_ids": [],
709717
},
@@ -777,6 +785,8 @@ def test_get_permissions(data_fixture):
777785
"dashboard.data_source.read",
778786
"dashboard.list_data_sources",
779787
"dashboard.data_source.dispatch",
788+
"automation.list_workflows",
789+
"automation.workflow.list_nodes",
780790
],
781791
"workspace_template_ids": [],
782792
},
@@ -833,6 +843,8 @@ def test_get_permissions(data_fixture):
833843
"dashboard.data_source.read",
834844
"dashboard.list_data_sources",
835845
"dashboard.data_source.dispatch",
846+
"automation.list_workflows",
847+
"automation.workflow.list_nodes",
836848
],
837849
"workspace_template_ids": [],
838850
},
@@ -906,6 +918,8 @@ def test_get_permissions(data_fixture):
906918
"dashboard.data_source.read",
907919
"dashboard.list_data_sources",
908920
"dashboard.data_source.dispatch",
921+
"automation.list_workflows",
922+
"automation.workflow.list_nodes",
909923
],
910924
"workspace_template_ids": [],
911925
},
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "feature",
3+
"message": "Support automation templates",
4+
"issue_origin": "github",
5+
"issue_number": 3871,
6+
"domain": "automation",
7+
"bullet_points": [],
8+
"created_at": "2026-03-10"
9+
}

web-frontend/modules/automation/applicationTypes.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { populateAutomationWorkflow } from '@baserow/modules/automation/store/au
66
import { DEVELOPMENT_STAGES } from '@baserow/modules/core/constants'
77
import { pageFinished } from '@baserow/modules/core/utils/routing'
88
import { nextTick } from '#imports'
9+
import WorkflowTemplate from '@baserow/modules/automation/components/workflow/WorkflowTemplate.vue'
10+
import WorkflowTemplateSideBar from '@baserow/modules/automation/components/workflow/WorkflowTemplateSideBar.vue'
911

1012
export class AutomationApplicationType extends ApplicationType {
1113
static getType() {
@@ -52,6 +54,21 @@ export class AutomationApplicationType extends ApplicationType {
5254
return SidebarComponentAutomation
5355
}
5456

57+
getTemplateSidebarComponent() {
58+
return WorkflowTemplateSideBar
59+
}
60+
61+
getTemplatesPageComponent() {
62+
return WorkflowTemplate
63+
}
64+
65+
getTemplatePage(application) {
66+
return {
67+
automation: application,
68+
page: application.workflows[0],
69+
}
70+
}
71+
5572
delete(application) {
5673
const { $store, $router } = this.app
5774
const workflowSelected = $store.getters['automationWorkflow/getWorkflows'](

web-frontend/modules/automation/components/AutomationHeader.vue

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
<template>
22
<header class="layout__col-2-1 header header--space-between">
3-
<ul class="header__filter">
4-
<li
5-
v-if="
6-
$hasPermission(
7-
'application.update',
8-
automation,
9-
automation.workspace.id
10-
)
11-
"
12-
class="header__filter-item"
13-
>
3+
<ul
4+
class="header__filter"
5+
v-if="
6+
$hasPermission(
7+
'application.update',
8+
automation,
9+
automation.workspace.id
10+
)
11+
"
12+
>
13+
<li class="header__filter-item">
1414
<a
1515
data-item-type="settings"
1616
class="header__filter-link"
1717
@click="openSettingsModal"
1818
><i class="header__filter-icon iconoir-settings"></i>
19-
<span class="header__filter-name">{{
20-
$t('automationHeader.settingsBtn')
21-
}}</span>
19+
<span class="header__filter-name"
20+
>{{ $t('automationHeader.settingsBtn') }}
21+
</span>
2222
</a>
2323
</li>
2424
<li class="header__filter-item">
@@ -62,7 +62,16 @@
6262
</li>
6363
</ul>
6464

65-
<div class="header__right">
65+
<div
66+
class="header__right"
67+
v-if="
68+
$hasPermission(
69+
'application.update',
70+
automation,
71+
automation.workspace.id
72+
)
73+
"
74+
>
6675
<span class="header__switch-container">
6776
<template v-if="!publishedOn">
6877
<Badge color="cyan" rounded size="small">{{

0 commit comments

Comments
 (0)