Hook based pushing of account data to keycloak.
Showing
8 changed files
with
509 additions
and
0 deletions
entity/Keycloak.eecas.xml
0 → 100644
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!-- | ||
3 | This software is in the public domain under CC0 1.0 Universal plus a | ||
4 | Grant of Patent License. | ||
5 | |||
6 | To the extent possible under law, the author(s) have dedicated all | ||
7 | copyright and related and neighboring rights to this software to the | ||
8 | public domain worldwide. This software is distributed without any | ||
9 | warranty. | ||
10 | |||
11 | You should have received a copy of the CC0 Public Domain Dedication | ||
12 | along with this software (see the LICENSE.md file). If not, see | ||
13 | <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
14 | --> | ||
15 | <eecas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/entity-eca-3.xsd"> | ||
16 | <!-- | ||
17 | moqui.security.UserGroup | ||
18 | moqui.security.UserGroupMember | ||
19 | moqui.security.UserGroupPermission | ||
20 | moqui.security.UserPermission | ||
21 | mantle.party.PartyClassification | ||
22 | |||
23 | moqui.security.UserPermission -> userPermission:$id | ||
24 | mantle.party.PartyClassification -> partyClassification:$id | ||
25 | mantle.party.RoleType -> roleType:$id | ||
26 | |||
27 | moqui.security.UserAccount | ||
28 | |||
29 | moqui.security.UserAccount | ||
30 | mantle.party.Party | ||
31 | mantle.party.PartyClassificationAppl | ||
32 | mantle.party.PartyRole | ||
33 | mantle.party.Person | ||
34 | mantle.party.RoleType | ||
35 | mantle.party.contact.ContactMech | ||
36 | mantle.party.contact.TelecomNumber | ||
37 | mantle.party.contact.PostalAddress | ||
38 | mantle.party.contact.PartyContactMech | ||
39 | |||
40 | Future use: | ||
41 | mantle.party.PartyRelationship | ||
42 | --> | ||
43 | <eeca id="ContactMech" entity="mantle.party.contact.ContactMech" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
44 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'ContactMech', value: contactMechId]"/></actions> | ||
45 | </eeca> | ||
46 | <eeca id="Party" entity="mantle.party.Party" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
47 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'Party', value: partyId]"/></actions> | ||
48 | </eeca> | ||
49 | <eeca id="PartyClassification" entity="mantle.party.PartyClassification" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
50 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'PartyClassification', value: partyClassificationId]"/></actions> | ||
51 | </eeca> | ||
52 | <eeca id="PartyClassificationAppl" entity="mantle.party.PartyClassificationAppl" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
53 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'Party', value: partyId]"/></actions> | ||
54 | </eeca> | ||
55 | <eeca id="PartyContactMech" entity="mantle.party.contact.PartyContactMech" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
56 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'Party', value: partyId]"/></actions> | ||
57 | </eeca> | ||
58 | <eeca id="PartyRole" entity="mantle.party.PartyRole" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
59 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'Party', value: partyId]"/></actions> | ||
60 | </eeca> | ||
61 | <eeca id="Person" entity="mantle.party.Person" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
62 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'Party', value: partyId]"/></actions> | ||
63 | </eeca> | ||
64 | <eeca id="PostalAddress" entity="mantle.party.contact.PostalAddress" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
65 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'ContactMech', value: contactMechId]"/></actions> | ||
66 | </eeca> | ||
67 | <eeca id="RoleType" entity="mantle.party.RoleType" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
68 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'RoleType', value: roleTypeId]"/></actions> | ||
69 | </eeca> | ||
70 | <eeca id="TelecomNumber" entity="mantle.party.contact.TelecomNumber" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
71 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'ContactMech', value: contactMechId]"/></actions> | ||
72 | </eeca> | ||
73 | <eeca id="UserAccount" entity="moqui.security.UserAccount" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
74 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'UserAccount', value: userId]"/></actions> | ||
75 | </eeca> | ||
76 | <eeca id="UserGroup" entity="moqui.security.UserGroup" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
77 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'UserGroup', value: userGroupId]"/></actions> | ||
78 | </eeca> | ||
79 | <eeca id="UserGroupMember" entity="moqui.security.UserGroupMember" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
80 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'UserAccount', value: userId]"/></actions> | ||
81 | </eeca> | ||
82 | <eeca id="UserGroupPermission" entity="moqui.security.UserGroupPermission" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
83 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'UserGroup', value: userGroupId]"/></actions> | ||
84 | </eeca> | ||
85 | <eeca id="UserPermission" entity="moqui.security.UserPermission" on-create="true" on-update="true" on-delete="true" run-on-error="false" get-entire-entity="false" get-original-value="false"> | ||
86 | <actions><service-call name="keycloak.HookServices.handle#EntityUpdate" in-map="[entityName: 'UserPermission', value: userPermissionId]"/></actions> | ||
87 | </eeca> | ||
88 | </eecas> |
1 | <screen-extend xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/xml-screen-3.xsd"> | ||
2 | |||
3 | <form-single name="UpdateUserAccount"> | ||
4 | <field name="externalUserId"><default-field><text-line size="60"/></default-field></field> | ||
5 | </form-single> | ||
6 | |||
7 | </screen-extend> |
1 | <screen-extend xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/xml-screen-3.xsd"> | ||
2 | |||
3 | <form-single name="UpdateUserAccount"> | ||
4 | <field name="externalUserId"><default-field><text-line size="60"/></default-field></field> | ||
5 | <field-layout> | ||
6 | <fields-not-referenced/> | ||
7 | <field-row><field-ref name="externalUserId"/></field-row> | ||
8 | <field-row><field-ref name="requirePasswordChange"/><field-ref name="disabled"/></field-row> | ||
9 | <field-row><field-ref name="successiveFailedLogins"/><field-ref name="disabledDateTime"/></field-row> | ||
10 | <field-ref name="submitButton"/> | ||
11 | </field-layout> | ||
12 | </form-single> | ||
13 | <!-- | ||
14 | |||
15 | |||
16 | --> | ||
17 | </screen-extend> |
service/Keycloak.secas.xml
0 → 100644
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!-- | ||
3 | This software is in the public domain under CC0 1.0 Universal plus a | ||
4 | Grant of Patent License. | ||
5 | |||
6 | To the extent possible under law, the author(s) have dedicated all | ||
7 | copyright and related and neighboring rights to this software to the | ||
8 | public domain worldwide. This software is distributed without any | ||
9 | warranty. | ||
10 | |||
11 | You should have received a copy of the CC0 Public Domain Dedication | ||
12 | along with this software (see the LICENSE.md file). If not, see | ||
13 | <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
14 | --> | ||
15 | <secas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/service-eca-3.xsd"> | ||
16 | <!-- Invoice GL Posting --> | ||
17 | <seca id="updatePasswordInternal" service="org.moqui.impl.UserServices.update#PasswordInternal" when="post-service" run-on-error="false"> | ||
18 | <condition><expression>updateSuccessful</expression></condition> | ||
19 | <actions><service-call name="keycloak.HookServices.handle#UpdatePasswordInternal" in-map="context"/></actions> | ||
20 | </seca> | ||
21 | <!-- | ||
22 | <service verb="update" noun="PasswordInternal" authenticate="false" allow-remote="false"> | ||
23 | <in-parameters> | ||
24 | <parameter name="userId" required="true"/> | ||
25 | <parameter name="newPassword" required="true"/> | ||
26 | <parameter name="newPasswordVerify" required="true"/> | ||
27 | <parameter name="requirePasswordChange" default-value="N"/> | ||
28 | </in-parameters> | ||
29 | <out-parameters> | ||
30 | <parameter name="passwordIssues" type="Boolean"/> | ||
31 | <parameter name="updateSuccessful" type="Boolean"/> | ||
32 | </out-parameters> | ||
33 | --> | ||
34 | </secas> |
service/keycloak/HookServices.groovy
0 → 100644
1 | import javax.transaction.Synchronization | ||
2 | import javax.transaction.xa.XAResource | ||
3 | import javax.transaction.xa.Xid | ||
4 | |||
5 | import groovy.transform.Field | ||
6 | |||
7 | import org.slf4j.Logger | ||
8 | import org.slf4j.LoggerFactory | ||
9 | |||
10 | import org.moqui.util.RestClient | ||
11 | import org.moqui.util.ObjectUtilities | ||
12 | import org.moqui.context.ExecutionContext | ||
13 | import org.moqui.entity.EntityCondition | ||
14 | import org.moqui.entity.EntityFind | ||
15 | import org.moqui.entity.EntityList | ||
16 | import org.moqui.entity.EntityValue | ||
17 | |||
18 | @Field Logger logger = LoggerFactory.getLogger(getClass().getName()) | ||
19 | //'HookServices') | ||
20 | |||
21 | class HookSynchronization implements Synchronization { | ||
22 | private final ExecutionContext ec; | ||
23 | |||
24 | private static class EntityToken { | ||
25 | protected final String entityName | ||
26 | protected final String keyName | ||
27 | protected final Object keyValue | ||
28 | protected final Map<String, Object> extraParameters = new HashMap<String, Object>() | ||
29 | |||
30 | protected EntityToken(String entityName, String keyName, Object keyValue) { | ||
31 | this.entityName = entityName | ||
32 | this.keyName = keyName | ||
33 | this.keyValue = keyValue | ||
34 | } | ||
35 | |||
36 | public boolean equals(Object other) { | ||
37 | if (!(other instanceof EntityToken)) { | ||
38 | return false | ||
39 | } | ||
40 | EntityToken that = (EntityToken) other | ||
41 | return entityName.equals(that.entityName) && keyName.equals(that.keyName) && keyValue.equals(that.keyValue) | ||
42 | } | ||
43 | |||
44 | public int hashCode() { | ||
45 | return entityName.hashCode() ^ keyName.hashCode() ^ keyValue.hashCode() | ||
46 | } | ||
47 | } | ||
48 | |||
49 | private Map<EntityToken, Map<String, Object>> updates = new LinkedHashMap<>() | ||
50 | |||
51 | protected HookSynchronization(ExecutionContext ec) { | ||
52 | this.ec = ec | ||
53 | } | ||
54 | |||
55 | protected void add(String entityName, String keyName, Object keyValue, Map<String, Object> extraParameters) { | ||
56 | EntityToken entityToken = new EntityToken(entityName, keyName, keyValue) | ||
57 | // This always move the value to the end of the list | ||
58 | Map<String, Object> existingExtraParameters = updates.remove(entityToken) | ||
59 | Map<String, Object> newExtraParameters = [:] | ||
60 | if (existingExtraParameters) { | ||
61 | newExtraParameters.putAll(existingExtraParameters) | ||
62 | } | ||
63 | if (extraParameters) { | ||
64 | newExtraParameters.putAll(extraParameters) | ||
65 | } | ||
66 | updates.put(entityToken, newExtraParameters) | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public void beforeCompletion() { | ||
71 | List<Map<String, Object>> updates = [] | ||
72 | for (Map.Entry<EntityToken, Map<String, Object>> entry: this.updates.entrySet()) { | ||
73 | EntityToken token = entry.getKey() | ||
74 | Map<String, Object> extraParameters = entry.getValue() | ||
75 | updates.add([ | ||
76 | entityName: token.entityName, | ||
77 | keyName: token.keyName, | ||
78 | keyValue: token.keyValue, | ||
79 | extraParameters: extraParameters, | ||
80 | ]) | ||
81 | } | ||
82 | ec.getService().async().name("keycloak.HookServices.process#Updates").parameter('updates', updates).call() | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public void afterCompletion(int status) { | ||
87 | |||
88 | } | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | class HookXAResource implements XAResource { | ||
93 | private static class EntityPk { | ||
94 | protected String entityName; | ||
95 | protected Map<String, Object> pk; | ||
96 | |||
97 | protected EntityPk(EntityValue entity) { | ||
98 | this.entityName = entity.getEntityName() | ||
99 | this.pk = entity.getPrimaryKeys() | ||
100 | } | ||
101 | |||
102 | public boolean equals(Object other) { | ||
103 | if (!(object instanceof EntityPk)) { | ||
104 | return false | ||
105 | } | ||
106 | EntityPk that = (EntityPk) other | ||
107 | return entityName.equals(that.entityName) && pk.equals(that.pk) | ||
108 | } | ||
109 | |||
110 | public int hashCode() { | ||
111 | return entityName.hashCode ^ pk.hashCode() | ||
112 | } | ||
113 | } | ||
114 | |||
115 | private Map<Xid, Set<EntityPk>> modifiedValues = new HashMap<>() | ||
116 | private int timeout = 60 | ||
117 | |||
118 | @Override | ||
119 | public void commit(Xid xid, boolean onePhase) { | ||
120 | |||
121 | } | ||
122 | |||
123 | @Override | ||
124 | public void end(Xid xid, int flags) { | ||
125 | if (flags & TMFAIL) { | ||
126 | |||
127 | } else if (flags & TMSUSPEND) { | ||
128 | |||
129 | } else if (flags & TMSUCCESS) { | ||
130 | |||
131 | } | ||
132 | } | ||
133 | |||
134 | @Override | ||
135 | public void forget(Xid xid) { | ||
136 | modifiedValues.remove(xid) | ||
137 | } | ||
138 | |||
139 | @Override | ||
140 | public int getTransactionTimeout() { | ||
141 | return timeout | ||
142 | } | ||
143 | |||
144 | @Override | ||
145 | public boolean isSameRM(XAResource xar) { | ||
146 | return getClass().equals(xar.getClass()) | ||
147 | } | ||
148 | |||
149 | @Override | ||
150 | public int prepare(Xid xid) { | ||
151 | if (!keycloak.connected()) { | ||
152 | throw new XAException(XAException.XAERR_RMFAIL) | ||
153 | } | ||
154 | } | ||
155 | |||
156 | @Override | ||
157 | public Xid[] recover(int flag) { | ||
158 | |||
159 | } | ||
160 | |||
161 | @Override | ||
162 | public void rollback(Xid xid) { | ||
163 | |||
164 | } | ||
165 | |||
166 | @Override | ||
167 | public boolean setTransactionTimeout(int timeout) { | ||
168 | this.timeout = timeout | ||
169 | } | ||
170 | |||
171 | @Override | ||
172 | public void start(Xid xid, int flags) { | ||
173 | |||
174 | } | ||
175 | |||
176 | } | ||
177 | */ | ||
178 | |||
179 | HookSynchronization getHookSync() { | ||
180 | HookSynchronization hookSync = ec.transaction.getActiveSynchronization(getClass().getName()) | ||
181 | if (hookSync == null) { | ||
182 | hookSync = new HookSynchronization(ec) | ||
183 | ec.transaction.putAndEnlistActiveSynchronization(getClass().getName(), hookSync) | ||
184 | } | ||
185 | return hookSync | ||
186 | } | ||
187 | |||
188 | Map<String, Object> handleEntityUpdate() { | ||
189 | logger.info("handleEntityUpdate: ${context.entityName}[${context.value}]") | ||
190 | logger.info("context: ${context}") | ||
191 | ExecutionContext ec = context.ec | ||
192 | Map<String, Object> contextRoot = ec.getContextRoot() | ||
193 | Map<String, Set<Object>> toRegister = contextRoot['KeycloakEntityRegistrations'] | ||
194 | logger.info("toRegister: ${toRegister}") | ||
195 | if (toRegister == null) { | ||
196 | toRegister = contextRoot['KeycloakEntityRegistrations'] = [:] | ||
197 | } | ||
198 | |||
199 | HookSynchronization hookSync = getHookSync() | ||
200 | |||
201 | List<Map<String, Object>> queue = [[entityName: context.entityName, value: context.value]] | ||
202 | |||
203 | while (!queue.isEmpty()) { | ||
204 | Map<String, Object> entry = queue.remove(0) | ||
205 | logger.info("processing entry: ${entry}") | ||
206 | String entityName = entry.entityName | ||
207 | Object value = entry.value | ||
208 | Set<Object> entityRegistrations = toRegister[entityName] | ||
209 | if (entityRegistrations == null) { | ||
210 | entityRegistrations = toRegister[entityName] = new HashSet() | ||
211 | entityRegistrations.add(value) | ||
212 | } else if (entityRegistrations.contains(value)) { | ||
213 | continue | ||
214 | } | ||
215 | String keyName | ||
216 | switch (entityName) { | ||
217 | case 'Party': | ||
218 | EntityList userAccounts = ec.entity.find('UserAccount').condition('partyId', value).list() | ||
219 | for (EntityValue userAccount: userAccounts) { | ||
220 | queue.add([entityName: 'UserAccount', value: userAccount.userId]) | ||
221 | } | ||
222 | continue | ||
223 | case 'ContactMech': | ||
224 | EntityList partyContactMechs = ec.entity.find('PartyContactMech').condition('contactMechId', value).list() | ||
225 | for (EntityValue partyContactMech: partyContactMechs) { | ||
226 | queue.add([entityName: 'Party', value: partyContactMech.partyId]) | ||
227 | } | ||
228 | continue | ||
229 | case 'UserAccount': | ||
230 | keyName = 'userId' | ||
231 | break | ||
232 | case 'UserGroup': | ||
233 | keyName = 'userGroupId' | ||
234 | break | ||
235 | case 'UserGroupMember': | ||
236 | keyName = 'userGroupId' | ||
237 | break | ||
238 | case 'UserPermission': | ||
239 | keyName = 'userPermissionId' | ||
240 | break | ||
241 | case 'PartyClassification': | ||
242 | keyName = 'partyClassificationId' | ||
243 | break | ||
244 | case 'RoleType': | ||
245 | keyName = 'roleTypeId' | ||
246 | break | ||
247 | } | ||
248 | ec.getLogger().info("Registered synchronization for ${entityName}: [${value}]") | ||
249 | hookSync.add(entityName, keyName, value, [:]) | ||
250 | //ec.getService().special().name("keycloak.KeycloakServices.send#${entityName}").parameter(keyName, value).registerOnCommit() | ||
251 | } | ||
252 | } | ||
253 | |||
254 | Map<String, Object> handleUpdatePasswordInternal() { | ||
255 | String userId = ec.context.userId | ||
256 | String newPassword = ec.context.newPassword | ||
257 | Boolean requirePasswordChange = ec.context.requirePasswordChange | ||
258 | ec.getLogger().info("Registered synchronization for update#PasswordInternal: [${userId}]") | ||
259 | HookSynchronization hookSync = getHookSync() | ||
260 | hookSync.add('UserAccount', 'userId', userId, [ | ||
261 | newPassword: newPassword, | ||
262 | requirePasswordChange: requirePasswordChange, | ||
263 | ]) | ||
264 | } | ||
265 | |||
266 | Map<String, Object> processUpdates() { | ||
267 | List<Map<String, Object>> updates = context.updates | ||
268 | |||
269 | for (Map<String, Object> update: updates) { | ||
270 | Map<String, Object> parameters = [:] | ||
271 | parameters[update.keyName] = update.keyValue | ||
272 | parameters.putAll(update.extraParameters) | ||
273 | ec.getService().sync().name("keycloak.KeycloakServices.send#${update.entityName}").parameters(parameters).call() | ||
274 | } | ||
275 | return [:] | ||
276 | } | ||
277 |
service/keycloak/HookServices.xml
0 → 100644
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!-- | ||
3 | This software is in the public domain under CC0 1.0 Universal plus a | ||
4 | Grant of Patent License. | ||
5 | |||
6 | To the extent possible under law, the author(s) have dedicated all | ||
7 | copyright and related and neighboring rights to this software to the | ||
8 | public domain worldwide. This software is distributed without any | ||
9 | warranty. | ||
10 | |||
11 | You should have received a copy of the CC0 Public Domain Dedication | ||
12 | along with this software (see the LICENSE.md file). If not, see | ||
13 | <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
14 | --> | ||
15 | <services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/service-definition-3.xsd"> | ||
16 | |||
17 | <service verb="handle" noun="EntityUpdate" type="script" location="component://moqui-keycloak/service/keycloak/HookServices.groovy" method="handleEntityUpdate" authenticate="anonymous-all"> | ||
18 | <in-parameters> | ||
19 | <parameter name="entityName" type="String" required="true"/> | ||
20 | <parameter name="value" type="Object" required="true"/> | ||
21 | </in-parameters> | ||
22 | </service> | ||
23 | |||
24 | <service verb="handle" noun="UpdatePasswordInternal" type="script" location="component://moqui-keycloak/service/keycloak/HookServices.groovy" method="handleUpdatePasswordInternal" authenticate="anonymous-all"> | ||
25 | <in-parameters> | ||
26 | <parameter name="userId" required="true"/> | ||
27 | <parameter name="newPassword" required="true"/> | ||
28 | <parameter name="requirePasswordChange"/> | ||
29 | </in-parameters> | ||
30 | </service> | ||
31 | |||
32 | <service verb="process" noun="Updates" type="script" location="component://moqui-keycloak/service/keycloak/HookServices.groovy" method="processUpdates" authenticate="anonymous-all"> | ||
33 | <in-parameters> | ||
34 | <parameter name="updates" type="List" required="true"/> | ||
35 | </in-parameters> | ||
36 | </service> | ||
37 | </services> |
This diff is collapsed.
Click to expand it.
... | @@ -14,6 +14,55 @@ along with this software (see the LICENSE.md file). If not, see | ... | @@ -14,6 +14,55 @@ along with this software (see the LICENSE.md file). If not, see |
14 | --> | 14 | --> |
15 | <services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/service-definition-3.xsd"> | 15 | <services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/service-definition-3.xsd"> |
16 | 16 | ||
17 | <service verb="send" noun="UserAccount" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="syncUserAccount" authenticate="anonymous-all"> | ||
18 | <in-parameters> | ||
19 | <parameter name="userId" type="String" required="true"/> | ||
20 | <parameter name="newPassword" required="false"/> | ||
21 | <parameter name="requirePasswordChange"/> | ||
22 | </in-parameters> | ||
23 | </service> | ||
24 | |||
25 | <service verb="update" noun="PasswordInternal" authenticate="false" allow-remote="false" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="updatePasswordInternal"> | ||
26 | <in-parameters> | ||
27 | <parameter name="userId" required="true"/> | ||
28 | <parameter name="newPassword" required="true"/> | ||
29 | <parameter name="requirePasswordChange"/> | ||
30 | </in-parameters> | ||
31 | </service> | ||
32 | |||
33 | <service verb="send" noun="UserGroup" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="syncUserGroup" authenticate="anonymous-all"> | ||
34 | <in-parameters> | ||
35 | <parameter name="userGroupId" type="String" required="true"/> | ||
36 | </in-parameters> | ||
37 | </service> | ||
38 | |||
39 | <service verb="send" noun="UserPermission" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="syncUserPermission" authenticate="anonymous-all"> | ||
40 | <in-parameters> | ||
41 | <parameter name="userPermissionId" type="String" required="true"/> | ||
42 | </in-parameters> | ||
43 | </service> | ||
44 | |||
45 | <service verb="send" noun="RoleType" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="syncRoleType" authenticate="anonymous-all"> | ||
46 | <in-parameters> | ||
47 | <parameter name="roleTypeId" type="String" required="true"/> | ||
48 | </in-parameters> | ||
49 | </service> | ||
50 | |||
51 | <service verb="send" noun="PartyClassification" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="syncPartyClassification" authenticate="anonymous-all"> | ||
52 | <in-parameters> | ||
53 | <parameter name="partyClassificationId" type="String" required="true"/> | ||
54 | </in-parameters> | ||
55 | </service> | ||
56 | |||
17 | <service verb="get" noun="KeycloakUsers" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="getKeycloakUsers"> | 57 | <service verb="get" noun="KeycloakUsers" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="getKeycloakUsers"> |
18 | </service> | 58 | </service> |
59 | |||
60 | <!-- | ||
61 | <service verb="update" noun="PasswordInternal" type="script" location="component://moqui-keycloak/service/keycloak/KeycloakServices.groovy" method="updatePasswordInternal" authenticate="anonymous-all"> | ||
62 | <in-parameters> | ||
63 | <parameter name="userId" type="String" required="true"/> | ||
64 | <parameter name="newPassword" type="String" required="true"/> | ||
65 | </in-parameters> | ||
66 | </service> | ||
67 | --> | ||
19 | </services> | 68 | </services> | ... | ... |
-
Please register or sign in to post a comment