How To

Deactivate and Cleanup a Community User

DeactivateImage.jpgFor those orgs that have either customer or partner community users, you know that your users need the Manage External Users permission and then your system administrator needs to add the nested buttons to the contact or person account record page.

Under the Manage External Users button are additional nested buttons:

  • Enable Partner User
  • Enable Customer User
  • View Customer User
  • View Partner User
  • Disable Customer User
  • Disable Partner User
  • Enable Super User Access
  • Disable Partner Super Access

One security issue is that it assumes that everyone who has the ability to view as a community user also has the ability to disable the community user. This may not necessarily be the case for all businesses.

Here are a few security considerations I stumbled upon as I built this automation:

  • I only wanted selected individuals the ability to deactivate a portal user. Any unauthorized user clicking on the “Deactivate User Account” will get an error message. This will be done by assigning a custom permission “Ability to Deactivate a Portal User” to authorized users. My flow will check for the permission before letting them move forward with the automation. To assign the custom permission to specific users, I had to add it to a permission set. Additionally, to give the user the ability to assign permission sets to themselves, they need the Assign Permission Sets system permission.
  • To update information on a user record (username, community nickname, email, federation identifier, deactivate the user [IsActive] and deselect IsPortalEnabled), the user needs Manage Users system permission. Unfortunately, this single system permission enables a LOT of other permissions. Practicing least privilege access, you want to assign this permission sparingly and not assign it permanently. As a compromise, I am temporarily assigning a permission set during the automation that allows them to deactivate the portal user and update fields on the user record.
  • When you update the IsPortalEnabled on the portal user record to unchecked, Salesforce runs a process behind the scenes to disassociate a contact from the user record for a customer community user or contact and account from the user record for a partner community user.
  • A user can only assign permission sets to themselves. They cannot, however, remove permission sets assigned to themselves. As mentioned before, we need to remove the Manage Users permission from the user as it should only be temporarily assigned.  At the end of my portal user deactivation process, I set a remove permission set processing flag for the running user. While I could write a batch that runs several times a day to remove the permission set and reset the processing flag, I decided to go all declarative with a scheduled flow that runs daily to remove the permission set from the user and reset that processing flag. 

Business Use Case:  Addison Dogster is the system administrator at Universal Containers. Mary Markle is the Director of Operations. She only wants certain people on her team to have the ability to deactivate a community user and not everyone who can view as a community user. She also wanted a number of fields on the community user record to be updated when a community user is deactivated. Currently, she has people manually cleaning up records after the fact.

Solution: Addison is an #AwesomeAdmin and she was able to meet the business requirements declaratively using a custom field, a custom permission, two permission sets, two flows, (Classic users) a custom button, (Lightning Experience users) a quick action and updated contact page layout.

For the flows, there is a flow for assigning the permission set, deactivating the portal user and setting the processing flag and a scheduled flow to remove the permission set and resetting the processing flag.

DeactivateaPortalUserFlow.JPG

View image full screen

This flow does the following: (1) Check to see if the user has permission to deactivate the portal user, (2) if not, a screen is shown informing them that they do not have access, (3) if the user has access, it will look up the permission set id based on the perm set developer name, (4) look up to see if the user is already assigned to the Deactivate Portal User – Used in Flow permission set, (5) determine whether the user has the permission set, (6) assign the permission set if not already assigned, (7) show a toast message that the perm set was assigned, (8) get the portal user record information associated to the contact, (9) determine whether the portal user was found. (10) if not found, show a message that the user can’t be found or is already deactivated, (11) update the portal user record – deactivate, clean up fields, (12) set the processing flag on the running user’s user record, (13) show a toast message that the portal user is deactivated and lastly, (14) takes the user back to the contact record page.

RemoveDeactivatedPortalUserUsedinFlowPermSetFlow.JPG

This scheduled flow does the following: (1) Is set to run on Sundays at 1:20pm ET, (2) gets the permission set Id using the perm set developer name, (3) removes the permission set assignment of the Deactivate Portal User – Used in Flow permission set from the user and lastly, (4) updates the user’s record to reset the perm set processing field.

Prerequisites:

Note: In the event that only one installation link is provided, if you want to install it in a sandbox, right click the link and select copy link address.

Example: https://login.salesforce.com/packaging/installPackage.apexp?p0=04t1K0000033LMX

Take the “/packaging/installPackage.apexp?p0=04t1K0000033LMX” part of the URL and paste it at the end of your sandbox address.

Sandbox address example: https://jenwlee–dev.my.salesforce.com

