Úprava schvalovacího workflow v Oracle Identity Managementu


Tento článek popisuje jakým způsobem je možné upravit standardní schvalovací workflow v systému Sun Identity Manager (Oracle Waveset) tak, aby došlo ke schválení i v případě, kdy jeden ze schvalovatelů tuto akci zamítne. Dále zde bude rozebrána funkčnost, kdy jsou schvalovatelé definováni tím, že mají přiřazenou k tomu určenou roli.

Zde uvedu přesnější zadání problému, jehož řešení článek popisuje:


Tento článek popisuje jakým způsobem je možné upravit standardní schvalovací workflow v systému Sun Identity Manager (Oracle Waveset) tak, aby došlo ke schválení i v případě, kdy jeden ze schvalovatelů tuto akci zamítne. Dále zde bude rozebrána funkčnost, kdy jsou schvalovatelé definováni tím, že mají přiřazenou k tomu určenou roli.

Zde uvedu přesnější zadání problému, jehož řešení článek popisuje:

 

Následující obrázek naznačuje posloupnost volání jednotlivých workflow v Sun Identity Manageru:

Původní funkčnost:

Vyřešení „zamítnutí updatu jako celku“

Ukázka: definování proměnné bcvAttList:
<Activity id='2' name='Process Approvals' audit='true' hidden='true'>
        <Comments>      Iterate over the approvers for a particular object.      Call the standard "Multi Approval" subprocess.          </Comments>
        <Action id='0' process='Multi Approval'>
          <Argument name='approvers' value='$(approvals.approvers)'/>
          <Argument name='delegators' value='$(approvals.delegators)'/>
          <Argument name='approverObjects' value='$(approvals.approverObjects)'/>
          <Argument name='objectType' value='$(approvals.objectType)'/>
          <Argument name='objectName' value='$(approvals.objectName)'/>
          <Argument name='targetId' value='$(approvals.targetId)'/>
          <Argument name='targetName' value='$(approvals.targetName)'/>
          <Argument name='targetObjectClass' value='$(approvals.targetObjectClass)'/>
          <Argument name='authType' value='$(approvals.authType)'/>
          <Argument name='itemType' value='$(approvals.itemType)'/>
          <Argument name='timeout' value='$(approvals.timeout)'/>
          <Argument name='timeoutTask' value='$(approvals.timeoutTask)'/>
          <Argument name='escalators' value='$(approvals.escalators)'/>
          <Argument name='approvalForm' value='$(form)'/>
          <Argument name='approvalTemplate' value='$(template)'/>
          <Argument name='style' value='$(style)'/>
          <Return from='approved' to='approvals.approved'/>
        </Action>

        <Action id="1">
            <expression>
                <block>

                    <defvar name="objectType">
                        <ref>object.objectType</ref>
                    </defvar>

                    <if>
                        <eq>
                            <ref>objectType</ref>
                            <s>Role</s>
                        </eq>
                        <block>
                            <!--
                                Pokud se schvaluje role, nebude vysledny status nastaven.
                                Duvodem je to, aby se po neschvaleni jedne role nestopla cela editace.
                                Cela editace se stopne pri neschvaleni ostatnich veci, napr. organizace.
                                Vysledek schvaleni se prida do seznamu, ktery obsahuje kdo co schvalil ci neschvalil.
                            -->

                            <append name="bcvAttList">
                                <s>roleName</s>
                                <ref>approvals.objectName</ref>

                                <s>status</s>
                                <ref>approvals.approved</ref>

                                <s>actualApprover</s>
                                <ref>actualApprover</ref>
                            </append>

                            <setvar name="approvals.approved">
                                <s></s>
                            </setvar>
                        </block>
                    </if>

                </block>
            </expression>
        </Action>
        <Transition to='end'/>
      </Activity>
Ukázka kódu procesu Update User, aktivita Update User Variable
<Activity id="20" name="Update User Variable">

        <Action id="1">
            <expression>
                <block>

                    <!--
                         Role, ktere byly zamitnuty je treba
                         odebrat z user.waveset.roleInfos.
                    -->

                    <setvar name="user">
                        <rule name='removeNonApprovedRoleInfos'>
                            <argument name='user' value='$(user)'/>
                            <argument name='bcvAttList' value='$(bcvAttList)'/>
                        </rule>
                    </setvar>

                </block>
            </expression>
        </Action>

          <Transition to="Provision"/>
      </Activity>
