Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Post-init objects for midPoint. after-installation.sh should not be n…
…eeded anymore now.
ivan committed Nov 13, 2019
1 parent 74fc9ef commit 3d1d731
Showing 31 changed files with 2,552 additions and 0 deletions.
@@ -0,0 +1,52 @@
<archetype xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://grouper-demo.tier.internet2.edu"
oid="56f53812-047d-4b69-83e8-519a73d161e1">
<name>affiliation</name>
<extension>
<ext:grouperNamePrefix>ref:affiliation:</ext:grouperNamePrefix>
<ext:ldapRootDn>ou=Affiliations,ou=Groups,dc=internet2,dc=edu</ext:ldapRootDn>
<ext:midPointNamePrefix>affiliation_</ext:midPointNamePrefix>
<ext:midPointDisplayNamePrefix>Affiliation: </ext:midPointDisplayNamePrefix>
</extension>
<archetypePolicy>
<display>
<label>Affiliation</label>
<pluralLabel>Affiliations</pluralLabel>
<icon>
<cssClass>fa fa-superpowers</cssClass>
<color>steelblue</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<targetRef oid="bcaec940-50c8-44bb-aa37-b2b5bb2d5b90" relation="org:default" type="c:RoleType" /> <!-- metarole-grouper-provided-group -->
</assignment>
<assignment>
<targetRef oid="8da46694-bd71-4e1e-bfd7-73865ae2ea9a" relation="org:default" type="c:RoleType" /> <!-- metarole-ldap-group -->
</assignment>
<inducement>
<targetRef oid="1d7c0e3a-4456-409c-9f50-95407b2eb785" relation="org:default" type="c:OrgType" /> <!-- affiliations -->
</inducement>
<!-- Group-type-specific data -->
<inducement>
<construction>
<resourceRef oid="e417225d-8a08-46f3-9b5d-624990b52386" relation="org:default" type="c:ResourceType" /> <!-- Faculty CSV -->
</construction>
<order>2</order>
<condition>
<expression>
<script>
<code>assignmentPath[0].target.identifier == 'faculty'</code>
</script>
</expression>
</condition>
</inducement>
</archetype>
@@ -0,0 +1,63 @@
<archetype xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://grouper-demo.tier.internet2.edu"
oid="3dab9a72-118b-4e40-a138-bb691c335eca">
<name>course</name>
<extension>
<ext:grouperNamePrefix>ref:course:</ext:grouperNamePrefix>
<ext:ldapRootDn>ou=Courses,ou=Groups,dc=internet2,dc=edu</ext:ldapRootDn>
<ext:midPointNamePrefix>course_</ext:midPointNamePrefix>
<ext:midPointDisplayNamePrefix>Course: </ext:midPointDisplayNamePrefix>
</extension>
<archetypePolicy>
<display>
<label>Course</label>
<pluralLabel>Courses</pluralLabel>
<icon>
<cssClass>fa fa-university</cssClass>
<color>teal</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<targetRef oid="bcaec940-50c8-44bb-aa37-b2b5bb2d5b90" relation="org:default" type="c:RoleType" /> <!-- metarole-grouper-provided-group -->
</assignment>
<assignment>
<targetRef oid="8da46694-bd71-4e1e-bfd7-73865ae2ea9a" relation="org:default" type="c:RoleType" /> <!-- metarole-ldap-group -->
</assignment>
<inducement>
<targetRef oid="225e9360-0639-40ba-8a31-7f31bef067be" relation="org:default" type="c:OrgType" /> <!-- courses -->
</inducement>
<!-- Group-type-specific data -->
<inducement>
<construction>
<resourceRef oid="a343fc2e-3954-4034-ba1a-2b72c21e577a" relation="org:default" type="c:ResourceType" /> <!-- CS CSV -->
<attribute>
<c:ref>ri:courses</c:ref>
<outbound>
<strength>strong</strength>
<expression>
<script>
<code>assignmentPath[0].target.identifier</code>
</script>
</expression>
</outbound>
</attribute>
</construction>
<order>2</order>
<condition>
<expression>
<script>
<code>assignmentPath[0].target.identifier?.startsWith('CS')</code>
</script>
</expression>
</condition>
</inducement>
</archetype>
@@ -0,0 +1,53 @@
<archetype xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://grouper-demo.tier.internet2.edu"
oid="1cec5f78-8fba-459b-9547-ef7485009f40">
<name>department</name>
<extension>
<ext:grouperNamePrefix>ref:dept:</ext:grouperNamePrefix>
<ext:midPointNamePrefix>department_</ext:midPointNamePrefix>
<ext:midPointDisplayNamePrefix>Department: </ext:midPointDisplayNamePrefix>
</extension>
<archetypePolicy>
<display>
<label>Department</label>
<pluralLabel>Departments</pluralLabel>
<icon>
<cssClass>fa fa-building</cssClass>
<color>darkgreen</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<targetRef oid="bcaec940-50c8-44bb-aa37-b2b5bb2d5b90" relation="org:default" type="c:RoleType" /> <!-- metarole-grouper-provided-group -->
</assignment>
<!-- No LDAP metarole here: we deal with LDAP ourselves -->
<inducement>
<targetRef oid="bee44c51-2469-411d-bac7-695728e9c241" relation="org:default" type="c:OrgType" /> <!-- departments -->
</inducement>
<!-- Group-type-specific data -->
<inducement>
<construction>
<resourceRef oid="0a37121f-d515-4a23-9b6d-554c5ef61272" relation="org:default" type="c:ResourceType" /> <!-- LDAP -->
<attribute>
<ref>ri:businessCategory</ref>
<outbound>
<strength>strong</strength>
<expression>
<script>
<code>assignmentPath[0].target.identifier</code>
</script>
</expression>
</outbound>
</attribute>
</construction>
<order>2</order>
</inducement>
</archetype>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<archetype oid="9ea701a0-fefb-11e9-aa4a-6f55fba8896e"
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:org='http://midpoint.evolveum.com/xml/ns/public/common/org-3'>
<name>External</name>
<description>Non-academic person with no relation to the academy environment</description>
<archetypePolicy>
<display>
<label>External</label>
<pluralLabel>Externals</pluralLabel>
<tooltip>Person imported from the external database</tooltip>
<icon>
<cssClass>fa fa-space-shuttle</cssClass>
<color>olive</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<assignmentRelation>
<holderType>UserType</holderType>
</assignmentRelation>
</assignment>
</archetype>
@@ -0,0 +1,40 @@
<archetype xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://grouper-demo.tier.internet2.edu"
oid="5f2b96d2-49b5-4a8a-9601-14457309a69b">
<name>generic-grouper-group</name>
<extension>
<ext:grouperNamePrefix></ext:grouperNamePrefix>
<ext:ldapRootDn>ou=generic,ou=Groups,dc=internet2,dc=edu</ext:ldapRootDn>
<ext:midPointNamePrefix>generic_</ext:midPointNamePrefix>
<ext:midPointDisplayNamePrefix></ext:midPointDisplayNamePrefix>
</extension>
<archetypePolicy>
<display>
<label>Generic Grouper Group</label>
<pluralLabel>Generic Grouper Groups</pluralLabel>
<icon>
<cssClass>fa fa-users</cssClass>
<color>lightcoral</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<targetRef oid="bcaec940-50c8-44bb-aa37-b2b5bb2d5b90" relation="org:default" type="c:RoleType" /> <!-- metarole-grouper-provided-group -->
</assignment>
<assignment>
<targetRef oid="8da46694-bd71-4e1e-bfd7-73865ae2ea9a" relation="org:default" type="c:RoleType" /> <!-- metarole-ldap-group -->
</assignment>
<inducement>
<targetRef oid="1f339075-5b2f-4a18-9c98-451f3eb0d28d" relation="org:default" type="c:OrgType" /> <!-- generic-groups -->
</inducement>
<!-- Group-type-specific data -->
<!-- nothing here by now -->
</archetype>
@@ -0,0 +1,56 @@
<archetype xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://grouper-demo.tier.internet2.edu"
oid="1645d1dc-1f7c-4508-b50b-97b501ccdee3">
<name>mailing-list</name>
<extension>
<ext:grouperNamePrefix>app:mailinglist:</ext:grouperNamePrefix>
<ext:ldapRootDn>ou=generic,ou=Groups,dc=internet2,dc=edu</ext:ldapRootDn> <!-- could be also something specific e.g. ou=lists,ou=Groups,dc=internet2,dc=edu -->
<ext:midPointNamePrefix>mailinglist_</ext:midPointNamePrefix>
<ext:midPointDisplayNamePrefix>Mailing list: </ext:midPointDisplayNamePrefix>
</extension>
<archetypePolicy>
<display>
<label>Mailing list</label>
<pluralLabel>Mailing lists</pluralLabel>
<icon>
<cssClass>fa fa-list</cssClass>
<color>darkgoldenrod</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<targetRef oid="bcaec940-50c8-44bb-aa37-b2b5bb2d5b90" relation="org:default" type="c:RoleType" /> <!-- metarole-grouper-provided-group -->
</assignment>
<assignment>
<targetRef oid="8da46694-bd71-4e1e-bfd7-73865ae2ea9a" relation="org:default" type="c:RoleType" /> <!-- metarole-ldap-group -->
</assignment>
<inducement>
<targetRef oid="d81fb46c-20c7-44d3-8402-fef404ea1264" relation="org:default" type="c:OrgType" /> <!-- generic-groups -->
</inducement>
<!-- Group-type-specific data -->
<inducement>
<construction>
<resourceRef oid="fe805d13-481b-43ec-97d8-9d2df72cd38e" relation="org:default" type="c:ResourceType" /> <!-- Mailing lists CSV -->
<attribute>
<c:ref>ri:lists</c:ref>
<outbound>
<strength>strong</strength>
<expression>
<script>
<code>assignmentPath[0].target.identifier</code>
</script>
</expression>
</outbound>
</attribute>
</construction>
<order>2</order>
</inducement>
</archetype>
@@ -0,0 +1,32 @@
<archetype xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://grouper-demo.tier.internet2.edu"
oid="2be36917-71ad-4c3e-8789-89cadea2d5d6">
<name>midpoint-group</name>
<extension>
<ext:ldapRootDn>ou=midpoint,ou=Groups,dc=internet2,dc=edu</ext:ldapRootDn>
</extension>
<archetypePolicy>
<display>
<label>midPoint Group</label>
<pluralLabel>midPoint Groups</pluralLabel>
<icon>
<cssClass>fa fa-users</cssClass>
<color>darkgviolet</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<targetRef oid="8da46694-bd71-4e1e-bfd7-73865ae2ea9a" relation="org:default" type="c:RoleType" /> <!-- metarole-ldap-group -->
</assignment>
<inducement>
<targetRef oid="4790ab69-7ef0-41a4-8992-78877f3beb23" relation="org:default" type="c:OrgType" /> <!-- midpoint-groups -->
</inducement>
</archetype>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<archetype oid="958da09c-fefb-11e9-892d-975972472527"
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:org='http://midpoint.evolveum.com/xml/ns/public/common/org-3'>
<name>SIS Person</name>
<description>Person with a relation to the academy environment, coming from the SIS database</description>
<archetypePolicy>
<display>
<label>SIS Person</label>
<pluralLabel>SIS Persons</pluralLabel>
<tooltip>Person imported from the SIS database</tooltip>
<icon>
<cssClass>fa fa-graduation-cap</cssClass>
<color>darkgreen</color>
</icon>
</display>
</archetypePolicy>
<assignment>
<assignmentRelation>
<holderType>UserType</holderType>
</assignmentRelation>
</assignment>
</archetype>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<s:search xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3">
<s:type>c:ResourceType</s:type>
<s:searchFilter>
<q:inOid>
<q:value>0a37121f-d515-4a23-9b6d-554c5ef61272</q:value>
<q:value>4d70a0da-02dd-41cf-b0a1-00e75d3eaa15</q:value>
<q:value>a343fc2e-3954-4034-ba1a-2b72c21e577a</q:value>
<q:value>e417225d-8a08-46f3-9b5d-624990b52386</q:value>
<q:value>fe805d13-481b-43ec-97d8-9d2df72cd38e</q:value>
<q:value>1eff65de-5bb6-483d-9edf-8cc2c2ee0233</q:value>
</q:inOid>
</s:searchFilter>
<s:action>
<!-- XXX we test ALL resources here. Maybe we can just skip the query -->
<s:type>test-resource</s:type>
</s:action>
</s:search>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- (c) 2019 Evolveum, All rights reserved -->

