Skip to content
Permalink
Newer
Older
100644 192 lines (174 sloc) 10.3 KB
1
<!--
2
~ Copyright (c) 2019 Evolveum and contributors
3
~
4
~ This work is dual-licensed under the Apache License 2.0
5
~ and European Union Public License. See LICENSE file for details.
6
-->
7
8
<role xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
9
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
10
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
11
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
12
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
13
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
14
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
15
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
16
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
17
oid="bcaec940-50c8-44bb-aa37-b2b5bb2d5b90">
18
<name>metarole-grouper-provided-group</name>
19
<description>A metarole for archetyped Grouper-provided groups</description>
20
<!--
21
This metarole arranges everything that is needed for a Grouper group to live in midPoint.
22
The schema is the following:
23
24
Grouper group -> shadow -> org -> archetype -> this metarole
25
26
e.g.
27
28
ref:affiliation:member -> shadow -> affiliation_member -> affiliation (archetype) -> metarole-grouper-provided-group
29
30
1) Grouper group (e.g. ref:affiliation:member) has a shadow object.
31
32
2) An org object (affiliation_member) is created and linked to this shadow.
33
34
3) At the same time, appropriate archetype is assigned to the org, based on the Grouper name
35
(e.g. ref:affiliation:* leads to archetype affiliation).
36
37
4) This archetype defines basic parameters for the particular class of Grouper groups; e.g. where in midPoint
38
org tree they belong (e.g. under Affiliations org), where in LDAP tree they belong (e.g. under
39
ou=Affiliations,ou=Groups,dc=internet2,dc=edu), what's the schema for their midPoint name
40
(e.g. affiliation_...) and displayName (e.g. Affiliation: ...).
41
42
5) To avoid code duplication, these archetypes delegate specific processing
43
(i.e. filling-in appropriate properties of org objects) to metaroles:
44
to this one as well as to metarole-ldap-group.
45
46
This metarole is devoted to process Grouper-specific information for Grouper groups.
47
As a source it needs only two pieces of information: extension/grouperName (e.g. ref:affiliation:member)
48
and particular archetype (e.g. affiliation) with its configuration data.
49
50
It fills-in the following items: extension/grouperName -> identifier -> name and displayName
51
by inducing appropriate focus mappings to the org object.
52
-->
53
<inducement>
54
<focusMappings>
55
<mapping>
56
<name>identifier</name>
57
<description>This mapping fills-in org identifier (e.g. 'member') from extension/grouperName (e.g. 'ref:affiliation:member').
58
It uses extension/grouperNamePrefix information from the archetype (e.g. 'ref:affiliation:' defined in affiliation archetype)</description>
59
<strength>strong</strength>
60
<source>
61
<path>extension/grouperName</path>
62
</source>
63
<expression>
64
<script>
65
<code>
66
if (grouperName == null) {
67
null
68
} else {
69
archetype = assignmentPath[-2].source // e.g. archetype affiliation
70
log.info('archetype = {}', archetype)
71
if (archetype == null) {
72
throw new IllegalStateException('No archetype in assignment path: ' + assignmentPath)
73
}
74
grouperNamePrefix = basic.getExtensionPropertyValue(archetype, 'grouperNamePrefix') // e.g. 'ref:affiliation:'
75
if (grouperNamePrefix == null) {
76
throw new IllegalStateException('No grouper name prefix in archetype ' + archetype)
77
}
78
// grouperName is e.g. 'ref:affiliation:member'
79
if (grouperName.startsWith(grouperNamePrefix)) {
80
grouperName.substring(grouperNamePrefix.length()) // returning e.g. 'member'
81
} else {
82
throw new IllegalStateException('Grouper name ' + grouperName + ' does not match the expected prefix: ' + grouperNamePrefix)
83
}
84
}
85
</code>
86
</script>
87
</expression>
88
<target>
89
<path>identifier</path>
90
</target>
91
</mapping>
92
93
<mapping>
94
<name>name</name>
95
<description>This mapping fills-in org name (e.g. 'affiliation_member') from identifier (e.g. 'member').
96
It uses extension/midPointNamePrefix information from the archetype (e.g. 'affiliation_' defined in affiliation archetype)</description>
97
<strength>strong</strength>
98
<source>
99
<path>identifier</path>
100
</source>
101
<expression>
102
<script>
103
<code>
104
if (identifier == null) {
105
null
106
} else {
107
// e.g. identifier = 'member'
108
archetype = assignmentPath[-2].source // e.g. affiliation archetype
109
if (archetype == null) {
110
throw new IllegalStateException('No archetype in assignment path: ' + assignmentPath)
111
}
112
prefix = basic.getExtensionPropertyValue(archetype, 'midPointNamePrefix') // e.g. 'affiliation_'
113
prefix + identifier // e.g. 'affiliation_member'
114
}
115
</code>
116
</script>
117
</expression>
118
<target>
119
<path>name</path>
120
</target>
121
</mapping>
122
123
<mapping>
124
<name>displayName</name>
125
<description>This mapping fills-in org displayName (e.g. 'Affiliation: member') from identifier (e.g. 'member').
126
It uses extension/midPointDisplayNamePrefix information from the archetype (e.g. 'Affiliation: ' defined in affiliation archetype)</description>
127
<strength>strong</strength>
128
<source>
129
<path>identifier</path>
130
</source>
131
<expression>
132
<script>
133
<code>
134
if (identifier == null) {
135
null
136
} else {
137
archetype = assignmentPath[-2].source // e.g. affiliation archetype
138
if (archetype == null) {
139
throw new IllegalStateException('No archetype in assignment path: ' + assignmentPath)
140
}
141
prefix = basic.getExtensionPropertyValue(archetype, 'midPointDisplayNamePrefix') // e.g. 'Affiliation: '
142
prefix + identifier // e.g. 'Affiliation: member'
143
}
144
</code>
145
</script>
146
</expression>
147
<target>
148
<path>displayName</path>
149
</target>
150
</mapping>
151
152
<mapping>
153
<name>lifecycle state</name>
154
<description>This mapping sets org lifecycle state to be either "active" or "retired", depending on
155
whether Grouper group for this org still exists. Orgs in the latter state are on the way to deletion:
156
their members are unassigned and after no members are there, the org is automatically deleted.</description>
157
<strength>strong</strength>
158
<expression>
159
<script>
160
<code>
161
import com.evolveum.midpoint.model.impl.expr.*
162
import com.evolveum.midpoint.schema.*
163
import com.evolveum.midpoint.xml.ns._public.common.common_3.*
164
165
GROUPER_RESOURCE_OID = '1eff65de-5bb6-483d-9edf-8cc2c2ee0233'
166
167
modelContext = ModelExpressionThreadLocalHolder.lensContext
168
rsd = new ResourceShadowDiscriminator(GROUPER_RESOURCE_OID, ShadowKindType.ENTITLEMENT, 'group', null, false)
169
if (modelContext.findProjectionContext(rsd) != null) {
170
log.info('Projection context for Grouper group found, marking as "active"')
171
'active'
172
} else {
173
log.info('No projection context for Grouper group, marking as "retired"')
174
'retired'
175
}
176
</code>
177
</script>
178
</expression>
179
<target>
180
<path>lifecycleState</path>
181
</target>
182
</mapping>
183
</focusMappings>
184
185
<!--
186
Inducement order of 2 means these mappings are to be applied on org object, because the assignment structure is like this:
187
188
org -> archetype -> this-metarole
189
-->
190
<order>2</order>
191
</inducement>
192
</role>
You can’t perform that action at this time.