Concierge
view release on metacpan or search on metacpan
extends to anything an added component manages.
## How It Works
### Desks
A *desk* is a directory containing the configuration and data files for the
three identity-core components -- and, if you've added any, for those too.
You create one with `Concierge::Desk::Setup`, then open it at
runtime with `Concierge->open_desk()`. Opening a desk instantiates all components from
the saved configuration and runs session cleanup automatically.
```perl
# One-time setup (run once, not on every request)
use Concierge::Desk::Setup;
Concierge::Desk::Setup::build_desk({
base_dir => './desk',
auth => { backend => 'pwd' },
sessions => { backend => 'database' },
users => {
backend => 'database',
app_fields => ['department', 'theme'],
},
});
# Every request
use Concierge;
my $result = Concierge->open_desk('./desk');
my $concierge = $result->{concierge};
```
### User Participation Levels
Concierge provides three graduated levels, each returning a
`Concierge::Desk::User` object with methods appropriate to that level:
| Level | Method | User key | Session | User record | Auth |
|---|---|---|---|---|---|
| Visitor | `admit_visitor()` | Yes | No | No | No |
| Guest | `checkin_guest()` | Yes | Yes | No | No |
| Logged-in | `login_user()` | Yes | Yes | Yes | Yes |
A guest can be promoted to a logged-in user with `login_guest()`, which
transfers any session data (shopping cart, preferences, etc.) to the new
authenticated session.
Between requests, users are restored by `user_key` (typically stored in a
cookie): `restore_user($user_key)` rehydrates the correct object type with
the right data and backend access.
## Components
Concierge ships with a complete identity core out of the box, and the same
component pattern that powers it extends to anything else your
application needs to manage.
### Identity Core (built in)
#### Authentication â Concierge::Auth
- **Argon2** password hashing and verification; no plaintext credentials
written to disk
- Random value generators: hex IDs, alphanumeric tokens, UUIDs (v4),
word-passphrases from a system dictionary
- Designed for substitution: swap in any replacement that implements the
same method contract (`enroll`, `authenticate`, `is_id_known`,
`change_credentials`, `revoke`) for LDAP, OAuth, or other schemes
#### Sessions â Concierge::Sessions
- **Multiple backends**: SQLite (recommended) or flat-file
- Every session lives in memory first; data is only written to whichever
backend is configured when `->save()` is called. Some sessions never call
`save()` at all and exist purely for in-process continuity.
- Sessions carry arbitrary key/value data (shopping carts, wizard state,
preferences, etc.)
- Configurable timeout per session; expired sessions cleaned up automatically
on `open_desk()`
- **Single-session-per-user** enforced at login: a new session replaces any
prior session for that user
- Full lifecycle: create, get, update data, save, delete, cleanup
#### User Records â Concierge::Users
- **Multiple backends**: SQLite, YAML, CSV/TSV
- **Configurable field schema**: built-in standard fields plus
application-defined fields added at setup time
See the Concierge::Users README (Field Customization) for the full list of
standard fields.
Applications extend this with `app_fields` at setup time:
```perl
Concierge::Desk::Setup::build_desk({
base_dir => './desk',
auth => { backend => 'pwd' },
sessions => { backend => 'database' },
users => {
backend => 'database',
app_fields => [
{ field_name => 'department', type => 'text' },
{ field_name => 'plan', type => 'enum',
options => ['free', 'pro', 'enterprise'] },
],
},
});
```
Field definitions can also override built-in defaults (labels, null values,
required flags, etc.) via `field_overrides`.
All or selected standard fields may also be omitted entirely, except for the
required fields and automatic date fields.
### Extensibility (bring your own)
Each identity core component can itself be replaced with a conforming
alternative -- any drop-in that implements the same method contract (see
`EXTENSIBILITY` in `perldoc Concierge`) works in place of the built-in
Auth, Sessions, or Users component.
Beyond the identity core, a desk can carry any number of additional
components -- Organizations, Assets, Guides, Catalog, or anything else
your application manages the same way. A component only needs to satisfy
the duck-typed contract in `Concierge::Desk::Component` (a `new`/`setup`
constructor lifecycle and the `{ success => ..., message => ... }` return
( run in 0.845 second using v1.01-cache-2.11-cpan-0fb53d1c279 )