[B10025] UNSAccountB: Write permission denied for value “UID_UNSContainerB”

We have a customer with a number of custom target systems.  These are kept in sync each with its own Synchronization Project.  A few days ago, one of the CSV projects learned a new trick.  For every new record it detects in the CSV, it produces the following error in the synchronization log… 

[B10025] UNSAccountB: Write permission denied for value “UID_UNSContainerB”

If we delete a number of records from UNSAccountB, all these records are added to the list of errors on the next sync.

It’s possible that someone has edited UNSAccountB template code recently, but aside from this, absolutely nothing has changed on the system.

Anyone have any idea of what can be causing this? 

 

We found the exact same error for version 7.0.1 with a message that it was a bug that was fixed by a hotfix.  Our customer is on 8.0.2017.1104, is it possible that an old bug has returned?

---

The UID_UNSContainerB is set by the Sync-Project Mapping via a “Key resolution by reference” which is passed the Canonical-name of the container…

 

Here is the template code for UID_UNSContainerB…   data-sync is not checked in the workflow so this code should get skipped entirely.  As far as we are aware this is the only code that has been modified recently.

'$FK(UID_Person).UID_Department$

'$FK(UID_Person).UID_Locality$

'$FK(UID_Person).UID_ProfitCenter$

'#If ORG Then

'$FK(UID_Person).UID_Org$

'#End If

'If CBool(Connection.Variables.Get("FULLSYNC")) = False Then

If Not CBool(Variables("FULLSYNC")) Then

      Select Case ($FK(UID_TSBBehavior).ITDataUsage:Int$)

            Case 0:'do not get data from employee

            Case -1:'fill property initially from the ITData of the employee

                  If Not $[IsLoaded]:Bool$ Then

                        Value = TSB_ITDataFromOrg($UID_Person$, $UID_TSBAccountDef$, Base.TableDef.Columns("UID_UNSContainerB"))

                        If $FK(UID_UNSRootB).Ident_UNSRoot$ = "TOPdesk" Then

                              If $AccountDisabled:Bool$ Then

                                   Dim UID As String = CCC_getDataFromAnyTable("UNSContainerB", "CanonicalName", "TOPdesk/Operators/Archived", "UID_UNSContainerB")

                                   If Not String.IsNullOrEmpty(UID) Then

                                         Value = UID

                                   End If

                              End If

                        End If

                  End If

            Case 1:'update property depending on ITData of the employee

                  Value = TSB_ITDataFromOrg($UID_Person$, $UID_TSBAccountDef$, Base.TableDef.Columns("UID_UNSContainerB"))

                  If $FK(UID_UNSRootB).Ident_UNSRoot$ = "TOPdesk" Then

                        If $AccountDisabled:Bool$ Then

                              Dim UID As String = CCC_getDataFromAnyTable("UNSContainerB", "CanonicalName", "TOPdesk/Operators/Archived", "UID_UNSContainerB")

                              If Not String.IsNullOrEmpty(UID) Then

                                   Value = UID

                              End If

                        End If

                  End If

      End Select

End If

 

 

And here is the template code for “cn” which is triggered by a change to UID_UNSContainerB…   $Ident_UNSRoot$ = "TOPdesk" for the system with the problem.

If $UID_UNSRootB$ <> "" Then

 

      Dim cnFix, cnNew, DNold, DNnew, wherePart As String

      Dim f As ISqlFormatter = Connection.SqlFormatter

      'Dim p as IDnParser = VI_GetDnParser("LDAP")

 

      Dim attributeName as String = "CN"

 

      ' If targetsystem is configured without containers

      If Not $FK(UID_UNSRootB).UsesContainer:Bool$ Then

            attributeName = "user"

      End If

     

      cnFix = $cn$

     

      If $FK(UID_UNSRootB).Ident_UNSRoot$ = "TOPdesk" Then

            If Entity.Columns.Item("Lastname").IsChanged _

                        OrElse Entity.Columns.Item("Firstname").IsChanged _

                        OrElse Entity.Columns.Item("AccountName").IsChanged _

                        OrElse (Not cnFix.EndsWith(")") And Not String.IsNullOrWhiteSpace($AccountName$)) Then

                 

                  Dim cn = {$Firstname$, $Lastname$}

                  cnFix = String.Join(" ", cn.Where(Function(o) Not String.IsNullOrWhiteSpace(o)))

                 

                  If Not String.IsNullOrWhiteSpace($AccountName$) Then

                        cnFix = String.Format("{0} ({1})", cnFix, $AccountName$)

                  End If

            Else

                  cnFix = $cn$

            End If

      Else

            If Entity.Columns.Item("Lastname").IsChanged _

                        OrElse Entity.Columns.Item("Firstname").IsChanged Then

                 

                  Dim cn = {$Firstname$, $Lastname$}

                  cnFix = String.Join(" ", cn.Where(Function(o) Not String.IsNullOrWhiteSpace(o)))

 

            Else

                  cnFix = $cn$

            End If

      End If

 

      Dim cnLen as Integer = Entity.Columns.Item("cn").MaxLen

 

      cnFix = VID_Left(cnFix, cnLen)

 

      If $cn[o]$<>cnFix OrElse Entity.Columns.Item("UID_UNSContainerB").IsChanged Then

            Dim i As Integer = 1

            cnNew = cnFix

           

            'to avoid triggering template on change DistinguishedName of parent object no objectwalker used

            If $UID_UNSContainerB[o]$ <> "" Then

                  DNold = VI_GetValueOfObject ("UNSContainerB", "UID_UNSContainerB", $UID_UNSContainerB[o]$, "DistinguishedName")

            Else

                  DNold = VI_GetValueOfObject ("UNSRootB", "UID_UNSRootB", $UID_UNSRootB[o]$, "DistinguishedName")

            End If

            If $UID_UNSContainerB$ <> "" Then

                  DNnew = VI_GetValueOfObject ("UNSContainerB", "UID_UNSContainerB", $UID_UNSContainerB$, "DistinguishedName")

            Else

                  DNnew = VI_GetValueOfObject ("UNSRootB", "UID_UNSRootB", $UID_UNSRootB$, "DistinguishedName")

            End If

 

            wherePart = f.AndRelation( _

                                   f.UidComparison("UID_UNSAccountB", $UID_UNSAccountB$, CompareOperator.NotEqual), _

                                   f.UidComparison("UID_UNSRootB", $UID_UNSRootB$))

 

            Do While Connection.Exists(   "UNSAccountB", _

                                         f.OrRelation( _

                                               f.AndRelation( _

                                                     f.Comparison("DistinguishedName", TSB_CreateDN(attributeName, cnNew, DNnew), ValType.String), _

                                                     wherePart _

                                               ), _

                                               f.AndRelation( _

                                                     f.Comparison("DistinguishedName",TSB_CreateDN(attributeName, cnNew, DNOld), ValType.String), _

                                                     wherePart _

                                               ) _

                                         ))

 

                  cnNew = VID_Left(cnFix, cnLen - (1 + CStr(i).Length)) & "_" & i

                  i=i+1

            Loop

           

            Value = cnNew

           

      End If