Pravidlo, které upraví userView – odstraní neschválené role
<Rule id='#ID#Rule:removeNonApprovedRoleInfos' name='removeNonApprovedRoleInfos'>
    <MemberObjectGroups>
        <ObjectRef type='ObjectGroup' id='#ID#Top' name='Top'/>
    </MemberObjectGroups>

    <Comments>
        Odstrani z view z user.waveset.roleInfos role,
        ktere nebyly schvaleny.
    </Comments>

    <RuleArgument name="user"/>
    <RuleArgument name="bcvAttList">
        <Comments>
            Seznam ve formatu
            - List
              - jeden zaznam, @see getRulesFromBcvAttList
        </Comments>
    </RuleArgument>

    <!-- Uprava bcvAttList do lepsi podoby -->
    <defvar name="bcvAttListValues">
        <get>
            <ref>bcvAttList</ref>
            <i>0</i>
        </get>
    </defvar>

    <!-- Role, ktere budou odebrany z roleInfos. -->
    <defvar name="roleForRemove">
        <rule name='getRolesFromBcvAttList'>
            <argument name='status' value='false'/>
            <argument name='bcvAttListValues' value='$(bcvAttListValues)'/>
        </rule>
    </defvar>

    <defvar name="counter">
        <i>0</i>
    </defvar>

    <defvar name="actualRoleForRemove"/>

    <defvar name="bcvWavesetRoleInfos">
        <ref>user.waveset.roleInfos</ref>
    </defvar>

    <!--
        Prochazime seznam roli k odebrani.
        Kazdou roli odebereme z roleInfos.
        Seznam roleInfos obsahuje objekty com.waveset.object.GenericObject.
    -->

    <while>
        <lt>
            <ref>counter</ref>
            <length>
                <ref>roleForRemove</ref>
            </length>
        </lt>
        <block>
            <setvar name="actualRoleForRemove">
                <get>
                    <ref>roleForRemove</ref>
                    <ref>counter</ref>
                </get>
            </setvar>
            <setvar name="counter">
                <add>
                    <ref>counter</ref>
                    <i>1</i>
                </add>
            </setvar>

            <!-- Hledame roli s nazvem 'actualRoleForRemove' v roleInfos -->
            <defvar name="counter2">
                <i>0</i>
            </defvar>
            <defvar name="actualRoleInfos"/>
            <defvar name="actualRoleInfosName"/>

            <while>
                <lt>
                    <ref>counter2</ref>
                    <length>
                        <ref>bcvWavesetRoleInfos</ref>
                    </length>
                </lt>
                <block>
                    <setvar name="actualRoleInfos">
                        <get>
                            <ref>bcvWavesetRoleInfos</ref>
                            <ref>counter2</ref>
                        </get>
                    </setvar>
                    <setvar name="counter2">
                        <add>
                            <ref>counter2</ref>
                            <i>1</i>
                        </add>
                    </setvar>

                    <!-- Jmeno aktualni role z roleInfos -->
                    <setvar name="actualRoleInfosName">
                        <invoke name="getName">
                            <ref>actualRoleInfos</ref>
                        </invoke>
                    </setvar>

                    <if>
                        <eq>
                            <ref>actualRoleForRemove</ref>
                            <ref>actualRoleInfosName</ref>
                        </eq>
                        <remove name="bcvWavesetRoleInfos">
                            <ref>actualRoleInfos</ref>
                        </remove>
                    </if>

                </block>
            </while>

        </block>
    </while>

    <ref>user</ref>

</Rule>


Poté, co odstraníme neschválené role, můžeme udělat checkinView. Tímto jsme vyřešili první část úkolu. Nyní se pusťme do přidání dalšího úkolu.

Přidání dalších schvalovatelů