<s:search xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3">
<s:type>ObjectType</s:type>
<s:searchFilter>
<q:inOid>
<q:value>d48ec05b-fffd-4262-acd3-d9ff63365b62</q:value>
<q:value>e897468f-20bd-419c-8fc5-1fe60e2600de</q:value>
</q:inOid>
</s:searchFilter>
<s:action>
<s:type>recompute</s:type>
</s:action>
</s:search>
@@ -0,0 +1,180 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<functionLibrary oid="2eef4181-25fa-420f-909d-846a36ca90f3"
xmlns='http://midpoint.evolveum.com/xml/ns/public/common/common-3'
xmlns:c='http://midpoint.evolveum.com/xml/ns/public/common/common-3'
xmlns:t='http://prism.evolveum.com/xml/ns/public/types-3'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:piracy='http://midpoint.evolveum.com/xml/ns/samples/piracy'>
<name>grouper</name>
<description>Functions for Grouper AMQP connector</description>
<function>

<!-- Some examples:
{
encrypted=false,
esbEvent=[
{
sourceId=ldap,
membershipType=flattened,
fieldName=members,
groupId=00000000000000000000000000000001,
changeOccurred=false,
createdOnMicros=1551884863420000,
subjectId=banderson,
id=94320942304930294023940329403294,
sequenceNumber=1000,
eventType=MEMBERSHIP_ADD,
groupName=etc:midpointGroups
}
]}
{
"encrypted": false,
"esbEvent": [
{
"displayName": "ref:affiliation:alumni",
"changeOccurred": false,
"createdOnMicros": 1551884850499000,
"parentStemId": "9a7ce40af6c546148b41eec81b8ca18d",
"id": "00000000000000000000000000000002",
"sequenceNumber": "110",
"eventType": "GROUP_ADD",
"name": "ref:affiliation:alumni"
}
]
}
-->


<name>createUcfChange</name>
<parameter>
<name>message</name>
<type>c:AsyncUpdateMessageType</type>
</parameter>
<parameter>
<name>groupIncludePattern</name>
<type>xsd:anyType</type>
</parameter>
<parameter>
<name>groupExcludePattern</name>
<type>xsd:anyType</type>
</parameter>
<parameter>
<name>relevantSourceId</name>
<type>xsd:string</type>
</parameter>
<script>
<code>
import com.evolveum.midpoint.xml.ns._public.common.common_3.*
import com.evolveum.prism.xml.ns._public.types_3.*
import static com.evolveum.midpoint.schema.constants.SchemaConstants.*
import com.evolveum.midpoint.schema.util.*
import com.evolveum.midpoint.prism.path.*
import com.evolveum.midpoint.schema.constants.*
import com.evolveum.midpoint.prism.delta.*

PLAIN_GROUP_OBJECT_CLASS = new ItemName(MidPointConstants.NS_RI, 'CustomPlainGroupObjectClass')
TRIGGER_FIRE_AFTER = 60000
TRIGGER_SAFETY_MARGIN = 10000

esbEvent = midpoint.getMessageBodyAsMap(message)['esbEvent'][0]
log.info('esbEvent = {}', esbEvent)
eventType = esbEvent['eventType']
if (eventType == 'MEMBERSHIP_ADD' || eventType == 'MEMBERSHIP_DELETE') {
groupName = esbEvent['groupName']
if (groupName == null) {
log.warn('No group name in membership change message, ignoring it: {}', esbEvent)
return null
}
groupId = esbEvent['groupId']
if (groupId == null) {
log.warn('No group ID in membership change message, ignoring it: {}', esbEvent)
return null
}
isExported = matches(groupName, groupIncludePattern, groupExcludePattern)
if (!isExported) {
log.info('Irrelevant group membership change, ignoring it: {}', groupName)
return null
}
sourceId = esbEvent['sourceId']
if (sourceId != relevantSourceId) {
log.info('Irrelevant subject source ID in membership change message, ignoring it: {}', sourceId)
return null
}
subjectId = esbEvent['subjectId']
if (subjectId == null) {
log.info('Null subject ID in membership change message, ignoring it: {}', sourceId)
return null
}
log.info('### {} - {} - {}', subjectId, eventType, groupName)
identifiers = new HashMap()
identifiers.put(ICFS_NAME, groupName)
identifiers.put(ICFS_UID, groupId)
ObjectDeltaType delta
itemDelta = new ItemDeltaType()
itemDelta.modificationType = eventType == 'MEMBERSHIP_ADD' ? ModificationTypeType.ADD : ModificationTypeType.DELETE
itemDelta.path = new ItemPathType(ItemPath.create(ShadowType.F_ATTRIBUTES, 'member'))
itemDelta.value.add(RawType.fromPropertyRealValue(subjectId, null, prismContext))
delta = new ObjectDeltaType()
delta.changeType = ChangeTypeType.MODIFY
delta.itemDelta.add(itemDelta)

added = midpoint
.getOptimizingTriggerCreator(TRIGGER_FIRE_AFTER, TRIGGER_SAFETY_MARGIN)
.createForNamedUser(subjectId)
log.info('Recompute trigger for {}: {}', subjectId, added ? 'added' : 'not added (already present or user not found)')

return UcfChangeUtil.create(PLAIN_GROUP_OBJECT_CLASS, identifiers, delta, prismContext)
} else if (eventType == 'GROUP_ADD' || eventType == 'GROUP_DELETE') {
groupName = esbEvent['name']
groupId = esbEvent['id']
isExported = matches(groupName, groupIncludePattern, groupExcludePattern)
if (!isExported) {
log.info('Irrelevant group add/delete event, ignoring it: {}', groupName)
return null
}
identifiers = new HashMap()
identifiers.put(ICFS_NAME, groupName)
identifiers.put(ICFS_UID, groupId)
ObjectDeltaType delta
if (eventType == 'GROUP_DELETE') {
delta = new ObjectDeltaType()
delta.changeType = ChangeTypeType.DELETE
} else {
delta = null
}
return UcfChangeUtil.create(PLAIN_GROUP_OBJECT_CLASS, identifiers, delta, prismContext)
} else {
log.warn('Unsupported event type: {} -> {}', eventType, esbEvent)
return null
}

