@heavybit/shared-lib 1.3.2 → 2.7.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 +261 -0
- package/dist/cjs/access/index.js +9 -1
- package/dist/cjs/access/index.js.map +1 -1
- package/dist/cjs/approvals/index.js +137 -0
- package/dist/cjs/approvals/index.js.map +1 -0
- package/dist/cjs/audit/index.js +74 -0
- package/dist/cjs/audit/index.js.map +1 -0
- package/dist/cjs/cache/index.js +90 -16
- package/dist/cjs/cache/index.js.map +1 -1
- package/dist/cjs/cache/keyspace.js +101 -0
- package/dist/cjs/cache/keyspace.js.map +1 -0
- package/dist/cjs/common/circuit-breaker.js +74 -0
- package/dist/cjs/common/circuit-breaker.js.map +1 -0
- package/dist/cjs/common/errors.js +44 -5
- package/dist/cjs/common/errors.js.map +1 -1
- package/dist/cjs/common/index.js +4 -0
- package/dist/cjs/common/index.js.map +1 -1
- package/dist/cjs/common/internal-client.js +177 -0
- package/dist/cjs/common/internal-client.js.map +1 -0
- package/dist/cjs/common/internal-constants.js +12 -0
- package/dist/cjs/common/internal-constants.js.map +1 -0
- package/dist/cjs/common/internal-service-auth.js +160 -0
- package/dist/cjs/common/internal-service-auth.js.map +1 -0
- package/dist/cjs/common/money.js +215 -0
- package/dist/cjs/common/money.js.map +1 -0
- package/dist/cjs/common/phone.js +63 -11
- package/dist/cjs/common/phone.js.map +1 -1
- package/dist/cjs/common/response.js +78 -5
- package/dist/cjs/common/response.js.map +1 -1
- package/dist/cjs/common/time.js +28 -2
- package/dist/cjs/common/time.js.map +1 -1
- package/dist/cjs/config/index.js +140 -20
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/context/index.js +49 -0
- package/dist/cjs/context/index.js.map +1 -0
- package/dist/cjs/contracts/index.js +0 -2
- package/dist/cjs/contracts/index.js.map +1 -1
- package/dist/cjs/contracts/notification-dispatch.js +87 -63
- package/dist/cjs/contracts/notification-dispatch.js.map +1 -1
- package/dist/cjs/database/db.js +37 -0
- package/dist/cjs/database/db.js.map +1 -0
- package/dist/cjs/database/index.js +22 -51
- package/dist/cjs/database/index.js.map +1 -1
- package/dist/cjs/database/pagination.js +88 -0
- package/dist/cjs/database/pagination.js.map +1 -0
- package/dist/cjs/database/pool.js +60 -0
- package/dist/cjs/database/pool.js.map +1 -0
- package/dist/cjs/database/scoped-repository.js +132 -0
- package/dist/cjs/database/scoped-repository.js.map +1 -0
- package/dist/cjs/database/scopes.js +166 -0
- package/dist/cjs/database/scopes.js.map +1 -0
- package/dist/cjs/database/table-names.js +14 -0
- package/dist/cjs/database/table-names.js.map +1 -0
- package/dist/cjs/database/tables.js +71 -0
- package/dist/cjs/database/tables.js.map +1 -0
- package/dist/cjs/express/auth.js +88 -41
- package/dist/cjs/express/auth.js.map +1 -1
- package/dist/cjs/express/index.js +3 -0
- package/dist/cjs/express/index.js.map +1 -1
- package/dist/cjs/express/internal-caller.js +52 -0
- package/dist/cjs/express/internal-caller.js.map +1 -0
- package/dist/cjs/express/middleware.js +154 -34
- package/dist/cjs/express/middleware.js.map +1 -1
- package/dist/cjs/express/respond.js +47 -0
- package/dist/cjs/express/respond.js.map +1 -0
- package/dist/cjs/express/step-up.js +41 -0
- package/dist/cjs/express/step-up.js.map +1 -0
- package/dist/cjs/http/index.js +3 -71
- package/dist/cjs/http/index.js.map +1 -1
- package/dist/cjs/identity/index.js +269 -67
- package/dist/cjs/identity/index.js.map +1 -1
- package/dist/cjs/identity/step-up.js +52 -0
- package/dist/cjs/identity/step-up.js.map +1 -0
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/knex/columns.js +36 -0
- package/dist/cjs/knex/columns.js.map +1 -0
- package/dist/cjs/knex/index.js +26 -43
- package/dist/cjs/knex/index.js.map +1 -1
- package/dist/cjs/knex/migration-helpers.js +57 -0
- package/dist/cjs/knex/migration-helpers.js.map +1 -0
- package/dist/cjs/logging/index.js +76 -40
- package/dist/cjs/logging/index.js.map +1 -1
- package/dist/cjs/logging/redact.js +112 -0
- package/dist/cjs/logging/redact.js.map +1 -0
- package/dist/cjs/messaging/base-consumer.js +36 -0
- package/dist/cjs/messaging/base-consumer.js.map +1 -0
- package/dist/cjs/messaging/consumer.js +142 -73
- package/dist/cjs/messaging/consumer.js.map +1 -1
- package/dist/cjs/messaging/envelope.js +53 -10
- package/dist/cjs/messaging/envelope.js.map +1 -1
- package/dist/cjs/messaging/idempotency.js +95 -8
- package/dist/cjs/messaging/idempotency.js.map +1 -1
- package/dist/cjs/messaging/index.js +3 -1
- package/dist/cjs/messaging/index.js.map +1 -1
- package/dist/cjs/messaging/outbox.js +97 -55
- package/dist/cjs/messaging/outbox.js.map +1 -1
- package/dist/cjs/messaging/publisher.js +86 -38
- package/dist/cjs/messaging/publisher.js.map +1 -1
- package/dist/cjs/messaging/staff-notifier.js +36 -44
- package/dist/cjs/messaging/staff-notifier.js.map +1 -1
- package/dist/cjs/messaging/staff-recipients.js +57 -0
- package/dist/cjs/messaging/staff-recipients.js.map +1 -0
- package/dist/cjs/messaging/topology.js +41 -5
- package/dist/cjs/messaging/topology.js.map +1 -1
- package/dist/cjs/rate-limit/index.js +57 -6
- package/dist/cjs/rate-limit/index.js.map +1 -1
- package/dist/cjs/rate-limit/keys.js +47 -0
- package/dist/cjs/rate-limit/keys.js.map +1 -0
- package/dist/cjs/socket/index.js +127 -16
- package/dist/cjs/socket/index.js.map +1 -1
- package/dist/cjs/socket/ticket.js +124 -0
- package/dist/cjs/socket/ticket.js.map +1 -0
- package/dist/cjs/testing/index.js +23 -14
- package/dist/cjs/testing/index.js.map +1 -1
- package/dist/cjs/validation/index.js +27 -3
- package/dist/cjs/validation/index.js.map +1 -1
- package/dist/esm/access/index.js +9 -1
- package/dist/esm/access/index.js.map +1 -1
- package/dist/esm/approvals/index.js +127 -0
- package/dist/esm/approvals/index.js.map +1 -0
- package/dist/esm/audit/index.js +70 -0
- package/dist/esm/audit/index.js.map +1 -0
- package/dist/esm/cache/index.js +70 -13
- package/dist/esm/cache/index.js.map +1 -1
- package/dist/esm/cache/keyspace.js +95 -0
- package/dist/esm/cache/keyspace.js.map +1 -0
- package/dist/esm/common/circuit-breaker.js +70 -0
- package/dist/esm/common/circuit-breaker.js.map +1 -0
- package/dist/esm/common/errors.js +42 -4
- package/dist/esm/common/errors.js.map +1 -1
- package/dist/esm/common/index.js +4 -0
- package/dist/esm/common/index.js.map +1 -1
- package/dist/esm/common/internal-client.js +173 -0
- package/dist/esm/common/internal-client.js.map +1 -0
- package/dist/esm/common/internal-constants.js +9 -0
- package/dist/esm/common/internal-constants.js.map +1 -0
- package/dist/esm/common/internal-service-auth.js +150 -0
- package/dist/esm/common/internal-service-auth.js.map +1 -0
- package/dist/esm/common/money.js +207 -0
- package/dist/esm/common/money.js.map +1 -0
- package/dist/esm/common/phone.js +63 -11
- package/dist/esm/common/phone.js.map +1 -1
- package/dist/esm/common/response.js +75 -5
- package/dist/esm/common/response.js.map +1 -1
- package/dist/esm/common/time.js +27 -2
- package/dist/esm/common/time.js.map +1 -1
- package/dist/esm/config/index.js +136 -19
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/context/index.js +44 -0
- package/dist/esm/context/index.js.map +1 -0
- package/dist/esm/contracts/index.js +0 -2
- package/dist/esm/contracts/index.js.map +1 -1
- package/dist/esm/contracts/notification-dispatch.js +85 -62
- package/dist/esm/contracts/notification-dispatch.js.map +1 -1
- package/dist/esm/database/db.js +32 -0
- package/dist/esm/database/db.js.map +1 -0
- package/dist/esm/database/index.js +9 -45
- package/dist/esm/database/index.js.map +1 -1
- package/dist/esm/database/pagination.js +81 -0
- package/dist/esm/database/pagination.js.map +1 -0
- package/dist/esm/database/pool.js +51 -0
- package/dist/esm/database/pool.js.map +1 -0
- package/dist/esm/database/scoped-repository.js +128 -0
- package/dist/esm/database/scoped-repository.js.map +1 -0
- package/dist/esm/database/scopes.js +157 -0
- package/dist/esm/database/scopes.js.map +1 -0
- package/dist/esm/database/table-names.js +11 -0
- package/dist/esm/database/table-names.js.map +1 -0
- package/dist/esm/database/tables.js +61 -0
- package/dist/esm/database/tables.js.map +1 -0
- package/dist/esm/express/auth.js +87 -40
- package/dist/esm/express/auth.js.map +1 -1
- package/dist/esm/express/index.js +3 -0
- package/dist/esm/express/index.js.map +1 -1
- package/dist/esm/express/internal-caller.js +49 -0
- package/dist/esm/express/internal-caller.js.map +1 -0
- package/dist/esm/express/middleware.js +146 -27
- package/dist/esm/express/middleware.js.map +1 -1
- package/dist/esm/express/respond.js +42 -0
- package/dist/esm/express/respond.js.map +1 -0
- package/dist/esm/express/step-up.js +38 -0
- package/dist/esm/express/step-up.js.map +1 -0
- package/dist/esm/http/index.js +3 -70
- package/dist/esm/http/index.js.map +1 -1
- package/dist/esm/identity/index.js +246 -64
- package/dist/esm/identity/index.js.map +1 -1
- package/dist/esm/identity/step-up.js +47 -0
- package/dist/esm/identity/step-up.js.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/knex/columns.js +28 -0
- package/dist/esm/knex/columns.js.map +1 -0
- package/dist/esm/knex/index.js +8 -34
- package/dist/esm/knex/index.js.map +1 -1
- package/dist/esm/knex/migration-helpers.js +51 -0
- package/dist/esm/knex/migration-helpers.js.map +1 -0
- package/dist/esm/logging/index.js +68 -39
- package/dist/esm/logging/index.js.map +1 -1
- package/dist/esm/logging/redact.js +106 -0
- package/dist/esm/logging/redact.js.map +1 -0
- package/dist/esm/messaging/base-consumer.js +32 -0
- package/dist/esm/messaging/base-consumer.js.map +1 -0
- package/dist/esm/messaging/consumer.js +139 -71
- package/dist/esm/messaging/consumer.js.map +1 -1
- package/dist/esm/messaging/envelope.js +50 -10
- package/dist/esm/messaging/envelope.js.map +1 -1
- package/dist/esm/messaging/idempotency.js +91 -7
- package/dist/esm/messaging/idempotency.js.map +1 -1
- package/dist/esm/messaging/index.js +3 -1
- package/dist/esm/messaging/index.js.map +1 -1
- package/dist/esm/messaging/outbox.js +97 -54
- package/dist/esm/messaging/outbox.js.map +1 -1
- package/dist/esm/messaging/publisher.js +86 -38
- package/dist/esm/messaging/publisher.js.map +1 -1
- package/dist/esm/messaging/staff-notifier.js +36 -43
- package/dist/esm/messaging/staff-notifier.js.map +1 -1
- package/dist/esm/messaging/staff-recipients.js +53 -0
- package/dist/esm/messaging/staff-recipients.js.map +1 -0
- package/dist/esm/messaging/topology.js +39 -4
- package/dist/esm/messaging/topology.js.map +1 -1
- package/dist/esm/rate-limit/index.js +41 -6
- package/dist/esm/rate-limit/index.js.map +1 -1
- package/dist/esm/rate-limit/keys.js +43 -0
- package/dist/esm/rate-limit/keys.js.map +1 -0
- package/dist/esm/socket/index.js +112 -17
- package/dist/esm/socket/index.js.map +1 -1
- package/dist/esm/socket/ticket.js +117 -0
- package/dist/esm/socket/ticket.js.map +1 -0
- package/dist/esm/testing/index.js +24 -15
- package/dist/esm/testing/index.js.map +1 -1
- package/dist/esm/validation/index.js +27 -2
- package/dist/esm/validation/index.js.map +1 -1
- package/dist/types/access/index.d.ts +9 -3
- package/dist/types/access/index.d.ts.map +1 -1
- package/dist/types/alerting/index.d.ts +1 -1
- package/dist/types/alerting/index.d.ts.map +1 -1
- package/dist/types/approvals/index.d.ts +99 -0
- package/dist/types/approvals/index.d.ts.map +1 -0
- package/dist/types/audit/index.d.ts +82 -0
- package/dist/types/audit/index.d.ts.map +1 -0
- package/dist/types/cache/index.d.ts +64 -14
- package/dist/types/cache/index.d.ts.map +1 -1
- package/dist/types/cache/keyspace.d.ts +84 -0
- package/dist/types/cache/keyspace.d.ts.map +1 -0
- package/dist/types/common/circuit-breaker.d.ts +51 -0
- package/dist/types/common/circuit-breaker.d.ts.map +1 -0
- package/dist/types/common/errors.d.ts +48 -7
- package/dist/types/common/errors.d.ts.map +1 -1
- package/dist/types/common/index.d.ts +4 -0
- package/dist/types/common/index.d.ts.map +1 -1
- package/dist/types/common/internal-client.d.ts +116 -0
- package/dist/types/common/internal-client.d.ts.map +1 -0
- package/dist/types/common/internal-constants.d.ts +9 -0
- package/dist/types/common/internal-constants.d.ts.map +1 -0
- package/dist/types/common/internal-service-auth.d.ts +102 -0
- package/dist/types/common/internal-service-auth.d.ts.map +1 -0
- package/dist/types/common/money.d.ts +104 -0
- package/dist/types/common/money.d.ts.map +1 -0
- package/dist/types/common/phone.d.ts +45 -6
- package/dist/types/common/phone.d.ts.map +1 -1
- package/dist/types/common/response.d.ts +66 -5
- package/dist/types/common/response.d.ts.map +1 -1
- package/dist/types/common/time.d.ts +20 -2
- package/dist/types/common/time.d.ts.map +1 -1
- package/dist/types/config/index.d.ts +252 -28
- package/dist/types/config/index.d.ts.map +1 -1
- package/dist/types/context/index.d.ts +39 -0
- package/dist/types/context/index.d.ts.map +1 -0
- package/dist/types/contracts/index.d.ts +0 -2
- package/dist/types/contracts/index.d.ts.map +1 -1
- package/dist/types/contracts/notification-dispatch.d.ts +204 -86
- package/dist/types/contracts/notification-dispatch.d.ts.map +1 -1
- package/dist/types/database/db.d.ts +46 -0
- package/dist/types/database/db.d.ts.map +1 -0
- package/dist/types/database/index.d.ts +9 -22
- package/dist/types/database/index.d.ts.map +1 -1
- package/dist/types/database/pagination.d.ts +68 -0
- package/dist/types/database/pagination.d.ts.map +1 -0
- package/dist/types/database/pool.d.ts +39 -0
- package/dist/types/database/pool.d.ts.map +1 -0
- package/dist/types/database/scoped-repository.d.ts +92 -0
- package/dist/types/database/scoped-repository.d.ts.map +1 -0
- package/dist/types/database/scopes.d.ts +159 -0
- package/dist/types/database/scopes.d.ts.map +1 -0
- package/dist/types/database/table-names.d.ts +13 -0
- package/dist/types/database/table-names.d.ts.map +1 -0
- package/dist/types/database/tables.d.ts +748 -0
- package/dist/types/database/tables.d.ts.map +1 -0
- package/dist/types/express/auth.d.ts +63 -11
- package/dist/types/express/auth.d.ts.map +1 -1
- package/dist/types/express/index.d.ts +3 -0
- package/dist/types/express/index.d.ts.map +1 -1
- package/dist/types/express/internal-caller.d.ts +53 -0
- package/dist/types/express/internal-caller.d.ts.map +1 -0
- package/dist/types/express/middleware.d.ts +86 -7
- package/dist/types/express/middleware.d.ts.map +1 -1
- package/dist/types/express/respond.d.ts +41 -0
- package/dist/types/express/respond.d.ts.map +1 -0
- package/dist/types/express/step-up.d.ts +38 -0
- package/dist/types/express/step-up.d.ts.map +1 -0
- package/dist/types/http/index.d.ts +3 -31
- package/dist/types/http/index.d.ts.map +1 -1
- package/dist/types/identity/index.d.ts +159 -21
- package/dist/types/identity/index.d.ts.map +1 -1
- package/dist/types/identity/step-up.d.ts +41 -0
- package/dist/types/identity/step-up.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/knex/columns.d.ts +15 -0
- package/dist/types/knex/columns.d.ts.map +1 -0
- package/dist/types/knex/index.d.ts +3 -11
- package/dist/types/knex/index.d.ts.map +1 -1
- package/dist/types/knex/migration-helpers.d.ts +28 -0
- package/dist/types/knex/migration-helpers.d.ts.map +1 -0
- package/dist/types/logging/index.d.ts +30 -4
- package/dist/types/logging/index.d.ts.map +1 -1
- package/dist/types/logging/redact.d.ts +54 -0
- package/dist/types/logging/redact.d.ts.map +1 -0
- package/dist/types/messaging/base-consumer.d.ts +33 -0
- package/dist/types/messaging/base-consumer.d.ts.map +1 -0
- package/dist/types/messaging/consumer.d.ts +59 -21
- package/dist/types/messaging/consumer.d.ts.map +1 -1
- package/dist/types/messaging/envelope.d.ts +50 -11
- package/dist/types/messaging/envelope.d.ts.map +1 -1
- package/dist/types/messaging/idempotency.d.ts +60 -3
- package/dist/types/messaging/idempotency.d.ts.map +1 -1
- package/dist/types/messaging/index.d.ts +8 -0
- package/dist/types/messaging/index.d.ts.map +1 -1
- package/dist/types/messaging/outbox.d.ts +62 -22
- package/dist/types/messaging/outbox.d.ts.map +1 -1
- package/dist/types/messaging/publisher.d.ts +54 -21
- package/dist/types/messaging/publisher.d.ts.map +1 -1
- package/dist/types/messaging/staff-notifier.d.ts +69 -38
- package/dist/types/messaging/staff-notifier.d.ts.map +1 -1
- package/dist/types/messaging/staff-recipients.d.ts +50 -0
- package/dist/types/messaging/staff-recipients.d.ts.map +1 -0
- package/dist/types/messaging/topology.d.ts +40 -8
- package/dist/types/messaging/topology.d.ts.map +1 -1
- package/dist/types/rate-limit/index.d.ts +40 -4
- package/dist/types/rate-limit/index.d.ts.map +1 -1
- package/dist/types/rate-limit/keys.d.ts +52 -0
- package/dist/types/rate-limit/keys.d.ts.map +1 -0
- package/dist/types/socket/index.d.ts +86 -2
- package/dist/types/socket/index.d.ts.map +1 -1
- package/dist/types/socket/ticket.d.ts +90 -0
- package/dist/types/socket/ticket.d.ts.map +1 -0
- package/dist/types/testing/index.d.ts +31 -10
- package/dist/types/testing/index.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +62 -15
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/validation/index.d.ts +33 -2
- package/dist/types/validation/index.d.ts.map +1 -1
- package/package.json +3 -1
- package/dist/cjs/contracts/editorial-draft.js +0 -120
- package/dist/cjs/contracts/editorial-draft.js.map +0 -1
- package/dist/cjs/contracts/upload-import.js +0 -54
- package/dist/cjs/contracts/upload-import.js.map +0 -1
- package/dist/esm/contracts/editorial-draft.js +0 -117
- package/dist/esm/contracts/editorial-draft.js.map +0 -1
- package/dist/esm/contracts/upload-import.js +0 -51
- package/dist/esm/contracts/upload-import.js.map +0 -1
- package/dist/types/contracts/editorial-draft.d.ts +0 -610
- package/dist/types/contracts/editorial-draft.d.ts.map +0 -1
- package/dist/types/contracts/upload-import.d.ts +0 -96
- package/dist/types/contracts/upload-import.d.ts.map +0 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlatformScopeDefinition = exports.PlatformScope = exports.OwnerScope = void 0;
|
|
4
|
+
exports.resolveColumn = resolveColumn;
|
|
5
|
+
exports.defineScope = defineScope;
|
|
6
|
+
exports.definePlatformScope = definePlatformScope;
|
|
7
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
8
|
+
const errors_js_1 = require("../common/errors.js");
|
|
9
|
+
/**
|
|
10
|
+
* Finds a table column by its database name.
|
|
11
|
+
*
|
|
12
|
+
* @throws Error when the table has no such column (a wiring bug, caught at startup or in tests).
|
|
13
|
+
*/
|
|
14
|
+
function resolveColumn(table, dbName) {
|
|
15
|
+
const columns = (0, drizzle_orm_1.getTableColumns)(table);
|
|
16
|
+
for (const [key, column] of Object.entries(columns)) {
|
|
17
|
+
if (column.name === dbName)
|
|
18
|
+
return { key, column };
|
|
19
|
+
}
|
|
20
|
+
throw new Error(`Table has no column "${dbName}"`);
|
|
21
|
+
}
|
|
22
|
+
function requireValue(value, scopeName, code) {
|
|
23
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
24
|
+
throw new errors_js_1.ForbiddenError(`A ${scopeName} scope is required`, { code });
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
/** Sets `column` on `row` to `value`; refuses a row that carries a different value. */
|
|
29
|
+
function stampColumn(table, row, dbName, value, scopeName) {
|
|
30
|
+
const { key } = resolveColumn(table, dbName);
|
|
31
|
+
const current = row[key];
|
|
32
|
+
if (current !== undefined && current !== null && current !== value) {
|
|
33
|
+
throw new errors_js_1.ForbiddenError(`Row belongs to another ${scopeName}`, { code: 'SCOPE_MISMATCH' });
|
|
34
|
+
}
|
|
35
|
+
return { ...row, [key]: value };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Defines a scope whose value comes from the request context (the gateway-signed identity, never a
|
|
39
|
+
* request body).
|
|
40
|
+
*
|
|
41
|
+
* @example const workspaceScope = defineScope({ name: 'workspace', column: 'workspace_id', contextKey: 'workspaceId' });
|
|
42
|
+
*/
|
|
43
|
+
function defineScope(options) {
|
|
44
|
+
const { name, column, contextKey } = options;
|
|
45
|
+
const valueOf = (ctx) => requireValue(ctx?.[contextKey], name, 'SCOPE_REQUIRED');
|
|
46
|
+
return Object.freeze({
|
|
47
|
+
name,
|
|
48
|
+
column,
|
|
49
|
+
contextKey,
|
|
50
|
+
valueOf,
|
|
51
|
+
condition: (table, ctx) => (0, drizzle_orm_1.eq)(resolveColumn(table, column).column, valueOf(ctx)),
|
|
52
|
+
stamp: (table, row, ctx) => stampColumn(table, row, column, valueOf(ctx), name),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Rows owned by one principal (e.g. a user's own records). Refuses a missing owner id, so an
|
|
57
|
+
* anonymous call can never fall through to "all owners".
|
|
58
|
+
*
|
|
59
|
+
* @example const ownerScope = new OwnerScope({ name: 'owner', column: 'user_id' });
|
|
60
|
+
*/
|
|
61
|
+
class OwnerScope {
|
|
62
|
+
/** Readable name (e.g. `owner`). */
|
|
63
|
+
name;
|
|
64
|
+
/** Database name of the owner column (e.g. `user_id`). */
|
|
65
|
+
column;
|
|
66
|
+
/** @param options `name` for messages, `column` = database name of the owner column. */
|
|
67
|
+
constructor(options) {
|
|
68
|
+
this.name = options.name;
|
|
69
|
+
this.column = options.column;
|
|
70
|
+
}
|
|
71
|
+
/** The owner id from `ctx`; throws ForbiddenError (`OWNER_REQUIRED`) when it is missing. */
|
|
72
|
+
ownerIdOf(ctx) {
|
|
73
|
+
return requireValue(ctx?.ownerId, this.name, 'OWNER_REQUIRED');
|
|
74
|
+
}
|
|
75
|
+
/** `owner column = ownerId`. @throws ForbiddenError (`OWNER_REQUIRED`) without an owner id. */
|
|
76
|
+
condition(table, ctx) {
|
|
77
|
+
return (0, drizzle_orm_1.eq)(resolveColumn(table, this.column).column, this.ownerIdOf(ctx));
|
|
78
|
+
}
|
|
79
|
+
/** Sets the owner column. @throws ForbiddenError (`OWNER_REQUIRED`, `SCOPE_MISMATCH`). */
|
|
80
|
+
stamp(table, row, ctx) {
|
|
81
|
+
return stampColumn(table, row, this.column, this.ownerIdOf(ctx), this.name);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.OwnerScope = OwnerScope;
|
|
85
|
+
const ISSUE = Symbol('PlatformScope.issue');
|
|
86
|
+
/**
|
|
87
|
+
* Proof that an identity may act across scopes. Only {@link PlatformScopeDefinition.authorize} can
|
|
88
|
+
* create one, and only when the definition's predicate approves the identity.
|
|
89
|
+
*/
|
|
90
|
+
class PlatformScope {
|
|
91
|
+
#definition;
|
|
92
|
+
/** @internal Use `definePlatformScope(...).authorize(identity)`. */
|
|
93
|
+
constructor(token, definition) {
|
|
94
|
+
if (token !== ISSUE)
|
|
95
|
+
throw new errors_js_1.ForbiddenError('Platform scope must be authorized', { code: 'PLATFORM_SCOPE_REQUIRED' });
|
|
96
|
+
this.#definition = definition;
|
|
97
|
+
}
|
|
98
|
+
/** True when this grant was issued by `definition`. */
|
|
99
|
+
issuedBy(definition) {
|
|
100
|
+
return this.#definition === definition;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.PlatformScope = PlatformScope;
|
|
104
|
+
/**
|
|
105
|
+
* Cross-scope access for platform operators. Rows of every scope are reachable, but the query still
|
|
106
|
+
* filters on the scope column (`IS NOT NULL`) and inserts must name their scope explicitly.
|
|
107
|
+
*/
|
|
108
|
+
class PlatformScopeDefinition {
|
|
109
|
+
/** Readable name (e.g. `platform`). */
|
|
110
|
+
name;
|
|
111
|
+
/** Database name of the scope column the platform scope spans. */
|
|
112
|
+
column;
|
|
113
|
+
#predicate;
|
|
114
|
+
/** Prefer {@link definePlatformScope}. */
|
|
115
|
+
constructor(options) {
|
|
116
|
+
this.name = options.name;
|
|
117
|
+
this.column = options.column;
|
|
118
|
+
this.#predicate = options.predicate;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Issues a {@link PlatformScope} for `identity`.
|
|
122
|
+
*
|
|
123
|
+
* @throws ForbiddenError (`PLATFORM_SCOPE_DENIED`) when the predicate refuses (or throws).
|
|
124
|
+
*/
|
|
125
|
+
authorize(identity) {
|
|
126
|
+
let allowed = false;
|
|
127
|
+
try {
|
|
128
|
+
allowed = identity != null && this.#predicate(identity);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
allowed = false;
|
|
132
|
+
}
|
|
133
|
+
if (!allowed)
|
|
134
|
+
throw new errors_js_1.ForbiddenError('Platform access is required', { code: 'PLATFORM_SCOPE_DENIED' });
|
|
135
|
+
return new PlatformScope(ISSUE, this);
|
|
136
|
+
}
|
|
137
|
+
/** `scope column IS NOT NULL`. @throws ForbiddenError (`PLATFORM_SCOPE_REQUIRED`) without a grant from this scope. */
|
|
138
|
+
condition(table, ctx) {
|
|
139
|
+
this.assertGrant(ctx);
|
|
140
|
+
return (0, drizzle_orm_1.isNotNull)(resolveColumn(table, this.column).column);
|
|
141
|
+
}
|
|
142
|
+
/** Requires the row to name its scope. @throws ForbiddenError (`PLATFORM_SCOPE_REQUIRED`, `SCOPE_REQUIRED`). */
|
|
143
|
+
stamp(table, row, ctx) {
|
|
144
|
+
this.assertGrant(ctx);
|
|
145
|
+
const { key } = resolveColumn(table, this.column);
|
|
146
|
+
requireValue(row[key], this.name, 'SCOPE_REQUIRED');
|
|
147
|
+
return row;
|
|
148
|
+
}
|
|
149
|
+
assertGrant(ctx) {
|
|
150
|
+
if (!(ctx instanceof PlatformScope) || !ctx.issuedBy(this)) {
|
|
151
|
+
throw new errors_js_1.ForbiddenError('Platform access is required', { code: 'PLATFORM_SCOPE_REQUIRED' });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.PlatformScopeDefinition = PlatformScopeDefinition;
|
|
156
|
+
/**
|
|
157
|
+
* Defines the platform (cross-scope) scope.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* const platformScope = definePlatformScope({ name: 'platform', column: 'workspace_id', predicate: (u: AuthUser) => u.isSuperAdmin });
|
|
161
|
+
* const grant = platformScope.authorize(req.user); // throws 403 for anyone else
|
|
162
|
+
*/
|
|
163
|
+
function definePlatformScope(options) {
|
|
164
|
+
return new PlatformScopeDefinition(options);
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../../src/database/scopes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OUTBOX_EXCHANGES = exports.SCHEDULER_RUN_STATUSES = exports.DEFAULT_SCHEDULER_RUNS_TABLE = exports.DEFAULT_PROCESSED_EVENTS_TABLE = exports.DEFAULT_OUTBOX_TABLE = void 0;
|
|
4
|
+
/** Default name of the transactional outbox table. */
|
|
5
|
+
exports.DEFAULT_OUTBOX_TABLE = 'event_outbox';
|
|
6
|
+
/** Default name of the consumer idempotency ledger. */
|
|
7
|
+
exports.DEFAULT_PROCESSED_EVENTS_TABLE = 'processed_events';
|
|
8
|
+
/** Default name of the scheduled-job runs table. */
|
|
9
|
+
exports.DEFAULT_SCHEDULER_RUNS_TABLE = 'scheduler_runs';
|
|
10
|
+
/** Scheduler run states, shared by the Drizzle table and the Knex helper. */
|
|
11
|
+
exports.SCHEDULER_RUN_STATUSES = ['running', 'succeeded', 'failed'];
|
|
12
|
+
/** Logical exchanges an outbox row can target: topic events or direct commands. */
|
|
13
|
+
exports.OUTBOX_EXCHANGES = ['events', 'commands'];
|
|
14
|
+
//# sourceMappingURL=table-names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-names.js","sourceRoot":"","sources":["../../../src/database/table-names.ts"],"names":[],"mappings":";;;AAAA,sDAAsD;AACzC,QAAA,oBAAoB,GAAG,cAAc,CAAC;AACnD,uDAAuD;AAC1C,QAAA,8BAA8B,GAAG,kBAAkB,CAAC;AACjE,oDAAoD;AACvC,QAAA,4BAA4B,GAAG,gBAAgB,CAAC;AAC7D,6EAA6E;AAChE,QAAA,sBAAsB,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC;AAClF,mFAAmF;AACtE,QAAA,gBAAgB,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAU,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.schedulerRuns = exports.processedEvents = exports.outbox = exports.SCHEDULER_RUN_STATUSES = exports.OUTBOX_EXCHANGES = exports.DEFAULT_SCHEDULER_RUNS_TABLE = exports.DEFAULT_PROCESSED_EVENTS_TABLE = exports.DEFAULT_OUTBOX_TABLE = void 0;
|
|
4
|
+
exports.outboxTable = outboxTable;
|
|
5
|
+
exports.processedEventsTable = processedEventsTable;
|
|
6
|
+
exports.schedulerRunsTable = schedulerRunsTable;
|
|
7
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
8
|
+
const table_names_js_1 = require("./table-names.js");
|
|
9
|
+
Object.defineProperty(exports, "DEFAULT_OUTBOX_TABLE", { enumerable: true, get: function () { return table_names_js_1.DEFAULT_OUTBOX_TABLE; } });
|
|
10
|
+
Object.defineProperty(exports, "DEFAULT_PROCESSED_EVENTS_TABLE", { enumerable: true, get: function () { return table_names_js_1.DEFAULT_PROCESSED_EVENTS_TABLE; } });
|
|
11
|
+
Object.defineProperty(exports, "DEFAULT_SCHEDULER_RUNS_TABLE", { enumerable: true, get: function () { return table_names_js_1.DEFAULT_SCHEDULER_RUNS_TABLE; } });
|
|
12
|
+
Object.defineProperty(exports, "OUTBOX_EXCHANGES", { enumerable: true, get: function () { return table_names_js_1.OUTBOX_EXCHANGES; } });
|
|
13
|
+
Object.defineProperty(exports, "SCHEDULER_RUN_STATUSES", { enumerable: true, get: function () { return table_names_js_1.SCHEDULER_RUN_STATUSES; } });
|
|
14
|
+
const mysql_core_1 = require("drizzle-orm/mysql-core");
|
|
15
|
+
/**
|
|
16
|
+
* Drizzle definitions of the infrastructure tables every service may own. Each matches the Knex
|
|
17
|
+
* helper of the same name in `@heavybit/shared-lib/knex` (`outboxColumns`, `processedEventsColumns`,
|
|
18
|
+
* `schedulerRunsColumns`); a test keeps the two in step. Pass a custom name when a service needs one.
|
|
19
|
+
*/
|
|
20
|
+
const ms = (name) => (0, mysql_core_1.datetime)(name, { mode: 'date', fsp: 3 });
|
|
21
|
+
const createdNow = (name) => ms(name).notNull().default((0, drizzle_orm_1.sql) `CURRENT_TIMESTAMP(3)`);
|
|
22
|
+
/** Transactional outbox (`event_outbox` by default): domain change and message in one transaction. */
|
|
23
|
+
function outboxTable(name = table_names_js_1.DEFAULT_OUTBOX_TABLE) {
|
|
24
|
+
return (0, mysql_core_1.mysqlTable)(name, {
|
|
25
|
+
id: (0, mysql_core_1.char)('id', { length: 26 }).primaryKey(),
|
|
26
|
+
routingKey: (0, mysql_core_1.varchar)('routing_key', { length: 191 }).notNull(),
|
|
27
|
+
/** Logical exchange: `events` (topic fan-out) or `commands` (direct, one owner). */
|
|
28
|
+
exchange: (0, mysql_core_1.mysqlEnum)('exchange', table_names_js_1.OUTBOX_EXCHANGES).notNull().default('events'),
|
|
29
|
+
payload: (0, mysql_core_1.json)('payload').notNull(),
|
|
30
|
+
/** Correlation id of the request that staged the row; the relay sends it as `x-correlation-id`. */
|
|
31
|
+
correlationId: (0, mysql_core_1.varchar)('correlation_id', { length: 64 }),
|
|
32
|
+
attempts: (0, mysql_core_1.int)('attempts', { unsigned: true }).notNull().default(0),
|
|
33
|
+
lastError: (0, mysql_core_1.varchar)('last_error', { length: 500 }),
|
|
34
|
+
createdAt: createdNow('created_at'),
|
|
35
|
+
publishedAt: ms('published_at'),
|
|
36
|
+
}, (t) => [(0, mysql_core_1.index)(`${name}_published_at_id_index`).on(t.publishedAt, t.id)]);
|
|
37
|
+
}
|
|
38
|
+
/** Consumer idempotency ledger: one row per (consumer, event id). */
|
|
39
|
+
function processedEventsTable(name = table_names_js_1.DEFAULT_PROCESSED_EVENTS_TABLE) {
|
|
40
|
+
return (0, mysql_core_1.mysqlTable)(name, {
|
|
41
|
+
id: (0, mysql_core_1.char)('id', { length: 26 }).primaryKey(),
|
|
42
|
+
consumer: (0, mysql_core_1.varchar)('consumer', { length: 191 }).notNull(),
|
|
43
|
+
eventId: (0, mysql_core_1.varchar)('event_id', { length: 64 }).notNull(),
|
|
44
|
+
processedAt: createdNow('processed_at'),
|
|
45
|
+
}, (t) => [
|
|
46
|
+
(0, mysql_core_1.uniqueIndex)(`${name}_consumer_event_id_unique`).on(t.consumer, t.eventId),
|
|
47
|
+
(0, mysql_core_1.index)(`${name}_processed_at_index`).on(t.processedAt),
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
/** Scheduled-job runs: one row per (job, run key), so a run is never executed twice. */
|
|
51
|
+
function schedulerRunsTable(name = table_names_js_1.DEFAULT_SCHEDULER_RUNS_TABLE) {
|
|
52
|
+
return (0, mysql_core_1.mysqlTable)(name, {
|
|
53
|
+
id: (0, mysql_core_1.char)('id', { length: 26 }).primaryKey(),
|
|
54
|
+
job: (0, mysql_core_1.varchar)('job', { length: 191 }).notNull(),
|
|
55
|
+
runKey: (0, mysql_core_1.varchar)('run_key', { length: 191 }).notNull(),
|
|
56
|
+
status: (0, mysql_core_1.mysqlEnum)('status', table_names_js_1.SCHEDULER_RUN_STATUSES).notNull().default('running'),
|
|
57
|
+
error: (0, mysql_core_1.varchar)('error', { length: 500 }),
|
|
58
|
+
startedAt: createdNow('started_at'),
|
|
59
|
+
finishedAt: ms('finished_at'),
|
|
60
|
+
}, (t) => [
|
|
61
|
+
(0, mysql_core_1.uniqueIndex)(`${name}_job_run_key_unique`).on(t.job, t.runKey),
|
|
62
|
+
(0, mysql_core_1.index)(`${name}_job_started_at_index`).on(t.job, t.startedAt),
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
/** `event_outbox` with the default name. */
|
|
66
|
+
exports.outbox = outboxTable();
|
|
67
|
+
/** `processed_events` with the default name. */
|
|
68
|
+
exports.processedEvents = processedEventsTable();
|
|
69
|
+
/** `scheduler_runs` with the default name. */
|
|
70
|
+
exports.schedulerRuns = schedulerRunsTable();
|
|
71
|
+
//# sourceMappingURL=tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../../../src/database/tables.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/express/auth.js
CHANGED
|
@@ -1,72 +1,119 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.requireRole = exports.requireAllPermissions = exports.requirePermission = void 0;
|
|
3
|
+
exports.requireRole = exports.requireOtpVerified = exports.requireAllPermissions = exports.requirePermission = void 0;
|
|
4
4
|
exports.authenticateFromGateway = authenticateFromGateway;
|
|
5
5
|
exports.optionalAuthFromGateway = optionalAuthFromGateway;
|
|
6
|
-
exports.requireInternalServiceSecret = requireInternalServiceSecret;
|
|
7
6
|
const index_js_1 = require("../access/index.js");
|
|
8
|
-
const crypto_js_1 = require("../common/crypto.js");
|
|
9
7
|
const response_js_1 = require("../common/response.js");
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
if (result.status === 'invalid') {
|
|
18
|
-
options.logger?.warn('Rejected forged or stale gateway identity', { reason: result.reason, path: req.path });
|
|
19
|
-
return 'invalid';
|
|
20
|
-
}
|
|
21
|
-
return 'anonymous';
|
|
8
|
+
const middleware_js_1 = require("./middleware.js");
|
|
9
|
+
const index_js_2 = require("../context/index.js");
|
|
10
|
+
const index_js_3 = require("../identity/index.js");
|
|
11
|
+
/** Collapses the user's scope id lists into the request context's `key → id` map (lists are comma-joined). */
|
|
12
|
+
function contextScopes(user) {
|
|
13
|
+
return Object.fromEntries(Object.entries(user.scopes).filter(([, ids]) => ids.length).map(([key, ids]) => [key, ids.join(',')]));
|
|
22
14
|
}
|
|
23
|
-
|
|
15
|
+
function createResolver(options) {
|
|
16
|
+
const secret = (0, index_js_3.assertGatewaySecret)(options.secret ?? process.env.GATEWAY_SIGNING_SECRET);
|
|
17
|
+
const reject = (req, reason) => {
|
|
18
|
+
const event = { reason, method: req.method, path: (0, index_js_3.canonicalPath)(req.originalUrl), requestId: (0, middleware_js_1.correlationId)(req) };
|
|
19
|
+
options.logger?.warn('Rejected gateway identity', { reason, method: event.method, path: event.path });
|
|
20
|
+
if (!options.onRejected)
|
|
21
|
+
return;
|
|
22
|
+
Promise.resolve()
|
|
23
|
+
.then(() => options.onRejected?.(event, req))
|
|
24
|
+
.catch((error) => options.logger?.error('Identity onRejected hook failed', { error: error.message }));
|
|
25
|
+
};
|
|
26
|
+
return (req) => {
|
|
27
|
+
const result = (0, index_js_3.verifyGatewayIdentity)({
|
|
28
|
+
headers: req.headers, method: req.method, path: req.originalUrl, secret, protocol: options.protocol,
|
|
29
|
+
maxAgeMs: options.maxAgeMs, maxFutureMs: options.maxFutureMs,
|
|
30
|
+
});
|
|
31
|
+
if (result.status === 'authenticated') {
|
|
32
|
+
req.user = result.user;
|
|
33
|
+
(0, index_js_2.updateRequestContext)({ userId: result.user.id, scopes: contextScopes(result.user) });
|
|
34
|
+
return 'ok';
|
|
35
|
+
}
|
|
36
|
+
if (result.status === 'invalid')
|
|
37
|
+
reject(req, result.reason);
|
|
38
|
+
return result.status === 'invalid' ? 'invalid' : 'anonymous';
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const unauthenticated = (req, res, message = 'Authentication required') => res.status(401).json((0, response_js_1.errorBody)('UNAUTHENTICATED', message, { requestId: (0, middleware_js_1.correlationId)(req) }));
|
|
42
|
+
/**
|
|
43
|
+
* Requires a valid gateway-signed (v2) identity and sets `req.user`; 401 UNAUTHENTICATED (with `requestId`)
|
|
44
|
+
* otherwise. Also fills the request context's `userId` and `scopes` so log lines carry them.
|
|
45
|
+
* Throws at startup when the secret is missing or shorter than 32 characters.
|
|
46
|
+
*
|
|
47
|
+
* @param options Protocol, secret, replay window, logger and rejection hook.
|
|
48
|
+
* @returns Express middleware.
|
|
49
|
+
* @example router.use(authenticateFromGateway({ protocol, logger, onRejected: publishSecurityEvent }));
|
|
50
|
+
*/
|
|
24
51
|
function authenticateFromGateway(options) {
|
|
52
|
+
const resolve = createResolver(options);
|
|
25
53
|
return (req, res, next) => {
|
|
26
|
-
if (
|
|
54
|
+
if (resolve(req) === 'ok')
|
|
27
55
|
return next();
|
|
28
|
-
|
|
56
|
+
unauthenticated(req, res);
|
|
29
57
|
};
|
|
30
58
|
}
|
|
31
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Attaches `req.user` when a valid identity is present and continues anonymously when none is sent,
|
|
61
|
+
* for public routes that personalise. A forged or stale identity is still rejected with 401, never
|
|
62
|
+
* downgraded to anonymous.
|
|
63
|
+
*
|
|
64
|
+
* @param options Same as {@link authenticateFromGateway}.
|
|
65
|
+
* @returns Express middleware.
|
|
66
|
+
* @example router.get('/items', optionalAuthFromGateway({ protocol }), controller.list);
|
|
67
|
+
*/
|
|
32
68
|
function optionalAuthFromGateway(options) {
|
|
69
|
+
const resolve = createResolver(options);
|
|
33
70
|
return (req, res, next) => {
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
71
|
+
if (resolve(req) === 'invalid')
|
|
72
|
+
return unauthenticated(req, res, 'Invalid identity');
|
|
38
73
|
next();
|
|
39
74
|
};
|
|
40
75
|
}
|
|
41
76
|
function guard(check, message = 'You do not have permission to perform this action') {
|
|
42
77
|
return (req, res, next) => {
|
|
43
|
-
if (!req.user)
|
|
44
|
-
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
78
|
+
if (!req.user)
|
|
79
|
+
return unauthenticated(req, res);
|
|
47
80
|
if (!check(req.user)) {
|
|
48
|
-
res.status(403).json((0, response_js_1.
|
|
81
|
+
res.status(403).json((0, response_js_1.errorBody)('FORBIDDEN', message, { requestId: (0, middleware_js_1.correlationId)(req) }));
|
|
49
82
|
return;
|
|
50
83
|
}
|
|
51
84
|
next();
|
|
52
85
|
};
|
|
53
86
|
}
|
|
54
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* Allows callers holding any of `permissions` (401 without identity, 403 FORBIDDEN otherwise).
|
|
89
|
+
* A super admin passes every permission guard.
|
|
90
|
+
*
|
|
91
|
+
* @example router.post('/refunds', requirePermission('refunds.create'), controller.create);
|
|
92
|
+
*/
|
|
55
93
|
const requirePermission = (...permissions) => guard((u) => (0, index_js_1.hasPermission)(u, ...permissions));
|
|
56
94
|
exports.requirePermission = requirePermission;
|
|
57
|
-
/**
|
|
58
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Allows callers holding every one of `permissions`. Accepts a list or rest arguments.
|
|
97
|
+
*
|
|
98
|
+
* @example router.delete('/x/:id', requireAllPermissions('x.read', 'x.delete'), controller.remove);
|
|
99
|
+
*/
|
|
100
|
+
const requireAllPermissions = (...permissions) => {
|
|
101
|
+
const required = permissions.flat();
|
|
102
|
+
return guard((u) => (0, index_js_1.hasAllPermissions)(u, ...required));
|
|
103
|
+
};
|
|
59
104
|
exports.requireAllPermissions = requireAllPermissions;
|
|
60
|
-
/**
|
|
105
|
+
/**
|
|
106
|
+
* Allows callers whose session passed the one-time-code (second factor) check; 403 FORBIDDEN otherwise.
|
|
107
|
+
*
|
|
108
|
+
* @example router.post('/security/settings', requireOtpVerified(), controller.update);
|
|
109
|
+
*/
|
|
110
|
+
const requireOtpVerified = () => guard((u) => u.otpVerified === true, 'One-time code verification is required');
|
|
111
|
+
exports.requireOtpVerified = requireOtpVerified;
|
|
112
|
+
/**
|
|
113
|
+
* Allows callers with any of `roles`. Prefer permissions; roles are for coarse gates only.
|
|
114
|
+
*
|
|
115
|
+
* @example router.use('/ops', requireRole('platform_admin'));
|
|
116
|
+
*/
|
|
61
117
|
const requireRole = (...roles) => guard((u) => (0, index_js_1.hasRole)(u, ...roles), 'Insufficient role');
|
|
62
118
|
exports.requireRole = requireRole;
|
|
63
|
-
/** Guards `/internal/*` routes: requires the shared service secret header. */
|
|
64
|
-
function requireInternalServiceSecret(secret) {
|
|
65
|
-
return (req, res, next) => {
|
|
66
|
-
const provided = req.headers[index_js_2.CONTEXT_HEADERS.INTERNAL_SECRET];
|
|
67
|
-
if (typeof provided === 'string' && secret && (0, crypto_js_1.safeEqual)(provided, secret))
|
|
68
|
-
return next();
|
|
69
|
-
res.status(401).json((0, response_js_1.errorResponse)('Invalid internal service credentials', undefined, 'UNAUTHENTICATED'));
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
119
|
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/express/auth.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/express/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,4 +18,7 @@ __exportStar(require("./auth.js"), exports);
|
|
|
18
18
|
__exportStar(require("./middleware.js"), exports);
|
|
19
19
|
__exportStar(require("./health.js"), exports);
|
|
20
20
|
__exportStar(require("./security.js"), exports);
|
|
21
|
+
__exportStar(require("./respond.js"), exports);
|
|
22
|
+
__exportStar(require("./step-up.js"), exports);
|
|
23
|
+
__exportStar(require("./internal-caller.js"), exports);
|
|
21
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/express/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,kDAAgC;AAChC,8CAA4B;AAC5B,gDAA8B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/express/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,kDAAgC;AAChC,8CAA4B;AAC5B,gDAA8B;AAC9B,+CAA6B;AAC7B,+CAA6B;AAC7B,uDAAqC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createInternalCallerGuards = createInternalCallerGuards;
|
|
4
|
+
const response_js_1 = require("../common/response.js");
|
|
5
|
+
const internal_service_auth_js_1 = require("../common/internal-service-auth.js");
|
|
6
|
+
const index_js_1 = require("../identity/index.js");
|
|
7
|
+
const middleware_js_1 = require("./middleware.js");
|
|
8
|
+
const isUnderPrefix = (path, prefix) => path === prefix || path.startsWith(`${prefix}/`);
|
|
9
|
+
/**
|
|
10
|
+
* Builds the internal-caller guard for a service, bound to its internal path prefix and accepted credentials.
|
|
11
|
+
*
|
|
12
|
+
* @param options Path prefix, credentials and logger.
|
|
13
|
+
* @returns `{ requireInternalCaller }`.
|
|
14
|
+
* @throws Error when the prefix is not an absolute path; ConfigError when env credentials are malformed.
|
|
15
|
+
* @example
|
|
16
|
+
* const { requireInternalCaller } = createInternalCallerGuards({ pathPrefix: '/internal', logger });
|
|
17
|
+
* router.get('/internal/records/:id', requireInternalCaller(['alpha-service']), controller.get);
|
|
18
|
+
*/
|
|
19
|
+
function createInternalCallerGuards(options) {
|
|
20
|
+
const prefix = options.pathPrefix.replace(/\/+$/, '');
|
|
21
|
+
if (!prefix.startsWith('/'))
|
|
22
|
+
throw new Error('createInternalCallerGuards: pathPrefix must be an absolute path such as /internal');
|
|
23
|
+
const credentials = options.credentials ?? (0, internal_service_auth_js_1.internalServiceAuthConfigFromEnv)().credentials;
|
|
24
|
+
return {
|
|
25
|
+
requireInternalCaller(allowed) {
|
|
26
|
+
if (!allowed.length)
|
|
27
|
+
throw new Error('requireInternalCaller: list at least one caller');
|
|
28
|
+
const callers = [...allowed];
|
|
29
|
+
return (req, res, next) => {
|
|
30
|
+
const path = (0, index_js_1.canonicalPath)(req.originalUrl);
|
|
31
|
+
const requestId = (0, middleware_js_1.correlationId)(req);
|
|
32
|
+
if (!isUnderPrefix(path, prefix)) {
|
|
33
|
+
options.logger?.warn('Internal guard outside the internal prefix', { path });
|
|
34
|
+
res.status(403).json((0, response_js_1.errorBody)('FORBIDDEN', 'Not an internal route', { requestId }));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const verdict = (0, internal_service_auth_js_1.verifyInternalCaller)({ headers: req.headers, credentials, allowed: callers });
|
|
38
|
+
if (verdict.ok) {
|
|
39
|
+
req.internalCaller = verdict.caller;
|
|
40
|
+
return next();
|
|
41
|
+
}
|
|
42
|
+
options.logger?.warn('Rejected internal caller', { reason: verdict.reason, caller: verdict.caller, path });
|
|
43
|
+
if (verdict.status === 401) {
|
|
44
|
+
res.status(401).json((0, response_js_1.errorBody)('UNAUTHENTICATED', 'Invalid internal service credentials', { requestId }));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
res.status(403).json((0, response_js_1.errorBody)('FORBIDDEN', 'This service may not call this route', { requestId }));
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=internal-caller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-caller.js","sourceRoot":"","sources":["../../../src/express/internal-caller.ts"],"names":[],"mappings":";;AA8DA,gEA+BC;AAjFD,uDAAkD;AAClD,iFAA4G;AAC5G,mDAAqD;AAErD,mDAAgD;AAkChD,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,MAAc,EAAW,EAAE,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;AAElH;;;;;;;;;GASG;AACH,SAAgB,0BAA0B,CAAC,OAAmC;IAC5E,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAC;IAClI,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,IAAA,2DAAgC,GAAE,CAAC,WAAW,CAAC;IAE1F,OAAO;QACL,qBAAqB,CAAC,OAAO;YAC3B,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACxF,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;YAC7B,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;gBACzD,MAAM,IAAI,GAAG,IAAA,wBAAa,EAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBAC5C,MAAM,SAAS,GAAG,IAAA,6BAAa,EAAC,GAAG,CAAC,CAAC;gBACrC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;oBACjC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,4CAA4C,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC7E,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,uBAAS,EAAC,WAAW,EAAE,uBAAuB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;oBACrF,OAAO;gBACT,CAAC;gBACD,MAAM,OAAO,GAAG,IAAA,+CAAoB,EAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC9F,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;oBACf,GAAG,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;oBACpC,OAAO,IAAI,EAAE,CAAC;gBAChB,CAAC;gBACD,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3G,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC3B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,uBAAS,EAAC,iBAAiB,EAAE,sCAAsC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;oBAC1G,OAAO;gBACT,CAAC;gBACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,uBAAS,EAAC,WAAW,EAAE,sCAAsC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YACtG,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|