Pro badatele přidávám ještě pravidlo, které vrátí seznam přímo přidaných rolí z userView :-)

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC 'waveset.dtd' 'waveset.dtd'>
<Rule id='#ID#Rule:getAddedRolesInView' name='getAddedRolesInView'>

    <!--
        Vrati seznam primo pridanych roli uzivateli.

        Pr. role KapOd obsahuje roli Kap. Pridame uzivateli roli
        KapOd  (tzv. primo), nasledkem toho se prida i role Kap.
        Toto pravidlo vsak do vysledku roli Kap nezahrne!
    -->

    <RuleArgument name="user">
        <Comments>User view</Comments>
    </RuleArgument>

    <MemberObjectGroups>
        <ObjectRef type='ObjectGroup' id='#ID#Top' name='Top'/>
    </MemberObjectGroups>

    <defvar name="updateAccounts">
        <ref>user.update.accounts</ref>
    </defvar>

    <!-- Ziskani Lighthouse uctu -->

    <defvar name="counter">
        <i>0</i>
    </defvar>
    <defvar name="bcvUserAccount"/>

    <while>
        <lt>
            <ref>counter</ref>
            <length>
                <ref>updateAccounts</ref>
            </length>
        </lt>
        <block>
            <setvar name="bcvUserAccount">
                <get>
                    <ref>updateAccounts</ref>
                    <ref>counter</ref>
                </get>
            </setvar>
            <setvar name="counter">
                <add>
                    <ref>counter</ref>
                    <i>1</i>
                </add>
            </setvar>

            <if>
                <eq>
                    <invoke name="getName">
                            <ref>bcvUserAccount</ref>
                    </invoke>
                    <s>Lighthouse</s>
                </eq>
                <setvar name="counter">
                    <length>
                        <ref>updateAccounts</ref>
                    </length>
                </setvar>
                <setvar name="bcvUserAccount">
                    <null/>
                </setvar>
            </if>
        </block>
    </while>

    <defvar name="bcvChanges">
        <invoke name="get">
            <ref>bcvUserAccount</ref>
            <s>changes</s>
        </invoke>
    </defvar>

    <defvar name="counter2">
        <i>0</i>
    </defvar>

    <defvar name="bcvRoleInfos"/>

    <!-- Ziskani changes objektu roleInfos, ktery obsahuje seznamy novych a starych roli -->

    <while>
        <lt>
            <ref>counter2</ref>
            <length>
                <ref>bcvChanges</ref>
            </length>
        </lt>
        <block>
            <setvar name="bcvRoleInfos">
                <get>
                    <ref>bcvChanges</ref>
                    <ref>counter2</ref>
                </get>
            </setvar>
            <setvar name="counter2">
                <add>
                    <ref>counter2</ref>
                    <i>1</i>
                </add>
            </setvar>

           <if>
                <eq>
                    <invoke name="getName">
                            <ref>bcvRoleInfos</ref>
                    </invoke>
                    <s>roleInfos</s>
                </eq>
                <setvar name="counter2">
                    <length>
                        <ref>bcvChanges</ref>
                    </length>
                </setvar>
                <setvar name="bcvRoleInfos">
                    <null/>
                </setvar>
            </if>
        </block>
    </while>

    <!-- Nyni je treba ziskat seznamy Stringu s nazvy puvodnich a pridanych roli -->

    <defvar name="bcvAddedAsListOfGenericAttribute">
        <removeAll>
            <appendAll>
                <invoke name="get">
                    <ref>bcvRoleInfos</ref>
                    <s>new</s>
                </invoke>
            </appendAll>
            <appendAll>
                <invoke name="get">
                    <ref>bcvRoleInfos</ref>
                    <s>old</s>
                </invoke>
            </appendAll>
        </removeAll>
    </defvar>

    <!-- Nyni je treba projit bcvAddedAsListOfGenericAttribute a do vysledku pridat nazvy roli -->

    <defvar name="counter3">
        <i>0</i>
    </defvar>

    <defvar name="bcvActualGenericAttribute"/>

    <defvar name="result"/>

    <while>
        <lt>
            <ref>counter3</ref>
            <length>
                <ref>bcvAddedAsListOfGenericAttribute</ref>
            </length>
        </lt>
        <block>
            <setvar name="bcvActualGenericAttribute">
                <get>
                    <ref>bcvAddedAsListOfGenericAttribute</ref>
                    <ref>counter3</ref>
                </get>
            </setvar>
            <setvar name="counter3">
                <add>
                    <ref>counter3</ref>
                    <i>1</i>
                </add>
            </setvar>
            <!-- Z generic atributu se vytvori genericobject, na nem se zavola getName -->

            <defvar name="bcvActualGenericObject">
                <invoke name="get">
                    <ref>bcvActualGenericAttribute</ref>
                  </invoke>
            </defvar>

            <defvar name="bcvAssignedBy">
                <invoke name="get">
                    <ref>bcvActualGenericObject</ref>
                    <s>assignedBy</s>
                </invoke>
            </defvar>

            <if>
                <isnull>
                    <ref>bcvAssignedBy</ref>
                </isnull>
                <append name="result">
                    <invoke name="getName">
                      <ref>bcvActualGenericObject</ref>
                    </invoke>
                </append>
            </if>
        </block>
    </while>

    <ref>result</ref>
</Rule>


Doufám, že tento poměrně zdlouhavý návod na řešení ne úplně snadného problému někomu usnadní práci. Kdybych já osobně měl na začátku práce něco podobného k dispozici, ušetřil bych asi 40% času :-)

Líbí se mi to:

Další témata