0 votes

Hi - v. quick question.

I have an automated action (scheduled task in this instance) that updates a attribute values (custom Adaxes attribute in this instance) that then sends an email containing whatwas intended to be the new value. However, when this email is sent, even though it is *after* the attribute is updated, it contains the old value.

I can get an email sent with the new value by having a seperate business rule that triggers 'on change' of object, which works OK, but I'm just checking this is the expected behaviour i.e. that serial actions sets only see the 'on trigger' state of the object (this makes sense programatically but just want to make sure).

Regards

by (1.6k points)

1 Answer

0 votes
by (215k points)

Hello,

The thing is that when you use value references (like %department%, %username%, or %adm-CustomAttributeText1%) in a Scheduled Task action, they are resolved all at once for the whole Task. That is, before executing a Scheduled Task on a specific object, Adaxes collects all value references that the Task uses and resolves them into their actual values. It is only then that Adaxes starts performing the actions defined by the Task.

What I suggest in your case is that you send the email message with a script using with the Run a program or PowerShell script action. To get a property of an object in your script, you can use the Get method of the IADs interface that is exposed by any directory object. Take a look at the description of the IADs interface for information and examples on how to use this method. For information on how to send emails from PowerShell scripts, see Sending Emails and SMS

0

Thanks v. much.

Final question on the subject of sequencing actions :) - and this one hurts my head to think about, let alone write!

We are trying to use the approval flow to generate an account review process. Simply:-

>User created, CustomDate1 field set to date + 1 year (Review Date)
>On the Review Date, a daily scheduled task triggers (date = Review Date) to update the review date (+ 1 year) but requires manager approval.
At this point the manager of the account gets an approval request - when they accept, the date is updated and the account is 're-approved'
>If they haven't replied within 28 days the account disabled, deleted etc.
>Over these 28 days they get weekly, then daily reminder emails.

The issues we have are:-

1) If they let the request 'age out' and the account is deleted, is there any way to remove the approval request from their list automatically?

2) If they mark the account for deletion (cancel the approval), is there any way to stop the reminder emails and go straight to removal of the account? I have racked my brains over this one (didn't take long!) - going through 'tick-tick' attribute changes, shuffling dates, trying to take advantage of the fact that original trigger date is already 'in memory' and the actual attribute could be altered by another process etc, and I can't logically think of a way to get it to work unless I can trigger an action if the original approval action is cancelled?

Plan B, that I originally toyed with, uses a combination of date strings added to one of the freeform native AD record attributes and LDAP view filters to create a 'Approve Account' Home page item that only shows accounts in this review window, and executes a custom command to update the review date when you select and OK it. It actually works quite well (though I need 2 separate custom commands/home page actions - one to immediately approval the renewal and one to immediately mark for removal, which is a bit clumsy), but it also doesn't take advantage of the standard approval flow/menus etc.

So very interested to know if 1) you understand what I'm on about, and 2) can think of a solution option I can't!

Rgds

0

Hello,

A tricky task, but we think that you can achieve this with Adaxes. You will need to create two Scheduled Tasks and a Business Rule. The workflow will be as follows:

  1. On the 'Review Date' (specified in CustomAttributeDate1), the first Scheduled Task will set the 'Review Date' (specified in CustomAttributeDate1) to current date + 1 year and will send this operation for approval.
  2. Another Scheduled Task will check whether the Review Date of a user has passed, and if it has, it will check, whether there are any Pending Approval Requests that require operations on the user. If there are any pending Requests, the Task will send email notifications to the approver. The notifications sent by the Task will be sent to approvers of all the Approval Requests related to the user (not only the ones cerated by the first Scheduled Task), but if you want, as an option, it is also possible to check whether the initiator of the Request is the first Scheduled Task and send notifications only for Requests initiated by the first Task.
  3. If the Approval Request gets approved, the Review Date will be set to +1 year, so both the Scheduled Tasks will skip the user.
  4. If the Approval Request gets denied or canceled, the second Scheduled Task will skip the user because the state of the approval request will not be Pending.
  5. If a user gets deleted, a Business Rule triggered after user deletion will Deny all Approval Requests, where the user is the target object.

