Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная

Продолжаем реализацию концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint. У нас на стороне Админа все выстроилось все назначается, теперь надо это реализовать со стороны пользователей! Даже если вы думаете что напишите свою GUI тут надо в первую очередь решить проблемы с авторизацией для просмотра для действий для этого подойдёт и встроенное GUI — в данный момент(4.9.1) частично не работает частично невозможно получается — кое что пришлось переделать по сравнению с частью 1,2 этого повествования.

Окончательная схема работающей концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint 4.9.1

Files: SVG,PNG

Files: SVG,PNG

Окончательный код на Github IDM-Midpoint-POC-Employments-and-Positions

Вид для Админов

Если мы не ищем всё по personalNumber, то на самом User сотрудник(архетип Person) мы не видим какие у него актуальные трудоустройства и назначения, можем это добавить в шапку.

Идем в ArchetypesPerson и вставляем код

<adminGuiConfiguration>
    <objectDetails>
        <summaryPanel>
            <title1>
                <expression>
                    <script>
                        <code>import com.evolveum.midpoint.xml.ns._public.common.common_3.*
user_personalNumber = object.getPersonalNumber()
query_user = midpoint.queryFor(UserType.class, "personalNumber = $user_personalNumber and extension/person_employment_type = 'Основное' and archetypeRef matches (oid = '441f8e23-33cd-41f2-bbb6-beea20feeaee') and activation/effectiveStatus!='disabled'") 
result_user = midpoint.searchObjects(query_user)


if (basic.isEmpty(result_user))
{
return "Основного трудоустройства нет"
} else {
return ("Основное трудоустройство в " + basic.stringify(result_user.costCenter))
}</code>
                    </script>
                </expression>
            </title1>
            <title2>
                <expression>
                    <script>
                        <code>import com.evolveum.midpoint.xml.ns._public.common.common_3.*
user_personalNumber = object.getPersonalNumber()
query_user = midpoint.queryFor(UserType.class, "personalNumber = $user_personalNumber and archetypeRef matches (oid = '441f8e23-33cd-41f2-bbb6-beea20feeaee') and activation/effectiveStatus!='disabled'") 
result_user = midpoint.searchObjects(query_user)

if (basic.isEmpty(result_user))
{
return ""
} else {
return ("Трудоустройства: " + result_user.name.join(", "))
}</code>
                    </script>
                </expression>
            </title2>
            <title3>
                <expression>
                    <script>
                        <code>import com.evolveum.midpoint.xml.ns._public.common.common_3.*
user_personalNumber = object.getPersonalNumber()
query_user = midpoint.queryFor(UserType.class, "personalNumber = $user_personalNumber and archetypeRef matches (oid = '0d1b1269-0011-49e6-b9f1-e62e7827dfed') and activation/effectiveStatus!='disabled'") 
result_user = midpoint.searchObjects(query_user)

if (basic.isEmpty(result_user))
{
return ""
} else {
return ("Назначения: " + result_user.name.join(", "))
}</code>
                    </script>
                </expression>
            </title3>
        </summaryPanel>
...
    </objectDetails>
</adminGuiConfiguration>

Теперь у пользователя с архетипом Persona такая шапка

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 2

Видно какие у сотрудника активные трудоустройства и назначения

GUI сотрудника не начальника

Создаем роль черную POCE GUI End user

в ней код

<activation>
    <effectiveStatus>enabled</effectiveStatus>
    <enableTimestamp>2025-04-07T06:23:39.326Z</enableTimestamp>
</activation>
<authorization id="1">
    <name>gui-self-service-access</name>
    <description>
            Allow access to all self-service operations in GUI.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll</action>
</authorization>
<authorization id="2">
    <name>self-read</name>
    <description>
            Allow to read all the properties of "self" object. I.e. every logged-in user can read
            object that represent his own identity.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="16">
        <special>self</special>
    </object>
</authorization>
<authorization id="3">
    <name>self-shadow-read</name>
    <description>
            Allow to read all the properties of all the shadows that belong to "self" object.
            I.e. every logged-in user can read all his accounts.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="17">
        <type>ShadowType</type>
        <owner>
            <special>self</special>
        </owner>
    </object>
</authorization>
<authorization id="5">
    <name>self-credentials-request</name>
    <description>
            Allow to modify user's own credentials.
            Note that this is a request phase authorization. It also requires corresponding execution-phase authorization.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#changeCredentials</action>
    <phase>request</phase>
    <object id="19">
        <special>self</special>
    </object>
    <item>credentials</item>
</authorization>
<authorization id="6">
    <name>self-shadow-credentials-request</name>
    <description>
            Allow to modify credentials of all users accounts.
            Note that this is a request phase authorization. It also requires corresponding execution-phase authorization.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#changeCredentials</action>
    <phase>request</phase>
    <object id="20">
        <type>ShadowType</type>
        <owner>
            <special>self</special>
        </owner>
    </object>
    <item>credentials</item>
</authorization>
<authorization id="7">
    <name>read-roles</name>
    <description>
            Allow to read  roles
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="21">
        <type>RoleType</type>
    </object>
    <item>name</item>
    <item>displayName</item>
    <item>description</item>
    <item>costCenter</item>
    <item>assignment</item>
</authorization>
<authorization id="10">
    <name>self-execution-modify</name>
    <description>
            Authorization that allows to self-modification of some properties, but only in execution phase.
            The limitation real limitation of these operations is done in the request phase.
            E.g. the modification of assignments is controlled in the request phase by using the #assign
            authorization.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <phase>execution</phase>
    <object id="24">
        <special>self</special>
    </object>
    <item>credentials</item>
    <item>assignment</item>
</authorization>
<authorization id="11">
    <name>self-shadow-execution-add-modify-delete</name>
    <description>
            Authorization that allows to self-modification of user's accounts, but only in execution phase.
            The real limitation of these operations is done in the request phase.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#add</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#delete</action>
    <phase>execution</phase>
    <object id="25">
        <type>ShadowType</type>
        <owner>
            <special>self</special>
        </owner>
    </object>
</authorization>
<authorization id="13">
    <name>operational-objects-get</name>
    <description>
            Authorization that allows to read all the object that are possible to use for (not only) GUI
            customizations. E.g there might be lookup tables used for attributes, custom form types defined, etc.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#get</action>
    <object id="31">
        <type>LookupTableType</type>
    </object>
</authorization>
<authorization id="15">
    <name>self-owned-task-read</name>
    <description>
            Authorization that allows to see all tasks owned by a currently logged-in user.
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="33">
        <type>TaskType</type>
        <owner>
            <special>self</special>
        </owner>
    </object>
