Forum Discussion

Upkar's avatar
Upkar
New Contributor II
3 years ago

Restricting Approver to Revert Workflow

Hi All!

 

We had gotten an ad hoc request to give certain access and restrictions to Preparer Users and Approver Users. Where the Preparer can complete workflow and revert workflow and the Approver can only certify in the Workflow profile. We have been able to successfully achieve restriction on completing workflow for the Approver but not able to restrict them from stopping the Revert workflow. Even after placing conditions to stop the revert workflow the certify is also getting restricted for the approver.
below is the code without any restrictions for Revert workflow for now.  if anyone has resolution for this it will be greatly appreciated. 

 

  • JackLacava's avatar
    JackLacava
    Community Manager

    Hey Upkar,

    I can't help but thinking, however, that this should be achieved with a clean separation of duties, i.e. having a WF profile that is just "Certify" and is only accessible to Approvers, but anyway...

    You didn't post where you're triggering your check, but the following technique might work. Instead of working on accessing the Certify step, you let them see the screen but then don't allow them to change state with a DataQualityEventHandler.

     

    Case Is = BREventOperationType.DataQuality.Certify.StartSetCertifyState
         If si.UserName.XFEqualsIgnoreCase("admin") Then       ' replace this with your checks
              Dim info As CertifyProcessInfo = args.inputs(0)  ' cast input object
              ' SignOffState is the state we're moving towards, in this case we're certifying
              If info.SignOffState.Equals(CertSignOffStates.ProfileCertified) Then 
                  Throw New XFUserMsgException(si, "General", "general param1", "Message")
              End If
         end if
    

     

    Otherwise, the general technique in a Workflow Handler relies on looking up the status of tasks or the overall status of the step. You can explore what is available by casting the object and looking at its properties.

    Dim wfinfo As WorkflowInfo = args.inputs(0)
    ' overall status (i.e. "green bar")
    brapi.ErrorLog.LogMessage(si, wfinfo.GetOverallStatus().ToString)
    ' individual step status, you can have multiple ones e.g. Load and Process
    brapi.ErrorLog.LogMessage(si, wfinfo.CurrentStep.Status.ToString)
    • Upkar's avatar
      Upkar
      New Contributor II

      Hi Jack! 

      Thank you for your inputs! 
      My Team and I were able to get a breakthrough (I hope), we created event handlers for Forms and Workflow. for now, it's working out as we want it, need to further test it. Below is the code we have in place, please let us know what you think and if we can improve on it. 

      Form Event handler- 

      Imports System.Collections.Generic
      Imports System.Data
      Imports System.Data.Common
      Imports System.Globalization
      Imports System.IO
      Imports System.Linq
      Imports System.Windows.Forms
      Imports Microsoft.VisualBasic
      Imports OneStream.Finance.Database
      Imports OneStream.Finance.Engine
      Imports OneStream.Shared.Common
      Imports OneStream.Shared.Database
      Imports OneStream.Shared.Engine
      Imports OneStream.Shared.Wcf
      Imports OneStream.Stage.Database
      Imports OneStream.Stage.Engine
      
      Namespace OneStream.BusinessRule.FormsEventHandler.FormsEventHandler
      	Public Class MainClass
      		Public Function Main(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As FormsEventHandlerArgs) As Object
      			Try
      				Dim returnValue As Object = args.DefaultReturnValue
      				args.UseReturnValueFromBusinessRule = False
      				args.Cancel = False				
      
                      Select Case args.OperationName
      					Case Is = BREventOperationType.Forms.CompleteForm
      						Dim cubeName = brapi.Workflow.Metadata.GetProfile(si, si.WorkflowClusterPk).CubeName
      						If (cubeName = "CCR") Then
      							If Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver") Then
      						    ' Do nothing
      							
      							Else
      								If BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver") And Not BRApi.Security.Authorization.IsUserInGroup(si, "Administrators") And Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Preparer")Then
      									If (args.IsBeforeEvent = False) Then	
      										Throw (New XFUserMsgException(si, Nothing, Nothing, "Security Access Error. Only preparer can execute the current workflow step"))
      									End If
      								End If
      							End If
      						End If
      					
      					Case Is = BREventOperationType.Forms.RevertForm
      						Dim cubeName = brapi.Workflow.Metadata.GetProfile(si, si.WorkflowClusterPk).CubeName
      							If (cubeName = "CCR") Then
      								If Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver")  Then
      							    ' Do nothing
      								
      								Else
      									If BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver") And Not BRApi.Security.Authorization.IsUserInGroup(si, "Administrators") And Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Preparer") Then
      										If (args.IsBeforeEvent = False) Then
      											Throw (New XFUserMsgException(si, Nothing, Nothing, "Security Access Error. Only preparer can execute the current workflow step"))
      										End If
      									End If
      								End If
      							End If
      							
      					Case Is = BREventOperationType.Forms.SaveForm
      						Dim cubeName = brapi.Workflow.Metadata.GetProfile(si, si.WorkflowClusterPk).CubeName
      						If (cubeName = "CCR") Then
      							If Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver")  Then
      						    ' Do nothing
      							
      							Else
      								If BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver") And Not BRApi.Security.Authorization.IsUserInGroup(si, "Administrators") And Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Preparer") Then
      									If (args.IsBeforeEvent) Then
      										Throw (New XFUserMsgException(si, Nothing, Nothing, "Security Access Error. Only preparer can execute the current workflow step."))
      									End If
      								End If
      							End If
      						End If
      						
      					Case Is = BREventOperationType.Forms.StartUpdateFormWorkflow
      						Dim cubeName = brapi.Workflow.Metadata.GetProfile(si, si.WorkflowClusterPk).CubeName
      						If (cubeName = "CCR") Then
      							If Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver")  Then
      						    ' Do nothing
      							
      							Else
      								If BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver") And Not BRApi.Security.Authorization.IsUserInGroup(si, "Administrators") And Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Preparer") Then
      									If (args.IsBeforeEvent=False) Then
      										Throw (New XFUserMsgException(si, Nothing, Nothing, "Security Access Error. Only preparer can execute the current workflow step."))
      									End If
      								End If
      							End If
      						End If	
      				End Select
      				Return returnValue
      			Catch ex As Exception
      				Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
      			End Try
      		End Function
      	End Class
      End Namespace



      workflow Event handler - 

      Imports System.Data
      Imports System.Data.Common
      Imports System.IO
      Imports System.Collections.Generic
      Imports System.Globalization
      Imports System.Linq
      Imports Microsoft.VisualBasic
      Imports System.Windows.Forms
      Imports OneStream.Shared.Common
      Imports OneStream.Shared.Wcf
      Imports OneStream.Shared.Engine
      Imports OneStream.Shared.Database
      Imports OneStream.Stage.Engine
      Imports OneStream.Stage.Database
      Imports OneStream.Finance.Engine
      Imports OneStream.Finance.Database
      
      Namespace OneStream.BusinessRule.WorkflowEventHandler.WorkflowEventHandler
      	Public Class MainClass
      		Public Function Main(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As WorkflowEventHandlerArgs) As Object
      			Try
      				Dim returnValue As Object = args.DefaultReturnValue
      				args.UseReturnValueFromBusinessRule = False
      				args.Cancel = False
      				
      				Select Case args.OperationName
      					Case Is = BREventOperationType.Workflow.UpdateWorkflowStatus
      				
      					If (args.IsBeforeEvent) Then
      						
      						Dim cubeName = brapi.Workflow.Metadata.GetProfile(si, si.WorkflowClusterPk).CubeName
      						Dim wfName = BRApi.Workflow.Metadata.GetProfile(si, si.WorkflowClusterPk).Name
      						Dim wftype = BRApi.Workflow.Metadata.GetProfile(si, si.WorkflowClusterPk).Type.ToString
      
      						If (cubeName = "CCR" )Then
      							If Not wftype = "BaseInput" Then
      								If BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Approver") And  Not BRApi.Security.Authorization.IsUserInGroup(si, "Administrators") And Not BRApi.Security.Authorization.IsUserInGroup(si, "WF_CCR_All_Preparer")  Then								
      									'' APPROVER SHOUDLD CERITFY	
      						   			Dim NextIncompleteTaskname As String = BRApi.Workflow.Status.GetWorkflowStatus(si, si.WorkflowClusterPk, True).NextStep.Name.ToString			
      									If Not NextIncompleteTaskname.Equals("Certify Workflow Unit") Then	
      										Throw (New XFUserMsgException(si, Nothing, Nothing, "Security Access Error. Only preparer can execute the current workflow step."))
      									End If	
      								End If
      							End If
      						End If
      					End If
      				End Select
      
      				Return returnValue
      			Catch ex As Exception
      				Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
      			End Try
      		End Function
      	End Class
      End Namespace