The second Scheduled Task and the Business Rule will require PowerShell scripts to accomplish. If you are OK with the solution, we will provide you with details and the scripts.

0

Yes - I would be interested, sounds like a interesting solution and exactly what we'd want!

We have just finalised the purchase so are busy getting the initial rollout underway. Currently we are not deploying "management" functions (other than self-service) to business users, and will then probably wait until we upgrade to the 2013.1 release before enhancing the functionality, so no rush ;)

And can I say - one day you'll twig that most companies charge the earth for this level of customisation/scripting advice, and that will be a sad day!

0

Hello,

OK, we've already assigned our scripting guy to the task. However, since he's overloaded with tasks for the new release and since you are not in a rush to get this functionality implemented, he'll proceed to the task after the new release is available. Is that OK with you?

And can I say - one day you'll twig that most companies charge the earth for this level of customisation/scripting advice, and that will be a sad day!

We already know that, but that's not our policy. ;)

0

Yes - that's absolutely fine by me, knowing that we can do something around this means we can safely park the final implementation for now.

From my perspective, regular lifecycle reviews of accounts is a key AD requirement in our industry, so I'd suggest that you look at building this function into the product long-term / releasing your solution as a FAQ article - I have lots of contemporaries who buy Adaxes for that alone!

Good luck with the 2013 release!

0

Thanks for the suggestion. We'll discuss that with our team.

Good luck with the 2013 release!

Thank you! ;)

0

Hi,

With 2013.1 in and running, this is now something we're starting to look at again. Any chance your scripting guy can put it in his TODO list now?!

Cheers

0

Hello,

Actually, it is good timing from you as he's already done the job. To implement the solution that we've described in one of the previous posts:

I. Scheduled Task to postpone the review date

First of all, you need to set up a Scheduled Task that sets the 'Review Date' to current date + 1 year. To create such a Task:

  1. Create a new Scheduled Task.
  2. On the 3rd step of the Create Scheduled Task wizard, select the User object type.
  3. On the 4th step, add the Update the User action and click Add.
  4. Expand the Property to modify drop-down list.
  5. Select the Show all properties option.
  6. Select CustomAttributeDate1.
  7. Click the calendar button embedded in the New value field.
  8. Activate the Generate date tab.
  9. In the Set the date to drop-down list, select Current Date/Time.
  10. Select plus 1 year and click OK two times.
  11. Activate the Get approval for this action option and specify the approvers.

II. Scheduled Task to notify managers that approvals are pending