</authorization>
<adminGuiConfiguration>
    <feedbackMessagesHook>
        <stackTraceVisibility>hidden</stackTraceVisibility>
    </feedbackMessagesHook>
    <accessRequest>
        <targetSelection>
            <allowRequestForMyself>false</allowRequestForMyself>
            <allowRequestForOthers>false</allowRequestForOthers>
        </targetSelection>
    </accessRequest>
    <homePage id="34">
        <type>UserType</type>
        <widget id="35">
            <identifier>myWorkItems</identifier>
            <visibility>hidden</visibility>
        </widget>
        <widget id="37">
            <identifier>listUsersWidget</identifier>
            <visibility>hidden</visibility>
        </widget>
        <widget id="38">
            <identifier>listResourcesWidget</identifier>
            <visibility>hidden</visibility>
        </widget>
        <widget id="36">
            <identifier>myHistory</identifier>
            <visibility>hidden</visibility>
        </widget>
        <widget id="39">
            <identifier>myRequests</identifier>
            <action id="40">
                <identifier>viewAll</identifier>
                <visibility>hidden</visibility>
            </action>
        </widget>
        <widget id="135">
            <identifier>myRequests</identifier>
            <visibility>hidden</visibility>
        </widget>
        <widget id="235">
            <identifier>myAccounts</identifier>
            <visibility>hidden</visibility>
        </widget>
        <widget id="335">
            <identifier>myCertificationItems</identifier>
            <visibility>hidden</visibility>
        </widget>
    </homePage>
    <selfProfilePage>
        <type>UserType</type>
        <panel id="41">
            <identifier>history</identifier>
            <visibility>hidden</visibility>
        </panel>
        <panel id="43">
            <identifier>focusTriggers</identifier>
            <visibility>hidden</visibility>
        </panel>
        <panel id="44">
            <identifier>password</identifier>
            <visibility>hidden</visibility>
        </panel>
        <panel id="893">
            <identifier>personas</identifier>
            <visibility>hidden</visibility>
        </panel>
        <panel id="894">
            <identifier>focusMarks</identifier>
            <visibility>hidden</visibility>
        </panel>
        <panel id="45">
            <identifier>assignments</identifier>
            <panel id="46">
                <identifier>constructionAssignments</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="47">
                <identifier>indirectAssignments</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="48">
                <identifier>dataProtectionAssignments</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="49">
                <identifier>orgAssignments</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="50">
                <identifier>roleAssignments</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="51">
                <identifier>serviceAssignments</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="892">
                <identifier>policyAssignments</identifier>
                <visibility>hidden</visibility>
            </panel>
        </panel>
        <panel id="895">
            <identifier>requestAccess</identifier>
            <visibility>hidden</visibility>
        </panel>
    </selfProfilePage>
</adminGuiConfiguration>
...
</role>

Делаем в архетипе Person inducement в неё. И теперь все сотрудники с архетипом Person могут заходит на GUI Midpoint но у них достаточно пусто

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 3

Вьюха мои IDM объекты

Сделаем пользователю вьюху своих объектов, для этого добавим Collection.

В ConfigurationImport object вставляем код

<objectCollection>
    <name>my-idm-objects-view</name>
    <type>UserType</type>
    <filter>
        <text>
          personalNumber = `actor.personalNumber` and activation/effectiveStatus!="disabled"
        </text>
    </filter>
</objectCollection>

Тут появляется словечко actor, нигде в документации Midpoint не упоминается и не описывается. Но оно в применении к фильтрам в коллекциях выдает данные того кто эту коллекцию запускает, что нам очень кстати.

Редактировать Collection можно в ConfigurationRepository ObjectObject collection

Теперь сама вьюха она прячется в ConfigurationSystemAdmin GUI configurationObject detail views тут все мягко говоря поломано! И в версии 4.9.1 но и в 4.8 так было. Можно открыть RAW но нельзя его сохранить, потому что недописаны некоторые строки — ошибка тут же говорит что надо исправить…

Добавляем кодом

<objectCollectionView id="309">
    <identifier>my-idm-objects</identifier>
    <display>
        <label>My IDM Users</label>
        <singularLabel>My IDM User</singularLabel>
        <pluralLabel>My IDM Users</pluralLabel>
        <icon>
            <cssClass>fa fa-compass-drafting</cssClass>
        </icon>
    </display>
    <visibility>hidden</visibility>
    <displayOrder>10</displayOrder>
    <column id="317">
        <name>Name</name>
        <path>c:name</path>
    </column>
    <column id="319">
        <name>Full Name</name>
        <path>c:fullName</path>
        <previousColumn>Co.</previousColumn>
    </column>
    <column id="335">
        <name>Employment Type</name>
        <path xmlns:gen795="http://example.com/xml/ns/mySchema">c:extension/gen795:person_employment_type</path>
        <previousColumn>Name</previousColumn>
    </column>
    <column id="337">
        <name>Co.</name>
        <path>c:costCenter</path>
        <previousColumn>Employment Type</previousColumn>
    </column>
    <type>c:UserType</type>
    <collection>
        <collectionRef oid="1c3bd39e-ed63-11ed-b1ac-0050568cc7f8" relation="org:default" type="c:ObjectCollectionType">
            <!-- my-idm-objects-view -->
        </collectionRef>
    </collection>
</objectCollectionView>

...
</objectCollectionViews>

Эта виюха по умолчанию скрыта

Нам нужно чтобы эта вьюха была у пользователя

Делаем роль черную POCE GUI My IDM Objects

В неё вставляем код

<authorization id="3">
    <name>read users with same personalNumber</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="16">
        <type>UserType</type>
        <filter>
            <q:text>personalNumber = `actor.personalNumber`</q:text>
        </filter>
    </object>
    <item>assignment</item>
    <item>name</item>
    <item>fullName</item>
    <item>costCenter</item>
    <item>extension/person_employment_type</item>
    <item>roleMembershipRef</item>
    <item>organizationalUnit</item>
    <item>organization</item>
</authorization>
...
</role>

Это нам в принципе разрешает читать всех пользователей у которых такой же personalNumber

<authorization id="2">
    <name>to see Users folder</name>
    <description>to see Users folder
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#usersView</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#userDetails</action>
</authorization>
...
</role>

Это нам в принципе разрешает видеть вкладку Users и все вьюхи — увидим сразу Persons

<adminGuiConfiguration>
    <objectCollectionViews>
        <objectCollectionView id="1761">
            <identifier>person-view</identifier>
            <visibility>hidden</visibility>
            <type>UserType</type>
        </objectCollectionView>
        <objectCollectionView id="1760">
            <identifier>my-idm-objects</identifier>
            <visibility>visible</visibility>
            <type>UserType</type>
        </objectCollectionView>
    </objectCollectionViews>
    <objectDetails>
...
    </objectCollectionViews>
        ...
</adminGuiConfiguration>
</role>

Запрещаем показывать Personas, и разрешаем нашу my-idm-objects

У пользователя мы видим ограниченное количество атрибутов но в меню есть все пустые поля, так что поимённо скрываем.

<adminGuiConfiguration>
...
    <objectDetails>
        <objectDetailsPage id="1762">
            <type>c:UserType</type>
            <panel id="1763">
                <identifier>projections</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1765">
                <identifier>password</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1766">
                <identifier>activation</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1767">
                <identifier>history</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1768">
                <identifier>focusTriggers</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1769">
                <identifier>igaAccesses</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1770">
                <identifier>personas</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1771">
                <identifier>userDelegations</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1772">
                <identifier>delegatedToMe</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1773">
                <identifier>focusCases</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1774">
                <identifier>focusMarks</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1775">
                <identifier>clearances</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1776">
                <identifier>applications</identifier>
                <visibility>hidden</visibility>
            </panel>
            <panel id="1777">
                <identifier>assignments</identifier>
                <panelType>allAssignments</panelType>
                <panel id="1778">
                    <identifier>allAssignments</identifier>
                    <visibility>hidden</visibility>
                </panel>
                <panel id="1779">
                    <identifier>indirectAssignments</identifier>
                    <visibility>hidden</visibility>
                </panel>
                <panel id="1780">
                    <identifier>orgAssignments</identifier>
                    <visibility>hidden</visibility>
                </panel>
                <panel id="1781">
                    <identifier>roleAssignments</identifier>
                    <visibility>hidden</visibility>
                </panel>
                <panel id="1782">
                    <identifier>serviceAssignments</identifier>
                    <visibility>hidden</visibility>
                </panel>
                <panel id="1783">
                    <identifier>policyAssignments</identifier>
                    <visibility>hidden</visibility>
                </panel>
                <panel id="1784">
                    <identifier>constructionAssignments</identifier>
                    <visibility>hidden</visibility>
                </panel>
            </panel>
        </objectDetailsPage>
    </objectDetails>
</adminGuiConfiguration>
</role>

Теперь надо назначить роль POCE GUI My IDM Objects сотруднику когда у него в принципе имеется активное трудоустройство. Пойдём в ресурсе POCE 01 EMPLOYMENT Role у нас в Schem HandlerObject Type под названием POCE User есть association которая назначает роль трудоустройства, сама ассоциация это тригер для назначающего inbound добавляем туда еще один inbound c ролью POCE GUI My IDM Objects

