{"id":27,"date":"2018-09-05T04:04:15","date_gmt":"2018-09-05T04:04:15","guid":{"rendered":"https:\/\/www.aladan.net\/MIMicry\/?p=27"},"modified":"2018-09-10T12:18:40","modified_gmt":"2018-09-10T12:18:40","slug":"design-pattern-conditional-attribute-updates-using-scoped-sync-rules","status":"publish","type":"post","link":"https:\/\/www.aladan.net\/MIMicry\/2018\/09\/05\/design-pattern-conditional-attribute-updates-using-scoped-sync-rules\/","title":{"rendered":"Design Pattern: Conditional Attribute Updates in Scoped Sync Rules"},"content":{"rendered":"<h3>The Problem<\/h3>\n<p>When it comes to attributes, MIM does two things well: setting them during object creation (initial flow), and setting them all the rest of the time (persistent flow).\u00a0 But setting things conditionally at other times often comes with gotchas.<\/p>\n<p>In particular, FIM&#8217;s insistence on not exporting attributes to equal or higher precedence MAs means we can&#8217;t do a handy loop like this:<\/p>\n<pre>AD.description -&gt; MV.description\r\nIIF(CustomExpression(IsPresent(description)),description,\"Default Descript\") -&gt; AD.description<\/pre>\n<p>Bummer&#8230;<\/p>\n<h3>The Simple Solution<\/h3>\n<p>One simple solution here is to tick the Equal Precedence box on the import precedence page.\u00a0 Then MIM skips the above check, and all is (somewhat) well.\u00a0 But there is another way, which might be useful if you don&#8217;t want to turn on Equal Precedence for some reason&#8230;<\/p>\n<h3>The MIM Service Attribute Loop Solution<\/h3>\n<p>This solution loops the attribute value through the MIM Service.\u00a0 This lets us subvert the MIM precedence check mechanism and conditionally update attributes (to MAs other than the FIM MA\/MIM Service) from scoped sync rules!<\/p>\n<p>In order to subvert the precedence check, we need to somehow break the MIM&#8217;s knowledge of the common source and destination of our data.\u00a0 These flows loop AD&#8217;s current &#8220;description&#8221; attribute value through the MIM Service:<\/p>\n<pre>AD.description -&gt; MV.description\r\nMV.description -&gt; MIMService.Description\r\nMIMService.Description -&gt; MV.existingDescription\r\nIIF(CustomExpression(IsPresent(existingDescription)),existingDescription,\"Default Description\") -&gt; AD.description<\/pre>\n<p>If AD.description is populated, that will flow into the MIM Service (Description) then back out again into a <em>different<\/em> metaverse attribute (existingDescription) that is not associated with AD.description, so it can be used in our export scoped sync rule.\u00a0 By going through the MIM Service in this manner, MIM doesn&#8217;t realise that our source and destination are one and the same, so we now have the flexibility to do whatever we want in our scoped source rule.<\/p>\n<p>Of course, with great power comes great responsibility.\u00a0 If the AD.description export rule does something foolish (like append to the description every time) then the above flows will loop without ceasing (extending AD.description on each cycle through).\u00a0 So you must configure your scoped sync rule so that the changes will eventually cease after a finite (and preferably very small) number of cycles.<\/p>\n<h3>Another Example<\/h3>\n<p>Using this pattern, the similar requirement from a previous post (where we wanted to <a href=\"https:\/\/www.aladan.net\/MIMicry\/2018\/09\/05\/skipped-not-precedent-only-cares-about-your-rules-not-your-data\/\">set gidNumber based on objectSid, but only if it is currently blank<\/a>) is now achievable.\u00a0 These flows give us what we want:<\/p>\n<pre>AD.objectSid -&gt; MV.objectSid\r\nAD.gidNumber -&gt; MV.gidNumber\r\nMV.gidNumber -&gt; MIMService.gidNumber\r\nMIMService.gidNumber -&gt; MV.existingGidNumber\r\nIIF(CustomExpression(IsPresent(existingGidNumber)),existingGidNumber,CustomExpression(Word(ConvertSidToString(objectSid),8,\"-\")+65536)) -&gt; AD.gidNumber<\/pre>\n<h3>But wait, there&#8217;s more&#8230;<\/h3>\n<p>The other thing that needs to be considered here is what happens with source-of-truth (mastering) for an attribute&#8217;s value when using this pattern.\u00a0 A change to the value of an attribute in the MIM Service will result in that value being exported to AD, but similarly a change to the value of the attribute in AD will result in that new value being updated in the MIM Service as well!\u00a0 So, rather interestingly this pattern essentially gives us an Equal Precedence solution, where the last update processed by the sync service &#8220;wins&#8221;.\u00a0 Which, amusingly enough, means that we&#8217;re actually back where we started with the &#8216;Simple Solution&#8217; above! \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Problem When it comes to attributes, MIM does two things well: setting them during object creation (initial flow), and setting them all the rest of the time (persistent flow).\u00a0 But setting things conditionally at other times often comes with gotchas. In particular, FIM&#8217;s insistence on not exporting attributes to equal or higher precedence MAs<span class=\"post-excerpt-end\">&hellip;<\/span><\/p>\n<p class=\"more-link\"><a href=\"https:\/\/www.aladan.net\/MIMicry\/2018\/09\/05\/design-pattern-conditional-attribute-updates-using-scoped-sync-rules\/\" class=\"themebutton\">Read More<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,3,6,8,7],"tags":[],"class_list":["post-27","post","type-post","status-publish","format-standard","hentry","category-design-patterns","category-good","category-howto","category-mimservice","category-sync"],"_links":{"self":[{"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/posts\/27","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":10,"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/posts\/27\/revisions"}],"predecessor-version":[{"id":55,"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/posts\/27\/revisions\/55"}],"wp:attachment":[{"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/media?parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/categories?post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aladan.net\/MIMicry\/wp-json\/wp\/v2\/tags?post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}