axiodb 9.7.9 → 11.9.12
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 +67 -2
- package/lib/Services/Auth/AuthEvents.service.d.ts +15 -0
- package/lib/Services/Auth/AuthEvents.service.js +17 -0
- package/lib/Services/Auth/AuthEvents.service.js.map +1 -0
- package/lib/Services/Auth/AuthSeeder.service.d.ts +16 -0
- package/lib/Services/Auth/AuthSeeder.service.js +99 -0
- package/lib/Services/Auth/AuthSeeder.service.js.map +1 -0
- package/lib/Services/Auth/AuthService.service.d.ts +53 -0
- package/lib/Services/Auth/AuthService.service.js +221 -0
- package/lib/Services/Auth/AuthService.service.js.map +1 -0
- package/lib/Services/Auth/ConfigDatabase.service.d.ts +22 -0
- package/lib/Services/Auth/ConfigDatabase.service.js +47 -0
- package/lib/Services/Auth/ConfigDatabase.service.js.map +1 -0
- package/lib/Services/Auth/CookieCodec.helper.d.ts +10 -0
- package/lib/Services/Auth/CookieCodec.helper.js +30 -0
- package/lib/Services/Auth/CookieCodec.helper.js.map +1 -0
- package/lib/Services/Auth/LoginRateLimiter.service.d.ts +35 -0
- package/lib/Services/Auth/LoginRateLimiter.service.js +89 -0
- package/lib/Services/Auth/LoginRateLimiter.service.js.map +1 -0
- package/lib/Services/Auth/PasswordHasher.helper.d.ts +9 -0
- package/lib/Services/Auth/PasswordHasher.helper.js +54 -0
- package/lib/Services/Auth/PasswordHasher.helper.js.map +1 -0
- package/lib/Services/Auth/PermissionChecker.helper.d.ts +21 -0
- package/lib/Services/Auth/PermissionChecker.helper.js +41 -0
- package/lib/Services/Auth/PermissionChecker.helper.js.map +1 -0
- package/lib/Services/Auth/SessionStore.service.d.ts +23 -0
- package/lib/Services/Auth/SessionStore.service.js +96 -0
- package/lib/Services/Auth/SessionStore.service.js.map +1 -0
- package/lib/Services/Collection/collection.operation.d.ts +6 -0
- package/lib/Services/Collection/collection.operation.js +10 -0
- package/lib/Services/Collection/collection.operation.js.map +1 -1
- package/lib/Services/Index/Index.service.d.ts +20 -0
- package/lib/Services/Index/Index.service.js +25 -1
- package/lib/Services/Index/Index.service.js.map +1 -1
- package/lib/Services/Indexation.operation.d.ts +4 -0
- package/lib/Services/Indexation.operation.js +20 -6
- package/lib/Services/Indexation.operation.js.map +1 -1
- package/lib/client/AxioDBCloud.client.d.ts +20 -1
- package/lib/client/AxioDBCloud.client.js +54 -3
- package/lib/client/AxioDBCloud.client.js.map +1 -1
- package/lib/client/CollectionProxy.d.ts +4 -0
- package/lib/client/CollectionProxy.js +11 -0
- package/lib/client/CollectionProxy.js.map +1 -1
- package/lib/client/types/client.types.d.ts +8 -0
- package/lib/client/types/client.types.js.map +1 -1
- package/lib/config/Interfaces/Auth/auth.interface.d.ts +70 -0
- package/lib/config/Interfaces/Auth/auth.interface.js +4 -0
- package/lib/config/Interfaces/Auth/auth.interface.js.map +1 -0
- package/lib/config/Interfaces/Operation/Indexation.operation.interface.d.ts +2 -0
- package/lib/config/Keys/Permissions.d.ts +64 -0
- package/lib/config/Keys/Permissions.js +121 -0
- package/lib/config/Keys/Permissions.js.map +1 -0
- package/lib/server/config/keys.d.ts +2 -2
- package/lib/server/config/keys.js +109 -1
- package/lib/server/config/keys.js.map +1 -1
- package/lib/server/config/server.js +6 -0
- package/lib/server/config/server.js.map +1 -1
- package/lib/server/controller/Auth/Auth.controller.d.ts +12 -0
- package/lib/server/controller/Auth/Auth.controller.js +162 -0
- package/lib/server/controller/Auth/Auth.controller.js.map +1 -0
- package/lib/server/controller/Auth/RoleManagement.controller.d.ts +9 -0
- package/lib/server/controller/Auth/RoleManagement.controller.js +89 -0
- package/lib/server/controller/Auth/RoleManagement.controller.js.map +1 -0
- package/lib/server/controller/Auth/UserManagement.controller.d.ts +11 -0
- package/lib/server/controller/Auth/UserManagement.controller.js +122 -0
- package/lib/server/controller/Auth/UserManagement.controller.js.map +1 -0
- package/lib/server/controller/Collections/Collection.controller.js +10 -0
- package/lib/server/controller/Collections/Collection.controller.js.map +1 -1
- package/lib/server/controller/Database/Databse.controller.js +17 -0
- package/lib/server/controller/Database/Databse.controller.js.map +1 -1
- package/lib/server/controller/Index/Index.controller.d.ts +35 -0
- package/lib/server/controller/Index/Index.controller.js +148 -0
- package/lib/server/controller/Index/Index.controller.js.map +1 -0
- package/lib/server/controller/Operation/CRUD.controller.js +31 -0
- package/lib/server/controller/Operation/CRUD.controller.js.map +1 -1
- package/lib/server/helper/responseBuilder.helper.d.ts +8 -0
- package/lib/server/helper/responseBuilder.helper.js +11 -1
- package/lib/server/helper/responseBuilder.helper.js.map +1 -1
- package/lib/server/middleware/auth.middleware.d.ts +14 -0
- package/lib/server/middleware/auth.middleware.js +64 -0
- package/lib/server/middleware/auth.middleware.js.map +1 -0
- package/lib/server/middleware/permission.middleware.d.ts +6 -0
- package/lib/server/middleware/permission.middleware.js +36 -0
- package/lib/server/middleware/permission.middleware.js.map +1 -0
- package/lib/server/public/AxioControl/.vite/manifest.json +2 -2
- package/lib/server/public/AxioControl/.vite/ssr-manifest.json +10 -0
- package/lib/server/public/AxioControl/assets/index-D3V1EZ2f.css +1 -0
- package/lib/server/public/AxioControl/assets/index-DyJg6FRw.js +75 -0
- package/lib/server/public/AxioControl/index.html +2 -2
- package/lib/server/public/AxioControl/sw.js +1 -1
- package/lib/server/router/Router.js +18 -1
- package/lib/server/router/Router.js.map +1 -1
- package/lib/server/router/Routers/Auth.routes.d.ts +2 -0
- package/lib/server/router/Routers/Auth.routes.js +27 -0
- package/lib/server/router/Routers/Auth.routes.js.map +1 -0
- package/lib/server/router/Routers/Collection.routes.js +20 -3
- package/lib/server/router/Routers/Collection.routes.js.map +1 -1
- package/lib/server/router/Routers/DB.routes.js +8 -5
- package/lib/server/router/Routers/DB.routes.js.map +1 -1
- package/lib/server/router/Routers/Index.routes.d.ts +7 -0
- package/lib/server/router/Routers/Index.routes.js +38 -0
- package/lib/server/router/Routers/Index.routes.js.map +1 -0
- package/lib/server/router/Routers/Operation.routes.js +31 -10
- package/lib/server/router/Routers/Operation.routes.js.map +1 -1
- package/lib/server/router/Routers/RoleManagement.routes.d.ts +2 -0
- package/lib/server/router/Routers/RoleManagement.routes.js +28 -0
- package/lib/server/router/Routers/RoleManagement.routes.js.map +1 -0
- package/lib/server/router/Routers/UserManagement.routes.d.ts +2 -0
- package/lib/server/router/Routers/UserManagement.routes.js +38 -0
- package/lib/server/router/Routers/UserManagement.routes.js.map +1 -0
- package/lib/tcp/config/keys.d.ts +8 -0
- package/lib/tcp/config/keys.js +8 -0
- package/lib/tcp/config/keys.js.map +1 -1
- package/lib/tcp/config/permissions.d.ts +16 -0
- package/lib/tcp/config/permissions.js +46 -0
- package/lib/tcp/config/permissions.js.map +1 -0
- package/lib/tcp/config/protocol.js +13 -0
- package/lib/tcp/config/protocol.js.map +1 -1
- package/lib/tcp/config/server.d.ts +1 -1
- package/lib/tcp/config/server.js +28 -6
- package/lib/tcp/config/server.js.map +1 -1
- package/lib/tcp/connection/ConnectionManager.d.ts +19 -0
- package/lib/tcp/connection/ConnectionManager.js +31 -0
- package/lib/tcp/connection/ConnectionManager.js.map +1 -1
- package/lib/tcp/connection/RequestContext.d.ts +4 -1
- package/lib/tcp/connection/RequestContext.js +4 -1
- package/lib/tcp/connection/RequestContext.js.map +1 -1
- package/lib/tcp/handler/CommandHandler.d.ts +5 -1
- package/lib/tcp/handler/CommandHandler.js +34 -4
- package/lib/tcp/handler/CommandHandler.js.map +1 -1
- package/lib/tcp/handler/handlers/Auth.handler.d.ts +16 -0
- package/lib/tcp/handler/handlers/Auth.handler.js +91 -0
- package/lib/tcp/handler/handlers/Auth.handler.js.map +1 -0
- package/lib/tcp/handler/handlers/Operation.handler.d.ts +4 -0
- package/lib/tcp/handler/handlers/Operation.handler.js +27 -0
- package/lib/tcp/handler/handlers/Operation.handler.js.map +1 -1
- package/lib/tcp/types/command.types.d.ts +2 -0
- package/lib/tcp/types/command.types.js +5 -0
- package/lib/tcp/types/command.types.js.map +1 -1
- package/lib/tcp/types/protocol.types.d.ts +2 -0
- package/lib/tcp/types/protocol.types.js.map +1 -1
- package/package.json +2 -1
- package/lib/server/public/AxioControl/assets/index-BRkVgnlw.js +0 -75
- package/lib/server/public/AxioControl/assets/index-C8TNGVxT.css +0 -1
package/README.md
CHANGED
|
@@ -63,6 +63,7 @@ SQLite is great, but it requires native bindings that break in Electron and cros
|
|
|
63
63
|
- **Transaction Support:** ACID-compliant transactions with savepoints, rollback, and Write-Ahead Logging (WAL)
|
|
64
64
|
- **Single Instance Architecture:** Unified management for unlimited databases, collections, and documents
|
|
65
65
|
- **Web-Based GUI Dashboard:** Visual database administration, query execution, and real-time monitoring at `localhost:27018`
|
|
66
|
+
- **Role-Based Access Control:** Built-in login for the Control Server with Super Admin/Admin/View roles and per-permission enforcement
|
|
66
67
|
- **AxioDBCloud Remote Access:** TCP-based client for connecting to AxioDB from anywhere—Docker, Cloud, or local network
|
|
67
68
|
- **Zero-Configuration Setup:** Serverless architecture—install and start building instantly
|
|
68
69
|
- **Custom Database Path:** Flexible storage locations for better project organization
|
|
@@ -161,9 +162,47 @@ const results = await users.query({ role: "admin" })
|
|
|
161
162
|
await client.disconnect();
|
|
162
163
|
```
|
|
163
164
|
|
|
165
|
+
### 🔐 TCP Authentication (NEW!)
|
|
166
|
+
|
|
167
|
+
TCP connections are unauthenticated by default (same as before). Opt in with `TCPAuth: true` to require a username/password on every connection, reusing the **exact same accounts and roles** as the GUI's RBAC system (see [Authentication & Access Control](#authentication--access-control-v98)) — one set of credentials for both.
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
// Server
|
|
171
|
+
const db = new AxioDB({ TCP: true, TCPAuth: true, RootName: 'MyDB', CustomPath: '.' });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
// Client - pass credentials in the constructor options; connect() authenticates automatically
|
|
176
|
+
const client = new AxioDBCloud("axiodb://localhost:27019", {
|
|
177
|
+
username: 'admin',
|
|
178
|
+
password: 'admin',
|
|
179
|
+
});
|
|
180
|
+
await client.connect();
|
|
181
|
+
|
|
182
|
+
console.log(client.authenticatedUser); // { username, role, mustChangePassword }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Or authenticate after connecting, e.g. if credentials are supplied at runtime:
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
const client = new AxioDBCloud("axiodb://localhost:27019");
|
|
189
|
+
await client.connect();
|
|
190
|
+
await client.login('admin', 'admin');
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**What's enforced:**
|
|
194
|
+
- Every command except `PING`/`DISCONNECT`/`AUTHENTICATE` requires a prior successful login on that connection.
|
|
195
|
+
- The same role permissions as the GUI apply per command (e.g. a `View`-role user gets `403` on `CREATE_DB`).
|
|
196
|
+
- The same per-IP login rate limiter as the GUI: 5 failed attempts within 15 minutes locks that IP out for 15 minutes (`429 Too Many Requests`), shared across both TCP and GUI login attempts from that IP.
|
|
197
|
+
- **Accounts that still need their forced password change are rejected outright** (`403`), not allowed through with a warning — there's no TCP command to change a password today, so log into the GUI (`http://localhost:27018`) to complete it first, or authenticate with an account that already has.
|
|
198
|
+
- If a Super Admin resets a user's password, changes their role, or deletes them via the GUI while that user has an open TCP connection, the TCP connection is immediately forced to re-authenticate on its next command.
|
|
199
|
+
|
|
200
|
+
**Known limitations:** the TCP protocol itself is unencrypted (no TLS) — deploy behind a private network, VPN, or your own TLS termination if connecting over an untrusted network. There's currently no TCP command to change a password; that must go through the GUI.
|
|
201
|
+
|
|
164
202
|
### Features
|
|
165
203
|
|
|
166
204
|
✅ **35+ Commands** - Full CRUD, aggregation, indexing
|
|
205
|
+
✅ **Optional Authentication (NEW!)** - Shared RBAC with the GUI, per-IP rate limiting, forced-password-change enforcement
|
|
167
206
|
✅ **Auto-Reconnect** - Exponential backoff with up to 10 retry attempts
|
|
168
207
|
✅ **Heartbeat Monitoring** - PING/PONG every 30 seconds
|
|
169
208
|
✅ **Request Correlation** - UUID-based request/response matching
|
|
@@ -254,6 +293,31 @@ const db = new AxioDB({ GUI: true, RootName: "MyDB", CustomPath: "./custom/path"
|
|
|
254
293
|
|
|
255
294
|
Access the GUI at `http://localhost:27018` when enabled.
|
|
256
295
|
|
|
296
|
+
### Authentication & Access Control (v9.8+)
|
|
297
|
+
|
|
298
|
+
The Control Server ships with built-in login and role-based access control (RBAC). On first start with `GUI: true`, AxioDB seeds a reserved `config` database (hidden from the regular database list) containing three collections—`users`, `roles`, `permissions`—and a default account:
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
Username: admin
|
|
302
|
+
Password: admin
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
You'll be forced to change this password on first login (this applies to every account, not just the default one). Three predefined roles are seeded automatically:
|
|
306
|
+
|
|
307
|
+
| Role | Access |
|
|
308
|
+
|------|--------|
|
|
309
|
+
| **Super Admin** | Full access, including creating users/roles |
|
|
310
|
+
| **Admin** | Full database/collection/document access, no user or role management |
|
|
311
|
+
| **View** | Read-only access to databases, collections, and documents |
|
|
312
|
+
|
|
313
|
+
A Super Admin can create additional roles from the predefined permission catalogue and create new users with any role. Sessions are held only in server memory (never persisted to disk) and are tied to an httpOnly cookie, so restarting the server logs everyone out.
|
|
314
|
+
|
|
315
|
+
**Login rate limiting (NEW!):** after 5 failed login attempts from the same IP within 15 minutes, that IP is locked out for 15 minutes (`429 Too Many Requests`) — regardless of username. This limiter is shared with [TCP AUTHENTICATE attempts](#tcp-authentication-new), so brute-forcing either surface counts against the same per-IP cooldown.
|
|
316
|
+
|
|
317
|
+
**Index management:** the Control Server also exposes `GET /api/index/list`, `POST /api/index/create`, and `DELETE /api/index/delete`, gated by the same `index:view` / `index:create` / `index:delete` permissions (View role gets view-only, Admin and Super Admin get all three).
|
|
318
|
+
|
|
319
|
+
> **Security note:** RBAC protects the Control Server's HTTP API; it is still intended for trusted local/network access, not public internet exposure.
|
|
320
|
+
|
|
257
321
|
---
|
|
258
322
|
|
|
259
323
|
## ⚙️ Architecture & Internal Mechanisms
|
|
@@ -407,8 +471,9 @@ console.log(results);
|
|
|
407
471
|
- `delete(query: object): Deleter`
|
|
408
472
|
- `aggregate(pipeline: object[]): Aggregation`
|
|
409
473
|
- `startSession(options?: SessionOptions): Session`
|
|
410
|
-
- `
|
|
474
|
+
- `newIndex(...fieldNames: string[]): Promise<SuccessInterface>`
|
|
411
475
|
- `dropIndex(indexName: string): Promise<SuccessInterface | ErrorInterface>`
|
|
476
|
+
- `getIndexes(): Promise<SuccessInterface | ErrorInterface>` — lists all indexes registered on the collection (**NEW!**)
|
|
412
477
|
|
|
413
478
|
### Reader
|
|
414
479
|
|
|
@@ -523,7 +588,7 @@ Yes. Full type definitions are included — no separate `@types` package needed.
|
|
|
523
588
|
No. AxioDB requires Node.js (v20+) and the filesystem. Server-side and desktop only.
|
|
524
589
|
|
|
525
590
|
**Q: What is AxioDBCloud?**
|
|
526
|
-
TCP-based remote access for AxioDB. Deploy AxioDB in Docker, connect from multiple clients with the exact same API. Supports 1,000+ concurrent connections with auto-reconnect.
|
|
591
|
+
TCP-based remote access for AxioDB. Deploy AxioDB in Docker, connect from multiple clients with the exact same API. Supports 1,000+ concurrent connections with auto-reconnect. Optional username/password authentication (`TCPAuth: true`) reuses the same RBAC accounts as the GUI.
|
|
527
592
|
|
|
528
593
|
---
|
|
529
594
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
/**
|
|
3
|
+
* Process-wide event bus for auth state changes that need to propagate beyond the
|
|
4
|
+
* HTTP SessionStore - namely, TCP connections holding a cached `AuthenticatedUser`
|
|
5
|
+
* (see ConnectionManager) for a user whose role, password, or account was just
|
|
6
|
+
* changed via AuthService.
|
|
7
|
+
*
|
|
8
|
+
* Services/Auth owns this abstraction; tcp/ subscribes to it (see tcp/config/server.ts).
|
|
9
|
+
* Dependency direction stays tcp -> Services/Auth, same as everywhere else in the
|
|
10
|
+
* codebase - Services/Auth never imports from tcp/, avoiding a layering violation.
|
|
11
|
+
*/
|
|
12
|
+
declare class AuthEvents extends EventEmitter {
|
|
13
|
+
}
|
|
14
|
+
declare const _default: AuthEvents;
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const events_1 = require("events");
|
|
4
|
+
/**
|
|
5
|
+
* Process-wide event bus for auth state changes that need to propagate beyond the
|
|
6
|
+
* HTTP SessionStore - namely, TCP connections holding a cached `AuthenticatedUser`
|
|
7
|
+
* (see ConnectionManager) for a user whose role, password, or account was just
|
|
8
|
+
* changed via AuthService.
|
|
9
|
+
*
|
|
10
|
+
* Services/Auth owns this abstraction; tcp/ subscribes to it (see tcp/config/server.ts).
|
|
11
|
+
* Dependency direction stays tcp -> Services/Auth, same as everywhere else in the
|
|
12
|
+
* codebase - Services/Auth never imports from tcp/, avoiding a layering violation.
|
|
13
|
+
*/
|
|
14
|
+
class AuthEvents extends events_1.EventEmitter {
|
|
15
|
+
}
|
|
16
|
+
exports.default = new AuthEvents();
|
|
17
|
+
//# sourceMappingURL=AuthEvents.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthEvents.service.js","sourceRoot":"","sources":["../../../source/Services/Auth/AuthEvents.service.ts"],"names":[],"mappings":";;AAAA,mCAAsC;AAEtC;;;;;;;;;GASG;AACH,MAAM,UAAW,SAAQ,qBAAY;CAAG;kBAEzB,IAAI,UAAU,EAAE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AxioDB } from "../Indexation.operation";
|
|
2
|
+
/**
|
|
3
|
+
* Idempotently creates the `config` database and its `users`/`roles`/`permissions`
|
|
4
|
+
* collections on first control-server start, then hydrates PermissionChecker's
|
|
5
|
+
* in-memory role->permissions cache on every boot (including subsequent restarts,
|
|
6
|
+
* where seeding itself is a no-op but the cache still needs rebuilding).
|
|
7
|
+
*/
|
|
8
|
+
export default class AuthSeeder {
|
|
9
|
+
private readonly axioDBInstance;
|
|
10
|
+
constructor(axioDBInstance: AxioDB);
|
|
11
|
+
seedIfNeeded(): Promise<void>;
|
|
12
|
+
private seedPermissions;
|
|
13
|
+
private seedRoles;
|
|
14
|
+
private seedDefaultAdmin;
|
|
15
|
+
private hydratePermissionCache;
|
|
16
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const PasswordHasher_helper_1 = __importDefault(require("./PasswordHasher.helper"));
|
|
16
|
+
const ConfigDatabase_service_1 = __importDefault(require("./ConfigDatabase.service"));
|
|
17
|
+
const PermissionChecker_helper_1 = __importDefault(require("./PermissionChecker.helper"));
|
|
18
|
+
const Permissions_1 = require("../../config/Keys/Permissions");
|
|
19
|
+
/**
|
|
20
|
+
* Idempotently creates the `config` database and its `users`/`roles`/`permissions`
|
|
21
|
+
* collections on first control-server start, then hydrates PermissionChecker's
|
|
22
|
+
* in-memory role->permissions cache on every boot (including subsequent restarts,
|
|
23
|
+
* where seeding itself is a no-op but the cache still needs rebuilding).
|
|
24
|
+
*/
|
|
25
|
+
class AuthSeeder {
|
|
26
|
+
constructor(axioDBInstance) {
|
|
27
|
+
this.axioDBInstance = axioDBInstance;
|
|
28
|
+
}
|
|
29
|
+
seedIfNeeded() {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
var _a;
|
|
32
|
+
const configDB = yield this.axioDBInstance.createDB(Permissions_1.RESERVED_DB_NAME);
|
|
33
|
+
const usersCollection = yield configDB.createCollection(Permissions_1.CONFIG_USERS_COLLECTION);
|
|
34
|
+
const rolesCollection = yield configDB.createCollection(Permissions_1.CONFIG_ROLES_COLLECTION);
|
|
35
|
+
const permissionsCollection = yield configDB.createCollection(Permissions_1.CONFIG_PERMISSIONS_COLLECTION);
|
|
36
|
+
ConfigDatabase_service_1.default.setCollections(usersCollection, rolesCollection, permissionsCollection);
|
|
37
|
+
// totalDocuments() counts the collection's "indexes" subfolder as an entry, so it
|
|
38
|
+
// reports a non-zero count even when no real document has been inserted yet - use
|
|
39
|
+
// an actual document query (filtered to real .axiodb files) to detect prior seeding.
|
|
40
|
+
const existingUsers = yield usersCollection.query({}).Limit(1).exec();
|
|
41
|
+
const alreadySeeded = "data" in existingUsers &&
|
|
42
|
+
Array.isArray((_a = existingUsers.data) === null || _a === void 0 ? void 0 : _a.documents) &&
|
|
43
|
+
existingUsers.data.documents.length > 0;
|
|
44
|
+
if (!alreadySeeded) {
|
|
45
|
+
yield this.seedPermissions(permissionsCollection);
|
|
46
|
+
yield this.seedRoles(rolesCollection);
|
|
47
|
+
yield this.seedDefaultAdmin(usersCollection);
|
|
48
|
+
}
|
|
49
|
+
yield this.hydratePermissionCache(rolesCollection);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
seedPermissions(permissionsCollection) {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
const documents = Permissions_1.PERMISSION_CATALOGUE.map((entry) => ({
|
|
55
|
+
key: entry.key,
|
|
56
|
+
group: entry.group,
|
|
57
|
+
description: entry.description,
|
|
58
|
+
}));
|
|
59
|
+
yield permissionsCollection.insertMany(documents);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
seedRoles(rolesCollection) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const now = new Date().toISOString();
|
|
65
|
+
const documents = Permissions_1.PREDEFINED_ROLES.map((role) => ({
|
|
66
|
+
roleName: role.roleName,
|
|
67
|
+
permissions: role.permissions,
|
|
68
|
+
isSystemRole: true,
|
|
69
|
+
createdAt: now,
|
|
70
|
+
}));
|
|
71
|
+
yield rolesCollection.insertMany(documents);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
seedDefaultAdmin(usersCollection) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
const passwordHash = yield PasswordHasher_helper_1.default.hashPassword(Permissions_1.DEFAULT_ADMIN_PASSWORD);
|
|
77
|
+
const document = {
|
|
78
|
+
username: Permissions_1.DEFAULT_ADMIN_USERNAME,
|
|
79
|
+
passwordHash,
|
|
80
|
+
role: Permissions_1.SUPER_ADMIN_ROLE,
|
|
81
|
+
mustChangePassword: true,
|
|
82
|
+
isActive: true,
|
|
83
|
+
createdAt: new Date().toISOString(),
|
|
84
|
+
};
|
|
85
|
+
yield usersCollection.insert(document);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
hydratePermissionCache(rolesCollection) {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
const result = yield rolesCollection.query({}).Limit(1000).exec();
|
|
91
|
+
if ("data" in result && result.data && Array.isArray(result.data.documents)) {
|
|
92
|
+
const roles = result.data.documents;
|
|
93
|
+
PermissionChecker_helper_1.default.hydrate(roles.map((role) => ({ roleName: role.roleName, permissions: role.permissions })));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.default = AuthSeeder;
|
|
99
|
+
//# sourceMappingURL=AuthSeeder.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthSeeder.service.js","sourceRoot":"","sources":["../../../source/Services/Auth/AuthSeeder.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { UserDocument, RoleDocument } from "../../config/Interfaces/Auth/auth.interface";
|
|
2
|
+
export interface AuthResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
message: string;
|
|
5
|
+
user?: UserDocument;
|
|
6
|
+
}
|
|
7
|
+
export interface MutationResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
message: string;
|
|
10
|
+
/** True when the failure means "this already exists" (HTTP 409) rather than a validation failure (HTTP 400). */
|
|
11
|
+
conflict?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface SafeUser {
|
|
14
|
+
username: string;
|
|
15
|
+
role: string;
|
|
16
|
+
mustChangePassword: boolean;
|
|
17
|
+
isActive: boolean;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Business logic for login, password management, and user/role administration.
|
|
22
|
+
* Backed entirely by AxioDB's own Collection API against the `config` database
|
|
23
|
+
* (see ConfigDatabase.service.ts) - no separate storage mechanism.
|
|
24
|
+
*/
|
|
25
|
+
export default class AuthService {
|
|
26
|
+
login(username: string, password: string): Promise<AuthResult>;
|
|
27
|
+
findUserByUsername(username: string): Promise<UserDocument | null>;
|
|
28
|
+
listUsers(): Promise<SafeUser[]>;
|
|
29
|
+
createUser(username: string, password: string, role: string): Promise<MutationResult>;
|
|
30
|
+
changeOwnPassword(username: string, currentPassword: string, newPassword: string): Promise<{
|
|
31
|
+
success: boolean;
|
|
32
|
+
message: string;
|
|
33
|
+
}>;
|
|
34
|
+
resetUserPassword(username: string, newPassword: string): Promise<{
|
|
35
|
+
success: boolean;
|
|
36
|
+
message: string;
|
|
37
|
+
}>;
|
|
38
|
+
updateUserRole(username: string, newRole: string): Promise<{
|
|
39
|
+
success: boolean;
|
|
40
|
+
message: string;
|
|
41
|
+
}>;
|
|
42
|
+
deleteUser(username: string): Promise<{
|
|
43
|
+
success: boolean;
|
|
44
|
+
message: string;
|
|
45
|
+
}>;
|
|
46
|
+
createRole(roleName: string, permissions: string[]): Promise<MutationResult>;
|
|
47
|
+
listRoles(): Promise<RoleDocument[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Rejects an operation that would leave zero active Super Admin users behind,
|
|
50
|
+
* preventing a permanent RBAC lockout.
|
|
51
|
+
*/
|
|
52
|
+
private assertNotLastSuperAdmin;
|
|
53
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const PasswordHasher_helper_1 = __importDefault(require("./PasswordHasher.helper"));
|
|
16
|
+
const ConfigDatabase_service_1 = __importDefault(require("./ConfigDatabase.service"));
|
|
17
|
+
const PermissionChecker_helper_1 = __importDefault(require("./PermissionChecker.helper"));
|
|
18
|
+
const SessionStore_service_1 = __importDefault(require("./SessionStore.service"));
|
|
19
|
+
const AuthEvents_service_1 = __importDefault(require("./AuthEvents.service"));
|
|
20
|
+
const Permissions_1 = require("../../config/Keys/Permissions");
|
|
21
|
+
/**
|
|
22
|
+
* Business logic for login, password management, and user/role administration.
|
|
23
|
+
* Backed entirely by AxioDB's own Collection API against the `config` database
|
|
24
|
+
* (see ConfigDatabase.service.ts) - no separate storage mechanism.
|
|
25
|
+
*/
|
|
26
|
+
class AuthService {
|
|
27
|
+
login(username, password) {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
const user = yield this.findUserByUsername(username);
|
|
30
|
+
if (!user || user.isActive === false) {
|
|
31
|
+
return { success: false, message: "Invalid username or password" };
|
|
32
|
+
}
|
|
33
|
+
const passwordMatches = yield PasswordHasher_helper_1.default.verifyPassword(password, user.passwordHash);
|
|
34
|
+
if (!passwordMatches) {
|
|
35
|
+
return { success: false, message: "Invalid username or password" };
|
|
36
|
+
}
|
|
37
|
+
return { success: true, message: "Login successful", user };
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
findUserByUsername(username) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
const result = yield ConfigDatabase_service_1.default.getUsersCollection()
|
|
43
|
+
.query({ username })
|
|
44
|
+
.findOne(true)
|
|
45
|
+
.exec();
|
|
46
|
+
if ("data" in result && result.data && result.data.documents) {
|
|
47
|
+
return result.data.documents;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
listUsers() {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
var _a;
|
|
55
|
+
const result = yield ConfigDatabase_service_1.default.getUsersCollection().query({}).Limit(1000).exec();
|
|
56
|
+
if (!("data" in result) || !((_a = result.data) === null || _a === void 0 ? void 0 : _a.documents)) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
const users = result.data.documents;
|
|
60
|
+
return users.map((user) => ({
|
|
61
|
+
username: user.username,
|
|
62
|
+
role: user.role,
|
|
63
|
+
mustChangePassword: user.mustChangePassword,
|
|
64
|
+
isActive: user.isActive,
|
|
65
|
+
createdAt: user.createdAt,
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
createUser(username, password, role) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
if (!PermissionChecker_helper_1.default.roleExists(role)) {
|
|
72
|
+
return { success: false, message: `Role "${role}" does not exist` };
|
|
73
|
+
}
|
|
74
|
+
const existingUser = yield this.findUserByUsername(username);
|
|
75
|
+
if (existingUser) {
|
|
76
|
+
return { success: false, message: "Username already exists", conflict: true };
|
|
77
|
+
}
|
|
78
|
+
const passwordHash = yield PasswordHasher_helper_1.default.hashPassword(password);
|
|
79
|
+
const document = {
|
|
80
|
+
username,
|
|
81
|
+
passwordHash,
|
|
82
|
+
role,
|
|
83
|
+
mustChangePassword: true,
|
|
84
|
+
isActive: true,
|
|
85
|
+
createdAt: new Date().toISOString(),
|
|
86
|
+
};
|
|
87
|
+
yield ConfigDatabase_service_1.default.getUsersCollection().insert(document);
|
|
88
|
+
return { success: true, message: "User created successfully" };
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
changeOwnPassword(username, currentPassword, newPassword) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const user = yield this.findUserByUsername(username);
|
|
94
|
+
if (!user) {
|
|
95
|
+
return { success: false, message: "User not found" };
|
|
96
|
+
}
|
|
97
|
+
const currentPasswordMatches = yield PasswordHasher_helper_1.default.verifyPassword(currentPassword, user.passwordHash);
|
|
98
|
+
if (!currentPasswordMatches) {
|
|
99
|
+
return { success: false, message: "Current password is incorrect" };
|
|
100
|
+
}
|
|
101
|
+
const passwordHash = yield PasswordHasher_helper_1.default.hashPassword(newPassword);
|
|
102
|
+
yield ConfigDatabase_service_1.default.getUsersCollection()
|
|
103
|
+
.update({ username })
|
|
104
|
+
.UpdateOne({ passwordHash, mustChangePassword: false });
|
|
105
|
+
return { success: true, message: "Password changed successfully" };
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
resetUserPassword(username, newPassword) {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
const user = yield this.findUserByUsername(username);
|
|
111
|
+
if (!user) {
|
|
112
|
+
return { success: false, message: "User not found" };
|
|
113
|
+
}
|
|
114
|
+
const passwordHash = yield PasswordHasher_helper_1.default.hashPassword(newPassword);
|
|
115
|
+
yield ConfigDatabase_service_1.default.getUsersCollection()
|
|
116
|
+
.update({ username })
|
|
117
|
+
.UpdateOne({ passwordHash, mustChangePassword: true });
|
|
118
|
+
SessionStore_service_1.default.revokeSessionsForUser(username);
|
|
119
|
+
AuthEvents_service_1.default.emit("user-revoked", username);
|
|
120
|
+
return { success: true, message: "Password reset successfully" };
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
updateUserRole(username, newRole) {
|
|
124
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
125
|
+
if (!PermissionChecker_helper_1.default.roleExists(newRole)) {
|
|
126
|
+
return { success: false, message: `Role "${newRole}" does not exist` };
|
|
127
|
+
}
|
|
128
|
+
const user = yield this.findUserByUsername(username);
|
|
129
|
+
if (!user) {
|
|
130
|
+
return { success: false, message: "User not found" };
|
|
131
|
+
}
|
|
132
|
+
if (user.role === Permissions_1.SUPER_ADMIN_ROLE && newRole !== Permissions_1.SUPER_ADMIN_ROLE) {
|
|
133
|
+
const lastAdminGuard = yield this.assertNotLastSuperAdmin(username);
|
|
134
|
+
if (!lastAdminGuard.success) {
|
|
135
|
+
return lastAdminGuard;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
yield ConfigDatabase_service_1.default.getUsersCollection()
|
|
139
|
+
.update({ username })
|
|
140
|
+
.UpdateOne({ role: newRole });
|
|
141
|
+
SessionStore_service_1.default.revokeSessionsForUser(username);
|
|
142
|
+
AuthEvents_service_1.default.emit("user-revoked", username);
|
|
143
|
+
return { success: true, message: "Role updated successfully" };
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
deleteUser(username) {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
+
const user = yield this.findUserByUsername(username);
|
|
149
|
+
if (!user) {
|
|
150
|
+
return { success: false, message: "User not found" };
|
|
151
|
+
}
|
|
152
|
+
if (user.role === Permissions_1.SUPER_ADMIN_ROLE) {
|
|
153
|
+
const lastAdminGuard = yield this.assertNotLastSuperAdmin(username);
|
|
154
|
+
if (!lastAdminGuard.success) {
|
|
155
|
+
return lastAdminGuard;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
yield ConfigDatabase_service_1.default.getUsersCollection().delete({ username }).deleteOne();
|
|
159
|
+
SessionStore_service_1.default.revokeSessionsForUser(username);
|
|
160
|
+
AuthEvents_service_1.default.emit("user-revoked", username);
|
|
161
|
+
return { success: true, message: "User deleted successfully" };
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
createRole(roleName, permissions) {
|
|
165
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
+
if (PermissionChecker_helper_1.default.roleExists(roleName)) {
|
|
167
|
+
return { success: false, message: "Role already exists", conflict: true };
|
|
168
|
+
}
|
|
169
|
+
const invalidPermissions = permissions.filter((key) => !Permissions_1.ALL_PERMISSION_KEYS.includes(key));
|
|
170
|
+
if (invalidPermissions.length > 0) {
|
|
171
|
+
return {
|
|
172
|
+
success: false,
|
|
173
|
+
message: `Unknown permission key(s): ${invalidPermissions.join(", ")}`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const document = {
|
|
177
|
+
roleName,
|
|
178
|
+
permissions,
|
|
179
|
+
isSystemRole: false,
|
|
180
|
+
createdAt: new Date().toISOString(),
|
|
181
|
+
};
|
|
182
|
+
yield ConfigDatabase_service_1.default.getRolesCollection().insert(document);
|
|
183
|
+
PermissionChecker_helper_1.default.setRolePermissions(roleName, permissions);
|
|
184
|
+
return { success: true, message: "Role created successfully" };
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
listRoles() {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
var _a;
|
|
190
|
+
const result = yield ConfigDatabase_service_1.default.getRolesCollection().query({}).Limit(1000).exec();
|
|
191
|
+
if (!("data" in result) || !((_a = result.data) === null || _a === void 0 ? void 0 : _a.documents)) {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
return result.data.documents;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Rejects an operation that would leave zero active Super Admin users behind,
|
|
199
|
+
* preventing a permanent RBAC lockout.
|
|
200
|
+
*/
|
|
201
|
+
assertNotLastSuperAdmin(excludingUsername) {
|
|
202
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
203
|
+
var _a;
|
|
204
|
+
const result = yield ConfigDatabase_service_1.default.getUsersCollection()
|
|
205
|
+
.query({ role: Permissions_1.SUPER_ADMIN_ROLE })
|
|
206
|
+
.Limit(1000)
|
|
207
|
+
.exec();
|
|
208
|
+
const superAdmins = "data" in result && ((_a = result.data) === null || _a === void 0 ? void 0 : _a.documents) ? result.data.documents : [];
|
|
209
|
+
const remaining = superAdmins.filter((user) => user.username !== excludingUsername && user.isActive !== false);
|
|
210
|
+
if (remaining.length === 0) {
|
|
211
|
+
return {
|
|
212
|
+
success: false,
|
|
213
|
+
message: "Cannot remove the last remaining Super Admin",
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return { success: true, message: "OK" };
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
exports.default = AuthService;
|
|
221
|
+
//# sourceMappingURL=AuthService.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthService.service.js","sourceRoot":"","sources":["../../../source/Services/Auth/AuthService.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Collection from "../Collection/collection.operation";
|
|
2
|
+
/**
|
|
3
|
+
* Holds long-lived references to the `config` database's `users`/`roles`/`permissions`
|
|
4
|
+
* collections. Collection instances are reused across requests instead of being
|
|
5
|
+
* recreated per call, since each `Collection` eagerly loads its index cache on
|
|
6
|
+
* construction - recreating it per request would repeatedly reload indexes for
|
|
7
|
+
* no benefit.
|
|
8
|
+
*/
|
|
9
|
+
declare class ConfigDatabase {
|
|
10
|
+
private static instance;
|
|
11
|
+
private usersCollection;
|
|
12
|
+
private rolesCollection;
|
|
13
|
+
private permissionsCollection;
|
|
14
|
+
static getInstance(): ConfigDatabase;
|
|
15
|
+
setCollections(usersCollection: Collection, rolesCollection: Collection, permissionsCollection: Collection): void;
|
|
16
|
+
isInitialized(): boolean;
|
|
17
|
+
getUsersCollection(): Collection;
|
|
18
|
+
getRolesCollection(): Collection;
|
|
19
|
+
getPermissionsCollection(): Collection;
|
|
20
|
+
}
|
|
21
|
+
declare const _default: ConfigDatabase;
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Holds long-lived references to the `config` database's `users`/`roles`/`permissions`
|
|
5
|
+
* collections. Collection instances are reused across requests instead of being
|
|
6
|
+
* recreated per call, since each `Collection` eagerly loads its index cache on
|
|
7
|
+
* construction - recreating it per request would repeatedly reload indexes for
|
|
8
|
+
* no benefit.
|
|
9
|
+
*/
|
|
10
|
+
class ConfigDatabase {
|
|
11
|
+
static getInstance() {
|
|
12
|
+
if (!ConfigDatabase.instance) {
|
|
13
|
+
ConfigDatabase.instance = new ConfigDatabase();
|
|
14
|
+
}
|
|
15
|
+
return ConfigDatabase.instance;
|
|
16
|
+
}
|
|
17
|
+
setCollections(usersCollection, rolesCollection, permissionsCollection) {
|
|
18
|
+
this.usersCollection = usersCollection;
|
|
19
|
+
this.rolesCollection = rolesCollection;
|
|
20
|
+
this.permissionsCollection = permissionsCollection;
|
|
21
|
+
}
|
|
22
|
+
isInitialized() {
|
|
23
|
+
return (this.usersCollection !== undefined &&
|
|
24
|
+
this.rolesCollection !== undefined &&
|
|
25
|
+
this.permissionsCollection !== undefined);
|
|
26
|
+
}
|
|
27
|
+
getUsersCollection() {
|
|
28
|
+
if (!this.usersCollection) {
|
|
29
|
+
throw new Error("Config database is not initialized yet");
|
|
30
|
+
}
|
|
31
|
+
return this.usersCollection;
|
|
32
|
+
}
|
|
33
|
+
getRolesCollection() {
|
|
34
|
+
if (!this.rolesCollection) {
|
|
35
|
+
throw new Error("Config database is not initialized yet");
|
|
36
|
+
}
|
|
37
|
+
return this.rolesCollection;
|
|
38
|
+
}
|
|
39
|
+
getPermissionsCollection() {
|
|
40
|
+
if (!this.permissionsCollection) {
|
|
41
|
+
throw new Error("Config database is not initialized yet");
|
|
42
|
+
}
|
|
43
|
+
return this.permissionsCollection;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.default = ConfigDatabase.getInstance();
|
|
47
|
+
//# sourceMappingURL=ConfigDatabase.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigDatabase.service.js","sourceRoot":"","sources":["../../../source/Services/Auth/ConfigDatabase.service.ts"],"names":[],"mappings":";;AAEA;;;;;;GAMG;AACH,MAAM,cAAc;IAMX,MAAM,CAAC,WAAW;QACvB,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;YAC7B,cAAc,CAAC,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;QACjD,CAAC;QACD,OAAO,cAAc,CAAC,QAAQ,CAAC;IACjC,CAAC;IAEM,cAAc,CACnB,eAA2B,EAC3B,eAA2B,EAC3B,qBAAiC;QAEjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;IACrD,CAAC;IAEM,aAAa;QAClB,OAAO,CACL,IAAI,CAAC,eAAe,KAAK,SAAS;YAClC,IAAI,CAAC,eAAe,KAAK,SAAS;YAClC,IAAI,CAAC,qBAAqB,KAAK,SAAS,CACzC,CAAC;IACJ,CAAC;IAEM,kBAAkB;QACvB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAEM,kBAAkB;QACvB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAEM,wBAAwB;QAC7B,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,qBAAqB,CAAC;IACpC,CAAC;CACF;kBAEc,cAAc,CAAC,WAAW,EAAE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CookiePayload } from "../../config/Interfaces/Auth/auth.interface";
|
|
2
|
+
/**
|
|
3
|
+
* Encodes/decodes the session cookie value. The cookie is intentionally not the
|
|
4
|
+
* security boundary by itself - it only carries a random `sid` used to look up the
|
|
5
|
+
* real session record in SessionStore's in-memory map. See SessionStore.service.ts.
|
|
6
|
+
*/
|
|
7
|
+
export default class CookieCodec {
|
|
8
|
+
static encode(payload: CookiePayload): string;
|
|
9
|
+
static decode(rawCookieValue: string): CookiePayload | null;
|
|
10
|
+
}
|