весь association теперь выглядит так и тому есть причина!

<association id="306">
    <ref>CSV members from employement to MP user</ref>
    <inbound id="478">
        <strength>normal</strength>
        <channel>http://midpoint.evolveum.com/xml/ns/public/common/channels-3#reconciliation</channel>
        <expression>
            <assignmentTargetSearch>
                <targetType>RoleType</targetType>
                <filter>
                    <q:equal>
                        <q:path>identifier</q:path>
                        <expression>
                            <script>
                                <code>
                                        if (basic.stringify(basic.getAttributeValue(entitlement, 'status_poce')) == "active")
{

 return basic.getAttributeValue(entitlement, 'main_id')
}
else
{
//return false
return "this_is_something_that_should_not_be_found"
}
                                </code>
                            </script>
                        </expression>
                    </q:equal>
                </filter>
            </assignmentTargetSearch>
        </expression>
        <target>
            <path>assignment</path>
            <set>
                <predefined>all</predefined>
            </set>
        </target>
        <condition>
            <script>
                <code>if (basic.stringify(basic.getAttributeValue(entitlement, 'status_poce')) == "active")
{
return true
}
else
{
return false
}
                </code>
            </script>
        </condition>
    </inbound>
    <inbound id="479">
        <strength>normal</strength>
        <channel>http://midpoint.evolveum.com/xml/ns/public/common/channels-3#reconciliation</channel>
        <expression>
            <assignmentTargetSearch>
                <targetType>RoleType</targetType>
                <oid>dc435ebd-4ee0-480b-a8a3-ff3c9e6ea467</oid>
            </assignmentTargetSearch>
        </expression>
        <target>
            <path>assignment</path>
        </target>
        <condition>
            <script>
                <code>if (basic.stringify(basic.getAttributeValue(entitlement, 'status_poce')) == "active")
{
return true
}
else
{ 
return false
}
                </code>
            </script>
        </condition>
    </inbound>
    <kind>entitlement</kind>
    <intent>intent POCE Employment Role</intent>
    <direction>objectToSubject</direction>
    <associationAttribute>ri:members_poce</associationAttribute>
    <valueAttribute>ri:main_id</valueAttribute>
    <explicitReferentialIntegrity>false</explicitReferentialIntegrity>
</association>

Эээ каждый раз когда думаешь что понял association в Midpoint случается всякая загакряказябина. Себе и всем на будущее на диагностику:

1. Кнопка реконсиляции на User, не повод сделать реконсиляцию на ресурсе в случае с association

2. Association устанавливает всего лишь связь, если удалять связь то и делаться ничего не будет связи то нет и все что наделалось останется по этой причине…

3. В Association мы вешаем assignment с condition, то что работает кондишен легко проверить, добавляем в script например

log.info „TRUE“

В нашем случае ответ кому ассаинить то же script в него тоже пишем log.info

И получается условия да-нет, а ассаинмент все равно случается в случае если больше одной ассоциации у user… Поэтому в скрипте поиска что ассаинит имеется тот же кондишион

if (basic.stringify(basic.getAttributeValue(entitlement, 'status_poce')) == "active")
{
 return basic.getAttributeValue(entitlement, 'main_id')
}
else
{
//return false
return "this_is_something_that_should_not_be_found"
}

А в случае если все таки того кого хотим выдать не active выдаем то что Midpoint ну никак не сможет найти для назначений «this_is_something_that_should_not_be_found»… return false тоже работает (4.9.2) но у меня был случай как реально выдал все роли у кого было пусто в identifier!

Рекомпилим ресурс POCE 01 EMPLOYMENT Role теперь у сотрудника в GUI такая картинка

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 4

У сотрудника есть возможность посмотреть что у него из активных трудоустройств, назначений, аккаунтов.

И в них видно минимум информации и назначенные роли

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 5

В Assigment не захожу там видны технические роли для трудоустройств и назначений, надо их убрать, а то сотрудники будут пугаться.

Добавляем еще один Object Collection в ConfigurationImport object вставляем код

<objectCollection>
    <name>my-idm-assignment-view</name>
    <type>AssignmentType</type>
    <filter>
        <text>
           targetRef/@/name not startsWith "POS" and targetRef/@/name not startsWith "EMP"
        </text>
    </filter>
</objectCollection>

Тут filter очень просто описывает не брать роль начинающиеся на POS и EMP

И в роли POCE GUI My IDM Objects

после

<adminGuiConfiguration>
     ...
        <objectDetails>
            <objectDetailsPage id="1762">
                <type>c:UserType</type>
                ...
                <panel id="1777">
                    <identifier>assignments</identifier>
                    <panelType>allAssignments</panelType>

вставляем код

<listView>
    <identifier>role-assignmnets-view</identifier>
    <type>c:AssignmentType</type>
    <collection>
        <collectionRef oid="9e81fed1-282c-4c56-85ea-861fb36d6b58" relation="org:default" type="c:ObjectCollectionType">
            <!-- my-idm-assignment-view -->
        </collectionRef>
    </collection>
</listView>

И теперь сотрудник в Assignments видеть только «реальные» роли

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 6

Но сотрудники все равно будут пугаться на Assignments цифра 13, а в показывается всего 5!

Настройка Request Access

В роль POCE GUI My IDM Objects добавляю

<adminGuiConfiguration>
...
    <accessRequest>
        <targetSelection>
            <allowRequestForMyself>false</allowRequestForMyself>
            <allowRequestForOthers>true</allowRequestForOthers>
            <group id="17656">
                <identifier>my-employments</identifier>
                <display>
                    <label>My Employments</label>
                    <icon>
                        <cssClass>fa fa-address-card</cssClass>
                    </icon>
                </display>
                <collection>
                    <filter>
                        <q:text>personalNumber = `actor.personalNumber` and archetypeRef matches (oid = "441f8e23-33cd-41f2-bbb6-beea20feeaee") and activation/effectiveStatus!="disabled"</q:text>
                    </filter>
                </collection>
                <autocompleteConfiguration>
                    <displayExpression>
                        <script>
                            <code>
                                    return "My Employment: " + object.fullName
                            </code>
                        </script>
                    </displayExpression>
                    <autocompleteMinChars>1</autocompleteMinChars>
                </autocompleteConfiguration>
            </group>
            <group id="17657">
                <identifier>my-positions</identifier>
                <display>
                    <label>My Positions</label>
                    <icon>
                        <cssClass>fa fa-user-tie</cssClass>
                    </icon>
                </display>
                <collection>
                    <filter>
                        <q:text>personalNumber = `actor.personalNumber` and archetypeRef matches (oid = "0d1b1269-0011-49e6-b9f1-e62e7827dfed") and activation/effectiveStatus!="disabled"</q:text>
                    </filter>
                </collection>
                <autocompleteConfiguration>
                    <displayExpression>
                        <script>
                            <code>
                                    return "My Position: " + object.fullName
                            </code>
                        </script>
                    </displayExpression>
                    <autocompleteMinChars>1</autocompleteMinChars>
                </autocompleteConfiguration>
            </group>
        </targetSelection>
    </accessRequest>
...
</adminGuiConfiguration>

Заходим пользователем в пользователя и смотрим его Request Access

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 7

Дальше все печальненько — автоподборка не работает (написал в Evolvium) так что надо жать на Select manually а там, нет ни малейшего намека на то что можно переделать вьюху choose object но так как я предусмотрительно всю инфу заснул в fullName то по нему можно понять что надо выбрать… если знаешь что надо конечно!

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 8

Все что мы тут видим привязано к авторизации, авторизация представляет из себя два непересекающихся пути — то что можно видеть, и то что можно делать. Крайне неудачный подход особенно в момент выбора роли. Также хотелось бы чтобы выбор на того кого запрашивать роль определял каике роли можно на него запросить — нет этого вообще нет! И один выход после выбора на кого запрашивать сотрудника послать в каталог где он должен выбрать Компанию и на кого запрашивать Employment или Position, тогда он увидит доступные для запроса роли! Опять же может и есть какой-то хитрый способ сделать это красивее но Evolvium его не озвучивает!