Now, you need to create a Scheduled Task that will notify your managers by email that certain Approval Requests created by the previous Task are still pending. To create such a Task:

  1. Create a new Scheduled Task.

  2. On the 3rd step of the Create Scheduled Task wizard, select the User object type.

  3. On the 4th step, add the Run a program or PowerShell script action and paste the following script in the Script field.

     # Name of the Scheduled Task that sets the Review Date to +1 year
     $scheduledTaskName = "Review Date" # TODO: modify me
     # Email message setings
     $subject = "My Subject" # TODO: modify me
     $htmlReportFirstPart = @"
     <h1><b> Requests awaiting your approval </b></h1><br/>
    
     "@ # TODO: modify me
    
     $htmlReportLastPart = @"
     <p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>
     "@ # TODO: modify me
    
     function GetWebInterfaceAddress()
     {
         $containerPath = $Context.GetWellKnownContainerPath("WebUISetting")
    
         $searcher = New-Object "Softerra.Adaxes.Adsi.Search.DirectorySearcher" $NULL, $False
         $searcher.SearchParameters.PageSize = 500
         $searcher.SearchParameters.SearchScope = "ADS_SCOPE_ONELEVEL"
         $searcher.SearchParameters.BaseObjectPath = $containerPath
         $searcher.SearchParameters.Filter = "(objectClass=adm-WebUISettings)"
         $searcher.SearchParameters.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
    
         $searcherResult = $searcher.ExecuteSearch()
         $result = $searcherResult.FetchAll()
         $searcherResult.Dispose()
    
         if ($result.Count -ne 0)
         {
             $webUIService = $Context.BindToObject(($result[0]).AdsPath)
             return $webUIService.ApplicationBaseUri
         }
    
         return $NULL
     }
    
     # Bind to the Approval Requests container
     $containerPath = $Context.GetWellKnownContainerPath("ApprovalRequests")
     $container = $Context.BindToObject($containerPath)
    
     # Get all pending approval requests
     $requests = $container.GetApprovalRequests("ADM_APPROVALSTATE_PENDING")
    
     foreach ($requestID in $requests)
     {
         # Bind to the approval request
         $guid = New-Object "System.Guid" (,$requestID)
         $guid = $guid.ToString()
         $requestPath = "Adaxes://<GUID=$guid>"
    
         $request = $Context.BindToObject($requestPath)
    
         # Get target object GUID
         $targetObjectGuid = New-Object "System.Guid" (,$request.Get("adm-TargetObjectGuid"))
         $targetObjectGuid = $targetObjectGuid.ToString()
    
         # Skip if the Approval Request does not request an operation on the target object
         if ($targetObjectGuid -ne "%objectGUID%")
         {
             continue
         }
    
         # Skip if the Approval Request was not initiated by the Review Date Scheduled Task
         $requestorName = $request.Requestor.Get("name")
         if ($requestorName -ne $scheduledTaskName)
         {
             continue
         }
    
         $approversInfo = $request.GetApproversInfo()
         $approvers = $approversInfo.GetApproversEx($request.Requestor, $request.TargetObject)
    
         $approverMails = @()
         foreach ($approver in $approvers)
         {
             try
             {
                 $approverMails += $approver.Get("mail")
             }
             catch
             {
                 continue
             }
         }
    
         $htmlReportFirstPart += "Operation: " + $request.DescriptionOfOperationToApprove + "<br/>"  # TODO: modify me
         $htmlReportFirstPart += "Requestor: " + $request.Requestor.Get("name") + "<br/>"  # TODO: modify me
         $htmlReportFirstPart += "Target User: " + $request.TargetObject.Get("name") + "<br/>"  # TODO: modify me
         $htmlReportFirstPart += "Request Time: " + $request.CreationDate + "<br/>"  # TODO: modify me
    
         $webInterfaceAddress = GetWebInterfaceAddress
         if ($webInterfaceAddress -ne $NULL)
         {
             $htmlReportFirstPart += "<br/><a href='$webInterfaceAddress/ViewObject.aspx?guid=$guid'>Click here to approve or deny the request</a><br/>" # TODO: modify me
         }
    
         # Build message body in HTML
         $htmlBody = $htmlReportFirstPart + $htmlReportLastPart
    
         # Send mail
         foreach($mail in $approverMails)
         {
             $Context.SendMail($mail, $subject, $NULL, $htmlBody)
         }
     }
    
  4. The script will send notifications to the approvers of Pending Approval Requests that were initiated by the Scheduled Task created on step I. In the script, $scheduledTaskName specifies the name of the Scheduled Task created on step I, and $subject, $htmlReportFirstPart and $htmlReportLastPart specify the subject, header and footer of the email notifications. Modify the script to your requirements.

  5. When done with the script, add a Custom Description for it and click OK.

  6. Now, you have to add a condition for the Scheduled Task to check Approval Requests for only those users, whose Review Date has already passed. Click the Add Condition button.

  7. Select the If <property> <relation> <value> condition.

  8. Expand the <property> drop-down list.

  9. Select Show all properties.

  10. Select CustomAttributeDate1.

  11. Select less or equal and click the calendar button.

  12. Activate the Generate date tab.

  13. In the Set the date to field, select Current Date/Time.

  14. Finish creation of the Scheduled Task.

III. Create a Business Rule to delete all pending Approval Requests requesting operations on a user after the user is deleted