def matches(String name, Collection includes, Collection excludes) {
matches(name, includes) &amp;&amp; !matches(name, excludes)
}

def matches(String name, Collection patterns) {
if (name == null || patterns == null) {
false
} else {
for (pattern in patterns) {
if (name ==~ pattern) {
return true
}
}
false
}
}
</code>
</script>
<returnType>c:UcfChangeType</returnType>
</function>
</functionLibrary>
@@ -0,0 +1,92 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<objectTemplate xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3" oid="8098b124-c20c-4965-8adf-e528abedf7a4">
<name>template-user</name>
<mapping>
<strength>strong</strength>
<source>
<path>name</path>
</source>
<expression>
<script>
<code>
import com.evolveum.midpoint.xml.ns._public.common.common_3.*
import com.evolveum.midpoint.schema.constants.*
import com.evolveum.midpoint.schema.*
import javax.xml.namespace.*
import com.evolveum.midpoint.util.*
import com.evolveum.midpoint.prism.path.*

GROUPER_RESOURCE_OID = '1eff65de-5bb6-483d-9edf-8cc2c2ee0233'
MEMBER_NAME = new QName(MidPointConstants.NS_RI, 'member')

memberDef = prismContext.definitionFactory().createPropertyDefinition(MEMBER_NAME, DOMUtil.XSD_STRING)
memberDef.setMaxOccurs(-1)

shadowQuery = prismContext.queryFor(ShadowType.class)
.item(ShadowType.F_RESOURCE_REF).ref(GROUPER_RESOURCE_OID)
.and().item(ShadowType.F_SYNCHRONIZATION_SITUATION).eq(SynchronizationSituationType.LINKED)
.and().item(ShadowType.F_KIND).eq(ShadowKindType.ENTITLEMENT)
.and().item(ShadowType.F_INTENT).eq('group')
.and().block().item(ShadowType.F_DEAD).isNull().or().item(ShadowType.F_DEAD).eq(false).endBlock()
.and().item(ItemPath.create(ShadowType.F_ATTRIBUTES, MEMBER_NAME), memberDef).eq(basic.stringify(name))
.build()

//log.info('shadowQuery = {}\n{}', shadowQuery, shadowQuery.debugDump())
options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch())
shadows = midpoint.searchObjects(ShadowType.class, shadowQuery, options)
//log.info('shadows found for {}: {}', name, shadows)

orgNames = shadows.collect { basic.stringify(it.name) } // todo - use attributes
log.info('org names = {}', orgNames)

if (!orgNames.isEmpty()) {
orgQueryBuilder = prismContext.queryFor(OrgType.class)

first = true
for (orgName in orgNames) {
if (first) {
first = false
} else {
orgQueryBuilder = orgQueryBuilder.or()
}
orgQueryBuilder = orgQueryBuilder.item(ItemPath.create(OrgType.F_EXTENSION, 'grouperName')).eq(orgName)
}

orgQuery = orgQueryBuilder.build()
//log.info('org query:\n', orgQuery.debugDump())

orgs = midpoint.searchObjects(OrgType.class, orgQuery, null)
log.info('orgs found: {}', orgs)

orgs.collect {
new AssignmentType(prismContext)
.subtype('grouper-group')
.targetRef(it.oid, OrgType.COMPLEX_TYPE)
}
} else {
null
}
</code>
</script>
</expression>
<target>
<path>assignment</path>
<set>
<condition>
<script>
<code>
assignment?.subtype.contains('grouper-group')
</code>
</script>
</condition>
</set>
</target>
</mapping>
</objectTemplate>
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<org xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="1d7c0e3a-4456-409c-9f50-95407b2eb785">
<name>affiliations</name>
<displayName>Affiliations</displayName>
</org>
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<org xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="225e9360-0639-40ba-8a31-7f31bef067be">
<name>courses</name>
<displayName>Courses</displayName>
</org>
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<org xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="bee44c51-2469-411d-bac7-695728e9c241">
<name>departments</name>
<displayName>Departments</displayName>
</org>
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<org xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="1f339075-5b2f-4a18-9c98-451f3eb0d28d">
<name>generic-groups</name>
<displayName>Generic groups</displayName>
</org>
@@ -0,0 +1,16 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<org xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="d48ec05b-fffd-4262-acd3-d9ff63365b62">
<name>org-grouper-sysadmin</name>
<displayName>Grouper Administrators</displayName>
<assignment id="1">
<targetRef oid="2be36917-71ad-4c3e-8789-89cadea2d5d6" type="ArchetypeType"/> <!-- archetype midpoint-group -->
</assignment>
<identifier>sysadmingroup</identifier>
</org>
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<org xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="d81fb46c-20c7-44d3-8402-fef404ea1264">
<name>mailing-lists</name>
<displayName>Mailing lists</displayName>
</org>
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<org xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="4790ab69-7ef0-41a4-8992-78877f3beb23">
<name>midpoint-groups</name>
<displayName>midPoint groups</displayName>
</org>
@@ -0,0 +1,341 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<resource oid="0a37121f-d515-4a23-9b6d-554c5ef61272"
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:t='http://prism.evolveum.com/xml/ns/public/types-3' xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3"
xmlns:my="http://whatever.com/my" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:mr="http://prism.evolveum.com/xml/ns/public/matching-rule-3"
xmlns:cap="http://midpoint.evolveum.com/xml/ns/public/resource/capabilities-3">

<name>LDAP (directory)</name>

<connectorRef type="ConnectorType">
<filter>
<q:equal>
<q:path>c:connectorType</q:path>
<q:value>com.evolveum.polygon.connector.ldap.LdapConnector</q:value>
</q:equal>
</filter>
</connectorRef>

<connectorConfiguration
xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3"
xmlns:icfcldap="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap/com.evolveum.polygon.connector.ldap.LdapConnector">
<icfc:configurationProperties
xmlns:icfcldap="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap/com.evolveum.polygon.connector.ldap.LdapConnector">
<icfcldap:port>389</icfcldap:port>
<icfcldap:host>directory</icfcldap:host>
<!-- <icfcldap:host>192.168.56.101</icfcldap:host> -->
<icfcldap:baseContext>dc=internet2,dc=edu</icfcldap:baseContext>
<icfcldap:bindDn>cn=Directory Manager</icfcldap:bindDn>
<icfcldap:bindPassword>
<t:clearValue>password</t:clearValue>
</icfcldap:bindPassword>
<icfcldap:uidAttribute>nsUniqueId</icfcldap:uidAttribute>
<icfcldap:pagingStrategy>spr</icfcldap:pagingStrategy> <!-- spr? -->
<!-- <icfcldap:vlvSortAttribute>uid</icfcldap:vlvSortAttribute> -->
<icfcldap:operationalAttributes>memberOf</icfcldap:operationalAttributes>
<icfcldap:operationalAttributes>createTimestamp</icfcldap:operationalAttributes>
<icfcldap:operationalAttributes>nsAccountLock</icfcldap:operationalAttributes>
<!-- >icfcldap:usePermissiveModify>always</icfcldap:usePermissiveModify>
<icfcldap:passwordHashAlgorithm>SSHA</icfcldap:passwordHashAlgorithm -->
<!-- >icfcldap:vlvSortAttribute>uid</icfcldap:vlvSortAttribute> <icfcldap:vlvSortOrderingRule>2.5.13.3</icfcldap:vlvSortOrderingRule -->
</icfc:configurationProperties>
<icfc:resultsHandlerConfiguration>
<icfc:enableNormalizingResultsHandler>false</icfc:enableNormalizingResultsHandler>
<icfc:enableFilteredResultsHandler>false</icfc:enableFilteredResultsHandler>
<icfc:enableAttributesToGetSearchResultsHandler>false</icfc:enableAttributesToGetSearchResultsHandler>
</icfc:resultsHandlerConfiguration>
</connectorConfiguration>

<schema>
<generationConstraints>
<generateObjectClass>ri:inetOrgPerson</generateObjectClass>
<generateObjectClass>ri:eduPerson</generateObjectClass>
<generateObjectClass>ri:groupOfUniqueNames</generateObjectClass>
<generateObjectClass>ri:groupOfNames</generateObjectClass>
<generateObjectClass>ri:organizationalUnit</generateObjectClass>
</generationConstraints>
</schema>