Так что нам нужно быстренько создать Каталог ролей, накидываю Organization

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 9
Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 10

В Object Template для Forward ролей POCE Forward Role Object Template

добавляем кодом

<item id="1">
    <ref>assignment</ref>
    <displayName>Assignment to Role Catalog</displayName>
    <mapping id="9">
        <name>Name</name>
        <source>
            <path xmlns:gen444="http://example.com/xml/ns/mySchema">c:extension/gen444:user_employment_parent</path>
        </source>
        <source>
            <path xmlns:gen189="http://example.com/xml/ns/mySchema">c:extension/gen189:role_purpose_type</path>
        </source>
        <expression>
            <assignmentTargetSearch>
                <targetType>OrgType</targetType>
                <filter>
                    <q:equal>
                        <q:path>identifier</q:path>
                        <expression>
                            <trace>true</trace>
                            <script>
                                <code>result =  "\RC\" + user_employment_parent + "\" + role_purpose_type
return result

                                </code>
                            </script>
                        </expression>
                    </q:equal>
                </filter>
            </assignmentTargetSearch>
        </expression>
    </mapping>
</item>
...
</objectTemplate>

Реконсилим все Forward роли, кнопкой из меню и смотрим — привязались

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 11

Этот роль каталог будем подсовывать сотрудникам

По умолчанию в SystemAdmin GUI configurationAccess Request уже есть три каталога.

Открываем RAW и удаляем код

<roleCatalog>
    <collection id="215">
        <identifier>allRoles</identifier>
        <default>true</default>
        <collectionIdentifier>allRoles</collectionIdentifier>
    </collection>
    <collection id="216">
        <identifier>allOrgs</identifier>
        <collectionIdentifier>allOrgs</collectionIdentifier>
    </collection>
    <collection id="217">
        <identifier>allServices</identifier>
        <collectionIdentifier>allServices</collectionIdentifier>
    </collection>
</roleCatalog>

Создадим роли черные

Name: POCE GUI Request Access OOO ODIN

Identifier: POCEGUIRequestAccessEMP001001

код

<authorization id="12">
    <name>assign-requestable-roles</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#assign</action>
    <target id="1">
        <type>RoleType</type>
        <archetypeRef oid="b527aa8f-9097-45d7-94c9-8c2d79e53832" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Forward Role ArcheType -->
        </archetypeRef>
        <filter>
            <q:text>extension/user_employment_parent  = "EMP001001" and activation/effectiveStatus != "DISABLED"</q:text>
        </filter>
    </target>
    <relation>org:default</relation>
</authorization>
<authorization id="4">
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <phase>execution</phase>
    <object id="123">
        <type>UserType</type>
        <filter>
            <q:text>personalNumber = `actor.personalNumber` and organization = "EMP001001" and activation/effectiveStatus != "DISABLED"</q:text>
        </filter>
    </object>
</authorization>

Name: POCE GUI Request Access OOO DOS

Identifier: POCEGUIRequestAccessEMP001002

код

<authorization id="4">
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <phase>execution</phase>
    <object id="123">
        <type>UserType</type>
        <filter>
            <q:text>personalNumber = `actor.personalNumber`  and activation/effectiveStatus != "DISABLED"</q:text>
        </filter>
    </object>
</authorization>
<authorization id="12">
    <name>assign-requestable-roles</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#assign</action>
    <target id="1">
        <type>RoleType</type>
        <archetypeRef oid="b527aa8f-9097-45d7-94c9-8c2d79e53832" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Forward Role ArcheType -->
        </archetypeRef>
        <filter>
            <q:text>extension/user_employment_parent  = "EMP001002"</q:text>
        </filter>
    </target>
    <relation>org:default</relation>
</authorization>

DISCLAIMER: То что касается assign настроено очень толсто так как сейчас в 4.9.1 не работает object который должен сообщать кому можно назначать

<authorization>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#assign</action>
    <object>
	X does not work
    </object>
    <target>
        <type>RoleType</type>
        <filter>
            <q:text>roleType = "application"</q:text>
        </filter>
    </target>
</authorization

https://docs.evolveum.com/midpoint/reference/master/security/authorization/configuration/

Выдавать их будем через Object Template той роли трудоустройства у кого это компания

добавляем в POCE Employment Role Object Template

<item id="20">
    <ref>inducement</ref>
    <displayName>Auto inducement to role POCE GUI Request Access intercative</displayName>
    <mapping id="19">
        <authoritative>true</authoritative>
        <strength>strong</strength>
        <source>
            <path xmlns:gen189="http://example.com/xml/ns/mySchema">c:extension/gen189:user_administrativeStatus</path>
        </source>
        <source>
            <path>locality</path>
        </source>
        <expression>
            <assignmentTargetSearch>
                <targetType>RoleType</targetType>
                <filter>
                    <q:equal>
                        <q:path>identifier</q:path>
                        <expression>
                            <script>
                                <code>result =  "POCEGUIRequestAccess" + locality
return result</code>
                            </script>
                        </expression>
                    </q:equal>
                </filter>
            </assignmentTargetSearch>
        </expression>
        <condition>
            <script>
                <code>
             user_administrativeStatus       
if (user_administrativeStatus == "ENABLED")
{return true}
else{return false}
                </code>
            </script>
        </condition>
    </mapping>
</item>

Способ интерактивный но не совсем красивый, роль выдается роли которая не только у сотрудника но и у user Трудоустройство, там она будет болтаться без дела в непрямых назначениях, у трудоустройства нет роли заходить на GUI, да и вообще пароля нет.

Выяснилось что каталог нужно разрешать смотреть весь, а не отдельно, а то тогда он показываться не будет. В роль POCE GUI My IDM Objects добавляем

...
<roleCatalog>
    <defaultView>table</defaultView>
    <showRolesOfTeammate>false</showRolesOfTeammate>
    <roleCatalogRef oid="19ad795d-bb6e-48dd-b131-d07018c73ec9" relation="org:default" type="c:OrgType">
        <!-- RC:Role Catalog Groundfloor -->
    </roleCatalogRef>
    <roleCatalogDepth>3</roleCatalogDepth>
</roleCatalog>
</accessRequest>
</adminGuiConfiguration>

и

<authorization id="666001">
    <name>read-requestable-roles</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="3">
        <type>OrgType</type>
        <archetypeRef oid="cd509999-d455-4852-b2a0-a3da588d9475" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Role Catalog ORG ArcheType -->
        </archetypeRef>
    </object>
</authorization>

Рекомпильнем с кнопки роли Трудоустройства, зайдем под пользователем у кого одно трудоустройство.

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 12

В роль каталоге две компании! Сотруднику надо помнить на какую компанию и на что(Employment или Positon) он собирается запрашивать… да и раздвигать Role catalog тоже надо будет самому, по умолчанию все свернуто! А вот видит он только те роли которые разрешают роли POCE GUI Request Access OOO… по роли трудоустройства.

Но запрашивать роли пока рано… у нас в процессе назначения роли есть скрипты, и по админом они запускались молча, а под другим пользователем не админом они не будут запускать просто так или никак!

Тут можно по двум путям прописать Expression Profile Configuration

https://docs.evolveum.com/midpoint/reference/master/expressions/expressions/profiles/configuration/

У меня не сработало с дичайщей ошибкой нет метода в библиотеке, хотя библиотека была подключена. Evolvium должен был подумать о безапосности исполнения скриптов и вот подумал! А о том чтобы они срабатывали тоже подумал поэтому есть вот Privilege Elevation

https://docs.evolveum.com/midpoint/reference/master/security/privilege-elevation/

Добавляем в POCE POLICY: identifier from Forward Role to User Forward Roles List