To create a Business Rule that will purge all pending Approval Request requesting operations on a user after deleting the user:

  1. Create a new Business Rule.

  2. On the 2nd step of the Create Business Rule wizard, select User and After Deleting a User.

  3. On the 3rd step, add the Run a program or PowerShell script action and paste the following script in the Script field.

     # Bind to the Approval Requests container
     $containerPath = $Context.GetWellKnownContainerPath("ApprovalRequests")
     $container = $Context.BindToObject($containerPath)
    
     # Get all pending approval requests
     $requests = $container.GetApprovalRequests("ADM_APPROVALSTATE_PENDING")
    
     foreach ($requestID in $requests)
     {
         # Bind to the approval request
         $guid = New-Object "System.Guid" (,$requestID)
         $guid = $guid.ToString("B")
         $requestPath = "Adaxes://<GUID=$guid>"
    
         $request = $Context.BindToObject($requestPath)
    
         # Get target object GUID
         $targetObjectGuid = New-Object "System.Guid" (,$request.Get("adm-TargetObjectGuid"))
         $targetObjectGuid = $targetObjectGuid.ToString()
    
         # Skip if the Approval Request does not request an operation on the target object
         if($targetObjectGuid -ne "%objectGUID%")
         {
             continue
         }
    
         # Deny the request
         $request.Deny("The user was deleted") # TODO: modify me
     }
    
  4. Finish creation of the Business Rule.

0

Wow - awesome, though you should have pretended that he wipped that up in the last hour..!

Will try that this weekend and report back :)

Rgds

0

Looking good..!

Note: I had to delete some of the '@' in the 'Step II' script to get it to work.

Couple of hopefully quick questions:-

> The request sent to the approver has the 'raw' action description rather than the 'friendly name' (Custom Action Description) - is this expected

> A more general question around scheduling. I want to run the review initiation task every day, so I only want it to fire if Review date == Current date. How can I best do this as, when I choose the 'Equals' condition, it seems to want to meet the exact dateTIME?

I usually set the Review Date with a 00:00 UTC time so that it just appears as dd/mm/yy in the displayed field, is this the correct way?

Many Thanks

0

The request sent to the approver has the 'raw' action description rather than the 'friendly name' (Custom Action Description) - is this expected

Yes. Currently, the description of the operation that is sent for approval contains only the standard description of the operation, and not the Custom Description that you assign.

A more general question around scheduling. I want to run the review initiation task every day, so I only want it to fire if Review date == Current date. How can I best do this as, when I choose the 'Equals' condition, it seems to want to meet the exact dateTIME?

Yes. Since virtual properties like CustomAttributeDate1 are date/time properties, the comparison is made taking into account the time component of the value.

To compare the value of the CustomAttributeDate1 property with the current date only, disregarding the time, you will need to use the If PowerShell Script returns true condition and a PowerShell script that compares the value of the CustomAttributeDate1 property to the current date. To add such a condition to your Scheduled Task.

  1. Open Adaxes Administration Console.

  2. Locate the Scheduled Task that you want to add the condition to.

  3. Select the set of actions and conditions that you want to add the condition to.

  4. Click the Add Condition button.

  5. Select the If PowerShell Script returns true condition and paste the following script in the Script field:

     $today = [System.DateTime]::Now.Date
     $reviewDate = $Context.TargetObject.Get("adm-CustomAttributeDate1").Date
     $Context.ConditionIsMet = ($today -eq $reviewDate)
    
  6. Click Save changes.

I usually set the Review Date with a 00:00 UTC time so that it just appears as dd/mm/yy in the displayed field, is this the correct way?

If you edit the property with Adaxes Web Interface, you can just leave the Time box empty. In this case, only the date will be saved.

0

Thanks for that. Final question..!

I'd like to create one more scheduled job that looks for any denied account approvals. This isn't the prettiest script (I guess using a script to return a TRUE\FALSE condition would be more elegant), but I've written the below.

This is based on your code, but I've managed to break something :?

