@open-core/identity 1.0.0 → 1.2.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/README.md +54 -658
- package/dist/contracts.d.ts +93 -0
- package/dist/contracts.js +21 -0
- package/dist/entities/account.entity.js +1 -2
- package/dist/entities/role.entity.js +1 -2
- package/dist/events/identity.events.js +1 -2
- package/dist/index.d.ts +86 -67
- package/dist/index.js +110 -99
- package/dist/providers/auth/api-auth.provider.d.ts +52 -0
- package/dist/providers/auth/api-auth.provider.js +82 -0
- package/dist/providers/auth/credentials-auth.provider.d.ts +63 -0
- package/dist/providers/auth/credentials-auth.provider.js +149 -0
- package/dist/providers/auth/local-auth.provider.d.ts +82 -0
- package/dist/providers/auth/local-auth.provider.js +151 -0
- package/dist/providers/identity-auth.provider.d.ts +0 -0
- package/dist/providers/identity-auth.provider.js +1 -0
- package/dist/providers/principal/api-principal.provider.d.ts +50 -0
- package/dist/providers/principal/api-principal.provider.js +84 -0
- package/dist/providers/principal/local-principal.provider.d.ts +77 -0
- package/dist/providers/principal/local-principal.provider.js +164 -0
- package/dist/repositories/account.repository.d.ts +4 -4
- package/dist/repositories/account.repository.js +2 -6
- package/dist/repositories/role.repository.d.ts +4 -4
- package/dist/repositories/role.repository.js +2 -6
- package/dist/services/account.service.d.ts +52 -57
- package/dist/services/account.service.js +80 -166
- package/dist/services/auth/api-auth.provider.js +7 -10
- package/dist/services/auth/credentials-auth.provider.js +8 -44
- package/dist/services/auth/local-auth.provider.js +7 -10
- package/dist/services/cache/memory-cache.service.js +4 -7
- package/dist/services/identity-auth.provider.js +7 -10
- package/dist/services/identity-principal.provider.js +12 -15
- package/dist/services/principal/api-principal.provider.js +9 -12
- package/dist/services/principal/local-principal.provider.js +12 -15
- package/dist/services/role.service.d.ts +33 -54
- package/dist/services/role.service.js +51 -109
- package/dist/setup.js +25 -28
- package/dist/tokens.d.ts +7 -0
- package/dist/tokens.js +7 -0
- package/dist/types/auth.types.js +1 -2
- package/dist/types/index.js +1 -2
- package/dist/types.d.ts +170 -0
- package/dist/types.js +1 -0
- package/package.json +13 -8
- package/migrations/001_accounts_table.sql +0 -16
- package/migrations/002_roles_table.sql +0 -21
- package/migrations/003_alter_accounts_add_role.sql +0 -24
- package/migrations/004_rename_uuid_to_linked_id.sql +0 -12
- package/migrations/005_add_password_hash.sql +0 -7
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
2
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
3
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -8,138 +7,81 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { injectable, inject } from "tsyringe";
|
|
14
|
+
import { IDENTITY_OPTIONS } from "../tokens";
|
|
15
|
+
import { RoleStore } from "../contracts";
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
17
|
+
* High-level service for managing security roles and their associated permissions.
|
|
18
|
+
*
|
|
19
|
+
* Provides a programmer-friendly API for role administration, including creation,
|
|
20
|
+
* updates, and permission retrieval. This service interacts with the configured
|
|
21
|
+
* {@link RoleStore}.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
* @injectable
|
|
18
25
|
*/
|
|
19
26
|
let RoleService = class RoleService {
|
|
20
|
-
constructor(repo) {
|
|
21
|
-
this.repo = repo;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Find a role by its ID.
|
|
25
|
-
*
|
|
26
|
-
* @param id - Role ID
|
|
27
|
-
* @returns The role or null if not found
|
|
28
|
-
*/
|
|
29
|
-
async findById(id) {
|
|
30
|
-
return this.repo.findById(id);
|
|
31
|
-
}
|
|
32
27
|
/**
|
|
33
|
-
*
|
|
28
|
+
* Initializes a new instance of the RoleService.
|
|
34
29
|
*
|
|
35
|
-
* @param
|
|
36
|
-
* @
|
|
30
|
+
* @param store - Persistence layer for role definitions.
|
|
31
|
+
* @param options - Identity system configuration options.
|
|
37
32
|
*/
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
constructor(store, options) {
|
|
34
|
+
this.store = store;
|
|
35
|
+
this.options = options;
|
|
40
36
|
}
|
|
41
37
|
/**
|
|
42
|
-
*
|
|
38
|
+
* Persists a new security role definition.
|
|
43
39
|
*
|
|
44
|
-
* @
|
|
40
|
+
* @param role - The complete role definition to create.
|
|
41
|
+
* @returns A promise that resolves when the role is saved.
|
|
45
42
|
*/
|
|
46
|
-
async
|
|
47
|
-
|
|
48
|
-
return result.data;
|
|
43
|
+
async create(role) {
|
|
44
|
+
await this.store.save(role);
|
|
49
45
|
}
|
|
50
46
|
/**
|
|
51
|
-
*
|
|
47
|
+
* Updates an existing role's rank or permissions.
|
|
52
48
|
*
|
|
53
|
-
* @
|
|
49
|
+
* @param name - The unique technical name of the role to update.
|
|
50
|
+
* @param data - Partial object containing the fields to modify.
|
|
51
|
+
* @returns A promise that resolves when the update is complete.
|
|
54
52
|
*/
|
|
55
|
-
async
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Create a new role.
|
|
60
|
-
*
|
|
61
|
-
* @param input - Role creation data
|
|
62
|
-
* @returns The created role
|
|
63
|
-
*/
|
|
64
|
-
async create(input) {
|
|
65
|
-
const now = new Date();
|
|
66
|
-
const role = {
|
|
67
|
-
id: 0, // Will be set by DB
|
|
68
|
-
name: input.name,
|
|
69
|
-
displayName: input.displayName,
|
|
70
|
-
rank: input.rank,
|
|
71
|
-
permissions: input.permissions ?? [],
|
|
72
|
-
isDefault: input.isDefault ?? false,
|
|
73
|
-
createdAt: now,
|
|
74
|
-
};
|
|
75
|
-
return this.repo.save(role);
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Update an existing role.
|
|
79
|
-
*
|
|
80
|
-
* @param id - Role ID
|
|
81
|
-
* @param input - Update data
|
|
82
|
-
* @returns The updated role or null if not found
|
|
83
|
-
*/
|
|
84
|
-
async update(id, input) {
|
|
85
|
-
const existing = await this.repo.findById(id);
|
|
53
|
+
async update(name, data) {
|
|
54
|
+
const existing = await this.store.findByName(name);
|
|
86
55
|
if (!existing)
|
|
87
|
-
return
|
|
88
|
-
|
|
56
|
+
return;
|
|
57
|
+
await this.store.save({
|
|
89
58
|
...existing,
|
|
90
|
-
...
|
|
91
|
-
|
|
92
|
-
}),
|
|
93
|
-
...(input.rank !== undefined && { rank: input.rank }),
|
|
94
|
-
...(input.permissions !== undefined && {
|
|
95
|
-
permissions: input.permissions,
|
|
96
|
-
}),
|
|
97
|
-
};
|
|
98
|
-
if (input.isDefault !== undefined) {
|
|
99
|
-
await this.repo.setDefault(id, input.isDefault);
|
|
100
|
-
updated.isDefault = input.isDefault;
|
|
101
|
-
}
|
|
102
|
-
return this.repo.save(updated);
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Delete a role.
|
|
106
|
-
*
|
|
107
|
-
* @param id - Role ID
|
|
108
|
-
* @returns true if deleted, false if not found
|
|
109
|
-
*/
|
|
110
|
-
async delete(id) {
|
|
111
|
-
return this.repo.delete(id);
|
|
59
|
+
...data,
|
|
60
|
+
});
|
|
112
61
|
}
|
|
113
62
|
/**
|
|
114
|
-
*
|
|
63
|
+
* Permanently removes a role definition from the system.
|
|
115
64
|
*
|
|
116
|
-
* @param
|
|
117
|
-
* @
|
|
65
|
+
* @param name - The technical name of the role to delete.
|
|
66
|
+
* @returns A promise that resolves when the role is deleted.
|
|
118
67
|
*/
|
|
119
|
-
async
|
|
120
|
-
|
|
121
|
-
if (!role)
|
|
122
|
-
return;
|
|
123
|
-
const permissions = new Set(role.permissions);
|
|
124
|
-
permissions.add(permission);
|
|
125
|
-
await this.repo.updatePermissions(roleId, Array.from(permissions));
|
|
68
|
+
async delete(name) {
|
|
69
|
+
await this.store.delete(name);
|
|
126
70
|
}
|
|
127
71
|
/**
|
|
128
|
-
*
|
|
72
|
+
* Retrieves the full list of permissions granted to a specific role.
|
|
129
73
|
*
|
|
130
|
-
* @param
|
|
131
|
-
* @
|
|
74
|
+
* @param name - The technical name of the role.
|
|
75
|
+
* @returns A promise resolving to an array of permission strings.
|
|
132
76
|
*/
|
|
133
|
-
async
|
|
134
|
-
const role = await this.
|
|
135
|
-
|
|
136
|
-
return;
|
|
137
|
-
const filtered = role.permissions.filter((p) => p !== permission);
|
|
138
|
-
await this.repo.updatePermissions(roleId, filtered);
|
|
77
|
+
async getPermissions(name) {
|
|
78
|
+
const role = await this.store.findByName(name);
|
|
79
|
+
return role?.permissions || [];
|
|
139
80
|
}
|
|
140
81
|
};
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
(
|
|
144
|
-
__metadata("design:paramtypes", [
|
|
82
|
+
RoleService = __decorate([
|
|
83
|
+
injectable(),
|
|
84
|
+
__param(1, inject(IDENTITY_OPTIONS)),
|
|
85
|
+
__metadata("design:paramtypes", [RoleStore, Object])
|
|
145
86
|
], RoleService);
|
|
87
|
+
export { RoleService };
|
package/dist/setup.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const api_principal_provider_1 = require("./services/principal/api-principal.provider");
|
|
14
|
-
const identity_auth_provider_1 = require("./services/identity-auth.provider");
|
|
15
|
-
const identity_principal_provider_1 = require("./services/identity-principal.provider");
|
|
1
|
+
import { AccountRepository } from "./repositories/account.repository";
|
|
2
|
+
import { RoleRepository } from "./repositories/role.repository";
|
|
3
|
+
import { AccountService } from "./services/account.service";
|
|
4
|
+
import { RoleService } from "./services/role.service";
|
|
5
|
+
import { MemoryCacheService } from "./services/cache/memory-cache.service";
|
|
6
|
+
import { LocalAuthProvider } from "./services/auth/local-auth.provider";
|
|
7
|
+
import { CredentialsAuthProvider } from "./services/auth/credentials-auth.provider";
|
|
8
|
+
import { ApiAuthProvider } from "./services/auth/api-auth.provider";
|
|
9
|
+
import { LocalPrincipalProvider } from "./services/principal/local-principal.provider";
|
|
10
|
+
import { ApiPrincipalProvider } from "./services/principal/api-principal.provider";
|
|
11
|
+
import { IdentityAuthProvider } from "./services/identity-auth.provider";
|
|
12
|
+
import { IdentityPrincipalProvider } from "./services/identity-principal.provider";
|
|
16
13
|
/**
|
|
17
14
|
* Register all Identity module singletons with the DI container.
|
|
18
15
|
*
|
|
@@ -45,49 +42,49 @@ const identity_principal_provider_1 = require("./services/identity-principal.pro
|
|
|
45
42
|
* });
|
|
46
43
|
* ```
|
|
47
44
|
*/
|
|
48
|
-
function setupIdentity(container, options = {}) {
|
|
45
|
+
export function setupIdentity(container, options = {}) {
|
|
49
46
|
const { authProvider = "local", principalProvider = "local", useDatabase = authProvider !== "api" && principalProvider !== "api", } = options;
|
|
50
47
|
// Always register cache service (needed for API providers)
|
|
51
|
-
container.registerSingleton(
|
|
48
|
+
container.registerSingleton(MemoryCacheService);
|
|
52
49
|
// Register database-dependent services only if needed
|
|
53
50
|
if (useDatabase) {
|
|
54
|
-
container.registerSingleton(
|
|
55
|
-
container.registerSingleton(
|
|
56
|
-
container.registerSingleton(
|
|
57
|
-
container.registerSingleton(
|
|
51
|
+
container.registerSingleton(AccountRepository);
|
|
52
|
+
container.registerSingleton(RoleRepository);
|
|
53
|
+
container.registerSingleton(AccountService);
|
|
54
|
+
container.registerSingleton(RoleService);
|
|
58
55
|
}
|
|
59
56
|
// Register Auth Provider based on strategy
|
|
60
57
|
switch (authProvider) {
|
|
61
58
|
case "credentials":
|
|
62
|
-
container.registerSingleton("AuthProviderContract",
|
|
59
|
+
container.registerSingleton("AuthProviderContract", CredentialsAuthProvider);
|
|
63
60
|
// Also register as IdentityAuthProvider for backward compatibility
|
|
64
61
|
// Note: CredentialsAuthProvider is not compatible with IdentityAuthProvider interface
|
|
65
62
|
// Users should use the new provider directly
|
|
66
63
|
break;
|
|
67
64
|
case "api":
|
|
68
|
-
container.registerSingleton("AuthProviderContract",
|
|
65
|
+
container.registerSingleton("AuthProviderContract", ApiAuthProvider);
|
|
69
66
|
// Note: ApiAuthProvider is not compatible with IdentityAuthProvider interface
|
|
70
67
|
// Users should use the new provider directly
|
|
71
68
|
break;
|
|
72
69
|
case "local":
|
|
73
70
|
default:
|
|
74
|
-
container.registerSingleton("AuthProviderContract",
|
|
71
|
+
container.registerSingleton("AuthProviderContract", LocalAuthProvider);
|
|
75
72
|
// Register LocalAuthProvider as the legacy IdentityAuthProvider for compatibility
|
|
76
|
-
container.registerSingleton(
|
|
73
|
+
container.registerSingleton(IdentityAuthProvider, LocalAuthProvider);
|
|
77
74
|
break;
|
|
78
75
|
}
|
|
79
76
|
// Register Principal Provider based on strategy
|
|
80
77
|
switch (principalProvider) {
|
|
81
78
|
case "api":
|
|
82
|
-
container.registerSingleton("PrincipalProviderContract",
|
|
79
|
+
container.registerSingleton("PrincipalProviderContract", ApiPrincipalProvider);
|
|
83
80
|
// Note: ApiPrincipalProvider is not compatible with IdentityPrincipalProvider interface
|
|
84
81
|
// Users should use the new provider directly
|
|
85
82
|
break;
|
|
86
83
|
case "local":
|
|
87
84
|
default:
|
|
88
|
-
container.registerSingleton("PrincipalProviderContract",
|
|
85
|
+
container.registerSingleton("PrincipalProviderContract", LocalPrincipalProvider);
|
|
89
86
|
// Register LocalPrincipalProvider as the legacy IdentityPrincipalProvider for compatibility
|
|
90
|
-
container.registerSingleton(
|
|
87
|
+
container.registerSingleton(IdentityPrincipalProvider, LocalPrincipalProvider);
|
|
91
88
|
break;
|
|
92
89
|
}
|
|
93
90
|
}
|
package/dist/tokens.d.ts
ADDED
package/dist/tokens.js
ADDED
package/dist/types/auth.types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/dist/types/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication strategy modes.
|
|
3
|
+
*
|
|
4
|
+
* - `local`: Automatic authentication based on FiveM connection identifiers (e.g., license, discord).
|
|
5
|
+
* Ideal for traditional FiveM servers where account creation should be transparent.
|
|
6
|
+
* - `credentials`: Manual authentication using username and password.
|
|
7
|
+
* Suitable for servers with an integrated registration system.
|
|
8
|
+
* - `api`: Delegation of authentication to an external HTTP API.
|
|
9
|
+
* Useful for servers integrated with a web dashboard or external auth service.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export type AuthMode = "local" | "credentials" | "api";
|
|
14
|
+
/**
|
|
15
|
+
* Authorization and principal resolution modes.
|
|
16
|
+
*
|
|
17
|
+
* - `roles`: Uses a static role hierarchy defined in the application code.
|
|
18
|
+
* Provides the best performance and version control for role definitions.
|
|
19
|
+
* - `db`: Fetches roles and permissions dynamically from a persistent store.
|
|
20
|
+
* - `api`: Fetches principal data from an external HTTP API on demand.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export type PrincipalMode = "roles" | "db" | "api";
|
|
25
|
+
/**
|
|
26
|
+
* Represents a security role within the identity system.
|
|
27
|
+
*
|
|
28
|
+
* Roles define base permissions and a rank hierarchy used by the framework's `@Guard` decorator.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export interface IdentityRole {
|
|
33
|
+
/**
|
|
34
|
+
* Technical identifier for the role (e.g., 'admin', 'moderator', 'user').
|
|
35
|
+
*/
|
|
36
|
+
name: string;
|
|
37
|
+
/**
|
|
38
|
+
* Hierarchical weight.
|
|
39
|
+
*
|
|
40
|
+
* Used for rank-based authorization.
|
|
41
|
+
* Logic: UserRank >= RequiredRank.
|
|
42
|
+
*/
|
|
43
|
+
rank: number;
|
|
44
|
+
/**
|
|
45
|
+
* List of permission strings granted to this role by default.
|
|
46
|
+
*
|
|
47
|
+
* Supports '*' wildcard for full framework access.
|
|
48
|
+
*/
|
|
49
|
+
permissions: string[];
|
|
50
|
+
/**
|
|
51
|
+
* Human-readable label for UI display or chat prefix.
|
|
52
|
+
*/
|
|
53
|
+
displayName?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Global configuration options for the OpenCore Identity System.
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export interface IdentityOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Authentication configuration.
|
|
63
|
+
*/
|
|
64
|
+
auth: {
|
|
65
|
+
/**
|
|
66
|
+
* The strategy to use for authenticating players.
|
|
67
|
+
*/
|
|
68
|
+
mode: AuthMode;
|
|
69
|
+
/**
|
|
70
|
+
* Whether to automatically create a new account when a player connects
|
|
71
|
+
* with valid identifiers that are not yet registered.
|
|
72
|
+
*
|
|
73
|
+
* Only applicable when mode is 'local'.
|
|
74
|
+
* @defaultValue true
|
|
75
|
+
*/
|
|
76
|
+
autoCreate?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* The primary FiveM identifier used to unique-link an account.
|
|
79
|
+
* @defaultValue 'license'
|
|
80
|
+
*/
|
|
81
|
+
primaryIdentifier?: string;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Authorization and permissions configuration.
|
|
85
|
+
*/
|
|
86
|
+
principal: {
|
|
87
|
+
/**
|
|
88
|
+
* The strategy to use for resolving roles and permissions.
|
|
89
|
+
*/
|
|
90
|
+
mode: PrincipalMode;
|
|
91
|
+
/**
|
|
92
|
+
* Static role definitions.
|
|
93
|
+
*
|
|
94
|
+
* Required when mode is 'roles'.
|
|
95
|
+
*/
|
|
96
|
+
roles?: Record<string, IdentityRole>;
|
|
97
|
+
/**
|
|
98
|
+
* The name of the role assigned to newly created accounts.
|
|
99
|
+
* @defaultValue 'user'
|
|
100
|
+
*/
|
|
101
|
+
defaultRole?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Time-to-live in milliseconds for cached principal data.
|
|
104
|
+
*
|
|
105
|
+
* Since principal resolution is a high-frequency operation, caching is
|
|
106
|
+
* critical for performance.
|
|
107
|
+
* @defaultValue 300000 (5 minutes)
|
|
108
|
+
*/
|
|
109
|
+
cacheTtl?: number;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Represents a persistent identity account.
|
|
114
|
+
*
|
|
115
|
+
* This object links a FiveM player to their persistent roles, permissions,
|
|
116
|
+
* and operational status (e.g., bans).
|
|
117
|
+
*
|
|
118
|
+
* @public
|
|
119
|
+
*/
|
|
120
|
+
export interface IdentityAccount {
|
|
121
|
+
/**
|
|
122
|
+
* Internal unique database/store ID.
|
|
123
|
+
*/
|
|
124
|
+
id: string;
|
|
125
|
+
/**
|
|
126
|
+
* External stable ID used by the framework (linkedID).
|
|
127
|
+
*
|
|
128
|
+
* Usually a UUID or an external system ID.
|
|
129
|
+
*/
|
|
130
|
+
linkedId: string;
|
|
131
|
+
/**
|
|
132
|
+
* Primary connection identifier (e.g., 'license:123...').
|
|
133
|
+
*/
|
|
134
|
+
identifier: string;
|
|
135
|
+
/**
|
|
136
|
+
* Current technical role name assigned to this account.
|
|
137
|
+
*/
|
|
138
|
+
roleName: string;
|
|
139
|
+
/**
|
|
140
|
+
* Optional technical username for credentials-based authentication.
|
|
141
|
+
*/
|
|
142
|
+
username?: string | null;
|
|
143
|
+
/**
|
|
144
|
+
* Hashed password for credentials-based authentication.
|
|
145
|
+
*
|
|
146
|
+
* @internal
|
|
147
|
+
*/
|
|
148
|
+
passwordHash?: string | null;
|
|
149
|
+
/**
|
|
150
|
+
* List of specific permission overrides for this account.
|
|
151
|
+
*
|
|
152
|
+
* - `+perm`: Explicitly grant a permission.
|
|
153
|
+
* - `-perm`: Explicitly revoke a permission (even if granted by role).
|
|
154
|
+
*/
|
|
155
|
+
customPermissions: string[];
|
|
156
|
+
/**
|
|
157
|
+
* Whether the account is currently prohibited from connecting.
|
|
158
|
+
*/
|
|
159
|
+
isBanned: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* The reason provided for the current ban.
|
|
162
|
+
*/
|
|
163
|
+
banReason?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Timestamp when the ban expires.
|
|
166
|
+
*
|
|
167
|
+
* If null and isBanned is true, the ban is permanent.
|
|
168
|
+
*/
|
|
169
|
+
banExpiresAt?: Date | null;
|
|
170
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-core/identity",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "Enterprise-grade identity, authentication, and authorization plugin for OpenCore Framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
7
15
|
"scripts": {
|
|
8
16
|
"build": "tsc -p tsconfig.json",
|
|
9
17
|
"clean": "rimraf dist",
|
|
@@ -30,7 +38,7 @@
|
|
|
30
38
|
},
|
|
31
39
|
"packageManager": "pnpm@10.13.1",
|
|
32
40
|
"dependencies": {
|
|
33
|
-
"@open-core/framework": "^
|
|
41
|
+
"@open-core/framework": "^0.2.4",
|
|
34
42
|
"bcrypt": "^6.0.0",
|
|
35
43
|
"reflect-metadata": "^0.2.2",
|
|
36
44
|
"tsyringe": "^4.10.0",
|
|
@@ -39,15 +47,12 @@
|
|
|
39
47
|
},
|
|
40
48
|
"devDependencies": {
|
|
41
49
|
"@types/bcrypt": "^6.0.0",
|
|
42
|
-
"@types/node": "^22.
|
|
43
|
-
"@typescript-eslint/eslint-plugin": "^8.48.1",
|
|
44
|
-
"@typescript-eslint/parser": "^8.48.1",
|
|
50
|
+
"@types/node": "^22.19.1",
|
|
45
51
|
"eslint": "^9.39.1",
|
|
46
52
|
"eslint-config-prettier": "^10.1.8",
|
|
47
|
-
"eslint-plugin-import": "^2.32.0",
|
|
48
53
|
"eslint-plugin-prettier": "^5.5.4",
|
|
49
54
|
"prettier": "3.7.1",
|
|
50
|
-
"rimraf": "^6.
|
|
55
|
+
"rimraf": "^6.1.2",
|
|
51
56
|
"typescript": "^5.9.3"
|
|
52
57
|
},
|
|
53
58
|
"files": [
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
CREATE TABLE IF NOT EXISTS accounts (
|
|
2
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
3
|
-
linked_id VARCHAR(255) UNIQUE NULL,
|
|
4
|
-
external_source VARCHAR(32) NULL,
|
|
5
|
-
license VARCHAR(64) UNIQUE,
|
|
6
|
-
discord VARCHAR(32) UNIQUE,
|
|
7
|
-
steam VARCHAR(32) UNIQUE,
|
|
8
|
-
username VARCHAR(64),
|
|
9
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
10
|
-
last_login_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
11
|
-
banned BOOLEAN DEFAULT FALSE,
|
|
12
|
-
ban_reason TEXT,
|
|
13
|
-
ban_expires TIMESTAMP NULL,
|
|
14
|
-
permissions JSON DEFAULT '[]'
|
|
15
|
-
);
|
|
16
|
-
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
-- Migration 002: Create roles table
|
|
2
|
-
-- This table stores security roles/ranks with hierarchical permissions.
|
|
3
|
-
|
|
4
|
-
CREATE TABLE IF NOT EXISTS roles (
|
|
5
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
6
|
-
name VARCHAR(64) NOT NULL UNIQUE,
|
|
7
|
-
display_name VARCHAR(128) NOT NULL,
|
|
8
|
-
rank INT NOT NULL DEFAULT 0,
|
|
9
|
-
permissions JSON DEFAULT '[]',
|
|
10
|
-
is_default BOOLEAN DEFAULT FALSE,
|
|
11
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
12
|
-
|
|
13
|
-
INDEX idx_name (name),
|
|
14
|
-
INDEX idx_is_default (is_default)
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
-- Insert default role for new accounts
|
|
18
|
-
INSERT INTO roles (name, display_name, rank, permissions, is_default)
|
|
19
|
-
VALUES ('user', 'Player', 0, '[]', TRUE)
|
|
20
|
-
ON DUPLICATE KEY UPDATE name=name;
|
|
21
|
-
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
-- Migration 003: Alter accounts table to use role-based permissions
|
|
2
|
-
-- IMPORTANT: Run this AFTER creating roles and inserting at least a default role.
|
|
3
|
-
|
|
4
|
-
-- Add role_id foreign key column
|
|
5
|
-
ALTER TABLE accounts
|
|
6
|
-
ADD COLUMN role_id INT NULL AFTER username;
|
|
7
|
-
|
|
8
|
-
-- Add custom_permissions column for per-account overrides
|
|
9
|
-
ALTER TABLE accounts
|
|
10
|
-
ADD COLUMN custom_permissions JSON DEFAULT '[]' AFTER role_id;
|
|
11
|
-
|
|
12
|
-
-- Drop old flat permissions column
|
|
13
|
-
ALTER TABLE accounts
|
|
14
|
-
DROP COLUMN IF EXISTS permissions;
|
|
15
|
-
|
|
16
|
-
-- Add foreign key constraint to roles
|
|
17
|
-
ALTER TABLE accounts
|
|
18
|
-
ADD CONSTRAINT fk_accounts_role
|
|
19
|
-
FOREIGN KEY (role_id) REFERENCES roles(id)
|
|
20
|
-
ON DELETE SET NULL;
|
|
21
|
-
|
|
22
|
-
-- Add index for faster role lookups
|
|
23
|
-
CREATE INDEX idx_role_id ON accounts(role_id);
|
|
24
|
-
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
-- Migration to rename uuid column to linked_id and add external_source
|
|
2
|
-
-- This migration is for existing installations that already have the accounts table
|
|
3
|
-
|
|
4
|
-
-- Rename uuid column to linked_id and increase length to support various ID formats
|
|
5
|
-
ALTER TABLE accounts CHANGE COLUMN uuid linked_id VARCHAR(255) UNIQUE NULL;
|
|
6
|
-
|
|
7
|
-
-- Add external_source column to track account origin
|
|
8
|
-
ALTER TABLE accounts ADD COLUMN external_source VARCHAR(32) NULL AFTER linked_id;
|
|
9
|
-
|
|
10
|
-
-- Update existing records to mark them as 'local' source
|
|
11
|
-
UPDATE accounts SET external_source = 'local' WHERE external_source IS NULL;
|
|
12
|
-
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
-- Add password_hash column for credentials-based authentication
|
|
2
|
-
-- This is optional and only needed if using CredentialsAuthProvider
|
|
3
|
-
|
|
4
|
-
ALTER TABLE accounts ADD COLUMN password_hash VARCHAR(255) NULL AFTER username;
|
|
5
|
-
|
|
6
|
-
-- Note: For existing systems, passwords can be set via AccountService.setPassword()
|
|
7
|
-
|