-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRoleProps.cs
More file actions
73 lines (66 loc) · 3.17 KB
/
Copy pathRoleProps.cs
File metadata and controls
73 lines (66 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using redb.Core.Attributes;
namespace redb.Identity.Core.Models;
/// <summary>
/// B.3 — first-class role entity. Roles exist independently of groups and
/// claim mappers: they're a named bucket of access an operator can assign
/// to a user (directly) or to a group (transitively to every member).
///
/// <para>
/// Three layers in our token-issuance pipeline now compose orthogonally:
/// <list type="number">
/// <item><b>Claim mappers</b> (<see cref="ClaimMapperProps"/>) — declarative
/// rules that translate user attributes / group membership into JWT
/// claims at sign-in time. Mappers are the WIRING layer.</item>
/// <item><b>Groups</b> (<see cref="GroupProps"/>) — hierarchical user
/// organisation; can carry per-membership role labels via
/// <see cref="GroupMemberProps"/>. Groups are the MEMBERSHIP layer.</item>
/// <item><b>Roles</b> (this entity) — first-class named access buckets,
/// audience-scoped (organization-wide OR per-application). Assigned
/// directly to users via <see cref="UserRoleAssignmentProps"/> or
/// transitively via groups via <see cref="GroupRoleAssignmentProps"/>.
/// Roles are the ACCESS layer that operators reason about.</item>
/// </list>
/// </para>
///
/// <para>
/// Token issuance walks the user's EFFECTIVE role set = direct user
/// assignments ∪ transitive assignments via every group the user belongs to
/// (including ancestor groups when claim mappers expand the tree). For
/// audience='application' roles the set is FILTERED to the client_id of the
/// token being issued — an "engineering-admin" role on app A doesn't leak
/// into a token issued for app B.
/// </para>
///
/// <para>
/// Uniqueness: (Name, Audience, ApplicationId) is unique. Built-in roles
/// (system / everyone / admin / impersonator) are seeded with
/// <see cref="IsSystem"/>=true and can't be deleted via the admin API.
/// </para>
/// </summary>
[RedbScheme("identity.role")]
public class RoleProps
{
/// <summary>
/// Identifier-safe name; appears verbatim in the emitted <c>roles</c>
/// claim. Convention: lowercase / hyphenated.
/// </summary>
public string Name { get; set; } = "";
/// <summary>Operator-facing label rendered in the admin UI.</summary>
public string? DisplayName { get; set; }
public string? Description { get; set; }
/// <summary>
/// "organization" — visible to every application in this Identity
/// instance; emitted on every token for which the user holds the role.
/// "application" — scoped to a single application; emitted only on
/// tokens issued for the matching <see cref="ApplicationId"/>.
/// </summary>
public string Audience { get; set; } = "organization";
/// <summary>FK to the Application object id when <see cref="Audience"/> = "application". Null for organization.</summary>
public long? ApplicationId { get; set; }
/// <summary>
/// True for system-seeded roles (system / everyone / admin / impersonator)
/// — the admin API rejects delete on these. Set on the seed insert only;
/// operator-created roles always have IsSystem=false.
/// </summary>
public bool IsSystem { get; set; }
}