Skip to content

Commit f1f8e37

Browse files
[BB-1686] add push attribute action support and example (#90)
* add push attribute action support and example * add missing attr after rebase * remove unnecessary if statement * use any instead of interface{} in normalizeValue func * add support for queries in actions * add ci test and validation for actionCfg
1 parent 8d72d04 commit f1f8e37

File tree

17 files changed

+703
-66
lines changed

17 files changed

+703
-66
lines changed

.github/workflows/ci.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,18 @@ jobs:
8888
connector: ./baton-sql
8989
account-email: [email protected]
9090
account-login: "robert'); drop table users; --"
91+
- name: Run update user attributes action test
92+
run: |
93+
./baton-sql --invoke-action=update_user_attributes --invoke-action-args='{
94+
"user_id": "jane.doe",
95+
"attrs": {
96+
"first_name": "Janet",
97+
"job_title": "Senior Software Engineer"
98+
},
99+
"attrs_update_mask": ["first_name", "job_title"]
100+
}'
101+
- name: Verify update user attributes action
102+
run: |
103+
psql -h localhost --user postgres -d batondb -t -c "SELECT attr_first_name, attr_job_title FROM users WHERE username = 'jane.doe'" | grep -q "Janet.*Senior Software Engineer"
104+
env:
105+
PGPASSWORD: secretpassword

examples/mysql-test.yml

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,110 @@ connect:
1111
user: "${DB_USER}"
1212
password: "${DB_PASSWORD}"
1313