It is triggered per user account when an account review is expected to be in progress (based on a custom attribute that we set when the review is triggered e.g. CustomText10="Review In Progress"). The assumption is that, if it cannot find a pending review approval for the user object the approval must have been denied, so we can then proceed with the removal process - in this case just an email until I'm sure it works!!

Can you see my (probably obvious) logic error as I have set the conditions necessary (triggering action for job should match 'Test User', approval has been denied so no outstanding approval is in the queue) but the final email is not being sent:-

$scheduledTaskName = "Review Initiation"  

 $htmlReportFirstPart = "<h3><b>Windows Account Review Rejected</b></h3>  
 $htmlReportLastPart = "<p><i>Footer text</i></p>"  

 # Bind to the approval requests container  
 $containerPath = $Context.GetWellKnownContainerPath("ApprovalRequests")  
 $container = $Context.BindToObject($containerPath)  

 # Get all pending approval requests  
 $requests = $container.GetApprovalRequests("ADM\_APPROVALSTATE\_PENDING")  

 foreach ($requestID in $requests)  
 {  
 # Bind to the approval request  
 $guid = New-Object "System.Guid" (,$requestID)  
 $guid = $guid.ToString()  
 $requestPath = "Adaxes://<GUID=$guid>"  
 $request = $Context.BindToObject($requestPath)  

 # Get target object GUID  
 $targetObjectGuid = New-Object "System.Guid" (,$request.Get("adm-TargetObjectGuid"))  
 $targetObjectGuid = $targetObjectGuid.ToString()  
 $requestorName = $request.Requestor.Get("name")  

 # Skip if the approval request does not relate to the current user object  
 if ($targetObjectGuid -ne "%objectGUID%")  
 {  
 continue  
 }  

 # Skip if the approval request is a pending review request for the current user object  
 if ($targetObjectGuid -eq "%objectGUID%" -And $requestorName -eq $scheduledTaskName)   
 {  
 continue  
 }  

 # Based on action triggering conditions for this script and the above script skip conditions, only denied re-approvals should get this far, so alert Operations  
 $htmlReportFirstPart += "Account Review Rejected: " + "%fullname%" + "<br/>"  
 $htmlReportFirstPart += "Account Manager: " + "%adm-ManagerFullName%" + "<br/>"  
 $htmlBody = $htmlReportFirstPart + $htmlReportLastPart  
 $subject = "Account Review Rejected - " + "%fullname%"  

 $Context.SendMail('<operations@acme.com>', $subject, $NULL, $htmlBody)  

 }
0

Apologies, my coding is awful, I have tweaked and the below works. I think this would be quite easy to convert to a return TRUE\FALSE script as well, as the final action is either going to be a hardcoded email, or longer term a deprovisioning action (once we're 100% sure we can't accidently trigger it!).

