Guide 07 · Developer docs

Members, accounts and gated content

Building a member area on Core dna: who a member is in the data, the sign-in flows and their templates, single sign-on and passkeys, the my-account routing convention, members-only content, sessions and the page cache, and the security checks to run before launch.

L2
Unit 01 · The identity model

Groups and permissions

Groups are named sets of people; permissions say what a user, a group or everyone may do with a module, an entity type or one record. How the layers combine when a member asks for a record, why groups suit access by role, and why access per record belongs in the data model instead.

Who this is for. The content modeller and developer deciding how members get access. Afterwards you can predict whether a member can read a record from its permissions, and choose between a group and a record of your own.

Groups

A group is a named set of people, managed under Users › Groups. Membership belongs to the person, not the user, so a person without a login can be in a group, and a member's groups are read through their person. People join groups:

  • on their record under Users › People;
  • on registration, through the registration setting Groups, which lists the groups every new member joins (it is empty by default);
  • through the API, by an integration with a backend user's credential (People).

A member cannot add themselves to a group: the profile route does not accept group changes. That makes a group safe to grant access by, as long as nothing else writes it on the member's behalf.

Permissions

A permission is set at one of three levels, each more specific than the last, and at each level for one of three kinds of holder:

LevelCoversSet in the admin
ModuleEverything in a module, such as PagesUsers › Permissions
Entity typeOne kind of record in a module, such as blog posts, or one custom entity typeUsers › Permissions
RecordOne record, and the records that inherit from itThe record's own permissions (Restricting one record)

The holders are a user, a group, and the default for everyone, shown as All user's permissions. A record that has an owner also has Owner permissions, for what its owner may do. The permissions themselves are Read, Create, Update, Delete, Publish and, for administration, Admin and Configure. On the website, the one that matters is Read: it decides whether a visitor gets a record at all. The others govern the admin and the API.

The admin works out each user's effective permissions from these settings and stores the result; you never edit that result directly. A change is applied on the site within seconds of saving.

The order permissions are resolved in

When a signed-in member asks for a record, the platform takes the first of these that says anything, grant or refusal:

  1. A setting for the member on the record: for their user, or for one of their groups.
  2. A setting for the member on the record's entity type, or, if there is none, on its module.
  3. The record's default, from its own permissions or, when it inherits, its parent's.
  4. The default for the entity type, or, if there is none, for the module.

A signed-out visitor has no user or groups, so only the last two apply.

The order has one consequence that surprises people: a grant to a group on the whole entity type outranks a refusal in a record's default. If the Members group has been given read on all pages, restricting one page by switching its default read off does not hide it from members: step 2 answers before step 3 is reached. Keep grants on whole entity types and modules for staff, and give members access record by record or section by section.

Groups are records with permissions too

A template that checks a member's groups reads them through getPerson()->getGroups(). Groups are permission-controlled like any other record, so that list holds only the groups the member may read. On a site that has never granted members read on Groups in the Users module, the list is empty for members while the same template works for an administrator. Grant the read, and test group checks with a real member account (Showing group content in a template).

Groups for roles, records for everything else

Groups are the right tool for coarse access: a handful of roles, each seeing a set of content that changes rarely. Staff, partners, subscribers. They are the wrong tool when access differs record by record, because every course, event or client becomes another group to create, wire into permissions and maintain by hand.

Per-record access belongs in the data model: a record that relates the member to the thing they may see, created when access is granted (Entitlements: access per record). A site often uses both: a group for "members" restricts the members' section, and entitlement records decide which course pages inside it show their lessons.

Go deeper

Was this page helpful?

Your answer goes to the docs team.