14+
actions:
15+
update_user_attributes:
16+
name: Update User Attributes
17+
description: Update the attributes of a user. Only provide the attributes you want to update.
18+
action_type:
19+
- account
20+
- account_update_profile
21+
arguments:
22+
user_id:
23+
name: User ID
24+
type: string
25+
required: true
26+
description: The ID of the user to update
27+
attrs:
28+
name: Attributes
29+
type: string_map
30+
required: true
31+
description: The updated attribute data (map of attribute names to values)
32+
attrs_update_mask:
33+
name: Attributes Update Mask
34+
type: string_list
35+
required: true
36+
description: The attributes to update (list of attribute names from attrs to actually update)
37+
vars:
38+
# Map each attribute in the attrs argument to a variable and a flag to indicate if the attribute should be updated
39+
manager_id: "'manager_id' in input.attrs ? input.attrs['manager_id'] : null"
40+
update_manager_id: "'manager_id' in input.attrs_update_mask"
41+
first_name: "'first_name' in input.attrs ? input.attrs['first_name'] : null"
42+
update_first_name: "'first_name' in input.attrs_update_mask"
43+
middle_name: "'middle_name' in input.attrs ? input.attrs['middle_name'] : null"
44+
update_middle_name: "'middle_name' in input.attrs_update_mask"
45+
last_name: "'last_name' in input.attrs ? input.attrs['last_name'] : null"
46+
update_last_name: "'last_name' in input.attrs_update_mask"
47+
display_name: "'display_name' in input.attrs ? input.attrs['display_name'] : null"
48+
update_display_name: "'display_name' in input.attrs_update_mask"
49+
job_title: "'job_title' in input.attrs ? input.attrs['job_title'] : null"
50+
update_job_title: "'job_title' in input.attrs_update_mask"
51+
department: "'department' in input.attrs ? input.attrs['department'] : null"
52+
update_department: "'department' in input.attrs_update_mask"
53+
division: "'division' in input.attrs ? input.attrs['division'] : null"
54+
update_division: "'division' in input.attrs_update_mask"
55+
company: "'company' in input.attrs ? input.attrs['company'] : null"
56+
update_company: "'company' in input.attrs_update_mask"
57+
employee_id: "'employee_id' in input.attrs ? input.attrs['employee_id'] : null"
58+
update_employee_id: "'employee_id' in input.attrs_update_mask"
59+
employee_number: "'employee_number' in input.attrs ? input.attrs['employee_number'] : null"
60+
update_employee_number: "'employee_number' in input.attrs_update_mask"
61+
employment_type: "'employment_type' in input.attrs ? input.attrs['employment_type'] : null"
62+
update_employment_type: "'employment_type' in input.attrs_update_mask"
63+
# We define the whole update logic with conditional attributes using CASE statements
64+
query: |
65+
UPDATE users
66+
SET
67+
manager_id = CASE
68+
WHEN ?<update_manager_id> THEN ?<manager_id>
69+
ELSE manager_id
70+
END,
71+
attr_first_name = CASE
72+
WHEN ?<update_first_name> THEN ?<first_name>
73+
ELSE attr_first_name
74+
END,
75+
attr_middle_name = CASE
76+
WHEN ?<update_middle_name> THEN ?<middle_name>
77+
ELSE attr_middle_name
78+
END,
79+
attr_last_name = CASE
80+
WHEN ?<update_last_name> THEN ?<last_name>
81+
ELSE attr_last_name
82+
END,
83+
attr_display_name = CASE
84+
WHEN ?<update_display_name> THEN ?<display_name>
85+
ELSE attr_display_name
86+
END,
87+
attr_job_title = CASE
88+
WHEN ?<update_job_title> THEN ?<job_title>
89+
ELSE attr_job_title
90+
END,
91+
attr_department = CASE
92+
WHEN ?<update_department> THEN ?<department>
93+
ELSE attr_department
94+
END,
95+
attr_division = CASE
96+
WHEN ?<update_division> THEN ?<division>
97+
ELSE attr_division
98+
END,
99+
attr_company = CASE
100+
WHEN ?<update_company> THEN ?<company>
101+
ELSE attr_company
102+
END,
103+
employee_id = CASE
104+
WHEN ?<update_employee_id> THEN ?<employee_id>
105+
ELSE employee_id
106+
END,
107+
attr_employee_number = CASE
108+
WHEN ?<update_employee_number> THEN ?<employee_number>
109+
ELSE attr_employee_number
110+
END,
111+
attr_employment_type = CASE
112+
WHEN ?<update_employment_type> THEN ?<employment_type>
113+
ELSE attr_employment_type
114+
END
115+
WHERE
116+
username = ?<user_id>
117+
14118
# Definition of different resource types managed by this connector
15119
resource_types:
16120
# Configuration for "user" resources in MySQL
@@ -37,7 +141,17 @@ resource_types:
37141
END as last_login,
38142
u.manager_id,
39143
m.username as manager_username,
40-
m.email as manager_email
144+
m.email as manager_email,
145+
u.attr_first_name,
146+
u.attr_middle_name,
147+
u.attr_last_name,
148+
u.attr_display_name,
149+
u.attr_job_title,
150+
u.attr_department,
151+
u.attr_division,
152+
u.attr_company,
153+
u.attr_employee_number,
154+
u.attr_employment_type
41155
FROM
42156
users u
43157
LEFT JOIN
@@ -83,6 +197,16 @@ resource_types:
83197
manager_id: ".manager_id"
84198
manager_username: ".manager_username"
85199
manager_email: ".manager_email"
200+
attr_first_name: ".attr_first_name"
201+
attr_middle_name: ".attr_middle_name"
202+
attr_last_name: ".attr_last_name"
203+
attr_display_name: ".attr_display_name"
204+
attr_job_title: ".attr_job_title"
205+
attr_department: ".attr_department"
206+
attr_division: ".attr_division"
207+
attr_company: ".attr_company"
208+
attr_employee_number: ".attr_employee_number"
209+
attr_employment_type: ".attr_employment_type"
86210

