I have always found CiviCRMs ACLs (Access Control Lists) system to be a bit of a mystery and a setting them up right to be a black art. In most standard demployments of CiviCRM, fiddling with the ACLs is almost completely unnecessary, but in larger organizational deployments there is often a requirements about protecting some data, or a group of contacts, from some set of users.

Recently I ran up against such requirements, and dove pretty deep into the ACL system. In this post, I share what I have learned (or re-learned) and some of the questions I answered for myself in the process.

Background On CiviCRM Permissions and Access Control

CiviCRM has an extensive list of permissions that can be managed through Drupal’s permission system. This is often enough to meet an organization’s needs. These permissions allow you to grant access by user role to various modules, and functions, like “View All Contacts” and “Edit All Contacts”, or “View All Custom Data” (these will be the two specific types of permissions I talk about below). Some of these permissions are perhaps not named as well as they should, which has caused confusion for me, and some clients I have worked with. For example “Access CiviContribute”: you might think that you should grant this permission to anon and authenticated users, if you want them to be able to make donations, right? WRONG. This permission gives access to CiviContribute! In the sense that you can access contributions and other information. There is a separate permission for “Make Online Contributions”

CiviCRM has an Access Control System (CiviCRM > Admin > Manage > Access Control) that lets you create more fine grained access to custom data groups, groups of contacts, profiles, and events.

Drupal’s permission system will override the ACLs you create, so in order for CiviCRM ACLs to do what you want them to do, you often must remove Drupal permissions like “View All Custom Data”.

Once you have removed permissions to something in CiviCRM from a Drupal user role, you then need to add back permissions to the specific users or groups of users that should have access using CiviCRM ACLs.

CiviCRM Access Control: The Basics

CiviCRM access control is split into three components:

  1. Roles
  2. Role Assignment
  3. Acess Control Lists

A “Role” can be thought of as a container, or even similar to the user roies in Drupal. It is nothing until you assign it to users, and grant specific permissions to it. But unlike in Drupal, you don’t assign the role to a specific user, and unlike Drupal, you do not have an exhaustive list of all available permissions.

Lets say you want to create a role for “Staff”, your first step is to create the role. Then you need to assign the role, and the way you do this is to assign it to a group of contacts. So you will need a “Staff” group in CiviCRM, and when you create it you should check the box “used for: access control,” and you will need to put your staff people in that group. That takes care of the first 2 pieces above, and now it gets interesting!

The next step is to create a rule or ACL. A rule applies to a type of data (a group of contacts, profile, custom data fields, events), an operation (view/edit) and a role (which you took care of creating already).

Managing Access To Custom Data Groups with ACLs

For this example, let’s say that you have one custom field group that you need to make visible only to your human resources department (we’ll assume you have already created the custom field group and fields), but you have a few other custom field groups that are available to everyone (literally, all other anonymous and authenticated users).

  1. Go to Drupal permissions and remove the “Access All Custom Data” from any Drupal role that should not be able to access all of your custom data groups.
  2. Go to CiviCRM > Admin > Manage > Access Control and click “Manage ACLs” and then click the “Add New ACL” button
  3. Under the “Type of Data” field, select the radio button for “A set of custom data fields”
  4. Then select the custom data field set to which you want to grant access, since the HR people are getting access to the HR Field group (let’s say that is what it is called) select that field group, though if they have access to ALL custom field groups, you could select the “All Custom Groups” option.
  5. Select the operation “Edit”
  6. Select the Role “HR Staff”
  7. Provide a description that will help you remember what this rule does in the future.

At this point, your HR Staff now have access to the field groups they need access to, but NO OTHER users have access to ANY custom field groups. Next we need to grant access to these other field groups to your other users. CiviCRM comes with two special roles “Everyone” that includes anonymous and authenticated users, and “Authenticated” which just includes all authenticated users. You will not see the “Everyone” role in the list of roles, but you will see it when you create an ACL. You will, however, see the “authenticated” role when you look at this list of roles.

  1. Go to CiviCRM > Admin > Manage > Access Control and click “Manage ACLs” and then click the “Add New ACL” button
  2. Under the “Type of Data” field, select the radio button for “A set of custom data fields”
  3. Then select the one of your other custom data field sets that everyone should have access to
  4. Select the operation “Edit”
  5. Select the Role “Everyone”
  6. Provide a description that will help you remember what this rule does in the future.
  7. Repeat this process for each custom field group that everyone should have access to.
  8. REMEMBER to add an ACL every time you add a new custom field group in the future.

Managing Access to Contact Groups With ACLs

Another common use of ACLs is to restrict access to a group of contacts, for example, VIPs. Perhaps you have volunteers working with your organization, taking care of database upkeep tasks, but you don’t want them to be able to pull a list of your VIPs.

  1. The first step here is to identify your VIPs, which could be done with a tag, or a group. Let’s say you use a tag, and apply it to your VIPs
  2. Then you need a group that has everyone but those VIPs, you could create this as a smart group, most likely using the search builder to select all contacts that are not tagged VIP.
  3. Create a group for your database volunteers and indicate that it is used for access control
  4. Go to Drupal permissions and remove the “View All Contacts” and the “Edit All Contacts” from any Drupal role that should not be able to access all of your contacts, in this case, perhaps you have a “Volunteer” role, remove the permission.
  5. In CiviCRM create a “Volunteer” role, and then give that role to the “Database Volunteer” group you created.
  6. Go to CiviCRM > Admin > Manage > Access Control and click “Manage ACLs” and then click the “Add New ACL” button
  7. Under the “Type of Data” field, select the radio button for “A group of contacts”
  8. Then select the group you created that consists of everyone BUT your VIPs
  9. Select the operation “Edit”
  10. Select the Role “Volunteers”
  11. Provide a description that will help you remember what this rule does in the future.

Assuming that your Drupal Staff role still has the permission (in Drupal Permissions) to “View All Contacts” and “Edit All Contacts” then you are done. A few interesting things to note here: let’s say I am in your database as a VIP. If a Database Volunteer types my name into the quick search, or any other search, she will not find me. If however she tries to add a new contact, with my information, and checks for duplicates, I will be revealed as being in the database. However, the volunteer will still not be able to access by record. Similarly, anywhere in CiviCRM where there are auto-complete fields, the contacts to which the user does not have access will not be displayed in those auto-complete fields.

In my next post, I am going to talk about a way that you could cleanly segment your entire database using some custom data fields, groups and ACLs.