Combined URL is: https://jenwlee–dev.my.salesforce.com/packaging/installPackage.apexp?p0=04t1K0000033LMX

This URL will take you to the package installation for your sandbox.

Steps: 

1.Create a custom checkbox field called “Remove Perm Set Assignment Processing” that if set to true will be picked up in a scheduled flow to remove the Deactivate Portal User – Used in Flow permission set from the user. Go to Setup | Object Manager | User | Field & Relationships, create new. Set the FLS for system administrator accordingly to view only.

Best practice tip: Provide a description so you and other/future admins know what this custom field is used for.

RemovePermSetAssignmentProcessing.JPGView image full screen

2. Create a custom permission called “Ability to Deactivate a Portal User” by going to Setup | Custom Permissions and click New. We will use the custom permission in our flow to see if the running user has this custom permission to be able to deactivate a portal user.

Best practice tip: Provide a description so you and other/future admins know what this custom permission is used for.

AbilitytoDeactivateaPortalUserCustomPermission.JPGView image full screen

3. Create a permission set called “Ability to Deactivate a Portal User.” Go to Setup | Permission Sets, click on the New button.

This permission set will include the Ability to Deactivate a Portal User custom permission, the ability to View All Users and to Assign Permission sets.

Best practice tip: Provide a description so you and other/future admins know what this permission set is used for.

AbilitytoDeactivateaPortalUserPermissionSet.JPGView image full screen

Go to Custom Permissions, click Edit, select the “Ability to Deactivate a Portal User” and click on the Add button and Save.

AbilitytoDeactivateaPortalUserPermissionSet-CustomPermission.JPGView image full screen

Navigate to System Permissions, click Edit, then check the Enabled checkbox for Assign Permission Sets and View All Users and Save.

AbilitytoDeactivateaPortalUserPermissionSet-SystemPermissions.JPGView image full screen

4. Create another permission set called “Deactivate Portal User – Used in Flow.” Go to Setup | Permission Sets, click on the New button.

This permission set includes the Manage Users permission, will be temporarily assigned to the running user so they can modify the portal user record to cleanup the fields of a deactivated portal user and to modify the user record to set a field for removing this permission set.

Best practice tip: Provide a description so you and other/future admins know what this permission set is used for.

DeactivatePortalUser-UsedinFlowPermissionSet.JPGView image full screen

Go to System Permissions and check the Enabled checkbox next to Manage Users and Save. By doing this, it will also enable other system permissions as well.

DeactivatePortalUser-UsedinFlowPermissionSet-SystemPermission.JPGView image full screen

Go to Object Permissions, click on Users, Edit and check the fields that the running user needs to be able to modify for cleanup purposes as part of your own company process. If the user does not have FLS access, the flow will fault.

5. Let’s create the flow. For those using Salesforce Classic, flow can be found in Create | Workflows & Approvals | Flows. In Lightning Experience, it is found under Process Automation | Flows.

DeactivateaPortalUserFlow.JPGView image full screen

A. Let’s create our flow resources.

Best practice tip: Provide a description so you and other/future admins know what this flow resource is used for.

Let’s create a text variable called “recordId” that will store the contact associated to the community portal user.

recordId.JPGView image full screen

We need to create a formula resource to get the current user’s Id.

In the formula “Insert a resource” field, you can look up current user information with $User. The end result is {!User.Id}.

CurrentUserFormula.JPGView image full screen

We need to create a formula resource to see if the user has the custom permission “Ability to Deactivate a Portal User.”

The data type is boolean (i.e. checkbox).

In the formula “Insert a resource” field, you can look up custom permissions in your org with $Permission. Look for the API name of the custom permission “Ability_to_Deactivate_a_Portal_User” so that the end result formula is {!$Permission.Ability_to_Deactivate_a_Portal_User}.

UserHasPermtoDeactivateFormula.JPGView image full screen

Create a text variable resource called “varPermissionSetAssignmentId.” This will store the permission set id that we look up in our flow so we are not hardcoding ids.

varPermissionSetAssignmentId.JPGView image full screen

Create a text variable called “varUserHasPermSet” which if it holds a value means that the user is assigned the Deactivated Portal User – Used in Flow permission set.

varUserHasPermSet.JPGView image full screen

Create a formula called “PermissionSetIDFormula” which takes the Id from the Get the Permission Set Get Records element and removes the last 3 characters to make a 15 character Id.

Formula: LEFT( {!Get_the_Permission_Set_Id.Id} , LEN({!Get_the_Permission_Set_Id.Id})- 3)

PermissionSetIDFormula.JPGView image full screen