87211
# Account provisioning configuration with password support
88212
account_provisioning:
@@ -128,7 +252,17 @@ resource_types:
128252
END as last_login,
129253
u.manager_id,
130254
m.username as manager_username,
131-
m.email as manager_email
255+
m.email as manager_email,
256+
u.attr_first_name,
257+
u.attr_middle_name,
258+
u.attr_last_name,
259+
u.attr_display_name,
260+
u.attr_job_title,
261+
u.attr_department,
262+
u.attr_division,
263+
u.attr_company,
264+
u.attr_employee_number,
265+
u.attr_employment_type
132266
FROM users u
133267
LEFT JOIN users m ON u.manager_id = m.id
134268
WHERE u.username = ?<username>

examples/oracle-test.yml

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,100 @@ connect:
1010
user: "${DB_USER}"
1111
password: "${DB_PASSWORD}"
1212

13+
actions:
14+
enable_user:
15+
name: Enable User
16+
description: Enable a disabled user account
17+
action_type:
18+
- account_enable
19+
arguments:
20+
user_id:
21+
name: User ID
22+
type: string
23+
required: true
24+
description: The ID of the user to enable
25+
query: |
26+
UPDATE users SET status = 'active' WHERE username = ?<user_id>
27+
disable_user:
28+
name: Disable User
29+
description: Disable a user account
30+
action_type:
31+
- account_disable
32+
arguments:
33+
user_id:
34+
name: User ID
35+
type: string
36+
required: true
37+
description: The ID of the user to disable
38+
query: |
39+
UPDATE users SET status = 'disabled' WHERE username = ?<user_id>
40+
update_user_attributes:
41+
name: Update User Attributes
42+
description: Update the attributes of a user. Only provide the attributes you want to update.
43+
action_type:
44+
- account
45+
- account_update_profile
46+
arguments:
47+
user_id:
48+
name: User ID
49+
type: string
50+
required: true
51+
description: The ID of the user to update
52+
attrs:
53+
name: Attributes
54+
type: string_map
55+
required: true
56+
description: The updated attribute data (map of attribute names to values)
57+
attrs_update_mask:
58+
name: Attributes Update Mask
59+
type: string_list
60+
required: true
61+
description: The attributes to update (list of attribute names from attrs to actually update)
62+
vars:
63+
# Map each attribute in the attrs argument to a variable and a flag to indicate if the attribute should be updated
64+
manager_id: "'manager_id' in input.attrs ? input.attrs['manager_id'] : null"
65+
update_manager_id: "'manager_id' in input.attrs_update_mask"
66+
first_name: "'first_name' in input.attrs ? input.attrs['first_name'] : null"
67+
update_first_name: "'first_name' in input.attrs_update_mask"
68+
middle_name: "'middle_name' in input.attrs ? input.attrs['middle_name'] : null"
69+
update_middle_name: "'middle_name' in input.attrs_update_mask"
70+
last_name: "'last_name' in input.attrs ? input.attrs['last_name'] : null"
71+
update_last_name: "'last_name' in input.attrs_update_mask"
72+
display_name: "'display_name' in input.attrs ? input.attrs['display_name'] : null"
73+
update_display_name: "'display_name' in input.attrs_update_mask"
74+
job_title: "'job_title' in input.attrs ? input.attrs['job_title'] : null"
75+
update_job_title: "'job_title' in input.attrs_update_mask"
76+
department: "'department' in input.attrs ? input.attrs['department'] : null"
77+
update_department: "'department' in input.attrs_update_mask"
78+
division: "'division' in input.attrs ? input.attrs['division'] : null"
79+
update_division: "'division' in input.attrs_update_mask"
80+
company: "'company' in input.attrs ? input.attrs['company'] : null"
81+
update_company: "'company' in input.attrs_update_mask"
82+
employee_id: "'employee_id' in input.attrs ? input.attrs['employee_id'] : null"
83+
update_employee_id: "'employee_id' in input.attrs_update_mask"
84+
employee_number: "'employee_number' in input.attrs ? input.attrs['employee_number'] : null"
85+
update_employee_number: "'employee_number' in input.attrs_update_mask"
86+
employment_type: "'employment_type' in input.attrs ? input.attrs['employment_type'] : null"
87+
update_employment_type: "'employment_type' in input.attrs_update_mask"
88+
# We define the whole update logic with conditional attributes
89+
query: |
90+
UPDATE users
91+
SET
92+
manager_id = DECODE(?<update_manager_id>, '1', ?<manager_id>, manager_id),
93+
attr_first_name = DECODE(?<update_first_name>, '1', ?<first_name>, attr_first_name),
94+
attr_middle_name = DECODE(?<update_middle_name>, '1', ?<middle_name>, attr_middle_name),
95+
attr_last_name = DECODE(?<update_last_name>, '1', ?<last_name>, attr_last_name),
96+
attr_display_name = DECODE(?<update_display_name>, '1', ?<display_name>, attr_display_name),
97+
attr_job_title = DECODE(?<update_job_title>, '1', ?<job_title>, attr_job_title),
98+
attr_department = DECODE(?<update_department>, '1', ?<department>, attr_department),
99+
attr_division = DECODE(?<update_division>, '1', ?<division>, attr_division),
100+
attr_company = DECODE(?<update_company>, '1', ?<company>, attr_company),
101+
employee_id = DECODE(?<update_employee_id>, '1', ?<employee_id>, employee_id),
102+
attr_employee_number = DECODE(?<update_employee_number>, '1', ?<employee_number>, attr_employee_number),
103+
attr_employment_type = DECODE(?<update_employment_type>, '1', ?<employment_type>, attr_employment_type)
104+
WHERE
105+
username = ?<user_id>
106+
13107
# Definition of different resource types managed by this connector
14108
resource_types:
15109
# Configuration for "user" resources in Oracle
@@ -31,7 +125,17 @@ resource_types:
31125
account_type as "account_type",
32126
created_at as "created_at",
33127
last_login as "last_login",
34-
manager_id as "manager_id"
128+
manager_id as "manager_id",
129+
attr_first_name as "attr_first_name",
130+
attr_middle_name as "attr_middle_name",
131+
attr_last_name as "attr_last_name",
132+
attr_display_name as "attr_display_name",
133+
attr_job_title as "attr_job_title",
134+
attr_department as "attr_department",
135+
attr_division as "attr_division",
136+
attr_company as "attr_company",
137+
attr_employee_number as "attr_employee_number",
138+
attr_employment_type as "attr_employment_type"
35139
FROM
36140
users
37141
ORDER BY id
@@ -65,6 +169,25 @@ resource_types:
65169
- ".employee_id"
66170
# Last login timestamp mapping
67171
last_login: ".last_login"
172+
# Manager information
173+
manager_id: ".manager_id"
174+
175+
# Profile details for the user
176+
profile:
177+
user_id: ".id"
178+
created_at: ".created_at"
179+
last_login: ".last_login"
180+
manager_id: ".manager_id"
181+
attr_first_name: ".attr_first_name"
182+
attr_middle_name: ".attr_middle_name"
183+
attr_last_name: ".attr_last_name"
184+
attr_display_name: ".attr_display_name"
185+
attr_job_title: ".attr_job_title"
186+
attr_department: ".attr_department"
187+
attr_division: ".attr_division"
188+
attr_company: ".attr_company"
189+
attr_employee_number: ".attr_employee_number"
190+
attr_employment_type: ".attr_employment_type"
68191
account_provisioning:
69192
# Schema definition for account creation form
70193
schema:
@@ -324,4 +447,4 @@ resource_types:
324447
- skip_if: ".PRIVILEGE != resource.ID || .ADMIN_OPTION != 'YES'" # Condition for admin-level privilege mapping
325448
principal_id: ".USERNAME" # Map the USERNAME to the principal ID
326449
principal_type: "user" # Define the principal type as user
327-
entitlement_id: "admin" # Apply the 'admin' entitlement when administrative rights are present
450+
entitlement_id: "admin" # Apply the 'admin' entitlement when administrative rights are present

0 commit comments

Comments
 (0)