<expression>
                    <privileges xsi:type="c:ExecutionPrivilegesSpecificationType">
                        <runPrivileged>true</runPrivileged>
                    </privileges>
                    <script>
                        <code>...

Так же надо сделать во всех заданиях на рекомпуть в архетипе POCE Position Role ArcheType, можно в GUI

А в POCE GUI My IDM Objects добавляем

<authorization id="3325">
    <name>poce-shadow-read</name>
    <description>
           POCE idm object Users
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="32325">
        <type>ShadowType</type>
        <owner>
            <type>UserType</type>
            <filter>
                <q:text>personalNumber = `actor.personalNumber`</q:text>
            </filter>
        </owner>
    </object>
</authorization>
<authorization id="11">
    <name>poce-shadow-execution-add-modify-delete</name>
    <description>
POCE idm object Users
    </description>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#add</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#delete</action>
    <phase>execution</phase>
    <object id="3325">
        <type>ShadowType</type>
        <owner>
            <type>UserType</type>
            <filter>
                <q:text>personalNumber = `actor.personalNumber`</q:text>
            </filter>
        </owner>
    </object>
</authorization>

Это чтобы при запросе роли сотрудникам в shadow тоже были возможны изменения, то есть в ресурсах, то есть в конечных системах

Пока у нас все было просто, мы не создавали учетки AD которые для Midpoint — персоны привязанные к User трудоустройства или назначения.

Добавим в роль POCE GUI My IDM Objects

<authorization id="55501">
    <name>my-idm-objects-persona-read</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="1233531">
        <type>UserType</type>
        <owner>
            <type>UserType</type>
            <filter>
                <q:text>personalNumber = `actor.personalNumber` and activation/effectiveStatus!="disabled"</q:text>
            </filter>
        </owner>
    </object>
    <item>assignment</item>
    <item>name</item>
    <item>fullName</item>
    <item>costCenter</item>
    <item>extension/person_employment_type</item>
    <item>roleMembershipRef</item>
    <item>organizationalUnit</item>
    <item>organization</item>
</authorization>
<authorization id="55502">
    <name>my-idm-objects-auth-persona-execute-add-EMP-ACC</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#add</action>
    <phase>execution</phase>
    <object id="1233532">
        <type>UserType</type>
        <archetypeRef oid="48077d8a-7cce-4999-b7cb-d31620983c1d" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Employment MS AD Account -->
        </archetypeRef>
    </object>
</authorization>
<authorization id="55503">
    <name>my-idm-objects-auth-persona-execute-modify-delete-EMP-ACC</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#delete</action>
    <phase>execution</phase>
    <object id="1233533">
        <type>UserType</type>
        <archetypeRef oid="48077d8a-7cce-4999-b7cb-d31620983c1d" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Employment MS AD Account -->
        </archetypeRef>
        <owner>
            <type>UserType</type>
            <filter>
                <q:text>personalNumber = `actor.personalNumber` and activation/effectiveStatus!="disabled"</q:text>
            </filter>
        </owner>
    </object>
</authorization>
<authorization id="55504">
    <name>my-idm-objects-auth-persona-execute-add-POS-ACC</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#add</action>
    <phase>execution</phase>
    <object id="1233534">
        <type>UserType</type>
        <archetypeRef oid="87471a3d-2d25-4309-b58a-af261683adfa" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Position MS AD Account -->
        </archetypeRef>
    </object>
</authorization>
<authorization id="55505">
    <name>my-idm-objects-auth-persona-execute-modify-delete-POS-ACC</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#delete</action>
    <phase>execution</phase>
    <object id="1233535">
        <type>UserType</type>
        <archetypeRef oid="87471a3d-2d25-4309-b58a-af261683adfa" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Position MS AD Account -->
        </archetypeRef>
        <owner>
            <type>UserType</type>
            <filter>
                <q:text>personalNumber = `actor.personalNumber` and activation/effectiveStatus!="disabled"</q:text>
            </filter>
        </owner>
    </object>
</authorization>
<authorization id="55510">
    <name>operation-with-my-nickName-role</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#add</action>
    <object id="3">
        <type>RoleType</type>
        <archetypeRef oid="7f71dcf3-c89d-4e23-930b-215423af3849" relation="org:default" type="c:ArchetypeType">
            <!-- POCE nickName Role archeType -->
        </archetypeRef>
        <filter>
            <q:text>extension/user_personalNumber = `actor.personalNumber`</q:text>
        </filter>
    </object>
</authorization>
<authorization id="55520">
    <name>search-on-resource</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#search</action>
</authorization>

55501 — читать персон не заблокированных User трудоустройства и назначений

55502 — в принципе возможность создавать персон с указанным архетипом для трудоустройства

55503 — изменять персон не заблокированных User трудоустройства

55504 — тоже самое что 55502 но для назначения

55505 — изменять персон не заблокированных User назначения

55510 — создание роли с архетипом nickName

55520 — вот тут толсто получилось, это разрешение искать, уточнить где Mipdpoint не дал, хотел искать только в одном Ресурсе для генерации nickName

С созданием учетки от сотрдуника возникла проблема… с пространством и временем! И правами… Ну скрипт который запускался на ура под админом и привязывал роль nickName к User сотрудник, под пользователем не запускается совсем никак, не сразу но отказался от этой идеи и все переделал что касается создание учетки AD. И тут всплыла проблема пространства и времени assignment на пользователя под админом однозначно повод для рекомпутации пользователя, но под сотрудником необезательно! Если до кучи всего происходит то вот в конце одной рекомпутации и не хватает…

Пришлось переделать чтобы работало так

1 User Employment получает роль OOO ODIN FR: Employment MS AD Account

— она пишет в Forward Roles строку

NICKNAME|EMP001001|Employment MS AD Account|EMP002001|null|null

2 Оbject Template на User Employment делает при изменении в Forward Roles

— если есть строка начинающеюся на NICKNAME|

ассаигнится или ассаинтся-создается(если нет) роль nickName [НЮАНС]

— если есть строка начинающеюся на NICKNAME|EMP001001|Employment MS AD Account|

ассаинит роль для создание персон Employment AD Account

НЮАНС — если мы админы и случился ассаимент OOO ODIN FR: Employment MS AD Account а за ним роль nickName то nickName у нас заполнятся по рекомпутации, которая после назначения роль nickName и вытягиваются данные из ассаненых ролей по link в архетипе… вот при запросе назначение под сотрудником это не случается, порядок действий видимо другой. Поэтому мы в роль nickName отдельно прописываем действие „писать в User“ и у нас два способа записи, и они нам оба нужны — link для всех случаев, другой для запроса из под сотрудника.

Но это не вся магия, роль nickName надо таки повесить на сотрудника User с архетипом Persona — чтобы получать ФИО из первоисточника. И случится это в момент смены фамилии на сотруднике. Сейчас в моменте в действующем User Employment актуальная фамилия, поэтому при первой необходимости в роль nickName мы её создаем беря ФИО из User Employment. При смене же фамилии происходит следующее:

1 У сотрудника меняется фамилия в User с архетипом Personal

2 Оbject Template на Person делает при изменеии в ФИО

— ассаинить на User роль nickName — если есть, если нет не ассаинить

3 Роль nickName получает новые ФИО от User с архетипом Personal

— переделывает свой nickName

— тыкает User Employment что тот обновил nickName

4 User Employment передает новый nickName своей персоне Employment AD Account

Изменению подверглись

Архетипы

POCE Employment User ArcheType

POCE Employment MS AD Account

POCE Position User ArcheType

POCE Position MS AD Account

Object Template

Person Object Template

POCE Employment MS AD Account Object Template

POCE Employment User Object Template

POCE Person Employment MS AD Account Object Template

POCE Person Position MS AD Account Object Template

POCE Position MS AD Account Object Template

POCE Position User Object Template

Может еще что-то задело, окончательный код смотрите на IDM-Midpoint-POC-Employments-and-Positions/

