Users and Roles
Accounts, roles, and the dot-notation permissions that guard routes and templates.
Users
A user is a folder at data/users/{username}/ with an index.json and a data.json, the same split as a page. The role and hashed password live in data.json.
phlat user:create adam --role=admin
phlat user:role adam editor
phlat user:password adam
A built-in guest user stands in for anyone not signed in.
Roles
A role is a folder with an index.json listing permissions. Site roles are checked before the framework's:
phlat/roles/admin/index.json ← ships with the framework
phlat/roles/guest/index.json
site/roles/editor/index.json ← yours
{
"locked": false,
"permissions": {
"admin": { "access": true },
"pages": { "edit": true, "publish": true }
}
}
Permissions are nested and checked with dot notation: pages.publish looks up permissions.pages.publish. A * key at any level is a wildcard for everything not listed there; the admin role is { "*": true }. A missing permission is denied.
Checking permissions
requirePermission() guards a route. It redirects to login when nobody is signed in and throws ForbiddenException (403) when the user lacks the permission:
$page->router->post('publish', function () use ($app, $page) {
$app->session->requirePermission('pages.publish');
// ...
});
requireLogin() accepts any signed-in user. can() checks without stopping the request:
if ($app->session->can('pages.edit')) { /* ... */ }
In Latte:
{if permission('pages.edit')}
<a href="{$page->url()}/edit">Edit</a>
{/if}
Put checks in a before() hook to guard a whole section (see Routing). To restrict a page and everything under it to signed-in users or specific roles, set its access instead. See Status and access.
Profile fields
Extra user fields are declared in roles/index.json under fields, like a view declares page fields. Each name refers to a global field in site/fields/, and values read like page fields.
{
"fields": {
"password": { "required": true },
"avatar": {},
"jobTitle": {}
}
}
Rate limiting
$app->session->isThrottled($key, $max, $window) and throttle($key, $window) count attempts per key. Login uses them to slow repeated failures; use them for any form.