<schemaHandling>
<objectType>
<kind>account</kind>
<displayName>Normal Account</displayName>
<default>true</default>
<objectClass>ri:inetOrgPerson</objectClass>
<auxiliaryObjectClass>ri:eduPerson</auxiliaryObjectClass>
<attribute>
<ref>ri:dn</ref>
<displayName>Distinguished Name</displayName>
<limitations>
<minOccurs>0</minOccurs>
</limitations>
<tolerant>false</tolerant>
<matchingRule>mr:distinguishedName</matchingRule>
<outbound>
<strength>strong</strength>
<source>
<path>name</path>
</source>
<expression>
<script>
<code>
'uid=' + name + ',ou=People,dc=internet2,dc=edu'
</code>
</script>
</expression>
</outbound>
</attribute>
<attribute>
<ref>ri:cn</ref>
<displayName>Common Name</displayName>
<limitations>
<minOccurs>0</minOccurs>
</limitations>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>fullName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:sn</ref>
<displayName>Surname</displayName>
<limitations>
<minOccurs>0</minOccurs>
</limitations>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>familyName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:givenName</ref>
<displayName>Given Name</displayName>
<limitations>
<minOccurs>0</minOccurs>
</limitations>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>givenName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:uid</ref>
<displayName>Login Name</displayName>
<tolerant>false</tolerant>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<strength>strong</strength>
<source>
<path>name</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:mail</ref>
<displayName>Mail</displayName>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>emailAddress</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:employeeNumber</ref>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>employeeNumber</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:businessCategory</ref>
<tolerant>false</tolerant>
</attribute>
<!-- <attribute>
<ref>ri:eduPersonAffiliation</ref>
<outbound>
<strength>strong</strength>
<source>
<path>extension/rawAffiliation</path>
</source>
</outbound>
<tolerant>false</tolerant>
</attribute> -->
<association>
<tolerant>false</tolerant>
<ref>ri:group</ref>
<kind>entitlement</kind>
<intent>group</intent>
<direction>objectToSubject</direction>
<associationAttribute>ri:uniqueMember</associationAttribute>
<valueAttribute>ri:dn</valueAttribute>
</association>
<protected>
<filter>
<q:equal>
<q:matching>http://prism.evolveum.com/xml/ns/public/matching-rule-3#distinguishedName</q:matching>
<q:path>attributes/ri:dn</q:path>
<q:value>cn=root,dc=internet2,dc=edu</q:value>
</q:equal>
</filter>
</protected>
<credentials>
<password>
<outbound/>
</password>
</credentials>
</objectType>

<objectType>
<kind>entitlement</kind>
<intent>group</intent>
<displayName>LDAP Group</displayName>
<objectClass>ri:groupOfUniqueNames</objectClass>
<attribute>
<ref>ri:uniqueMember</ref>
<matchingRule>mr:distinguishedName</matchingRule>
<fetchStrategy>minimal</fetchStrategy>
</attribute>
<attribute>
<ref>ri:dn</ref>
<matchingRule>mr:distinguishedName</matchingRule>
<outbound>
<strength>strong</strength>
<source>
<path>extension/ldapDn</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:cn</ref>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<strength>weak</strength>
<source>
<path>identifier</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:uniqueMember</ref>
<matchingRule>mr:distinguishedName</matchingRule>
<fetchStrategy>minimal</fetchStrategy>
</attribute>
</objectType>
</schemaHandling>

<synchronization>
<objectSynchronization>
<enabled>true</enabled>
<correlation>
<q:equal>
<q:path>name</q:path>
<expression>
<path>
declare namespace ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3";
$projection/attributes/ri:uid
</path>
</expression>
</q:equal>
</correlation>
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink</handlerUri>
</action>
</reaction>
<reaction>
<situation>unlinked</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
</reaction>
</objectSynchronization>
<objectSynchronization>
<name>group sync</name>
<objectClass>ri:groupOfUniqueNames</objectClass>
<kind>entitlement</kind>
<intent>group</intent>
<focusType>OrgType</focusType>
<enabled>true</enabled>
<condition>
<script>
<code>
import javax.naming.ldap.*
dn = new LdapName(basic.getAttributeValue(projection, 'http://midpoint.evolveum.com/xml/ns/public/resource/instance-3', 'dn'))
dn.startsWith(new LdapName('ou=Affiliations,ou=Groups,dc=internet2,dc=edu')) ||
dn.startsWith(new LdapName('ou=Courses,ou=Groups,dc=internet2,dc=edu')) ||
dn.startsWith(new LdapName('ou=generic,ou=Groups,dc=internet2,dc=edu')) ||
dn.startsWith(new LdapName('ou=midpoint,ou=Groups,dc=internet2,dc=edu'))
</code>
</script>
</condition>
<correlation>
<q:equal>
<q:path>extension/ldapDn</q:path>
<expression>
<path>$projection/attributes/ri:dn</path>
</expression>
</q:equal>
</correlation>
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink</handlerUri>
</action>
</reaction>
<reaction>
<situation>unlinked</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
</reaction>
</objectSynchronization>
</synchronization>
<consistency>
<avoidDuplicateValues>true</avoidDuplicateValues>
</consistency>
</resource>
@@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<resource oid="1eff65de-5bb6-483d-9edf-8cc2c2ee0233"
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3"
xmlns:rest="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-grouper-rest/com.evolveum.polygon.connector.grouper.rest.GrouperConnector"
xmlns:conf="http://midpoint.evolveum.com/xml/ns/public/connector/builtin-1/bundle/com.evolveum.midpoint.provisioning.ucf.impl.builtin.async/AsyncUpdateConnector"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<name>Grouper Resource</name>
<connectorRef type="c:ConnectorType">
<filter>
<q:equal>
<q:path>connectorType</q:path>
<q:value>com.evolveum.polygon.connector.grouper.rest.GrouperConnector</q:value>
</q:equal>
</filter>
</connectorRef>
<connectorConfiguration>
<icfc:configurationProperties>
<rest:baseUrl>https://grouper-ws:443</rest:baseUrl>
<rest:username>banderson</rest:username>
<rest:password>password</rest:password>
<rest:superGroup>etc:sysadmingroup</rest:superGroup> <!-- parameter name will be changed -->
<rest:groupIncludePattern>app:.*</rest:groupIncludePattern>
<rest:groupIncludePattern>test:.*</rest:groupIncludePattern>
<rest:groupIncludePattern>ref:.*</rest:groupIncludePattern>
<rest:groupExcludePattern>.*_(includes|excludes|systemOfRecord|systemOfRecordAndIncludes)</rest:groupExcludePattern>
<rest:subjectSource>ldap</rest:subjectSource>
<rest:groupSource>g:gsa</rest:groupSource>
<rest:ignoreSslValidation>true</rest:ignoreSslValidation>
<rest:exportStem>:</rest:exportStem>
</icfc:configurationProperties>
</connectorConfiguration>
<additionalConnector>
<name>AMQP async update connector</name>
<connectorRef type="c:ConnectorType">
<filter>
<q:equal>
<q:path>connectorType</q:path>
<q:value>AsyncUpdateConnector</q:value>
</q:equal>
</filter>
</connectorRef>
<connectorConfiguration>
<conf:sources>
<amqp091>
<uri>amqp://mq:5672</uri>
<username>guest</username>
<password>guest</password>
<queue>sampleQueue</queue>
</amqp091>
</conf:sources>
<conf:transformExpression>
<script>
<code>
// ------------------ START OF CONFIGURATION ------------------

parameters = [
groupIncludePattern: [ 'app:.*', 'test:.*', 'ref:.*' ],
groupExcludePattern: [ '.*_(includes|excludes|systemOfRecord|systemOfRecordAndIncludes)' ],
relevantSourceId: 'ldap'
]

// ------------------ END OF CONFIGURATION ------------------

parameters.put('message', message)
grouper.execute('createUcfChange', parameters)
</code>
</script>
</conf:transformExpression>
</connectorConfiguration>
</additionalConnector>
<schemaHandling>
<objectType>
<kind>entitlement</kind>
<intent>group</intent>
<objectClass>ri:CustomPlainGroupObjectClass</objectClass>
<default>true</default>
<attribute>
<ref>icfs:name</ref>
<inbound>
<strength>strong</strength>
<target>
<path>extension/grouperName</path>
</target>
</inbound>
<inbound>
<strength>strong</strength>
<expression>
<script>
<code>
import com.evolveum.midpoint.schema.util.*
import com.evolveum.midpoint.schema.constants.*