Rgds   

 # Name of the Scheduled Task that sets the Review Date to +1 year  

 $scheduledTaskName = "Review Initiation"  
 $ApprovalWaiting = 0   

 # Email message setings  

 $htmlReportFirstPart = "<h3><b><font color=#0101DF face='Segoe UI, Arial'>Windows Account Review Rejected</font></b></h3>  
 <p><font face='Segoe UI, Arial'>The manager of the identified user has rejected the annual account review</font></p>  
 <p><font face='Segoe UI, Arial'>Please initiate the standard account decommissioning procedures.</font></p>"   
 $htmlReportLastPart = "<p><i><font face='Segoe UI, Arial' size=2>Please do not reply to this e-mail.</font></i></p>"  

 # Bind to the approval requests container  
 $containerPath = $Context.GetWellKnownContainerPath("ApprovalRequests")  
 $container = $Context.BindToObject($containerPath)  

 # Get all pending approval requests  
 $requests = $container.GetApprovalRequests("ADM\_APPROVALSTATE\_PENDING")  

 foreach ($requestID in $requests)  
 {  
 # Bind to the approval request  
 $guid = New-Object "System.Guid" (,$requestID)  
 $guid = $guid.ToString()  
 $requestPath = "Adaxes://<GUID=$guid>"  
 $request = $Context.BindToObject($requestPath)  

 # Get target object GUID  
 $targetObjectGuid = New-Object "System.Guid" (,$request.Get("adm-TargetObjectGuid"))  
 $targetObjectGuid = $targetObjectGuid.ToString()  
 $requestorName = $request.Requestor.Get("name")  

 # Check for a pending review request for the current user object  
 if ($targetObjectGuid -eq "%objectGUID%" -And $requestorName -eq $scheduledTaskName)   
 {  
 $ApprovalWaiting = 1   
 }  
 }   

 # If no waiting request is found, trigger the action  
 if ($ApprovalWaiting -eq 0)   
 {  
 $htmlReportFirstPart += "Account Review Rejected: " + "%fullname%" + "<br/>"  
 $htmlReportFirstPart += "Account Manager: " + "%adm-ManagerFullName%" + "<br/>"  
 $htmlBody = $htmlReportFirstPart + $htmlReportLastPart  
 $subject = "Account Review Rejected - " + "%fullname%"  
 $Context.SendMail('<operations@acme.com>', $subject, $NULL, $htmlBody)  
 }
0

I really should smoke more - TRUE\FALSE return script, works perfectly as far as I can see..!

Thanks again.

$scheduledTaskName = "Review Initiation"  
$Context.ConditionIsMet = $True  

\# Bind to the approval requests container  
$containerPath = $Context.GetWellKnownContainerPath("ApprovalRequests")  
$container = $Context.BindToObject($containerPath)  

\# Get all pending approval requests  
$requests = $container.GetApprovalRequests("ADM\_APPROVALSTATE\_PENDING")  

foreach ($requestID in $requests)  
{  
 # Bind to the approval request  
 $guid = New-Object "System.Guid" (,$requestID)  
 $guid = $guid.ToString()  
 $requestPath = "Adaxes://<GUID=$guid>"  
 $request = $Context.BindToObject($requestPath)  

 # Get target object GUID  
 $targetObjectGuid = New-Object "System.Guid" (,$request.Get("adm-TargetObjectGuid"))  
 $targetObjectGuid = $targetObjectGuid.ToString()  
 $requestorName = $request.Requestor.Get("name")  

 # Check for a pending review request for the current user object  
 if ($targetObjectGuid -eq "%objectGUID%" -And $requestorName -eq $scheduledTaskName)   
 {  
 $Context.ConditionIsMet = $False  
 }  
}
0

Hello,

The script looks quite good for one tiny issue. The thing is that you check all pending requests in a foreach loop. In your version of the script, the $Context.ConditionIsMet property is set to $False once the script finds the necessary approval request, however setting $Context.ConditionIsMet to $False does not stop execution of the script. That is, the script will continue looping through the rest of the pending Approval Requests. To exit the script, you need to add return after setting $Context.ConditionIsMet to $False. See the modified script below.

$scheduledTaskName = "Review Initiation"
$Context.ConditionIsMet = $True

# Bind to the approval requests container
$containerPath = $Context.GetWellKnownContainerPath("ApprovalRequests")
$container = $Context.BindToObject($containerPath)

# Get all pending approval requests
$requests = $container.GetApprovalRequests("ADM_APPROVALSTATE_PENDING")

foreach ($requestID in $requests)
{
  # Bind to the approval request
  $guid = New-Object "System.Guid" (,$requestID)
  $guid = $guid.ToString()
  $requestPath = "Adaxes://<GUID=$guid>"
  $request = $Context.BindToObject($requestPath)

  # Get target object GUID
  $targetObjectGuid = New-Object "System.Guid" (,$request.Get("adm-TargetObjectGuid"))
  $targetObjectGuid = $targetObjectGuid.ToString()
  $requestorName = $request.Requestor.Get("name")

  # Check for a pending review request for the current user object
  if ($targetObjectGuid -eq "%objectGUID%" -And $requestorName -eq $scheduledTaskName)
  {
    $Context.ConditionIsMet = $False
    return
  }
}
0

