This post will explain how you can implement a plug-in that will allow the
  normal users without prvDeleteActivity (Delete
  privilege for the Activity table) to
  - end a recurring appointment series, update recurrence information, or
 
  - convert an existing appointment to a recurring appointment.
 
  In most of the Dynamics 365/Power Apps + Dataverse implementations, it is a
  common practice not to give the Delete privilege to the normal user
  security role to prevent users from accidentally deleting data. Leaving
  the Delete privilege empty for all tables works fine for
  most of the actions, but some out-of-the-box actions require
  the Delete privilege to be successfully performed.
Problem Statement
  If the user wants to
  end a recurring appointment series
  before the original end date specified during the creation of the series, the
  user can click on the "End Series" button on the recurring appointment
  form.  That action will call the DeleteOpenInstancesRequest
  which deletes all the “open” and “scheduled” future instances of the specified
  series from the date specified in the series end date. If the user does not
  have the prvDeleteActivity, the user will get the
  following Insufficient Permissions error.
  
    You do not have {0} permission to access {1} records. Contact your Microsoft Dynamics 365 administrator for help.
   
 
If you decipher the error message by
opening the Network tab in the browser Developer Tools, you will see that the error is due to the current user missing
prvDeleteActivity privilege.
  The same error happens when the user tries to convert an existing appointment to a recurring appointment by clicking on the "Recurrence" button on the appointment form. That action will call the 
AddRecurrenceRequest which creates a recurring appointment series and deletes the existing single   
Appointment. That is why the user will require
  the 
prvDeleteActivity to delete the existing single Appointment.
  
Solution
  
    In order to let the user perform those actions without
    giving prvDeleteActivity in the user's security role, you
    can implement a plug-in to delete the Appointments with an elevated user
    account or temporarily assign a security role
    with prvDeleteActivity while performing the action.
  
  
  
    Solution for Ending a Recurring Appointment Series
  
  
    The solution for this scenario is simple. The plug-in just needs to retrieve
    the appointments with the same SeriesId which are starting on or
    after the SeriesEndDate parameter and delete those appointments with
    SYSTEM user before the system does. If there is no future appointment
    after SeriesEndDate, the system will not try to delete in the
    current user's context and it will not show any error due to the lack
    of prvDeleteActivity privilege.
  
  
  
  
    The plug-in will only run for RecurringAppointmentMaster table and
    the DeleteOpenInstances message. Since the future appointments need
    to be deleted before the actual operation, the plug-in will be registered in
    the Pre-operation (stage 20). Two main important parameters are
    the GUID of the target recurring appointment and the series end date
    parameter entered by the user.
  
  
  
  
    DeleteFutureAppointments method will query the appointments with
    SeriesId same as the recurring appointment GUID and the
    ScheduledStart on or after the SeriesEndDate parameter. Then,
    it will loop through each appointment and delete as the SYSTEM user.
  
  
  
    
      Solution for Updating Recurrence Information of the Recurring Appointment
    
  
  
    The plug-in for this scenario is also similar to the previous one. The
    plug-in needs to be registered for the Update message instead and
    delete all the future instances of the original series before the actual
    operation.
  
  
  Solution for Ending a Recurring Appointment Series
  
    The solution for this scenario is a bit more complex than the previous
    ones. When the user tries to convert an existing appointment to a
    recurring appointment, AddRecurrenceRequest will delete the original
    appointment by GUID, so that even if the plug-in delete the appointment in
    the Pre-operation with SYSTEM user, the system will throw
    the following error because the appointment has already deleted when the
    main operation tried to delete the appointment by GUID.
  
  
    
      The requested record was not found or you do not have sufficient permissions to view it.
     
   
  
    
  
  
    The workaround solution is to share the Delete permission for the
    Appointment with the user. However, sharing the permission does not work if
    the user has no privilege at any level for the particular action. It will
    only work if the user has minimum User level Delete privilege
    for the Activity table. So the second step is to temporarily assign
    the security role
    with User level Delete privilege before
    the main operation and remove it afterwards.
  
  
  
  
  
    The plug-in will run for RecurringAppointmentMaster table
    as well and for the AddRecurrence message. The user will be
    assigned an elevated security role in
    the Pre-validation (stage 10) because making changes to the
    security roles of the user after validation
    in Pre-operation (stage 20) will not make any changes and
    the system will throw the same Insufficient Permissions error.
    In Post-operation (stage 40), the security role assigned in
    the previous step will be removed.
  
  
  
  
  
    In the ElevateDeleteAppointmentPermission method, the delete
    permission for that particular row is granted to the user first.
  
  
  
  
  
    Then, check if the user has the delete privilege to the activity at all and
    if the user does not any enough privilege, temporarily assign the role with
    DeleteActivityRoleName (security role which has User level
    Delete privilege for Activity table) in the same
    Business Unit as the user.
  
  
  
  
  
    After the main operation, the plug-in step
    in Post-operation (stage 40) will check if the user has a
    role with DeleteActivityRoleName (which may be assigned to
    the user in Pre-validation step) and remove the role from
    the user if there any.
  
Summary
  Some of the actions related to the recurring appointment will require the Delete privilege for the Activity table but if there is a business requirement not to grant the Delete privilege to the normal users, it can still be achieved by implementing the plug-in as above.
In my opinion, such OOB request action as deleting the future appointments in ending a recurring appointment series or deleting the original appointment in conversion to recurring appointment should automatically be handled by the elevated SYSTEM account instead of deleting with the initiating user's context. If you agree with me, please vote on my ideas in 
Dynamics 365 Application Ideas or 
Power Apps Ideas (or both).
You can download the above sample code snippet from my GitHub repository via 
this link.
 
 
 
Comments
Post a Comment