Hello Yoann,
We don't yet have this functionality in Adaxes, but it is in our TODO list.
Nevertheless, there is a workaround that we may suggest for the time being. You need to create two Custom Commands.
One of these Custom Commands, when executed on a user, will copy GUIDs of all the groups that the user is a member of to the CustomAttributeBinary1 property of the user who invokes the Custom Command. CustomAttributeBinary1 is one of the Adaxes virtual properties that can store binary data.
The other Custom Command will read the value of the CustomAttributeBinary1 property of the user who invokes the Custom Command. If this property is not empty, it will set the user, on which the command is performed, to be a member of the groups represented by the GUIDs.
To create a Custom Command that will copy group membership to CustomAttributeBinary1:
-
Create a new Custom Command
-
On the 2nd step of the Custom Command creation wizard, select User.
-
On the 3rd step of the wizard, add the Run a program or PowerShellScript action and paste the following script:
# Get a list of GUIDs of the groups the selected object is a member of.
$sourceGroupGuids = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid")
# Build a single-dimention array that will contain all GUIDs of the groups
$totalBytes = $sourceGroupGuids.Count * 16
$result = New-Object 'System.Collections.Generic.List[System.Byte]' $totalBytes
foreach ($groupGuidBytes in $sourceGroupGuids)
{
$result.AddRange($groupGuidBytes)
}
# Save the data to the adm-CustomAttributeBinary1 virtual property of the operation initiator.
$Context.Initiator.UserAdsObject.Put("adm-CustomAttributeBinary1", $result.ToArray())
$Context.Initiator.UserAdsObject.SetInfo()
To create a Custom Command that will 'paste' group membership from CustomAttributeBinary1:
-
Create a new Custom Command
-
On the 2nd step of the Custom Command creation wizard, select User.
-
On the 3rd step of the wizard, add the Run a program or PowerShellScript action and paste the following script:
# Get an array of group GUIDs
try
{
$sourceGroupGuids = $Context.Initiator.UserAdsObject.Get("adm-CustomAttributeBinary1")
}
catch
{
$Context.Cancel("Failed to get group GUIDs.")
}
# Calculate the number of GUIDs
$totalBytes = $sourceGroupGuids.Length
# Make sure that the total number of bytes is a divisible of 16
$remainder = 0
[System.Math]::DivRem($totalBytes, 16, [ref] $remainder)
if ($remainder -ne 0)
{
$Context.Cancel("Unexpected data length!")
}
$groupsToAdd = New-Object "System.Collections.Generic.HashSet[System.Guid]"
for ($i = 0; $i -lt ($totalBytes / 16); $i++)
{
$bytes = [System.Guid]::Empty.ToByteArray()
[System.Array]::Copy($sourceGroupGuids, $i * 16, $bytes, 0, 16)
$guid = New-Object "System.Guid" (,$bytes)
$groupsToAdd.Add($guid)
}
# Get GUIDs of the groups the user is a member of
$targetGroupGuids = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid")
# Adjust the list of groups to add the user to, and the list of groups to remove the user from
$groupsToRemove = New-Object "System.Collections.Generic.HashSet[System.Guid]"
foreach($targetGroupGuidBytes in $targetGroupGuids)
{
$guid = New-Object "System.Guid" (,$targetGroupGuidBytes)
if ($groupsToAdd.Contains($guid))
{
$groupsToAdd.Remove($guid) # already a member of the group
}
else
{
$groupsToRemove.Add($guid)
}
}
# Remove from groups that are not in the list of copied groups
foreach($groupGuid in $groupsToRemove)
{
$groupGuid = $groupGuid.ToString("B")
$groupPath = "Adaxes://<GUID=$groupGuid>"
$group = $Context.BindToObjectEx($groupPath, $True)
$group.Remove($Context.TargetObject.AdsPath)
}
# Add to groups
foreach($groupGuid in $groupsToAdd)
{
$groupGuid = $groupGuid.ToString("B")
$groupPath = "Adaxes://<GUID=$groupGuid>"
$group = $Context.BindToObjectEx($groupPath, $True)
$group.Add($Context.TargetObject.AdsPath)
}