Thanks for that - I was starting to think about the number of iterative searches our scripts may start running in the future, so anything to reduce overhead is welcome.

One final question - as we have started to set this up we can create nicely formatted and informational emails for the reminder emails, including descriptive text about account reviews, manager obligations and the impact of failing to review accounts. However, the very first email sent - the generic approval request - is obviously quite generic.

Not a massive issue really, but can you think of anyway to suppress the first email so all the users receive are the fully constructed emails?

As a general statement - the more I use Adaxes the more impressed I am, and I would heartily recommend you publish these scripts on a FAQ page - I'm sure you'll get some interested customers who have implemented some basic review cycle logic who would love the conditional reminders, automatic "clear-up" and other options you can leverage by tweaking these scripts (i.e. I've now got a Custom Command that gives a one-click button for admin's to reset an approval cycle manually).

Best REgards

0

Not a massive issue really, but can you think of anyway to suppress the first email so all the users receive are the fully constructed emails?

No, Approval Request notifications are always sent.

As a general statement - the more I use Adaxes the more impressed I am, and I would heartily recommend you publish these scripts on a FAQ page

Thank you for your good words, we really appreciate it! As for publishing scripts, currently we are working on one more section of our site, Adaxes Script Repository. In the Script Repository we will publish scripts that we think useful for our customers. The scripts are sure to be published there.

0

Many thanks.

That could be a feature request - ability to customise the approval request email content on a per Action basis.

Rgds

0

Final question/issue on this subject - I think this ties back into our very restrictive policy for AD permissions via Adaxes.

When we click on an old review request link that has been denied via the reset scripts the user gets a "You are not allowed to read 'objectClass' or 'ObjectGuid' properties' error. They are also unable to find the denied request in their 'My Approvals' UI.

I guess this is because the data is being stored somewhere where they do not have appropriate permissions to view. If so what permissions and where would we need to grant them to users so that they can see these auto-denied tickets?

Many Thanks

0

That could be a feature request - ability to customise the approval request email content on a per Action basis.

Thanks for the suggestion. We'll think on that.

As to the Approval Requests issue, we'll ask our QA team to investigate it. To help them investigating, can you post here or email to us screenshots of the Security Roles assigned to a user experiencing such an issue? to do this:

  1. View all Security Roles assigned to the user. See Viewing Security Roles assigned to Users or Groups for information on how to do this.
  2. Locate each Security Role in the Console Tree and make a screenshot. For information on how to locate a Role in the Tree, see the 5th step of the above article.

Our email address is support[at]adaxes.com.

0

Hi - email sent.

0

Hello,

The Security Roles look quite good.

Our QA team will be trying to reproduce the issue. We'll update you as soon as they come up with something.

0

Looks like we've managed to find the cause of the issue. Such behavior is reproduced when a user who is trying to view an Approval Request is granted the List Object permission for the account of Adaxes default service administrator (the user that you specified during Adaxes installation), but not granted the Read 'Object Class' Property and Read 'Object GUID' Property permissions for that account. For some reason, this causes the error that you reported.

Our QA team will continue investigating the issue to find out why this happens. As a workaround until a fix is available, we suggest that you additionally grant the users the Read 'Object Class' Property and Read 'Object GUID' Property permissions for the account of Adaxes default service administrator. For this mpurpose, you can create a new Security Role that grants such permissions, assign it to the users experiencing the issue and include the account of Adaxes default administrator in the Assignment Scope. To do this:

  1. Create a new Security Role.
  2. Click Add on the 2nd step of the Create Security Role wizard.
  3. In the dialog box that appears, select the User Object Type.
  4. In the Property-specific permissions section, select Show all properties.
  5. Select the Read 'Object Class' Property and Read 'Object GUID' Property permissions in the Allow column.
  6. Click OK.
  7. On the 3rd step of the wizard, assign the Role to the users who need to view Approval Requests and include the account of Adaxes default service administrator in the Assignment Scope.
