@open-core/identity 1.0.0 → 1.2.0
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/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.js +33 -73
- 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.js +12 -15
- 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.js +6 -9
- package/dist/setup.js +25 -28
- package/dist/types/auth.types.js +1 -2
- package/dist/types/index.js +1 -2
- 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,12 +7,10 @@ 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
|
-
|
|
15
|
-
const account_service_1 = require("../account.service");
|
|
16
|
-
const account_repository_1 = require("../../repositories/account.repository");
|
|
10
|
+
import { injectable } from "tsyringe";
|
|
11
|
+
import { Utils } from "@open-core/framework";
|
|
12
|
+
import { AccountService } from "../account.service";
|
|
13
|
+
import { AccountRepository } from "../../repositories/account.repository";
|
|
17
14
|
/**
|
|
18
15
|
* Local principal provider that reads roles and permissions from local database.
|
|
19
16
|
* This is the default/traditional principal provider for FiveM servers.
|
|
@@ -32,11 +29,11 @@ let LocalPrincipalProvider = class LocalPrincipalProvider {
|
|
|
32
29
|
async getPrincipal(player) {
|
|
33
30
|
const linked = player.accountID;
|
|
34
31
|
if (!linked) {
|
|
35
|
-
throw new
|
|
32
|
+
throw new Utils.AppError("UNAUTHORIZED", "Player is not authenticated (no linked account)", "server");
|
|
36
33
|
}
|
|
37
34
|
const result = await this.repo.findByLinkedIdWithRole(String(linked));
|
|
38
35
|
if (!result) {
|
|
39
|
-
throw new
|
|
36
|
+
throw new Utils.AppError("UNAUTHORIZED", "Linked account not found", "server");
|
|
40
37
|
}
|
|
41
38
|
const { account, role } = result;
|
|
42
39
|
if (this.accounts.isBanExpired(account)) {
|
|
@@ -44,7 +41,7 @@ let LocalPrincipalProvider = class LocalPrincipalProvider {
|
|
|
44
41
|
account.banned = false;
|
|
45
42
|
}
|
|
46
43
|
if (account.banned) {
|
|
47
|
-
throw new
|
|
44
|
+
throw new Utils.AppError("PERMISSION_DENIED", "Account is banned", "server", {
|
|
48
45
|
banReason: account.banReason,
|
|
49
46
|
banExpires: account.banExpires,
|
|
50
47
|
});
|
|
@@ -106,9 +103,9 @@ let LocalPrincipalProvider = class LocalPrincipalProvider {
|
|
|
106
103
|
return Array.from(base);
|
|
107
104
|
}
|
|
108
105
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
(
|
|
112
|
-
|
|
113
|
-
account_repository_1.AccountRepository])
|
|
106
|
+
LocalPrincipalProvider = __decorate([
|
|
107
|
+
injectable(),
|
|
108
|
+
__metadata("design:paramtypes", [AccountService,
|
|
109
|
+
AccountRepository])
|
|
114
110
|
], LocalPrincipalProvider);
|
|
111
|
+
export { LocalPrincipalProvider };
|
|
@@ -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,10 +7,8 @@ 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
|
-
const tsyringe_1 = require("tsyringe");
|
|
14
|
-
const role_repository_1 = require("../repositories/role.repository");
|
|
10
|
+
import { injectable } from "tsyringe";
|
|
11
|
+
import { RoleRepository } from "../repositories/role.repository";
|
|
15
12
|
/**
|
|
16
13
|
* Service for managing roles and their permissions.
|
|
17
14
|
* Handles CRUD operations and permission management for roles.
|
|
@@ -138,8 +135,8 @@ let RoleService = class RoleService {
|
|
|
138
135
|
await this.repo.updatePermissions(roleId, filtered);
|
|
139
136
|
}
|
|
140
137
|
};
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
(
|
|
144
|
-
__metadata("design:paramtypes", [role_repository_1.RoleRepository])
|
|
138
|
+
RoleService = __decorate([
|
|
139
|
+
injectable(),
|
|
140
|
+
__metadata("design:paramtypes", [RoleRepository])
|
|
145
141
|
], RoleService);
|
|
142
|
+
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/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/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-core/identity",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.0",
|
|
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
|
-
|