if (input == null) {
null
} else {
archetypeOid = '5f2b96d2-49b5-4a8a-9601-14457309a69b' // generic-grouper-group archetype
switch (input) {
case ~/ref:affiliation:.*/: archetypeOid = '56f53812-047d-4b69-83e8-519a73d161e1'; break; // affiliation archetype
case ~/ref:dept:.*/: archetypeOid = '1cec5f78-8fba-459b-9547-ef7485009f40'; break; // department archetype
case ~/ref:course:.*/: archetypeOid = '3dab9a72-118b-4e40-a138-bb691c335eca'; break; // course archetype
case ~/app:mailinglist:.*/: archetypeOid = '1645d1dc-1f7c-4508-b50b-97b501ccdee3'; break; // mailing-list archetype
}
ObjectTypeUtil.createAssignmentTo(archetypeOid, ObjectTypes.ARCHETYPE, prismContext)
}
</code>
</script>
</expression>
<target>
<path>assignment</path>
<set>
<predefined>all</predefined> <!-- we tolerate no other assignments -->
</set>
</target>
</inbound>
</attribute>
<attribute>
<ref>ri:member</ref>
<fetchStrategy>explicit</fetchStrategy>
<storageStrategy>indexOnly</storageStrategy>
</attribute>
</objectType>
</schemaHandling>
<synchronization>
<objectSynchronization>
<enabled>true</enabled>
<kind>entitlement</kind>
<intent>group</intent>
<objectClass>ri:CustomPlainGroupObjectClass</objectClass>
<focusType>OrgType</focusType>
<correlation>
<q:equal>
<q:path>extension/grouperName</q:path>
<expression>
<path>$projection/attributes/name</path>
</expression>
</q:equal>
</correlation>
<reaction>
<situation>linked</situation>
<channel>http://midpoint.evolveum.com/xml/ns/public/provisioning/channels-3#asyncUpdate</channel>
<synchronize>false</synchronize>
</reaction>
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<!-- a separate task will take care of deleted groups -->
<!-- we don't even need to unlink the shadow -->
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>unlinked</situation>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus</handlerUri>
</action>
</reaction>
</objectSynchronization>
</synchronization>
<caching>
<cachingStategy>passive</cachingStategy>
</caching>
</resource>
@@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<c:resource oid="4d70a0da-02dd-41cf-b0a1-00e75d3eaa15"
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3"
xmlns:mr="http://prism.evolveum.com/xml/ns/public/matching-rule-3"
xmlns:cap="http://midpoint.evolveum.com/xml/ns/public/resource/capabilities-3">

<c:name>SQL SIS persons (sources)</c:name>

<connectorRef type="ConnectorType">
<filter>
<q:equal>
<q:path>connectorType</q:path>
<q:value>net.tirasa.connid.bundles.db.scriptedsql.ScriptedSQLConnector</q:value>
</q:equal>
</filter>
</connectorRef>

<c:connectorConfiguration>

<icfc:configurationProperties
xmlns:icscscriptedsql="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/net.tirasa.connid.bundles.db.scriptedsql/net.tirasa.connid.bundles.db.scriptedsql.ScriptedSQLConnector">
<icscscriptedsql:host>sources</icscscriptedsql:host>
<icscscriptedsql:port>3306</icscscriptedsql:port>
<icscscriptedsql:quoting></icscscriptedsql:quoting>
<icscscriptedsql:user>root</icscscriptedsql:user>
<icscscriptedsql:password>
<clearValue>123321</clearValue>
</icscscriptedsql:password>
<icscscriptedsql:database>sis</icscscriptedsql:database>
<!-- >icscscriptedsql:clearTextPasswordToScript>true</icscscriptedsql:clearTextPasswordToScript -->
<icscscriptedsql:scriptingLanguage>GROOVY</icscscriptedsql:scriptingLanguage>

<icscscriptedsql:searchScriptFileName>/opt/midpoint/var/res/sis-persons/SearchScript.groovy</icscscriptedsql:searchScriptFileName>
<icscscriptedsql:testScriptFileName>/opt/midpoint/var/res/sis-persons/TestScript.groovy</icscscriptedsql:testScriptFileName>
<icscscriptedsql:schemaScriptFileName>/opt/midpoint/var/res/sis-persons/SchemaScript.groovy</icscscriptedsql:schemaScriptFileName>

<icscscriptedsql:reloadScriptOnExecution>false</icscscriptedsql:reloadScriptOnExecution>
<!-- >icscscriptedsql:syncScriptFileName>/opt/midpoint/var/res/SyncScript.groovy</icscscriptedsql:syncScriptFileName -->

<icscscriptedsql:validConnectionQuery></icscscriptedsql:validConnectionQuery>
<icscscriptedsql:jndiProperties></icscscriptedsql:jndiProperties>

<icscscriptedsql:jdbcDriver>org.mariadb.jdbc.Driver</icscscriptedsql:jdbcDriver>
<icscscriptedsql:jdbcUrlTemplate>jdbc:mysql://%h:%p/%d?useUnicode=true&amp;characterEncoding=utf8&amp;connectionCollation=utf8_bin</icscscriptedsql:jdbcUrlTemplate>
<icscscriptedsql:enableEmptyString>true</icscscriptedsql:enableEmptyString>
<icscscriptedsql:rethrowAllSQLExceptions>true</icscscriptedsql:rethrowAllSQLExceptions>
<icscscriptedsql:nativeTimestamps>false</icscscriptedsql:nativeTimestamps>
<icscscriptedsql:allNative>false</icscscriptedsql:allNative>
<!--<icscscriptedsql:changeLogColumn>timestamp</icscscriptedsql:changeLogColumn> -->
<icscscriptedsql:datasource></icscscriptedsql:datasource>
</icfc:configurationProperties>

<!-- Generic ICF configuration -->

</c:connectorConfiguration>

<schemaHandling>
<objectType>
<kind>account</kind>
<displayName>Normal Account</displayName>
<default>true</default>
<objectClass>ri:AccountObjectClass</objectClass>
<attribute>
<ref>ri:uid</ref>
<displayName>UID</displayName>
<inbound>
<target>
<path>name</path>
</target>
</inbound>
<inbound>
<strength>strong</strength>
<expression>
<assignmentTargetSearch>
<targetType>RoleType</targetType>
<oid>c89f31dd-8d4f-4e0a-82cb-58ff9d8c1b2f</oid> <!-- role-ldap-basic -->
<assignmentProperties>
<subtype>grouper-basic</subtype>
</assignmentProperties>
</assignmentTargetSearch>
</expression>
<target>
<path>assignment</path>
<set>
<condition>
<script>
<code>
assignment.subtype.contains('grouper-basic')
</code>
</script>
</condition>
</set>
</target>
</inbound>
<inbound>
<strength>strong</strength>
<expression>
<assignmentTargetSearch>
<targetType>ArchetypeType</targetType>
<oid>958da09c-fefb-11e9-892d-975972472527</oid> <!-- archetype-academic-person -->
<assignmentProperties>
<subtype>grouper-basic</subtype>
</assignmentProperties>
</assignmentTargetSearch>
</expression>
<target>
<path>assignment</path>
<set>
<condition>
<script>
<code>
assignment.subtype.contains('grouper-basic')
</code>
</script>
</condition>
</set>
</target>
</inbound>
</attribute>
<attribute>
<ref>ri:fullName</ref>
<displayName>Full Name</displayName>
<inbound>
<target>
<path>fullName</path>
</target>
</inbound>
</attribute>
<attribute>
<ref>ri:surname</ref>
<displayName>Surname</displayName>
<inbound>
<target>
<path>familyName</path>
</target>
</inbound>
</attribute>
<attribute>
<ref>ri:givenName</ref>
<displayName>Given Name</displayName>
<inbound>
<target>
<path>givenName</path>
</target>
</inbound>
</attribute>
<attribute>
<ref>ri:mail</ref>
<displayName>Mail</displayName>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<inbound>
<target>
<path>emailAddress</path>
</target>
</inbound>
</attribute>
</objectType>
</schemaHandling>

<synchronization>
<objectSynchronization>
<enabled>true</enabled>

<correlation>
<q:equal>
<q:path>name</q:path>
<expression>
<path>
declare namespace ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3";
$projection/attributes/ri:uid
</path>
</expression>
</q:equal>
</correlation>

<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink</handlerUri>
</action>
</reaction>

<reaction>
<situation>unlinked</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus</handlerUri>
</action>
</reaction>
</objectSynchronization>
</synchronization>

</c:resource>

@@ -0,0 +1,112 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<resource oid="a343fc2e-3954-4034-ba1a-2b72c21e577a" xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3" xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3" xmlns:my="http://myself.me/schemas/whatever"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3" xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">

<name>Target: Computer science portal (CSV)</name>

<connectorRef type="ConnectorType">
<filter>
<q:equal>
<q:path>c:connectorType</q:path>
<q:value>com.evolveum.polygon.connector.csv.CsvConnector</q:value>
</q:equal>
</filter>
</connectorRef>

<connectorConfiguration xmlns:icfi="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-csv/com.evolveum.polygon.connector.csv.CsvConnector">

<icfc:configurationProperties>
<icfi:filePath>/opt/midpoint/var/cs-portal.csv</icfi:filePath>
<icfi:encoding>utf-8</icfi:encoding>
<icfi:fieldDelimiter>,</icfi:fieldDelimiter>
<icfi:multivalueDelimiter>;</icfi:multivalueDelimiter>
<icfi:uniqueAttribute>identifier</icfi:uniqueAttribute>
</icfc:configurationProperties>

</connectorConfiguration>

<schemaHandling>
<objectType>
<displayName>Default Account</displayName>
<default>true</default>
<objectClass>ri:AccountObjectClass</objectClass>
<attribute>
<ref>ri:identifier</ref>
<outbound>
<strength>strong</strength>
<source>
<path>name</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:name</ref>
<outbound>
<strength>strong</strength>
<source>
<path>fullName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:mail</ref>
<outbound>
<strength>strong</strength>
<source>
<path>emailAddress</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:courses</ref>
<limitations>
<maxOccurs>unbounded</maxOccurs>
</limitations>
<tolerant>false</tolerant>
<!-- outbound is in metarole-course -->
</attribute>
</objectType>
</schemaHandling>
<synchronization>
<objectSynchronization>
<enabled>true</enabled>
<correlation>
<q:equal>
<q:path>name</q:path>
<expression>
<path>$projection/attributes/identifier</path>
</expression>
</q:equal>
</correlation>
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink</handlerUri>
</action>
</reaction>
<reaction>
<situation>unlinked</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
</reaction>
</objectSynchronization>
</synchronization>
</resource>
@@ -0,0 +1,128 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<resource oid="e417225d-8a08-46f3-9b5d-624990b52386" xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3" xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3" xmlns:my="http://myself.me/schemas/whatever"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3" xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">