0

Hi - this works as instructed.

Many Thanks

0

FYI We've worked out how we can suppress the original - non-customised - approval requests. We're probably not going to do it as it's a bit too much work and the benefit isn't huge, but in case anyone is reading this and saying "I wsh I could"...!

> Create a 'sinkhole' user account etc that is defined as the approver for all such requests, so the emails are sent but never received by end-users.

> Create another adaxes job that runs after the initial job that connects to the approval database, adds the target users' manager as an approver, deletes the original 'sinkhole' approver, then sends them a custom email to 'start' the process.

Like I've said previously about Adaxes - there's always a way if you look hard enough!

0

Hello,

Thanks for the update. Your active participation on this forum is really appreciated! ;)

0

Quick update/feedback.

Using the scripts\commands discussed in this thread we have identified a possible 'chase' condition.

It looks as if, if someone approves a request, there is a short window where the review is not marked as pending anymore, but the subsequent actions have not yet been completed. If the second task that detects 'denied' reviews is running at the same time it is possible that it can incorrectly trigger.

The 'follow on' actions in the original approval task (in our case anyway) overwrite the attribute changes that the 'denied approval detection' task make within seconds, although (again in our case) an email is sent to the manager saying the user has been marked for removal.

We thought this *may* be possible but was unlikely - but as luck would have it, it happened on one of our dry runs! In order to fix it we've tweaked the 'detection' task so that it actually has to fail twice, as below:-


This means the first time the check fails the user is marked (we use a timestamp as we've still got 5 free and don't want to 'waste' a Boolean\Text attribute!), and only if it triggers a second time does the actual 'meat' of the task trigger. The original approval task now also has a final action to clear the timestamp attribute also, so any 'half failed' accounts are cleared.

One general question that does come out of this (as we have halved the time repeat schedule so that a deletion is still detected within the same time window etc), do you have any advice on how regularily tasks such as this should run? This task is parsing through every user account, and every request etc, so would you recommend that we don't run these type of jobs *too* regularily?

It's not a problem, but good background so that we make sure we don't start stressing the processing engine by assuming we can just throw tasks at it etc.

Rgds

0

Hello,

Thanks for the update.

As for running Scheduled Task frequency, our general recommendation is to run Scheduled Tasks at night, when the load on Adaxes service and your network is minimal. This is even more applicable to your Tasks since almost each of them runs a PowerShell script, which involves creating the PowerShell runtime each time.

Related questions

0 votes
1 answer

Ok I have a few business rules in place. When a HD user creates a users I need it to get approved which I have not issues with. Once that is approved I would like the ... but I'm just getting started with adax and need to figure a few things out. thanks CJ

asked Apr 4, 2014 by chrisj (20 points)
0 votes
1 answer

We're utilizing the custom adaxes attributes for a few parts in our employee onboarding procedure. Among them is a step where we specify what buildings a user will need ... get all the values of "adm-CustomAttributeTextMultiValue1" to be sent out in an email?

asked Aug 9, 2021 by KruzGaffaney (50 points)
0 votes
1 answer

Dear Support, Is it possible in "generate default value" section of pattern for multivalued attribute to provide more than 1 value from "must be one of" section? E.g. Pattern ... E" and to have default generated values in web interface "A,C" Thanks for advise!

asked Jul 7, 2020 by Dmytro.Rudyi (850 points)
0 votes
0 answers

Hello, I'm working on an enable user option that does the following 1) Enables the user 2) Admin can manually adjust the Description of the user. 3) Moves the user to a ... them all and just want to make sure I select the correct attribute if it is one.

asked Jan 19, 2016 by jtop (680 points)
0 votes
1 answer

We recently added an a couple of attributes to our Active Directory Schema. Those attributes are available in the Property Display Names section, but not under a user to edit or ... . I've selected the show all properties in the dialogs. What am I missing?

asked Sep 30, 2020 by polley (1.2k points)
2,634 questions
2,369 answers
6,291 comments
971,360 users