Create a record variable called “PermissionSetAssignmentRecord” which will store all field information from the Get Records element.

PermissionSetAssignmentRecord.JPGView image full screen

Create a record variable called “varUser” which holds information about the portal user.

VarUser.JPGView image full screen

Create a formula resource to set the new community nickname value. Here, we want to add the word “deactivated” in front of the community nickname value and strip characters from the left of the community nickname so the end result value does not exceed 40 characters. Otherwise, your flow will fault.

Formula: “deactivated” + LEFT({!varUser.CommunityNickname},28)

CommunityNicknameFormula.JPGView image full screen

Create a formula resource to set the new username value. Here, we want to add the word “deactivated” in front of the username value.

Formula: “deactivated” + {!varUser.Username}

DeactivatedUsernameFormula.JPGView image full screen

Create a formula resource to set the new email value. Here, we want to add the word “deactivated” in front of the email address value.

Formula: “deactivated” + {!varUser.Email}

DeactivateEmailFormula.JPGView image full screen

B. Our first element is a Decision flow element to determine whether the running user has permission to deactivate a portal user (i.e. has the custom permission “Ability to Deactivate a Portal User”).

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

“Has Permission” Outcome: {!UserHasPermToDeactivateFormula} Equals {!GlobalConstant.True}

Default Outcome: No Permission (Note: It is best practice to name your default outcome and not leave it as “Default Outcome.”)

DeactivateaPortalUserFlow-Decision.JPGView image full screen

C. If the user does not have permission, we want to display a Screen flow element to to inform them that they do not have the necessary permission.

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Configure the screen properties as follows:

Control Navigation: deselect Previous and Pause

DeactivatePortalUserFlow-Screen1Properties.JPGView image full screen

Drag the Display Text component to the screen canvas and configure it as follows.

DeactivatePortalUserFlow-Screen1-DisplayText.JPGView image full screen

D. We now need a Get Records flow element to get the permission set id with the permission set developer name. Configure it as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Object: Permission Set

Name Equals Deactivate_Portal_User_Used_in_Flow

How Many Records to Store: Only the first record

How to Store Record Data: Automatically store all fields

DeactivateaPortalUserFlow-GetRecords.JPGView image full screen

E. We need another Get Records flow element to lookup the Permission Set Assignment object to see if the user is already assigned to the Deactivate Portal User – Used in Flow permission set.

When I tested this via debug, I noticed that my flow was faulting. I found in the Get Records results Step 4D that the permission set Id stores is the 18 character Id. If I left the 18 character Id, the Get Records will always result in no records found as it finds the assignments with a 15 character permission set id. To address this, I need to use a flow formula that removes the last 3 characters to keep it to 15 characters.

Configure it as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Object: Permission Set Assignment

Conditions are Met:

AssigneeId Equals {!CurrentUserFormula}

Id Equals {!PermissionSetIdFormula}

How Many Records to Store:  Only the first record

How to Store Record Data: Choose fields and assign variables (advanced)

Where to Store Field Values: Together in record variable

Record: {!PermissionSetAssignmentRecord}

When no records are returned, set specified variables to null: Checked

DeactivateaPortalUserFlow-GetRecords1.JPGView image full screen

F. We need another Decision flow element to determine whether the user already has the Deactivate Portal User – Used in Flow permission set from the previous step. Configure it as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

“Yes” Outcome: {!Look_up_Permission_Set_Assignment_for_this_user} Is Null {!GlobalConstant.False}

Default Outcome: No (Best practice is not to leave this as Default Outcome)

DeactivateaPortalUserFlow-Decision1.JPGView Image Full Screen

G. We need to Create Records flow element to assign the permission set to the user. Configure it as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

How Many Records to Create: One

How to Set the Record Fields: Use separate resources, and literal values

Object: Permission Set Assignment

