Resolve a role
A role, a list of what exists, and the names that role selects. One wildcard, and a deny that wins.
pnpm add @niscorp/charterWhat exists
Charter is always handed the list of what exists. Here it is the ids of the screens the theatre’s app ships. An id with a dot in it, like me.tickets, is just a name: the dot is there so one pattern can select a family.
import { resolvePrincipal } from '@niscorp/charter';
const screens = [
'welcome',
'programme',
'seats',
'me.tickets',
'me.pass',
'door.list',
'members',
'takings',
'settings',
];A role is a list of patterns
A charter is an object of roles. The shortest role is a list of patterns over the names that exist.
A plain name selects itself. * matches any run of characters, dots included, so me.* is every screen whose id starts with me.. There is no other pattern.
const charter = {
guest: ['welcome', 'programme'],
member: ['programme', 'seats', 'me.*'],
};Resolve it
resolvePrincipal takes the charter, the list of what exists, and the roles a person has. It answers with the set of names those roles select. Nothing outside the set is granted: what no role mentions is denied.
console.log('member:', [...resolvePrincipal(charter, screens, ['member'])]);
console.log('guest:', [...resolvePrincipal(charter, screens, ['guest'])]);Allow, then deny
A role can also be written as what it allows and what it denies. This one allows every screen and takes four back.
A deny wins over an allow in the same role, whatever order they are written in.
const withStaff = {
...charter,
staff: { allow: ['*'], deny: ['welcome', 'me.*', 'settings'] },
};
console.log('staff:', [...resolvePrincipal(withStaff, screens, ['staff'])]);Two roles on one person
A person with two roles has what either role selects. Roles add up. A deny in one role does not take away what another role gives.
console.log('member and staff:', [...resolvePrincipal(withStaff, screens, ['member', 'staff'])].length, 'screens');Run it.
The four screens a member has, the two a guest has, the five staff have once the denies are taken out, and how many somebody with both roles has.
npx tsx resolve.mtsmember: [ 'programme', 'seats', 'me.tickets', 'me.pass' ] guest: [ 'welcome', 'programme' ] staff: [ 'programme', 'seats', 'door.list', 'members', 'takings' ] member and staff: 7 screens