Теперь о главном — я строил концепцию на Linked Object она прекрасно работает на уровне системы, и совершенно не работает на уровне пользователя — в ситуациях когда пользователь что-то запрашивает для своих позиций и трудоустройств. Почему? Неизвестно! Видимо недописали авторизацию для этого процесса, Evolveum не отвечает так что будем думать что забили! И точно забили потому что включая логи авторизации там даже нет попытки что делать в этом направлении, никаких денайдов просто пусто.

Так как у нас в концепции канал данных передачи прав между Назначением и Трудоустройства то надо её пинать другим способом.

Сделаем таск рекомпиляции роли Назначения если на User Назначение внес изменения User Сотрудник… к сожалению в поиске по User нет поиска по полю History в User… Но в User есть информацию о том кто и когда сделал asssigment будем пытаться закрепиться за эту информацию!

…совершенно естественное желание любого инженера, да и просто пользователя, в поиске получать ответ на вопрос «у кого сделано, за последние 5 минут» — Evolvium этому противица всеми способами, опять всё валит на безопасноть, слушайте ну так всего боятся на кой тогда IDM’ом вообще занялись! Еще раз мы НЕ МОЖЕМ в Advanced search получить результат за последние пять минут.

Но способ есть, «описан тут» Using expressions in midPoint Query Language

https://docs.evolveum.com/midpoint/reference/support-4.9/concepts/query/midpoint-query-language/expressions/

И если верить презентации годичной давности How to Search for Information in MidPoint: MidPoint Query Language for Engineers https://www.youtube.com/watch?v=216ArG_Hq9w то реализован он только для

Evaluation of search expressions is limited. Fully works in:

• Dashboards

• Reports

• Object collections

А если не верить и попробовать то в Task оказывается тоже работает

Заходим в AdministrationServer TasksIterative action tasks создаем пустой под именем POCE Recompute Position roles if User Position has been mod bu main user и наполняем его кодом

<schedule>
    <recurrence>recurring</recurrence>
    <interval>300</interval>
</schedule>
<activity>
    <work>
        <iterativeScripting>
            <objects>
                <type>c:UserType</type>
                <archetypeRef oid="0d1b1269-0011-49e6-b9f1-e62e7827dfed" relation="org:default" type="c:ArchetypeType">
                    <!-- POCE Position User ArcheType -->
                </archetypeRef>
                <query>
                    <q:filter>
                        <q:and>
                            <q:text>
archetypeRef matches (oid = '0d1b1269-0011-49e6-b9f1-e62e7827dfed') and assignment/@metadata/storage/creatorRef/@/personalNumber equal personalNumber and assignment/@metadata/storage/createTimestamp greater ```
dateminus5m = basic.addDuration(basic.currentDateTime(), "-PT5M")
return dateminus5m 
```
                            </q:text>
                        </q:and>
                    </q:filter>
                </query>
                <useRepositoryDirectly>true</useRepositoryDirectly>
            </objects>
            <scriptExecutionRequest xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3">
                <s:action>
                    <s:type>execute-script</s:type>
                    <s:parameter>
                        <s:name>script</s:name>
                        <s:value xsi:type="c:ScriptExpressionEvaluatorType">
                            <code>
                                    import com.evolveum.midpoint.xml.ns._public.common.common_3.*
                                    import com.evolveum.midpoint.prism.delta.builder.*
                                    import com.evolveum.midpoint.model.api.*

role_name =  input.personalNumber query_role= midpoint.queryFor(RoleType.class, "archetypeRef matches (oid = '47374624-553c-4661-b116-d07952900451') and extension/user_personalNumber equal '$role_name'") 
result_role = midpoint.searchObjects(query_role)
midpoint.recompute(RoleType.class, basic.stringify(result_role.oid))



                            </code>
                        </s:value>
                    </s:parameter>
                </s:action>
            </scriptExecutionRequest>
        </iterativeScripting>
    </work>
</activity>

<scriptExecutionRequest> — мы тут посылаем команду рекомпутить роли Назначений у которых такой же extension/user_personalNumber как personalNumber у переданных из object ниже.

<object> — тут строка поиска — дай людей с архетипом user Назначения и у которых есть назначение сделанное user Сотрудником сравниваются personalNumber и не старше 5 минут.

Также у нас в процессе создания учетки есть создание роли nickName и поиск по ресурсу, добавлем в POCE GUI My IDM Objects

<authorization id="55510">
        <name>operation-with-my-nickName-role</name>
        <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#add</action>
        <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
        <object id="3">
            <type>RoleType</type>
            <archetypeRef oid="7f71dcf3-c89d-4e23-930b-215423af3849" relation="org:default" type="c:ArchetypeType">
                <!-- POCE nickName Role archeType -->
            </archetypeRef>
            <filter>
                <q:text>extension/user_personalNumber = `actor.personalNumber`</q:text>
            </filter>
        </object>
    </authorization>
    <authorization id="55520">
        <name>search-on-resource</name>
        <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#search</action>
    </authorization>

55510 — это добавление и модификация роли nickName у которой наш extension/user_personalNumber

55520 — а тут очень толсто, не удалось найти нужных слов чтобы разрешить искать только в ресурсе и только в одном… это нужно для скрипта который собирает login.

Проверяем:

Сотрудник 600667 зашел в GUI запросил на трудоустройство EMP002001 роли OOO ODIN FR: Food beer, OOO ODIN FR:ADG IT Level 2 и на назначение POS000101 роли OOO ODIN FR:ADG Jupiter WC, OOO ODIN FR:ADG Luna WC. Подождал 5 минут пока сработает таск POCE Recompute Position roles if User Position has been mod bu main user, или не ждал, а сразу запросил, а потом подождал, роль OOO ODIN FR: Employment MS AD Account

Идет у себя в GUI в UsersMy IDM Users

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 13

Появился новый My IDM Users под Name 600667 EMP002001 Employment MS AD Account это его реальный AD аккаунт, у которого в Assigments реальные AD роли группы, но собранные из трудоустройства и назначений

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 14

Сотрудник на User назначение POS000101 запрашивает роль OOO ODIN FR: Position MS AD Account (зеленые круги это уже полученные роли)

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 15

Смотрит в UsersMy IDM Users появился новый AD аккаунт

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 16

Если он сейчас пойдет в Assigments 600667 EMP002001 Employment MS AD Account тот там будут три AD Group — еще не сработал таск POCE Recompute Position roles if User Position has been mod bu main user. А когда сработает останется только форвард роль AD группы запрошенная на трудоустройство.

Запрос доступов начальником на своих сотрудников

Вот тут недописанность и негибкость в самом важном месте в поиске IDM Midpoint нас ударит особенно больно. Пойдем по тому пути который предлагает сам Midpoint — начальником User будет потому-что он зассаинен как manager орг роли(организации) в которой другие user заассаинены как default.

Сразу проблема поиск(Advanced) не может нам выдать всех пользователей организации в который мы manager — извините но поиск по пользователям в Midpoint работает только с пользователями при чем тут организация какая-то. Может нам на это ответит поиск по организациям — а организации в принципе не знают кто в них состоит потому что ну вот так это информация пишется в пользователя! Итого в поиске по пользователю есть — выдать членов организации по OID организации, но не более того, как-то интерактивно подставить в поиск членов организации OID из другого запроса — нельзя. Поэтому вьюха у нас будет очень толстая — дай нам всех пользователей у которых в принципе есть организации, а не есть организация в которой мы manager. (хотя можно было еще поколдовать со способом как в «5 минут», но я не стал.. а вы попробуйте!)

Кого из пользоватей мы так будем видеть ограничивается в авторизации. Тут есть код оператор, недописанный, который выдает пользователей организации в которой мы manager. И вот этот „мы“ никак не задаётся не настраивается, мы и всё. Поэтому чтобы User сотрудник запрашивал доступы на подченных User назначений, по его организации, нам надо User сотруднику выдавать организацию User назначения в которой он manager.

Быстренько накидаем Департаменты

Архетип POCE Department Catalog ArcheType