Set Field Values: AssigneeId {!CurrentUserFormula AND PermissionSetId {!PermissionSetIdFormula}

Manually assign variables (advanced): Checked

Variable: {!varPermissionSetAssignmentId}

DeactivateaPortalUserFlow-CreateRecords.JPGView image full screen

H. Drag the Action flow element to use the showToast local action. Configure it as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Message: You’ve been assigned the Deactivate Portal User permission set.

DeactivateaPortalUserFlow-ShowToast.JPGView image full screen

I. We need a Get Records flow element to see if we can locate a portal user associated to the contact. Configure as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Object: User

ContactId Equals {!recordId}

How Many Records to Store: Only the first record

How to Store Record Data: Choose fields and assign variables (advanced)

Where to Store Values: Together in a record variable

Select Variable to Store User:

Record: {!varUser}

Select User Fields to Store in Variable: ContactId, IsActive, Email, CommunityNickname, Username, FederationIdentifier

DeactivateaPortalUserFlow-GetRecords2.JPGView image full screen

J. Drag the Decision flow element to determine whether we found a portal user in the previous step. Configure it as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

“Record Found” Outcome: {!varUser} Is Null {!GlobalConstant.False} AND {varUser.IsActive} Equals {!GlobalConstant.True}

“Not Found” Outcome: {!varUser} Is Null {!GlobalConstant.True}

DeactivateaPortalUserFlow-Decision2.JPGView image full screen

K. Next, we add a Screen flow element to show a message if no community user is found associated to the contact. Configure as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Control Navigation: Unselect Previous and Pause

DeactivatePortalUserFlow-Screen2Properties.JPGView image full screen

Drag the Display Text component to the screen canvas as configure as follows:

DeactivatePortalUserFlow-Screen2-DisplayText.JPGView image full screen

L. We now need an Update Records flow element to deactivate the portal user, disable the community user and clean up certain fields on the user record. Configure it as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Object: User

Filter User Records: Id Equals {!varUser.Id}

Set Field Values for the User Records:

CommunityNickname: {!CommunityNicknameFormula}

Email: {!DeactivatedEmailFormula}

FederationIdentifier: {!GlobalConstant.EmptyString}

IsActive: {!GlobalConstant.False} (Note: This deactivates the user record)

IsPortalEnabled: {!GlobalConstant.False} (Note: This disables the community user)

Username: {!DeactivatedUsernameFormula}

DeactivatePortalUserFlow-UpdateRecords.JPGView image full screen

M. We need another Update Records flow element. This time, we need to update the current user’s user record to set the Remove Permission Set Assignment Processing flag to true for it to be picked up in the scheduled flow we will create in Step 5. Configure it as follows:

Object: User

Filter User Records: Id Equals {!CurrentUserFormula}

Set Field Values for User Records: Remove_Perm_Set_Assignment_Processing__c: {!GlobalConstant.True}

DeactivatePortalUserFlow-UpdateRecords1.JPGView image full screen

N. Drag an Action flow element and select the showToast local action. Configure it as follows:

Message: You have successfully deactivated the portal user.

Type: Success

DeactivatePortalUserFlow-ShowToast1.JPGView image full screen

O. Drag the Action flow element and select the navigateEverywhereLFA component to take the user back to the contact record once the flow is completed. Configure it as follows:

Destination Type: record

Destination Action: view

Destination Record Id: {!recordId}

DeactivateaPortalUserFlow-NavigateEverywhere.JPGView image full screen

P. Add the subflow Send Flow Fault Email. For instructions on how to create this, go to Step 2 of blog post: Maximize Maintainability With Process Builder and Componentized Visual Workflow. Set your flow starting point. And connect the flow elements, fault connectors and outcome connectors to match the below…

DeactivateaPortalUserFlow-Connectors.JPG

Q. Save/Save As and provide the following properties.

Best practice tip: Provide a description so you and other/future admins know what this flow is used for.

DeactivateaPortalUserFlow-Properties.JPGView image full screen

R. Click the “Activate” button.

5. Let’s create the flow. For those using Salesforce Classic, flow can be found in Create | Workflows & Approvals | Flows. In Lightning Experience, it is found under Process Automation | Flows.

RemoveDeactivatedPortalUserUsedinFlowPermSetFlow.JPGView image full screen

A. Let’s create our flow resource.

Best practice tip: Provide a description so you and other/future admins know what this flow resource is used for.

Let’s create a formula called “PermissionSetIDFormula” takes the 18 character permission set id that is returned in the Get Records flow element and trims it to 15 characters.

Formula: LEFT( {!Lookup_the_Permission_Set_Id.Id} , LEN({!Lookup_the_Permission_Set_Id.Id})- 3)

PermissionSetIDFormula1.JPGView image full screen

B. Setup the flow as a scheduled flow by clicking on the Start button.

What launches the Flow: Scheduled jobs-flow runs for a batch of records

Set a Schedule: I set mine to run at 5:00pm daily

Object: User

Remove_Perm_Set_Assignment_Processing__c Equals {!GlobalConstant.True}

RemoveDeactivatedPortalUserUsedinFlowPermSetFlow-Start.JPGView image full screen

C. We need a Delete Records flow element to remove the Deactivate Portal User – Used in Flow permission set from the user. Configure as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

How to Find Records to Delete: Specify conditions

Object: Permission Set Assignment

Filter Permission Set Assignment Records: AssigneeId Equals {!Record.Id} AND PermissionSetId Equals {!PermissionSetIDFormula}

RemoveDeactivatedPortalUserUsedinFlowPermSetFlow-DeleteRecords.JPGView image full screen

D. Add an Update Records flow element to set the Remove Perm Set Assignment Processing flag to false for the current user. Configure as follows:

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Object: User

Filter User Records: Id Equals {!Record.Id}

Set Field Values for the User Records: Remove_Perm_Set_Assignment_Processing__c: {!GlobalConstant.False}

RemoveDeactivatedPortalUserUsedinFlowPermSetFlow-UpdateRecords.JPGView image full screen

E. Set your flow starting point. And connect the flow elements, fault connectors and outcome connectors to match the below…

RemoveDeactivatedPortalUserUsedinFlowPermSetFlow-Connectors.JPG

F. Save/Save As and provide the following properties.

Best practice tip: Provide a description so you and other/future admins know what this flow is used for.

RemoveDeactivatedPortalUserUsedinFlowPermSetFlow-Properties.JPG

G. Click the “Activate” button.

6A. If you are on Lightning Experience, we will create a Quick Action for the user to invoke the Deactivate Portal User flow. In Setup | Object Manager | Contact | Buttons, Links and Actions | New Action. Configure as follows:

Best practice tip: Provide a description so you and other/future admins know what this quick action is used for.

DeactivateUserAccountQA.JPGView image full screen

6B. If you are on Classic, we will create a custom button for the user to invoke the Deactivate Portal User flow.

First, you need to locate the flow URL. Go to Create | Workflows & Approvals | Flows, locate the Deactivate a Portal User flow, click the down arrow, select View Details and Versions, copy the URL “/flow/Deactivate_a_Portal_User1”.

DeactiveaPortalUserFlowURL.JPGView image full screen

Now, we need to create the custom button. In Setup | Customize | Contact | Buttons, Links and Actions | New Button or Link. Configure as follows:

Best practice tip: Provide a description so you and other/future admins know what this custom button is used for.

Display Type: Detail Page Button

Behavior: Display in existing window without a sidebar or header

Button or Link URL: /flow/Deactivate_a_Portal_User1?recordId={!Contact.Id}&retURL=/{!Contact.Id}

/flow/Deactivate_a_Portal_User1 – the flow URL

?recordId={!Contact.Id} – sets the ContactId as the value in the recordId flow variable

&retURL=/{!Contact.Id} – Returns to the contact detail page upon completion of the flow.

DeactivateUserAccountButton.JPGView image full screen

7. Add the custom button or Quick Action to Contact page layout.

8. Assign the “Ability to Deactivate Portal User” permission set to the individuals in your org who should have the ability to deactivate a portal user.

Now, before you deploy the changes to Production, don’t forget to test your configuration changes.

(IMPORTANT NOTE: You cannot test this using Login As. You need to physically login as an actual business user. If you login as a business user, it will give you false results. As a system administrator, you have the ability to manage users and assign/remove permission sets. It will not simulate the permissions of the business user in this case.)

  1. Assign the Ability to Deactivate a Portal user to the test business user.
  2. Navigate to a contact record with a community user.
  3. Click on the Deactivate User Account button. Confirm that (1) you see the Deactivated Portal User – Used in Flow permission set toast message, (2) see the You have successfully deactivated the portal user toast message and (3) verify that the user record is deactivated, the associated contact is removed and fields are updated as expected and (4) verify that the process flag is checked on the business user’s user record.
  4. After the scheduled flow is run, verify that the Deactivate Portal User – Used in Flow permission set is removed from the business user and the processing flag is reset on the business user’s user record.
  5. Also, navigate to a contact with a community user as a business user without the Ability to Deactivate a Portal User permission set. Click on the Deactivate User Account button. Confirm that a screen message is shown noting the user does not have sufficient permissions.
  6. Navigate to the same contact in Step 3 and click on the Deactivate User Account button. Confirm that a screen message is shown noting that a portal user is not found.

Deployment Notes/Tips:

  • Custom field, custom permission, permission sets and flows can be deployed to Production in a change set (or can be deployed using a tool such as Metazoa’s Snapshot).
  • You will find flows in a change set under the Flow Definition component type.
  • Activate the flow post deployment as flows deploy inactive in Production, unless you have opted in on the Process Automation Settings screen, to “Deploy processes and flows as active.” NOTE: With this change, in order to successfully deploy a process or flow, your org’s Apex tests must launch at least 75% of the total number of active processes and active autolaunched flows in your org.