<name>Target: Faculty portal (CSV)</name>

<connectorRef type="ConnectorType">
<filter>
<q:equal>
<q:path>c:connectorType</q:path>
<q:value>com.evolveum.polygon.connector.csv.CsvConnector</q:value>
</q:equal>
</filter>
</connectorRef>

<connectorConfiguration xmlns:icfi="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-csv/com.evolveum.polygon.connector.csv.CsvConnector">

<icfc:configurationProperties>
<icfi:filePath>/opt/midpoint/var/faculty-portal.csv</icfi:filePath>
<icfi:encoding>utf-8</icfi:encoding>
<icfi:fieldDelimiter>,</icfi:fieldDelimiter>
<icfi:multivalueDelimiter>;</icfi:multivalueDelimiter>
<icfi:uniqueAttribute>uid</icfi:uniqueAttribute>
</icfc:configurationProperties>

</connectorConfiguration>
<schemaHandling>
<objectType>
<displayName>Default Account</displayName>
<default>true</default>
<objectClass>ri:AccountObjectClass</objectClass>
<attribute>
<ref>ri:uid</ref>
<outbound>
<strength>strong</strength>
<source>
<path>name</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:givenName</ref>
<outbound>
<strength>strong</strength>
<source>
<path>givenName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:familyName</ref>
<outbound>
<strength>strong</strength>
<source>
<path>familyName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:fullName</ref>
<outbound>
<strength>strong</strength>
<source>
<path>fullName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:mail</ref>
<outbound>
<strength>strong</strength>
<source>
<path>emailAddress</path>
</source>
</outbound>
</attribute>
</objectType>
</schemaHandling>
<synchronization>
<objectSynchronization>
<enabled>true</enabled>
<correlation>
<q:equal>
<q:path>name</q:path>
<expression>
<path>$projection/attributes/uid</path>
</expression>
</q:equal>
</correlation>
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink</handlerUri>
</action>
</reaction>
<reaction>
<situation>unlinked</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
<!-- TODO MidPoint Basics Training, LAB TODO: uncomment the following content -->
<!--
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#deleteShadow</handlerUri>
</action>
-->
<!-- TODO MidPoint Basics Training, LAB TODO: end of to-be-uncommented content -->
</reaction>
</objectSynchronization>
</synchronization>
</resource>
@@ -0,0 +1,102 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<resource oid="fe805d13-481b-43ec-97d8-9d2df72cd38e" xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3" xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3" xmlns:my="http://myself.me/schemas/whatever"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3" xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">

<name>Target: Mailing lists (CSV)</name>

<connectorRef type="ConnectorType">
<filter>
<q:equal>
<q:path>c:connectorType</q:path>
<q:value>com.evolveum.polygon.connector.csv.CsvConnector</q:value>
</q:equal>
</filter>
</connectorRef>

<connectorConfiguration xmlns:icfi="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-csv/com.evolveum.polygon.connector.csv.CsvConnector">

<icfc:configurationProperties>
<icfi:filePath>/opt/midpoint/var/mailing-lists.csv</icfi:filePath>
<icfi:encoding>utf-8</icfi:encoding>
<icfi:fieldDelimiter>,</icfi:fieldDelimiter>
<icfi:multivalueDelimiter>;</icfi:multivalueDelimiter>
<icfi:uniqueAttribute>uid</icfi:uniqueAttribute>
</icfc:configurationProperties>

</connectorConfiguration>
<schemaHandling>
<objectType>
<displayName>Default Account</displayName>
<default>true</default>
<objectClass>ri:AccountObjectClass</objectClass>
<attribute>
<ref>ri:uid</ref>
<outbound>
<strength>strong</strength>
<source>
<path>name</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:mail</ref>
<outbound>
<strength>strong</strength>
<source>
<path>emailAddress</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:lists</ref>
<limitations>
<maxOccurs>unbounded</maxOccurs>
</limitations>
<tolerant>false</tolerant>
<!-- outbound is in metarole-mailing-list -->
</attribute>
</objectType>
</schemaHandling>
<synchronization>
<objectSynchronization>
<enabled>true</enabled>
<correlation>
<q:equal>
<q:path>name</q:path>
<expression>
<path>$projection/attributes/uid</path>
</expression>
</q:equal>
</correlation>
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink</handlerUri>
</action>
</reaction>
<reaction>
<situation>unlinked</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
</reaction>
</objectSynchronization>
</synchronization>
</resource>
@@ -0,0 +1,192 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<role xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
oid="bcaec940-50c8-44bb-aa37-b2b5bb2d5b90">
<name>metarole-grouper-provided-group</name>
<description>A metarole for archetyped Grouper-provided groups</description>
<!--
This metarole arranges everything that is needed for a Grouper group to live in midPoint.
The schema is the following:
Grouper group -> shadow -> org -> archetype -> this metarole
e.g.
ref:affiliation:member -> shadow -> affiliation_member -> affiliation (archetype) -> metarole-grouper-provided-group
1) Grouper group (e.g. ref:affiliation:member) has a shadow object.
2) An org object (affiliation_member) is created and linked to this shadow.
3) At the same time, appropriate archetype is assigned to the org, based on the Grouper name
(e.g. ref:affiliation:* leads to archetype affiliation).
4) This archetype defines basic parameters for the particular class of Grouper groups; e.g. where in midPoint
org tree they belong (e.g. under Affiliations org), where in LDAP tree they belong (e.g. under
ou=Affiliations,ou=Groups,dc=internet2,dc=edu), what's the schema for their midPoint name
(e.g. affiliation_...) and displayName (e.g. Affiliation: ...).
5) To avoid code duplication, these archetypes delegate specific processing
(i.e. filling-in appropriate properties of org objects) to metaroles:
to this one as well as to metarole-ldap-group.
This metarole is devoted to process Grouper-specific information for Grouper groups.
As a source it needs only two pieces of information: extension/grouperName (e.g. ref:affiliation:member)
and particular archetype (e.g. affiliation) with its configuration data.
It fills-in the following items: extension/grouperName -> identifier -> name and displayName
by inducing appropriate focus mappings to the org object.
-->
<inducement>
<focusMappings>
<mapping>
<name>identifier</name>
<description>This mapping fills-in org identifier (e.g. 'member') from extension/grouperName (e.g. 'ref:affiliation:member').
It uses extension/grouperNamePrefix information from the archetype (e.g. 'ref:affiliation:' defined in affiliation archetype)</description>
<strength>strong</strength>
<source>
<path>extension/grouperName</path>
</source>
<expression>
<script>
<code>
if (grouperName == null) {
null
} else {
archetype = assignmentPath[-2].source // e.g. archetype affiliation
log.info('archetype = {}', archetype)
if (archetype == null) {
throw new IllegalStateException('No archetype in assignment path: ' + assignmentPath)
}
grouperNamePrefix = basic.getExtensionPropertyValue(archetype, 'grouperNamePrefix') // e.g. 'ref:affiliation:'
if (grouperNamePrefix == null) {
throw new IllegalStateException('No grouper name prefix in archetype ' + archetype)
}
// grouperName is e.g. 'ref:affiliation:member'
if (grouperName.startsWith(grouperNamePrefix)) {
grouperName.substring(grouperNamePrefix.length()) // returning e.g. 'member'
} else {
throw new IllegalStateException('Grouper name ' + grouperName + ' does not match the expected prefix: ' + grouperNamePrefix)
}
}
</code>
</script>
</expression>
<target>
<path>identifier</path>
</target>
</mapping>

<mapping>
<name>name</name>
<description>This mapping fills-in org name (e.g. 'affiliation_member') from identifier (e.g. 'member').
It uses extension/midPointNamePrefix information from the archetype (e.g. 'affiliation_' defined in affiliation archetype)</description>
<strength>strong</strength>
<source>
<path>identifier</path>
</source>
<expression>
<script>
<code>
if (identifier == null) {
null
} else {
// e.g. identifier = 'member'
archetype = assignmentPath[-2].source // e.g. affiliation archetype
if (archetype == null) {
throw new IllegalStateException('No archetype in assignment path: ' + assignmentPath)
}
prefix = basic.getExtensionPropertyValue(archetype, 'midPointNamePrefix') // e.g. 'affiliation_'
prefix + identifier // e.g. 'affiliation_member'
}
</code>
</script>
</expression>
<target>
<path>name</path>
</target>
</mapping>