End If

 

 

This is the custom function called by the template code..

 

Public Function CCC_getDataFromAnyTable(ByVal TableName As String, ByVal CompareAttribute As String, ByVal CompareValue As String, ByVal ReturnAttributeName As String) As String

      Dim f As ISqlFormatter = connection.SqlFormatter

      Dim ccc_objects As IColDbObject = Connection.CreateCol(TableName) 'Maak een collectie van objecten uit deze tabel

            ccc_objects.prototype.whereclause = f.Comparison(CompareAttribute,CompareValue,Valtype.string,CompareOperator.Equal)

            'Select ... from <table> where <Compareattribute> = '<comparevalue'>

            ccc_objects.prototype.Columns(Returnattributename).isDisplayItem = True

            'Select ... is translated to a return column here

            ccc_objects.Load() 'Load all objects

           

                  If ccc_objects.Count > 0 Then

                        Dim ccc_object As IColElem = ccc_objects(0)

                        Return ccc_object.GetValue(ReturnAttributeName).String

                  End If

                 

      Return ""

End Function

Parents
  • That discussion is already quite old.
    However, it has never been resolved.

    At the moment there is a Service Request for exactly the same problem.
    And we discovered the root cause.

    It's bug #34750.

    Explanation:

    The UID_UNSContainerB is changeable only if the UNSRootB has the option "UsesContainer".
    BUT: If the UNSAccountB doesn't have an UNSRootB assigned, the UID_UNSContainerB is also not changeable.
    For an existing object the UNSRootB cannot be empty, because it's mandatory.
    However, in the case of a newly created object, it depends on the order in which the individual properties are written to the object.
    If the UID_UNSContainerB is set BEFORE the UID_UNSRootB, you get the error.
    It works only, if the UID_UNSContainerB is set AFTER the UID_UNSRootB.

    The right order is calculated automatically based on different sources.
    One source are the implemented rules in the Customizer.
    Another source are dependencies implemented in TEMPLATES.
    And that explains why the change of the template code obviously has an influence.
    The template itself will not be executed, but the code is used by the algorithm to calculate the sort order.
    By adding another reference in the template (in the above case it's "$FK(UID_UNSRootB).Ident_UNSRoot$") the "sort order algorithm" calculates another (wrong) sort order.

Reply
  • That discussion is already quite old.
    However, it has never been resolved.

    At the moment there is a Service Request for exactly the same problem.
    And we discovered the root cause.

    It's bug #34750.

    Explanation:

    The UID_UNSContainerB is changeable only if the UNSRootB has the option "UsesContainer".
    BUT: If the UNSAccountB doesn't have an UNSRootB assigned, the UID_UNSContainerB is also not changeable.
    For an existing object the UNSRootB cannot be empty, because it's mandatory.
    However, in the case of a newly created object, it depends on the order in which the individual properties are written to the object.
    If the UID_UNSContainerB is set BEFORE the UID_UNSRootB, you get the error.
    It works only, if the UID_UNSContainerB is set AFTER the UID_UNSRootB.

    The right order is calculated automatically based on different sources.
    One source are the implemented rules in the Customizer.
    Another source are dependencies implemented in TEMPLATES.
    And that explains why the change of the template code obviously has an influence.
    The template itself will not be executed, but the code is used by the algorithm to calculate the sort order.
    By adding another reference in the template (in the above case it's "$FK(UID_UNSRootB).Ident_UNSRoot$") the "sort order algorithm" calculates another (wrong) sort order.

Children
No Data