@veap/auth 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +167 -2
- package/dist/actions/auth.actions.d.ts +23 -0
- package/dist/actions/auth.actions.js +40 -0
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/client/auth.context.d.ts +29 -0
- package/dist/client/auth.context.js +64 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/common/augment.d.ts +26 -0
- package/dist/common/augment.js +63 -0
- package/dist/common/context.d.ts +30 -0
- package/dist/common/context.js +36 -0
- package/dist/common/index.d.ts +7 -0
- package/dist/common/index.js +7 -0
- package/dist/common/logic.d.ts +64 -0
- package/dist/common/logic.js +133 -0
- package/dist/common/registry.d.ts +28 -0
- package/dist/common/registry.js +76 -0
- package/dist/common/routes.d.ts +3 -0
- package/dist/common/routes.js +2 -0
- package/dist/common/tokens.d.ts +10 -0
- package/dist/common/tokens.js +8 -0
- package/dist/common/types.d.ts +178 -0
- package/dist/common/types.js +9 -0
- package/dist/crypto/aes-cipher.d.ts +8 -0
- package/dist/crypto/aes-cipher.js +12 -0
- package/dist/crypto/bcrypt-hasher.d.ts +12 -0
- package/dist/crypto/bcrypt-hasher.js +37 -0
- package/dist/crypto/contracts.d.ts +36 -0
- package/dist/crypto/contracts.js +3 -0
- package/dist/crypto/encryption.d.ts +18 -0
- package/dist/crypto/encryption.js +69 -0
- package/dist/crypto/index.d.ts +6 -0
- package/dist/crypto/index.js +6 -0
- package/dist/crypto/password.d.ts +19 -0
- package/dist/crypto/password.js +27 -0
- package/dist/crypto/token-generator.d.ts +10 -0
- package/dist/crypto/token-generator.js +25 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/migrations/0001_create_auth_tables.d.ts +4 -0
- package/dist/migrations/0001_create_auth_tables.js +122 -0
- package/dist/migrations/index.d.ts +4 -0
- package/dist/migrations/index.js +7 -0
- package/dist/models/EmailVerification.d.ts +23 -0
- package/dist/models/EmailVerification.js +19 -0
- package/dist/models/PasswordResetSession.d.ts +25 -0
- package/dist/models/PasswordResetSession.js +21 -0
- package/dist/models/Permission.d.ts +20 -0
- package/dist/models/Permission.js +19 -0
- package/dist/models/Role.d.ts +20 -0
- package/dist/models/Role.js +19 -0
- package/dist/models/Session.d.ts +22 -0
- package/dist/models/Session.js +21 -0
- package/dist/models/User.d.ts +32 -0
- package/dist/models/User.js +31 -0
- package/dist/models/index.d.ts +6 -0
- package/dist/models/index.js +6 -0
- package/dist/models.d.ts +1 -0
- package/dist/models.js +1 -0
- package/dist/passwords/contracts.d.ts +28 -0
- package/dist/passwords/contracts.js +2 -0
- package/dist/passwords/index.d.ts +4 -0
- package/dist/passwords/index.js +4 -0
- package/dist/passwords/password-reset.facade.d.ts +14 -0
- package/dist/passwords/password-reset.facade.js +57 -0
- package/dist/passwords/password-reset.repository.d.ts +10 -0
- package/dist/passwords/password-reset.repository.js +39 -0
- package/dist/passwords/password-reset.service.d.ts +38 -0
- package/dist/passwords/password-reset.service.js +242 -0
- package/dist/providers/auth.provider.d.ts +9 -0
- package/dist/providers/auth.provider.js +199 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/setup.d.ts +7 -0
- package/dist/providers/setup.js +29 -0
- package/dist/rbac/contracts.d.ts +75 -0
- package/dist/rbac/contracts.js +4 -0
- package/dist/rbac/index.d.ts +4 -0
- package/dist/rbac/index.js +4 -0
- package/dist/rbac/rbac.facade.d.ts +23 -0
- package/dist/rbac/rbac.facade.js +85 -0
- package/dist/rbac/rbac.repository.d.ts +30 -0
- package/dist/rbac/rbac.repository.js +137 -0
- package/dist/rbac/rbac.service.d.ts +35 -0
- package/dist/rbac/rbac.service.js +143 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +3 -0
- package/dist/session/auth.service.d.ts +35 -0
- package/dist/session/auth.service.js +207 -0
- package/dist/session/contracts.d.ts +33 -0
- package/dist/session/contracts.js +2 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.js +5 -0
- package/dist/session/session.facade.d.ts +14 -0
- package/dist/session/session.facade.js +75 -0
- package/dist/session/session.repository.d.ts +15 -0
- package/dist/session/session.repository.js +55 -0
- package/dist/session/session.service.d.ts +63 -0
- package/dist/session/session.service.js +221 -0
- package/dist/users/contracts.d.ts +33 -0
- package/dist/users/contracts.js +2 -0
- package/dist/users/index.d.ts +4 -0
- package/dist/users/index.js +4 -0
- package/dist/users/user.facade.d.ts +28 -0
- package/dist/users/user.facade.js +92 -0
- package/dist/users/user.repository.d.ts +16 -0
- package/dist/users/user.repository.js +60 -0
- package/dist/users/user.service.d.ts +80 -0
- package/dist/users/user.service.js +201 -0
- package/dist/validation/index.d.ts +90 -0
- package/dist/validation/index.js +46 -0
- package/dist/verification/contracts.d.ts +25 -0
- package/dist/verification/contracts.js +2 -0
- package/dist/verification/index.d.ts +4 -0
- package/dist/verification/index.js +4 -0
- package/dist/verification/verification.facade.d.ts +10 -0
- package/dist/verification/verification.facade.js +49 -0
- package/dist/verification/verification.repository.d.ts +7 -0
- package/dist/verification/verification.repository.js +23 -0
- package/dist/verification/verification.service.d.ts +44 -0
- package/dist/verification/verification.service.js +122 -0
- package/package.json +84 -4
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { UserPermission, UserRole } from "../common/index.js";
|
|
2
|
+
export type { UserPermission, UserRole };
|
|
3
|
+
/** A role as persisted (already mapped to a plain object). */
|
|
4
|
+
export interface RoleRecord {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string | null;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
/** Minimal `{ id, name }` reference used by RBAC read models. */
|
|
11
|
+
export interface AccessGrant {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The roles and permissions graph of a single user, as loaded from the
|
|
17
|
+
* persistence layer.
|
|
18
|
+
*/
|
|
19
|
+
export interface UserAccess {
|
|
20
|
+
roles: Array<AccessGrant & {
|
|
21
|
+
permissions: AccessGrant[];
|
|
22
|
+
}>;
|
|
23
|
+
directPermissions: AccessGrant[];
|
|
24
|
+
}
|
|
25
|
+
export interface CreateRoleRecord {
|
|
26
|
+
name: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Role persistence port.
|
|
31
|
+
*/
|
|
32
|
+
export interface IRoleRepository {
|
|
33
|
+
findAll(): Promise<RoleRecord[]>;
|
|
34
|
+
findById(id: string): Promise<RoleRecord | undefined>;
|
|
35
|
+
findByName(name: string): Promise<RoleRecord | null>;
|
|
36
|
+
create(record: CreateRoleRecord): Promise<RoleRecord>;
|
|
37
|
+
remove(id: string): Promise<void>;
|
|
38
|
+
/** Permissions granted to a role. */
|
|
39
|
+
getPermissions(roleId: string): Promise<AccessGrant[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Loads the full role/permission graph for a user.
|
|
42
|
+
* Returns `null` when the user does not exist.
|
|
43
|
+
*/
|
|
44
|
+
loadUserAccess(userId: string): Promise<UserAccess | null>;
|
|
45
|
+
assignToUser(userId: string, roleId: string): Promise<void>;
|
|
46
|
+
revokeFromUser(userId: string, roleId: string): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/** Injection token for the role repository port. */
|
|
49
|
+
export declare const ROLE_REPOSITORY: unique symbol;
|
|
50
|
+
/** A permission as persisted (already mapped to a plain object). */
|
|
51
|
+
export interface PermissionRecord {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
description?: string | null;
|
|
55
|
+
[key: string]: any;
|
|
56
|
+
}
|
|
57
|
+
export interface CreatePermissionRecord {
|
|
58
|
+
name: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Permission persistence port.
|
|
63
|
+
*/
|
|
64
|
+
export interface IPermissionRepository {
|
|
65
|
+
findAll(): Promise<PermissionRecord[]>;
|
|
66
|
+
findById(id: string): Promise<PermissionRecord | undefined>;
|
|
67
|
+
create(record: CreatePermissionRecord): Promise<PermissionRecord>;
|
|
68
|
+
remove(id: string): Promise<void>;
|
|
69
|
+
assignToRole(roleId: string, permissionId: string): Promise<void>;
|
|
70
|
+
revokeFromRole(roleId: string, permissionId: string): Promise<void>;
|
|
71
|
+
assignToUser(userId: string, permissionId: string): Promise<void>;
|
|
72
|
+
revokeFromUser(userId: string, permissionId: string): Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
/** Injection token for the permission repository port. */
|
|
75
|
+
export declare const PERMISSION_REPOSITORY: unique symbol;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare function getRoles(): Promise<import("./contracts.js").RoleRecord[]>;
|
|
2
|
+
export declare function getRoleById(roleId: string): Promise<import("./contracts.js").RoleRecord | undefined>;
|
|
3
|
+
export declare function createRole(name: string, description?: string): Promise<import("./contracts.js").RoleRecord[]>;
|
|
4
|
+
export declare function deleteRole(roleId: string): Promise<void>;
|
|
5
|
+
export declare function getPermissions(): Promise<import("./contracts.js").PermissionRecord[]>;
|
|
6
|
+
export declare function getPermissionById(permissionId: string): Promise<import("./contracts.js").PermissionRecord | undefined>;
|
|
7
|
+
export declare function createPermission(name: string, description?: string): Promise<import("./contracts.js").PermissionRecord[]>;
|
|
8
|
+
export declare function deletePermission(permissionId: string): Promise<void>;
|
|
9
|
+
export declare function getRolePermissions(roleId: string): Promise<import("./contracts.js").AccessGrant[]>;
|
|
10
|
+
export declare function assignPermissionToRole(roleId: string, permissionId: string): Promise<void>;
|
|
11
|
+
export declare function revokePermissionFromRole(roleId: string, permissionId: string): Promise<void>;
|
|
12
|
+
export declare function assignRoleToUser(userId: string, roleId: string): Promise<void>;
|
|
13
|
+
export declare function revokeRoleFromUser(userId: string, roleId: string): Promise<void>;
|
|
14
|
+
export declare function assignPermissionToUser(userId: string, permissionId: string): Promise<void>;
|
|
15
|
+
export declare function revokePermissionFromUser(userId: string, permissionId: string): Promise<void>;
|
|
16
|
+
export declare function getUserRbacData(userId: string): Promise<{
|
|
17
|
+
roles: {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
}[];
|
|
21
|
+
directPermissions: import("./contracts.js").AccessGrant[];
|
|
22
|
+
effectivePermissions: import("./contracts.js").AccessGrant[];
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { app } from "@veap/kernel";
|
|
3
|
+
import { authContext, isAuthContextBound } from "../common/context.js";
|
|
4
|
+
import { RbacService } from "./rbac.service.js";
|
|
5
|
+
async function resolveRbacService() {
|
|
6
|
+
const g = globalThis;
|
|
7
|
+
if (g.__VEAP_BOOTSTRAPPING_PROMISE__) {
|
|
8
|
+
try {
|
|
9
|
+
await g.__VEAP_BOOTSTRAPPING_PROMISE__;
|
|
10
|
+
}
|
|
11
|
+
catch { }
|
|
12
|
+
}
|
|
13
|
+
if (isAuthContextBound()) {
|
|
14
|
+
return authContext().rbac;
|
|
15
|
+
}
|
|
16
|
+
return await app(RbacService);
|
|
17
|
+
}
|
|
18
|
+
// --- Roles ---
|
|
19
|
+
export async function getRoles() {
|
|
20
|
+
const service = await resolveRbacService();
|
|
21
|
+
return service.getRoles();
|
|
22
|
+
}
|
|
23
|
+
export async function getRoleById(roleId) {
|
|
24
|
+
const service = await resolveRbacService();
|
|
25
|
+
return service.getRoleById(roleId);
|
|
26
|
+
}
|
|
27
|
+
export async function createRole(name, description) {
|
|
28
|
+
const service = await resolveRbacService();
|
|
29
|
+
return service.createRole(name, description);
|
|
30
|
+
}
|
|
31
|
+
export async function deleteRole(roleId) {
|
|
32
|
+
const service = await resolveRbacService();
|
|
33
|
+
return service.deleteRole(roleId);
|
|
34
|
+
}
|
|
35
|
+
// --- Permissions ---
|
|
36
|
+
export async function getPermissions() {
|
|
37
|
+
const service = await resolveRbacService();
|
|
38
|
+
return service.getPermissions();
|
|
39
|
+
}
|
|
40
|
+
export async function getPermissionById(permissionId) {
|
|
41
|
+
const service = await resolveRbacService();
|
|
42
|
+
return service.getPermissionById(permissionId);
|
|
43
|
+
}
|
|
44
|
+
export async function createPermission(name, description) {
|
|
45
|
+
const service = await resolveRbacService();
|
|
46
|
+
return service.createPermission(name, description);
|
|
47
|
+
}
|
|
48
|
+
export async function deletePermission(permissionId) {
|
|
49
|
+
const service = await resolveRbacService();
|
|
50
|
+
return service.deletePermission(permissionId);
|
|
51
|
+
}
|
|
52
|
+
// --- Mappings ---
|
|
53
|
+
export async function getRolePermissions(roleId) {
|
|
54
|
+
const service = await resolveRbacService();
|
|
55
|
+
return service.getRolePermissions(roleId);
|
|
56
|
+
}
|
|
57
|
+
export async function assignPermissionToRole(roleId, permissionId) {
|
|
58
|
+
const service = await resolveRbacService();
|
|
59
|
+
return service.assignPermissionToRole(roleId, permissionId);
|
|
60
|
+
}
|
|
61
|
+
export async function revokePermissionFromRole(roleId, permissionId) {
|
|
62
|
+
const service = await resolveRbacService();
|
|
63
|
+
return service.revokePermissionFromRole(roleId, permissionId);
|
|
64
|
+
}
|
|
65
|
+
// --- User Assignment ---
|
|
66
|
+
export async function assignRoleToUser(userId, roleId) {
|
|
67
|
+
const service = await resolveRbacService();
|
|
68
|
+
return service.assignRoleToUser(userId, roleId);
|
|
69
|
+
}
|
|
70
|
+
export async function revokeRoleFromUser(userId, roleId) {
|
|
71
|
+
const service = await resolveRbacService();
|
|
72
|
+
return service.revokeRoleFromUser(userId, roleId);
|
|
73
|
+
}
|
|
74
|
+
export async function assignPermissionToUser(userId, permissionId) {
|
|
75
|
+
const service = await resolveRbacService();
|
|
76
|
+
return service.assignPermissionToUser(userId, permissionId);
|
|
77
|
+
}
|
|
78
|
+
export async function revokePermissionFromUser(userId, permissionId) {
|
|
79
|
+
const service = await resolveRbacService();
|
|
80
|
+
return service.revokePermissionFromUser(userId, permissionId);
|
|
81
|
+
}
|
|
82
|
+
export async function getUserRbacData(userId) {
|
|
83
|
+
const service = await resolveRbacService();
|
|
84
|
+
return service.getUserRbacData(userId);
|
|
85
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AccessGrant, CreatePermissionRecord, CreateRoleRecord, IPermissionRepository, IRoleRepository, PermissionRecord, RoleRecord, UserAccess } from "./contracts.js";
|
|
2
|
+
/**
|
|
3
|
+
* `IRoleRepository` adapter backed by the `Role` ActiveRecord model and the
|
|
4
|
+
* `users_to_roles` pivot table.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ActiveRecordRoleRepository implements IRoleRepository {
|
|
7
|
+
findAll(): Promise<RoleRecord[]>;
|
|
8
|
+
findById(id: string): Promise<RoleRecord | undefined>;
|
|
9
|
+
findByName(name: string): Promise<RoleRecord | null>;
|
|
10
|
+
create(record: CreateRoleRecord): Promise<RoleRecord>;
|
|
11
|
+
remove(id: string): Promise<void>;
|
|
12
|
+
getPermissions(roleId: string): Promise<AccessGrant[]>;
|
|
13
|
+
loadUserAccess(userId: string): Promise<UserAccess | null>;
|
|
14
|
+
assignToUser(userId: string, roleId: string): Promise<void>;
|
|
15
|
+
revokeFromUser(userId: string, roleId: string): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* `IPermissionRepository` adapter backed by the `Permission` ActiveRecord model
|
|
19
|
+
* and the `roles_to_permissions` / `users_to_permissions` pivot tables.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ActiveRecordPermissionRepository implements IPermissionRepository {
|
|
22
|
+
findAll(): Promise<PermissionRecord[]>;
|
|
23
|
+
findById(id: string): Promise<PermissionRecord | undefined>;
|
|
24
|
+
create(record: CreatePermissionRecord): Promise<PermissionRecord>;
|
|
25
|
+
remove(id: string): Promise<void>;
|
|
26
|
+
assignToRole(roleId: string, permissionId: string): Promise<void>;
|
|
27
|
+
revokeFromRole(roleId: string, permissionId: string): Promise<void>;
|
|
28
|
+
assignToUser(userId: string, permissionId: string): Promise<void>;
|
|
29
|
+
revokeFromUser(userId: string, permissionId: string): Promise<void>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { getKnex } from "@veap/database";
|
|
2
|
+
import { Permission } from "../models/Permission.js";
|
|
3
|
+
import { Role } from "../models/Role.js";
|
|
4
|
+
import { User } from "../models/User.js";
|
|
5
|
+
/**
|
|
6
|
+
* `IRoleRepository` adapter backed by the `Role` ActiveRecord model and the
|
|
7
|
+
* `users_to_roles` pivot table.
|
|
8
|
+
*/
|
|
9
|
+
export class ActiveRecordRoleRepository {
|
|
10
|
+
async findAll() {
|
|
11
|
+
const roles = await Role.query().orderBy("name", "asc").get();
|
|
12
|
+
return roles.map((role) => role.toJSON());
|
|
13
|
+
}
|
|
14
|
+
async findById(id) {
|
|
15
|
+
const role = await Role.find(id);
|
|
16
|
+
return role ? role.toJSON() : undefined;
|
|
17
|
+
}
|
|
18
|
+
async findByName(name) {
|
|
19
|
+
const role = await Role.where("name", name).first();
|
|
20
|
+
return role ? role.toJSON() : null;
|
|
21
|
+
}
|
|
22
|
+
async create(record) {
|
|
23
|
+
const role = await Role.create({
|
|
24
|
+
name: record.name,
|
|
25
|
+
description: record.description,
|
|
26
|
+
});
|
|
27
|
+
return role.toJSON();
|
|
28
|
+
}
|
|
29
|
+
async remove(id) {
|
|
30
|
+
await Role.destroy(id);
|
|
31
|
+
}
|
|
32
|
+
async getPermissions(roleId) {
|
|
33
|
+
const role = await Role.find(roleId);
|
|
34
|
+
if (!role)
|
|
35
|
+
return [];
|
|
36
|
+
const permissions = await role.permissions().get();
|
|
37
|
+
return permissions.map((permission) => ({
|
|
38
|
+
id: permission.id,
|
|
39
|
+
name: permission.name,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
async loadUserAccess(userId) {
|
|
43
|
+
const user = await User.query()
|
|
44
|
+
.with("roles.permissions", "permissions")
|
|
45
|
+
.find(userId);
|
|
46
|
+
if (!user)
|
|
47
|
+
return null;
|
|
48
|
+
const roles = user.getRelation("roles") || [];
|
|
49
|
+
const direct = user.getRelation("permissions") || [];
|
|
50
|
+
return {
|
|
51
|
+
roles: roles.map((role) => ({
|
|
52
|
+
id: role.id,
|
|
53
|
+
name: role.name,
|
|
54
|
+
permissions: (role.getRelation("permissions") || []).map((permission) => ({
|
|
55
|
+
id: permission.id,
|
|
56
|
+
name: permission.name,
|
|
57
|
+
})),
|
|
58
|
+
})),
|
|
59
|
+
directPermissions: direct.map((permission) => ({
|
|
60
|
+
id: permission.id,
|
|
61
|
+
name: permission.name,
|
|
62
|
+
})),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async assignToUser(userId, roleId) {
|
|
66
|
+
const knex = getKnex();
|
|
67
|
+
await knex("users_to_roles")
|
|
68
|
+
.insert({ user_id: userId, role_id: roleId })
|
|
69
|
+
.onConflict(["user_id", "role_id"])
|
|
70
|
+
.ignore();
|
|
71
|
+
}
|
|
72
|
+
async revokeFromUser(userId, roleId) {
|
|
73
|
+
const knex = getKnex();
|
|
74
|
+
await knex("users_to_roles")
|
|
75
|
+
.where({
|
|
76
|
+
user_id: userId,
|
|
77
|
+
role_id: roleId,
|
|
78
|
+
})
|
|
79
|
+
.delete();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* `IPermissionRepository` adapter backed by the `Permission` ActiveRecord model
|
|
84
|
+
* and the `roles_to_permissions` / `users_to_permissions` pivot tables.
|
|
85
|
+
*/
|
|
86
|
+
export class ActiveRecordPermissionRepository {
|
|
87
|
+
async findAll() {
|
|
88
|
+
const permissions = await Permission.query().orderBy("name", "asc").get();
|
|
89
|
+
return permissions.map((permission) => permission.toJSON());
|
|
90
|
+
}
|
|
91
|
+
async findById(id) {
|
|
92
|
+
const permission = await Permission.find(id);
|
|
93
|
+
return permission ? permission.toJSON() : undefined;
|
|
94
|
+
}
|
|
95
|
+
async create(record) {
|
|
96
|
+
const permission = await Permission.create({
|
|
97
|
+
name: record.name,
|
|
98
|
+
description: record.description,
|
|
99
|
+
});
|
|
100
|
+
return permission.toJSON();
|
|
101
|
+
}
|
|
102
|
+
async remove(id) {
|
|
103
|
+
await Permission.destroy(id);
|
|
104
|
+
}
|
|
105
|
+
async assignToRole(roleId, permissionId) {
|
|
106
|
+
const knex = getKnex();
|
|
107
|
+
await knex("roles_to_permissions")
|
|
108
|
+
.insert({ role_id: roleId, permission_id: permissionId })
|
|
109
|
+
.onConflict(["role_id", "permission_id"])
|
|
110
|
+
.ignore();
|
|
111
|
+
}
|
|
112
|
+
async revokeFromRole(roleId, permissionId) {
|
|
113
|
+
const knex = getKnex();
|
|
114
|
+
await knex("roles_to_permissions")
|
|
115
|
+
.where({
|
|
116
|
+
role_id: roleId,
|
|
117
|
+
permission_id: permissionId,
|
|
118
|
+
})
|
|
119
|
+
.delete();
|
|
120
|
+
}
|
|
121
|
+
async assignToUser(userId, permissionId) {
|
|
122
|
+
const knex = getKnex();
|
|
123
|
+
await knex("users_to_permissions")
|
|
124
|
+
.insert({ user_id: userId, permission_id: permissionId })
|
|
125
|
+
.onConflict(["user_id", "permission_id"])
|
|
126
|
+
.ignore();
|
|
127
|
+
}
|
|
128
|
+
async revokeFromUser(userId, permissionId) {
|
|
129
|
+
const knex = getKnex();
|
|
130
|
+
await knex("users_to_permissions")
|
|
131
|
+
.where({
|
|
132
|
+
user_id: userId,
|
|
133
|
+
permission_id: permissionId,
|
|
134
|
+
})
|
|
135
|
+
.delete();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { User } from "../common/index.js";
|
|
2
|
+
import { type AccessGrant, type IPermissionRepository, type IRoleRepository, type PermissionRecord, type RoleRecord } from "./contracts.js";
|
|
3
|
+
/**
|
|
4
|
+
* Core RBAC use cases. Persistence lives behind the role/permission
|
|
5
|
+
* repositories, so this service stays framework-free and testable.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RbacService {
|
|
8
|
+
private readonly roles;
|
|
9
|
+
private readonly permissions;
|
|
10
|
+
constructor(roles: IRoleRepository, permissions: IPermissionRepository);
|
|
11
|
+
getRoles(): Promise<RoleRecord[]>;
|
|
12
|
+
getRoleById(roleId: string): Promise<RoleRecord | undefined>;
|
|
13
|
+
createRole(name: string, description?: string): Promise<RoleRecord[]>;
|
|
14
|
+
deleteRole(roleId: string): Promise<void>;
|
|
15
|
+
getPermissions(): Promise<PermissionRecord[]>;
|
|
16
|
+
getPermissionById(permissionId: string): Promise<PermissionRecord | undefined>;
|
|
17
|
+
createPermission(name: string, description?: string): Promise<PermissionRecord[]>;
|
|
18
|
+
deletePermission(permissionId: string): Promise<void>;
|
|
19
|
+
getRolePermissions(roleId: string): Promise<AccessGrant[]>;
|
|
20
|
+
assignPermissionToRole(roleId: string, permissionId: string): Promise<void>;
|
|
21
|
+
revokePermissionFromRole(roleId: string, permissionId: string): Promise<void>;
|
|
22
|
+
assignRoleToUser(userId: string, roleId: string): Promise<void>;
|
|
23
|
+
revokeRoleFromUser(userId: string, roleId: string): Promise<void>;
|
|
24
|
+
assignPermissionToUser(userId: string, permissionId: string): Promise<void>;
|
|
25
|
+
revokePermissionFromUser(userId: string, permissionId: string): Promise<void>;
|
|
26
|
+
getUserRbacData(userId: string): Promise<{
|
|
27
|
+
roles: {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
}[];
|
|
31
|
+
directPermissions: AccessGrant[];
|
|
32
|
+
effectivePermissions: AccessGrant[];
|
|
33
|
+
}>;
|
|
34
|
+
coreRbacAugmenter(user: User): Promise<Record<string, any>>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Inject, Injectable } from "@veap/kernel";
|
|
14
|
+
import { PERMISSION_REPOSITORY, ROLE_REPOSITORY, } from "./contracts.js";
|
|
15
|
+
/**
|
|
16
|
+
* Core RBAC use cases. Persistence lives behind the role/permission
|
|
17
|
+
* repositories, so this service stays framework-free and testable.
|
|
18
|
+
*/
|
|
19
|
+
let RbacService = class RbacService {
|
|
20
|
+
roles;
|
|
21
|
+
permissions;
|
|
22
|
+
constructor(roles, permissions) {
|
|
23
|
+
this.roles = roles;
|
|
24
|
+
this.permissions = permissions;
|
|
25
|
+
}
|
|
26
|
+
async getRoles() {
|
|
27
|
+
return await this.roles.findAll();
|
|
28
|
+
}
|
|
29
|
+
async getRoleById(roleId) {
|
|
30
|
+
return await this.roles.findById(roleId);
|
|
31
|
+
}
|
|
32
|
+
async createRole(name, description) {
|
|
33
|
+
const role = await this.roles.create({ name, description });
|
|
34
|
+
return [role];
|
|
35
|
+
}
|
|
36
|
+
async deleteRole(roleId) {
|
|
37
|
+
await this.roles.remove(roleId);
|
|
38
|
+
}
|
|
39
|
+
async getPermissions() {
|
|
40
|
+
return await this.permissions.findAll();
|
|
41
|
+
}
|
|
42
|
+
async getPermissionById(permissionId) {
|
|
43
|
+
return await this.permissions.findById(permissionId);
|
|
44
|
+
}
|
|
45
|
+
async createPermission(name, description) {
|
|
46
|
+
const permission = await this.permissions.create({ name, description });
|
|
47
|
+
return [permission];
|
|
48
|
+
}
|
|
49
|
+
async deletePermission(permissionId) {
|
|
50
|
+
await this.permissions.remove(permissionId);
|
|
51
|
+
}
|
|
52
|
+
async getRolePermissions(roleId) {
|
|
53
|
+
return await this.roles.getPermissions(roleId);
|
|
54
|
+
}
|
|
55
|
+
async assignPermissionToRole(roleId, permissionId) {
|
|
56
|
+
await this.permissions.assignToRole(roleId, permissionId);
|
|
57
|
+
}
|
|
58
|
+
async revokePermissionFromRole(roleId, permissionId) {
|
|
59
|
+
await this.permissions.revokeFromRole(roleId, permissionId);
|
|
60
|
+
}
|
|
61
|
+
async assignRoleToUser(userId, roleId) {
|
|
62
|
+
await this.roles.assignToUser(userId, roleId);
|
|
63
|
+
}
|
|
64
|
+
async revokeRoleFromUser(userId, roleId) {
|
|
65
|
+
await this.roles.revokeFromUser(userId, roleId);
|
|
66
|
+
}
|
|
67
|
+
async assignPermissionToUser(userId, permissionId) {
|
|
68
|
+
await this.permissions.assignToUser(userId, permissionId);
|
|
69
|
+
}
|
|
70
|
+
async revokePermissionFromUser(userId, permissionId) {
|
|
71
|
+
await this.permissions.revokeFromUser(userId, permissionId);
|
|
72
|
+
}
|
|
73
|
+
async getUserRbacData(userId) {
|
|
74
|
+
const access = await this.roles.loadUserAccess(userId);
|
|
75
|
+
if (!access) {
|
|
76
|
+
return {
|
|
77
|
+
roles: [],
|
|
78
|
+
directPermissions: [],
|
|
79
|
+
effectivePermissions: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const roles = access.roles.map((role) => ({
|
|
83
|
+
id: role.id,
|
|
84
|
+
name: role.name,
|
|
85
|
+
}));
|
|
86
|
+
const directPermissions = access.directPermissions;
|
|
87
|
+
const effective = new Map();
|
|
88
|
+
for (const permission of directPermissions) {
|
|
89
|
+
effective.set(permission.id, permission);
|
|
90
|
+
}
|
|
91
|
+
for (const role of access.roles) {
|
|
92
|
+
for (const permission of role.permissions) {
|
|
93
|
+
effective.set(permission.id, permission);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
roles,
|
|
98
|
+
directPermissions,
|
|
99
|
+
effectivePermissions: Array.from(effective.values()),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async coreRbacAugmenter(user) {
|
|
103
|
+
const userId = user?.id;
|
|
104
|
+
if (!userId) {
|
|
105
|
+
return { roles: [], permissions: [] };
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const access = await this.roles.loadUserAccess(userId);
|
|
109
|
+
if (!access) {
|
|
110
|
+
return { roles: [], permissions: [] };
|
|
111
|
+
}
|
|
112
|
+
const roles = access.roles.map((role) => role.name);
|
|
113
|
+
const permissions = new Set();
|
|
114
|
+
for (const permission of access.directPermissions) {
|
|
115
|
+
if (permission.name) {
|
|
116
|
+
permissions.add(permission.name);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const role of access.roles) {
|
|
120
|
+
for (const permission of role.permissions) {
|
|
121
|
+
if (permission.name) {
|
|
122
|
+
permissions.add(permission.name);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
roles,
|
|
128
|
+
permissions: Array.from(permissions),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.error("[Auth:RBAC] Failed to augment user:", error);
|
|
133
|
+
return { roles: [], permissions: [] };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
RbacService = __decorate([
|
|
138
|
+
Injectable(),
|
|
139
|
+
__param(0, Inject(ROLE_REPOSITORY)),
|
|
140
|
+
__param(1, Inject(PERMISSION_REPOSITORY)),
|
|
141
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
142
|
+
], RbacService);
|
|
143
|
+
export { RbacService };
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ICacheProvider } from "@veap/kernel";
|
|
2
|
+
import type { AuthResponse, SessionFlags } from "../common/index.js";
|
|
3
|
+
import { type IPasswordHasher } from "../crypto/contracts.js";
|
|
4
|
+
import { UserService } from "../users/user.service.js";
|
|
5
|
+
import type { LoginInput, RegisterInput } from "../validation/index.js";
|
|
6
|
+
import { EmailVerificationService } from "../verification/verification.service.js";
|
|
7
|
+
import { SessionService } from "./session.service.js";
|
|
8
|
+
export declare class AuthService {
|
|
9
|
+
private userService;
|
|
10
|
+
private sessionService;
|
|
11
|
+
private emailVerificationService;
|
|
12
|
+
private readonly hasher;
|
|
13
|
+
private readonly cache?;
|
|
14
|
+
private failedAttempts;
|
|
15
|
+
constructor(userService: UserService, sessionService: SessionService, emailVerificationService: EmailVerificationService, hasher: IPasswordHasher, cache?: ICacheProvider | undefined);
|
|
16
|
+
private isRateLimited;
|
|
17
|
+
private recordFailedAttempt;
|
|
18
|
+
private clearFailedAttempts;
|
|
19
|
+
/**
|
|
20
|
+
* Sign In Logic
|
|
21
|
+
*/
|
|
22
|
+
signIn(data: LoginInput): Promise<AuthResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Sign Up Logic
|
|
25
|
+
*/
|
|
26
|
+
signUp(data: RegisterInput): Promise<AuthResponse>;
|
|
27
|
+
/**
|
|
28
|
+
* Finalize Login Logic (used by MFA/Interceptions)
|
|
29
|
+
*/
|
|
30
|
+
finalizeLogin(userId: string, flags?: SessionFlags): Promise<AuthResponse>;
|
|
31
|
+
/**
|
|
32
|
+
* Sign Out Logic
|
|
33
|
+
*/
|
|
34
|
+
signOut(): Promise<void>;
|
|
35
|
+
}
|