<mapping>
<name>displayName</name>
<description>This mapping fills-in org displayName (e.g. 'Affiliation: member') from identifier (e.g. 'member').
It uses extension/midPointDisplayNamePrefix information from the archetype (e.g. 'Affiliation: ' defined in affiliation archetype)</description>
<strength>strong</strength>
<source>
<path>identifier</path>
</source>
<expression>
<script>
<code>
if (identifier == null) {
null
} else {
archetype = assignmentPath[-2].source // e.g. affiliation archetype
if (archetype == null) {
throw new IllegalStateException('No archetype in assignment path: ' + assignmentPath)
}
prefix = basic.getExtensionPropertyValue(archetype, 'midPointDisplayNamePrefix') // e.g. 'Affiliation: '
prefix + identifier // e.g. 'Affiliation: member'
}
</code>
</script>
</expression>
<target>
<path>displayName</path>
</target>
</mapping>

<mapping>
<name>lifecycle state</name>
<description>This mapping sets org lifecycle state to be either "active" or "retired", depending on
whether Grouper group for this org still exists. Orgs in the latter state are on the way to deletion:
their members are unassigned and after no members are there, the org is automatically deleted.</description>
<strength>strong</strength>
<expression>
<script>
<code>
import com.evolveum.midpoint.model.impl.expr.*
import com.evolveum.midpoint.schema.*
import com.evolveum.midpoint.xml.ns._public.common.common_3.*

GROUPER_RESOURCE_OID = '1eff65de-5bb6-483d-9edf-8cc2c2ee0233'

modelContext = ModelExpressionThreadLocalHolder.lensContext
rsd = new ResourceShadowDiscriminator(GROUPER_RESOURCE_OID, ShadowKindType.ENTITLEMENT, 'group', null, false)
if (modelContext.findProjectionContext(rsd) != null) {
log.info('Projection context for Grouper group found, marking as "active"')
'active'
} else {
log.info('No projection context for Grouper group, marking as "retired"')
'retired'
}
</code>
</script>
</expression>
<target>
<path>lifecycleState</path>
</target>
</mapping>
</focusMappings>

<!--
Inducement order of 2 means these mappings are to be applied on org object, because the assignment structure is like this:
org -> archetype -> this-metarole
-->
<order>2</order>
</inducement>
</role>
@@ -0,0 +1,128 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<role xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
oid="8da46694-bd71-4e1e-bfd7-73865ae2ea9a">
<name>metarole-ldap-group</name>
<description>A metarole for archetyped LDAP groups</description>
<!--
This metarole supports LDAP groups that correspond to appropriately archetyped
org objects.
The schema is the following:
org -> archetype -> this metarole
e.g.
affiliation_member -> archetype affiliation -> metarole-ldap-group
or org-grouper-sysadmin -> archetype midpoint-group -> metarole-ldap-group
1) An org has appropriate archetype e.g. affiliation_member has an archetype of affiliation;
org-grouper-sysadmin has an archetype of midpoint-group.
2) This archetype defines LDAP root the particular class of orgs e.g.
ou=Affiliations,ou=Groups,dc=internet2,dc=edu for affiliations or
ou=midpoint,ou=Groups,dc=internet2,dc=edu for midPoint-defined groups.
3) To avoid code duplication, these archetypes delegate everything related
to LDAP to this metarole.
This metarole does the three things:
1) It ensures that extension/ldapDn is filled in for particular org object.
This property is then used by LDAP resource outbound mappings to provide
a value for ri:dn attribute.
The value of extension/ldapDn is determined as
cn=identifier (in org) + ldapRootDn (in archetype)
2) It ensures that appropriate group object is created in LDAP.
This is done by inducing a construction with kind=entitlement,
intent=group to the org object (i.e. inducement order=2).
3) It ensures that appropriate group membership is created in LDAP
for any user that has an assignment to the org object. This is done
by inducing a construction with default kind and intent (i.e. regular
account) to the user that has assigned the org object (i.e. inducement order=3).
-->

<!-- Fills-in extension/ldapDn in org object -->
<inducement>
<focusMappings>
<mapping>
<name>ldapDn</name>
<strength>strong</strength>
<source>
<path>identifier</path>
</source>
<expression>
<script>
<code>
if (identifier == null) {
null
} else {
// identifier = e.g. 'member'
metarole = assignmentPath[-2].source // e.g. metarole-affiliation
log.info('metarole = {}', metarole)
if (metarole == null) {
throw new IllegalStateException('No metarole in assignment path: ' + assignmentPath)
}
'cn=' + identifier + ',' + basic.getExtensionPropertyValue(metarole, 'ldapRootDn')
}
</code>
</script>
</expression>
<target>
<path>extension/ldapDn</path>
</target>
</mapping>
</focusMappings>
<order>2</order> <!-- order=2 means the org object: org->archetype->metarole -->
</inducement>

<!-- Provides LDAP group for the org object -->
<inducement>
<construction>
<resourceRef oid="0a37121f-d515-4a23-9b6d-554c5ef61272" relation="org:default" type="c:ResourceType" />
<kind>entitlement</kind>
<intent>group</intent>
</construction>
<order>2</order> <!-- order=2 means the org object: org->archetype->metarole -->
</inducement>