Подкрасим

    <archetypePolicy>
        <display>
            <label>Department Catalogs</label>
            <icon>
                <cssClass>fa fa-people-roof</cssClass>
                <color>#14aed8</color>
            </icon>
        </display>
    </archetypePolicy>
...
</archetype>

Создал,заассаинил друг на друга в нем орг роли.

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 17

Они собрались в дерево

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 18

Делаем черную роль, называем её POCE Policy: Assign ORG to another user if

вставляем код

<inducement id="9">
    <policyRule>
        <name>Script</name>
        <policyConstraints>
            <or id="14">
                <modification id="15">
                    <name>Name 2</name>
                    <item>c:activation/c:effectiveStatus</item>
                </modification>
                <modification id="152">
                    <name>Name 1</name>
                    <item>c:extension/c:person_you_are_boss</item>
                </modification>
            </or>
        </policyConstraints>
        <policyActions>
            <scriptExecution id="11">
                <name>Some script</name>
                <object>
                    <currentObject>
                        <type>c:UserType</type>
                    </currentObject>
                </object>
                <executeScript xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3">
                    <_metadata id="7">
                        <provenance>
                            <acquisition id="8">
                                <actorRef oid="00000000-0000-0000-0000-000000000002" relation="org:default" type="c:UserType">
                                    <!-- administrator -->
                                </actorRef>
                                <channel>http://midpoint.evolveum.com/xml/ns/public/common/channels-3#user</channel>
                                <timestamp>2025-04-21T08:50:49.237Z</timestamp>
                            </acquisition>
                        </provenance>
                    </_metadata>
                    <s:pipeline list="true">
                        <s:action>
                            <s:type>execute-script</s:type>
                            <s:parameter>
                                <s:name>script</s:name>
                                <s:value>
                                    <code xmlns:a="http://prism.evolveum.com/xml/ns/public/annotation-3">
import com.evolveum.midpoint.xml.ns._public.common.common_3.*
import com.evolveum.midpoint.prism.delta.builder.*
import com.evolveum.midpoint.model.api.*
import com.evolveum.midpoint.schema.constants.SchemaConstants;


user_personalNumber = input.personalNumber
user_isboss = basic.stringify(basic.getExtensionPropertyValue(input, "http://example.com/xml/ns/mySchema", "person_you_are_boss"))
user_organizationalUnit = basic.stringify(input.organizationalUnit)
user_status = basic.stringify(input.activation.effectiveStatus)


if (user_isboss == 'true' &amp;&amp;  user_organizationalUnit &amp;&amp; user_status != "DISABLED")
{


query_target_user = midpoint.queryFor(UserType.class, "personalNumber = '$input.personalNumber' and archetypeRef matches (oid = '00000000-0000-0000-0000-000000000702') and activation/effectiveStatus!='disabled'") 
target_user = midpoint.searchObjects(query_target_user)



if (target_user)
{

query_org_for_ass = midpoint.queryFor(OrgType.class, "identifier endsWith '$user_organizationalUnit' and archetypeRef matches (oid = '7cab0b16-142a-4d37-8b60-9668e95b4b94') and activation/effectiveStatus!='disabled'") 
org_for_ass = midpoint.searchObjects(query_org_for_ass)
log.info "Data:" + org_for_ass


orgUnit = new ObjectReferenceType()
orgUnit.setOid(org_for_ass.oid)
orgUnit.setRelation(SchemaConstants.ORG_MANAGER)
orgUnit.setType(OrgType.COMPLEX_TYPE)

addAssignment = new AssignmentType()
addAssignment.setTargetRef(orgUnit)
addAssignment.setDocumentation(basic.stringify(input.name))
def delta = []
delta = prismContext.deltaFor(UserType.class).item(FocusType.F_ASSIGNMENT).add(addAssignment.asPrismContainerValue()).asObjectDelta(target_user.oid)
midpoint.modifyObject(delta, ModelExecuteOptions.createRaw())
midpoint.recompute(UserType, basic.stringify(target_user.oid))

}
} else {



query_target_user = midpoint.queryFor(UserType.class, "personalNumber = '$input.personalNumber' and archetypeRef matches (oid = '00000000-0000-0000-0000-000000000702')") 
target_user = midpoint.searchObjects(query_target_user)
 

if (user_organizationalUnit &amp;&amp; target_user)
{


assignmentsToDelete = []
query_org_for_ass = midpoint.queryFor(OrgType.class, "identifier endsWith '$user_organizationalUnit' and archetypeRef matches (oid = '7cab0b16-142a-4d37-8b60-9668e95b4b94') and activation/effectiveStatus!='disabled'") 
org_for_ass = midpoint.searchObjects(query_org_for_ass)
user_t = midpoint.getObject(UserType.class, basic.stringify(target_user.oid))

for (a in user_t.assignment)
{

if (a.documentation == basic.stringify(input.name) &amp;&amp; a.targetRef?.oid == basic.stringify(org_for_ass.oid)) 
{

def removeAssignment = new AssignmentType()
removeAssignment.id = a.id
assignmentsToDelete.add removeAssignment.asPrismContainerValue()
delta = prismContext.deltaFor(UserType.class).item(UserType.F_ASSIGNMENT).delete(assignmentsToDelete).asObjectDelta(target_user.oid)
midpoint.modifyObject(delta, ModelExecuteOptions.createRaw())
midpoint.recompute(UserType, basic.stringify(target_user.oid))
}
}


}

}

                                    </code>
                                </s:value>
                            </s:parameter>
                        </s:action>
                    </s:pipeline>
                </executeScript>
            </scriptExecution>
        </policyActions>
    </policyRule>
</inducement>

Делаем в архетипе POCE Position User ArcheType индусмент в роль POCE Policy: Assign ORG to another user if

Теперь при создание User Назначение если person_you_are_boss да, есть organizationalUnit и этот User не заблокирован то User сотрудник с таким же personalNumber будет назначена указанная организация, назначение будет параметрическим в Documentation напишем name User назначения, чтобы когда User назначение будет заблокирован или изменится person_you_are_boss true, отобрать именно это назначение у User сотрудника. Скрипт не рассчитан на замену организации, но рассчитан на исчезновение этой.

Теперь когда у нас в принципе есть выход на подчиненных по назначениям делаем просмотр.

В ConfigurationImport object вставляем код

<objectCollection>
    <name>pose-all-users-org-default-view</name>
    <type>UserType</type>
    <filter>
        <q:text>assignment/targetRef matches (relation = org:default and @ matches (name startsWith 'DC:')) and personalNumber != `actor.personalNumber` and activation/effectiveStatus != "disabled"</q:text>
    </filter>
</objectCollection>

В ConfigurationSystemAdmin GUI configurationObject detail views

Добавляем кодом

<objectCollectionViews>
...
    <objectCollectionView id="100274">
        <identifier>my-idm-subordinates</identifier>
        <display>
            <label>My IDM Subordinates</label>
            <pluralLabel>My IDM Subordinates</pluralLabel>
            <icon>
                <cssClass>fa fa-users-cog</cssClass>
            </icon>
        </display>
        <visibility>hidden</visibility>
        <displayOrder>100</displayOrder>
        <column id="100275">
            <name>Name</name>
            <path>c:name</path>
        </column>
        <column id="100276">
            <name>Full Name</name>
            <path>c:fullName</path>
            <previousColumn>Dep.ID</previousColumn>
        </column>
        <column id="100277">
            <name>Employment Type</name>
            <path xmlns:gen795="http://example.com/xml/ns/mySchema">c:extension/gen795:person_employment_type</path>
            <previousColumn>Name</previousColumn>
        </column>
        <column id="100278">
            <name>Co.</name>
            <path>c:costCenter</path>
            <display>
                <label>Company</label>
            </display>
            <previousColumn>Employment Type</previousColumn>
        </column>
        <column id="100289">
            <name>Dep.ID</name>
            <path>c:organizationalUnit</path>
            <display>
                <label>Department</label>
            </display>
            <previousColumn>Co.</previousColumn>
            <export>
                <expression>
                    <script>
                        <code>import com.evolveum.midpoint.xml.ns._public.common.common_3.*

