- Easily customizable
user
androle
collection generation. - Fine-grained access control configuration. All are editable in the
role
editing page! - Fully customizable
access
functions and access control handler functions (for endpoints). - Automatically populated
root
role with all access privileges. And aroot
user with this role as well!
- This plugin collects information from
collections
,globals
and user provided extrasynopses
to build a collection of unifiedfeatures
which looks like the following data structure:
{
feature: string, // the slug of a collection or a global
traits: string[], // a collection of field names or endpoint (which belongs to the collection or global) paths
verbs: string[], // create, read, update, delete
}[] // a collection of this of all the collections, globals and user provided synopses
- Then the data is used to bring to us this:
yarn add payload-warding
npm i payload-warding
// ...
import warding, { convention } from "payload-warding";
//...
export default buildConfig({
// ...
plugins: [
// ...
warding(
convention.opts({
root: { email: process.env.YOUR_ROOT_EMAIL!, password: process.env.YOUR_ROOT_PASSWORD! },
}),
),
// ...
],
// ...
});
// ...
The convention.opts
will deeply merge your options with predefined default options using a function implements RFC-7386 JSON Merge Patch
, see convention.ts for details.
root
/**
* The root user's email and password. If not provided, the root user will not
* be created.
*/
root?: {
email: string;
password: string;
};
Please note that the user created in the create-first-user
page will be automatically bound with a root
role. So it's fine to skip the root user creation.
user
/**
* The user {@link Options}.
*/
user?: Options;
type Options = {
slug: string;
fields?: Field[]; // payload's Field type
title?: string;
tag?: SpecLabels;
};
type SpecLabels = {
plural?: Record<string, string> | string;
singular?: Record<string, string> | string;
};
role
/**
* The role {@link Options}.
*/
role?: Options;
label
/**
* All the labels for plugin introduced collections, fields and select options.
*/
label?: Label;
ext
/**
* Extended features in the form of {@link Synopsis}s.
*/
ext?: Synopsis[];
type Synopsis = {
slug: string;
traits: [string, Label | undefined][];
label?: Label;
};
type Label = Record<string, string> | string;
This paired with the check
function in convention.ts can be used to build custom access control upon the user + role
system provided by this plugin.
mod
/**
* Modifies the {@link Built} result after {@link Warding.build}.
*/
mod?: (w: Built) => Built;
type Built = {
collections: { user: CollectionConfig; role: CollectionConfig };
warden: Warden;
populate: Populate;
initialize: Initialize;
initializationExtra?: { user: any; role: any };
};
Additional config options could be easily added to the user and role via this, See factory/spec.ts for details.
mute
/**
* Disable this plugin without uninstalling it.
*/
mute?: boolean;
Authorizations of Collections are provided by adding access
functions to all possible collections
, fields
...and so on. The said access
functions will ask for a specific feature
, traits
, verbs
combination to be present, or otherwise reject the operation it is assigned to.
For example, the expected feature
, traits
, verbs
combination for which an access.create
of a collection
chad will ask looks like this:
{
feature: "chad",
trais: [],
verbs: ["create"]
}
Any user who has a role
with a feature
chad and any trait
(which, if is left empty in the role editing page, will have a default "_" trait
assigned) of verb create can pass the check. As for the access.update
of a field
age of the collection
chad, it looks like this:
{
feature: "chad",
trais: ["age"],
verbs: ["update"]
}
Authorizations of Globals are provided the same way as Collections
Authorizations of Endpoints are provided by prepending check functions in the handler
function arrays. The check functions basically do the same as those access
functions mentioned above, in which case the verbs
are determined by the endpoint's http method as such:
{
post: "create",
connect: "read",
options: "read",
head: "read",
get: "read",
put: "update",
patch: "update",
delete: "delete",
}
You can also choose to skip the authorization for specific
collections
,globals
or some of theirfields
orendpoints
by assigning thecustom.warding.should
to false orcustom.warding.should.[verb]
flags of correspondingverbs
to false.
Alternatively, if an access function is customly assigned in
collections
,globals
orfields
, the authorization will always be skipped but a plugin generated authorization functionreq.context.warding
will be attached to the access function argument. So that plugin users can decide how and when to call the plugin generated authorization function.
The
custom.warding.should
andcustom.warding.should.[verb]
flags assigned infields
orendpoints
can override those assigned in their correspondingcollections
andglobals
.
The plugin generated authorization function
req.context.warding
will always be attached to the handler function's argument whenendpoints
have thecustom.warding.should
flag orcustom.warding.should.[verb]
flags assigned to false.