<!-- Provides LDAP group membership for the org object members (users) -->
<inducement>
<construction>
<resourceRef oid="0a37121f-d515-4a23-9b6d-554c5ef61272" relation="org:default" type="c:ResourceType" />
<association>
<c:ref>ri:group</c:ref>
<outbound>
<expression>
<associationFromLink>
<projectionDiscriminator>
<kind>entitlement</kind>
<intent>group</intent>
</projectionDiscriminator>
<assignmentPathIndex>1</assignmentPathIndex> <!-- derive from the immediately assigned org -->
</associationFromLink>
</expression>
</outbound>
</association>
</construction>
<order>3</order> <!-- order=3 means the user object; user has an assignment to the org: user->org->archetype->metarole -->
</inducement>
</role>
@@ -0,0 +1,25 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<role xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
oid="c89f31dd-8d4f-4e0a-82cb-58ff9d8c1b2f">
<name>role-ldap-basic</name>
<inducement id="1">
<construction>
<resourceRef oid="0a37121f-d515-4a23-9b6d-554c5ef61272" relation="org:default" type="c:ResourceType" /> <!-- LDAP -->
</construction>
<order>1</order>
</inducement>
</role>
@@ -0,0 +1,257 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<systemConfiguration xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:apti="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3" xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3" xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3" xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3" xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" oid="00000000-0000-0000-0000-000000000001" version="2">
<name>SystemConfiguration</name>
<globalSecurityPolicyRef xmlns:tns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" oid="00000000-0000-0000-0000-000000000120" relation="org:default" type="tns:SecurityPolicyType"/>
<logging>
<classLogger id="1">
<level>ERROR</level>
<package>ro.isdc.wro.extensions.processor.css.Less4jProcessor</package>
</classLogger>
<classLogger id="2">
<level>OFF</level>
<package>org.hibernate.engine.jdbc.spi.SqlExceptionHelper</package>
</classLogger>
<classLogger id="3">
<level>OFF</level>
<package>org.hibernate.engine.jdbc.batch.internal.BatchingBatch</package>
</classLogger>
<classLogger id="4">
<level>WARN</level>
<package>org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl</package>
</classLogger>
<classLogger id="5">
<level>OFF</level>
<package>org.hibernate.internal.ExceptionMapperStandardImpl</package>
</classLogger>
<classLogger id="6">
<level>OFF</level>
<package>net.sf.jasperreports.engine.fill.JRFillDataset</package>
</classLogger>
<classLogger id="7">
<level>WARN</level>
<package>org.apache.wicket.resource.PropertiesFactory</package>
</classLogger>
<classLogger id="8">
<level>ERROR</level>
<package>org.springframework.context.support.ResourceBundleMessageSource</package>
</classLogger>
<classLogger id="9">
<level>INFO</level>
<package>com.evolveum.midpoint.model.impl.lens.projector.Projector</package>
</classLogger>
<classLogger id="10">
<level>INFO</level>
<package>com.evolveum.midpoint.model.impl.lens.Clockwork</package>
</classLogger>
<appender id="11" xsi:type="c:FileAppenderConfigurationType">
<pattern>%date [%X{subsystem}] [%thread] %level \(%logger\): %msg%n</pattern>
<name>MIDPOINT_LOG</name>
<fileName>${midpoint.home}/log/midpoint.log</fileName>
<filePattern>${midpoint.home}/log/midpoint-%d{yyyy-MM-dd}.%i.log</filePattern>
<maxHistory>10</maxHistory>
<maxFileSize>100MB</maxFileSize>
<append>true</append>
</appender>
<appender id="12" xsi:type="c:FileAppenderConfigurationType">
<pattern>%date %level: %msg%n</pattern>
<name>MIDPOINT_PROFILE_LOG</name>
<fileName>${midpoint.home}/log/midpoint-profile.log</fileName>
<filePattern>${midpoint.home}/log/midpoint-profile-%d{yyyy-MM-dd}.%i.log</filePattern>
<maxHistory>10</maxHistory>
<maxFileSize>100MB</maxFileSize>
<append>true</append>
</appender>
<rootLoggerAppender>MIDPOINT_LOG</rootLoggerAppender>
<rootLoggerLevel>INFO</rootLoggerLevel>
<auditing>
<enabled>false</enabled>
<details>false</details>
</auditing>
</logging>
<defaultObjectPolicyConfiguration id="101">
<type>UserType</type>
<objectTemplateRef xmlns:tns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" oid="8098b124-c20c-4965-8adf-e528abedf7a4" relation="org:default" type="tns:ObjectTemplateType"/>
</defaultObjectPolicyConfiguration>
<defaultObjectPolicyConfiguration>
<type>OrgType</type>
<lifecycleStateModel>
<state>
<name>retired</name>
<!-- object in this model is active but on its way to deletion -->
</state>
</lifecycleStateModel>
</defaultObjectPolicyConfiguration>
<cleanupPolicy>
<auditRecords>
<maxAge>P3M</maxAge>
</auditRecords>
<closedTasks>
<maxAge>P1M</maxAge>
</closedTasks>
</cleanupPolicy>
<internals>
<enableExperimentalCode>true</enableExperimentalCode>
<operationExecutionRecording>
<skipWhenSuccess>true</skipWhenSuccess>
</operationExecutionRecording>
<focusConstraintsChecking>
<skipWhenNoChange>true</skipWhenNoChange>
<skipWhenNoIteration>true</skipWhenNoIteration>
</focusConstraintsChecking>
<projectionConstraintsChecking>
<skipWhenNoChange>true</skipWhenNoChange>
<skipWhenNoIteration>true</skipWhenNoIteration>
</projectionConstraintsChecking>
<synchronizationSituationUpdating>
<skipWhenNoChange>true</skipWhenNoChange>
</synchronizationSituationUpdating>
<caching>
<profile>
<global>true</global>
<localRepoCache>
<statistics>
<classification>perCacheAndObjectType</classification>
</statistics>
</localRepoCache>
<globalRepoCache>
<timeToLive>60</timeToLive>
<objectTypeSettings>
<objectType>SystemConfigurationType</objectType>
<objectType>ArchetypeType</objectType>
<objectType>ObjectTemplateType</objectType>
<objectType>SecurityPolicyType</objectType>
<objectType>ValuePolicyType</objectType>
<objectType>ResourceType</objectType>
<objectType>RoleType</objectType>
<objectType>OrgType</objectType>
<objectType>ServiceType</objectType>
<objectType>ShadowType</objectType>
</objectTypeSettings>
<statistics>
<classification>perCacheAndObjectType</classification>
</statistics>
</globalRepoCache>
</profile>
</caching>
<repository>
<statistics>
<classification>perOperationAndObjectType</classification>
</statistics>
</repository>
<tracing>
<profile>
<name>performance</name>
<displayName>Performance tracing</displayName>
<visible>true</visible>
<default>true</default>
<fileNamePattern>performance-trace %{timestamp} %{focusName} %{milliseconds}</fileNamePattern>
<createRepoObject>true</createRepoObject>
<compressOutput>true</compressOutput>
</profile>
<profile>
<name>functional</name>
<displayName>Functional tracing</displayName>
<visible>true</visible>
<fileNamePattern>functional-trace %{timestamp} %{focusName}</fileNamePattern>
<createRepoObject>true</createRepoObject>
<compressOutput>true</compressOutput>
<collectLogEntries>true</collectLogEntries>
<tracingTypeProfile>
<level>normal</level>
</tracingTypeProfile>
</profile>
<profile>
<name>functional-model-logging</name>
<displayName>Functional tracing (with model logging)</displayName>
<visible>true</visible>
<fileNamePattern>functional-trace %{timestamp} %{focusName}</fileNamePattern>
<createRepoObject>true</createRepoObject>
<compressOutput>true</compressOutput>
<collectLogEntries>true</collectLogEntries>
<loggingOverride>
<levelOverride>
<logger>com.evolveum.midpoint.model</logger>
<level>TRACE</level>
</levelOverride>
</loggingOverride>
<tracingTypeProfile>
<level>normal</level>
</tracingTypeProfile>
</profile>
<profile>
<name>functional-sql-logging</name>
<displayName>Functional tracing (with SQL logging)</displayName>
<visible>true</visible>
<fileNamePattern>functional-trace %{timestamp} %{focusName}</fileNamePattern>
<createRepoObject>true</createRepoObject>
<compressOutput>true</compressOutput>
<collectLogEntries>true</collectLogEntries>
<loggingOverride>
<levelOverride>
<logger>org.hibernate.SQL</logger>
<level>TRACE</level>
</levelOverride>
</loggingOverride>
<tracingTypeProfile>
<level>normal</level>
</tracingTypeProfile>
</profile>
</tracing>
</internals>
<deploymentInformation>
<name>demo/grouper</name>
</deploymentInformation>
<adminGuiConfiguration>
<userDashboardLink id="13">
<targetUrl>/self/profile</targetUrl>
<label>Profile</label>
<description>View/edit your profile</description>
<icon>
<cssClass>fa fa-user</cssClass>
</icon>
<color>green</color>
<authorization>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfProfile</authorization>
<authorization>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll</authorization>
</userDashboardLink>
<userDashboardLink id="14">
<targetUrl>/self/credentials</targetUrl>
<label>Credentials</label>
<description>View/edit your credentials</description>
<icon>
<cssClass>fa fa-shield</cssClass>
</icon>
<color>blue</color>
<authorization>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfCredentials</authorization>
<authorization>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll</authorization>
</userDashboardLink>
<userDashboardLink id="15">
<targetUrl>/admin/users</targetUrl>
<label>List users</label>
<icon>
<cssClass>fa fa-users</cssClass>
</icon>
<color>red</color>
<authorization>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#users</authorization>
</userDashboardLink>
<userDashboardLink id="16">
<targetUrl>/admin/resources</targetUrl>
<label>List resources</label>
<icon>
<cssClass>fa fa-database</cssClass>
</icon>
<color>purple</color>
<authorization>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#resources</authorization>
</userDashboardLink>
<enableExperimentalFeatures>true</enableExperimentalFeatures>
</adminGuiConfiguration>
<workflowConfiguration>
<useLegacyApproversSpecification>never</useLegacyApproversSpecification>
<useDefaultApprovalPolicyRules>never</useDefaultApprovalPolicyRules>
</workflowConfiguration>
</systemConfiguration>
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<!--
Looks for groups with the lifecycleState of 'retired' and completes their deletion:
- unassigns all the users (simply by recomputing them)
-->

<task xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mext="http://midpoint.evolveum.com/xml/ns/public/model/extension-3"
xmlns:scext="http://midpoint.evolveum.com/xml/ns/public/model/scripting/extension-3"
oid="1d7bef40-953e-443e-8e9a-ec6e313668c4">
<name>Group Scavenger</name>
<extension>
<scext:executeScript>
<s:action>
<s:type>execute-script</s:type>
<s:parameter>
<s:name>script</s:name>
<c:value xsi:type="c:ScriptExpressionEvaluatorType">
<c:code>import com.evolveum.midpoint.xml.ns._public.common.common_3.*

result = midpoint.currentResult
log.info('Processing dead group: {}', input)
query = prismContext.queryFor(UserType.class)
.item(UserType.F_ROLE_MEMBERSHIP_REF).ref(input.oid)
.build()
members = midpoint.repositoryService.searchObjects(UserType.class, query, null, result)
log.info('Found {} members: {}', members.size(), members)

for (member in members) {
log.info('Going to recompute {}', member)
try {
midpoint.recompute(UserType.class, member.oid)
} catch (Throwable t) {
log.error('Couldn\'t recompute {}: {}', member, t.message, t)
}
}
log.info('Members recomputed; checking if the org is still in "retired" state')
orgAfter = midpoint.repositoryService.getObject(OrgType.class, input.oid, null, result)
currentState = orgAfter.asObjectable().lifecycleState
log.info('Current state = {}', currentState)
if (currentState == 'retired') {
log.info('Deleting the org: {}', orgAfter)
midpoint.deleteObject(OrgType.class, orgAfter.oid, null)
} else {
log.info('State has changed, not deleting the org: {}', orgAfter)
}
log.info('Dead group processing done: {}', input)
</c:code>
</c:value>
</s:parameter>
</s:action>
</scext:executeScript>
<mext:objectType>OrgType</mext:objectType>
<mext:objectQuery>
<q:filter>
<q:equal>
<q:path>lifecycleState</q:path>
<q:value>retired</q:value>
</q:equal>
</q:filter>
</mext:objectQuery>
</extension>
<ownerRef oid="00000000-0000-0000-0000-000000000002"/>
<executionStatus>runnable</executionStatus>
<category>BulkActions</category>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/iterative-scripting/handler-3</handlerUri>
<recurrence>recurring</recurrence>
<schedule>
<interval>60</interval>
</schedule>
</task>
@@ -0,0 +1,27 @@
<!--
~ Copyright (c) 2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<user xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
oid="e897468f-20bd-419c-8fc5-1fe60e2600de">
<name>banderson</name>
<assignment id="1">
<targetRef oid="d48ec05b-fffd-4262-acd3-d9ff63365b62" relation="org:default" type="c:OrgType">
<!-- org-grouper-sysadmin -->
</targetRef>
</assignment>
<fullName>Bob Anderson</fullName>
<givenName>Bob</givenName>
<familyName>Anderson</familyName>
<credentials>
<password>
<value>password</value>
</password>
</credentials>
</user>

0 comments on commit 3d1d731

Please sign in to comment.