orgId = basic.stringify(input)
query_org = midpoint.queryFor(OrgType.class, "identifier endsWith '$orgId' and archetypeRef matches (oid = '7cab0b16-142a-4d37-8b60-9668e95b4b94') and activation/effectiveStatus!='disabled'") 
org_respond = midpoint.searchObjects(query_org)
orgIt = midpoint.getObject(OrgType.class, basic.stringify(org_respond.oid))

result =  basic.stringify(input) + ":" + basic.stringify(orgIt.displayName)
return result</code>
                    </script>
                </expression>
            </export>
        </column>
        <type>c:UserType</type>
        <collection>
            <collectionRef oid="6a23173b-fef8-43a0-9230-11edbaf0ac82" relation="org:default" type="c:ObjectCollectionType">
                <!-- pose-all-users-org-default-view -->
            </collectionRef>
        </collection>
    </objectCollectionView>
...
</objectCollectionViews>

Здесь данные в колонках да и сами колонки поднастроили под наш случай

Теперь сама возможность видеть вьюху создаем роль POCE GUI My Subordinates

Добавляю кодом

...
<authorization id="1761">
    <name>poce-read-member-of-my-org-manager</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="1762">
        <orgRelation>
            <subjectRelation>org:manager</subjectRelation>
            <scope>allDescendants</scope>
            <includeReferenceOrg>false</includeReferenceOrg>
        </orgRelation>
    </object>
    <item>assignment</item>
    <item>name</item>
    <item>fullName</item>
    <item>costCenter</item>
    <item>extension/person_employment_type</item>
    <item>roleMembershipRef</item>
    <item>organization</item>
    <item>organizationalUnit</item>
</authorization>
<authorization id="1766">
    <name>read-orgs</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="1767">
        <type>OrgType</type>
    </object>
</authorization>
<adminGuiConfiguration>
    <objectCollectionViews>
        <objectCollectionView id="1760">
            <identifier>my-idm-subordinates</identifier>
            <visibility>automatic</visibility>
            <type>UserType</type>
        </objectCollectionView>
    </objectCollectionViews>
    <accessRequest/>
</adminGuiConfiguration>
...
</role>

1762 авторизация брать всех пользователей которые в орг группе где User сотрудник manager

Эту роль сразу индусим в POCE GUI My IDM Objects, смысла вылавливать в какой момент кому её назначать не увидел, будет пусто или ошибка в My IDM Subordinates если нет подчинённых.

Захожу под самым начальственным пользователем и смотрю что видно

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 19

Теперь запрос на своих подчинённых. В роль POCE GUI My IDM Objects вставляем

...
<group id="17658">
    <identifier>my-subordinates</identifier>
    <display>
        <label>My Subordinates</label>
        <icon>
            <cssClass>fa fa-users-cog</cssClass>
        </icon>
    </display>
    <collection>
        <filter>
            <q:text>assignment/targetRef matches (relation = org:default and @ matches (name startsWith "DC:")) and personalNumber != `actor.personalNumber`  and activation/effectiveStatus != "disabled"</q:text>
        </filter>
    </collection>
    <autocompleteConfiguration>
        <displayExpression>
            <script>
                <code>
                                    return "My Subordinates: " + object.fullName
                </code>
            </script>
        </displayExpression>
        <autocompleteMinChars>1</autocompleteMinChars>
    </autocompleteConfiguration>
</group>
...
</accessRequest>
</adminGuiConfiguration>

А в роль добавляем POCE GUI My Subordinates

<authorization id="1763">
    <name>poce-shadow-subordinates-execution-add-modify-delete</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#add</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#delete</action>
    <phase>execution</phase>
    <object id="3325">
        <type>ShadowType</type>
        <owner>
            <orgRelation>
                <subjectRelation>org:manager</subjectRelation>
                <scope>allDescendants</scope>
                <includeReferenceOrg>false</includeReferenceOrg>
            </orgRelation>
        </owner>
    </object>
</authorization>
<authorization id="1765">
    <name>assign-requestable-roles</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#assign</action>
    <object id="1768">
        <orgRelation>
            <subjectRelation>org:manager</subjectRelation>
            <scope>allDescendants</scope>
            <includeReferenceOrg>false</includeReferenceOrg>
        </orgRelation>
    </object>
    <target id="1">
        <type>RoleType</type>
        <archetypeRef oid="b527aa8f-9097-45d7-94c9-8c2d79e53832" relation="org:default" type="c:ArchetypeType">
            <!-- POCE Forward Role ArcheType -->
        </archetypeRef>
        <filter>
            <q:text>extension/role_root_system != "NICKNAME"</q:text>
        </filter>
    </target>
    <relation>org:default</relation>
</authorization>
<authorization id="1764">
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify</action>
    <phase>execution</phase>
    <object id="1768">
        <orgRelation>
            <subjectRelation>org:manager</subjectRelation>
            <scope>allDescendants</scope>
            <includeReferenceOrg>false</includeReferenceOrg>
        </orgRelation>
    </object>
</authorization>
<authorization id="1767">
    <name>poce-shadow-subordinates-read</name>
    <action>http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read</action>
    <object id="3325">
        <type>ShadowType</type>
        <owner>
            <orgRelation>
                <subjectRelation>org:manager</subjectRelation>
                <scope>allDescendants</scope>
                <includeReferenceOrg>false</includeReferenceOrg>
            </orgRelation>
        </owner>
    </object>
</authorization>
...

</role>

1765 — должен бы работать но (см. Disclaimer) не работает, за него работают тольстые assign из других ролей.

Тут особенно погано получилось, надо запретить выдавать роли аккаунтов на подчиненных, потому что orgRelation выдает только Люди а нам надо personalNumber Люди чтобы авторизовать права и на person Люди и на роль nickName роли, но никак! Так что пока Evalveum не исправила говорим начальникам не запрашивать аккаунты на сотрудников.

Собственно все, но нам еще нужна таска которая будет доделовать то что авторизация не может авторизовать а именно Linked Object.

Делаем дубликат POCE Recompute Position roles if User Position has been mod bu main user называем POCE Recompute Position roles if User Position has been mod by Boss user

Object строка поиска будет

<q:text>
archetypeRef matches (oid = '0d1b1269-0011-49e6-b9f1-e62e7827dfed') and assignment/@metadata/storage/creatorRef/@/personalNumber != personalNumber and  assignment/@metadata/storage/creatorRef/@/personalNumber !not exists and assignment/@metadata/storage/createTimestamp greater ```
dateminus5m = basic.addDuration(basic.currentDateTime(), "-PT5M")
return dateminus5m 
```
</q:text>

Отсекает тех у кого нет personalNumber и у кого он равен своему, то есть изменения сделанные собой или админом

Теперь все видят такой Request Access

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 20

Так как начальник у нас есть только на назначениях, кстати это определяется строкой данных позиции

14;position;POS100885;EMP002003;;;;;Биг Босс;DEP10101;;active;;;manager

должен быть указан департамент DEP10101 в department_poce

и если начальник то manager в info_03

То видим мы только назначения, которые в департаменте в котором мы(user Сотрудник и user Назначение) manager

Реализация концепции Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint part 3 финальная - 21

Дальше запрашивается все как обычно, как для себя!

Вот так просто а главное быстро можно реализовать концепцию Сотрудник-Трудоустройство-Назначение на должность в IDM Midpoint!

Все статьи концепции:

1. Получение данных из кадрового ресурса, построение информационных связей и структуры.

2. Назначение ролей, создание AD учетки, реализация концепций Forward Ролей и nickName как роль.

3. Запрос ролей сотрудником, запрос начальником ролей для сотрудника.

Автор: AlexandrBu

Источник

Оставить комментарий