aws-service-stack 0.18.371 → 0.18.372
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 +0 -149
- package/dist/controller/controller-api.d.ts +0 -8
- package/dist/controller/controller-api.js +1 -39
- package/dist/controller/controller-api.js.map +1 -1
- package/dist/controller/index.d.ts +0 -1
- package/dist/controller/index.js +0 -1
- package/dist/controller/index.js.map +1 -1
- package/dist/function/cognito/cognito.function.d.ts +0 -5
- package/dist/function/cognito/cognito.function.js +0 -22
- package/dist/function/cognito/cognito.function.js.map +1 -1
- package/dist/function/cognito/index.d.ts +1 -3
- package/dist/function/cognito/index.js +0 -2
- package/dist/function/cognito/index.js.map +1 -1
- package/dist/function/index.d.ts +0 -2
- package/dist/model/base.config.d.ts +1 -12
- package/dist/model/base.config.js +0 -20
- package/dist/model/base.config.js.map +1 -1
- package/dist/model/base.model.d.ts +0 -19
- package/dist/model/base.model.js +1 -14
- package/dist/model/base.model.js.map +1 -1
- package/dist/model/index.d.ts +0 -1
- package/dist/model/index.js.map +1 -1
- package/dist/model/validation.model.d.ts +1 -1
- package/dist/model/validation.model.js.map +1 -1
- package/dist/service/index.d.ts +0 -3
- package/dist/service/index.js +0 -3
- package/dist/service/index.js.map +1 -1
- package/dist/utils/data.util.d.ts +20 -0
- package/dist/utils/data.util.js +73 -0
- package/dist/utils/data.util.js.map +1 -0
- package/dist/utils/date.util.d.ts +13 -0
- package/dist/utils/date.util.js +35 -0
- package/dist/utils/date.util.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +31 -31
- package/dist/_examples/controller/property/property-crud.d.ts +0 -4
- package/dist/_examples/controller/property/property-crud.js +0 -58
- package/dist/_examples/controller/property/property-crud.js.map +0 -1
- package/dist/_examples/controller/property/property.config.d.ts +0 -10
- package/dist/_examples/controller/property/property.config.js +0 -55
- package/dist/_examples/controller/property/property.config.js.map +0 -1
- package/dist/_examples/controller/property/property.controller.d.ts +0 -14
- package/dist/_examples/controller/property/property.controller.js +0 -72
- package/dist/_examples/controller/property/property.controller.js.map +0 -1
- package/dist/_examples/controller/property/property.permissions.d.ts +0 -2
- package/dist/_examples/controller/property/property.permissions.js +0 -19
- package/dist/_examples/controller/property/property.permissions.js.map +0 -1
- package/dist/controller/controller-role.d.ts +0 -56
- package/dist/controller/controller-role.js +0 -140
- package/dist/controller/controller-role.js.map +0 -1
- package/dist/model/role.model.d.ts +0 -20
- package/dist/model/role.model.js +0 -12
- package/dist/model/role.model.js.map +0 -1
- package/dist/service/permission.cache.d.ts +0 -24
- package/dist/service/permission.cache.js +0 -61
- package/dist/service/permission.cache.js.map +0 -1
- package/dist/service/permission.repo.d.ts +0 -16
- package/dist/service/permission.repo.js +0 -63
- package/dist/service/permission.repo.js.map +0 -1
- package/dist/service/permission.service.d.ts +0 -39
- package/dist/service/permission.service.js +0 -151
- package/dist/service/permission.service.js.map +0 -1
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONFIG_PROPERTY = exports.PropertyConfig = exports.path = exports.openSearch_order = void 0;
|
|
4
|
-
const base_config_1 = require("../../../model/base.config");
|
|
5
|
-
const core_1 = require("../../../index.js");
|
|
6
|
-
const order_repo_db_interface_1 = require("../../repositories/order/order-repo-db.interface");
|
|
7
|
-
// OpenSearch configuration
|
|
8
|
-
exports.openSearch_order = {
|
|
9
|
-
domain: "https://search-amplify-opense-1ddfdekgbbpwe-kgxh6aum57h2wc4moozm2jcvom.ap-southeast-1.es.amazonaws.com",
|
|
10
|
-
index: "order",
|
|
11
|
-
};
|
|
12
|
-
exports.path = "/property"; // url path base
|
|
13
|
-
// Order configuration
|
|
14
|
-
class PropertyConfig extends base_config_1.EntityConfigImpl {
|
|
15
|
-
constructor() {
|
|
16
|
-
// DYNAMODB
|
|
17
|
-
const tableName = "Property-dev";
|
|
18
|
-
const ownerFieldName = "ownerId";
|
|
19
|
-
const indexMap = new core_1.DynamoIndexMap()
|
|
20
|
-
.setFields("ownerId")
|
|
21
|
-
.set("byAgent", { field: "agentId", rFields: ["agentId"] })
|
|
22
|
-
.set("propertyByBranch", { field: "branchId", rFields: ["branchId"] })
|
|
23
|
-
.set("byOrg", { field: "organizationId", rFields: ["organizationId"] });
|
|
24
|
-
// PERMISSIONS
|
|
25
|
-
const adminGroupNames = ["adminUsers"];
|
|
26
|
-
const policyList = [
|
|
27
|
-
{ method: core_1.HttpMethod.GET, path: `${exports.path}`, access: [core_1.Access.USER, core_1.Access.PUBLIC, core_1.Access.ADMIN] },
|
|
28
|
-
{ method: core_1.HttpMethod.GET, path: `${exports.path}/search`, access: [core_1.Access.USER], response: order_repo_db_interface_1.RESPONSE_FIELDS_LIST },
|
|
29
|
-
{ method: core_1.HttpMethod.GET, path: `${exports.path}/search/query`, access: [core_1.Access.USER], response: order_repo_db_interface_1.RESPONSE_FIELDS_LIST },
|
|
30
|
-
{ method: core_1.HttpMethod.GET, path: `${exports.path}/search/query/total-count`, access: [core_1.Access.USER] },
|
|
31
|
-
{ method: core_1.HttpMethod.GET, path: `${exports.path}/{id}`, access: [core_1.Access.USER], response: order_repo_db_interface_1.RESPONSE_FIELDS_DETAILS },
|
|
32
|
-
{ method: core_1.HttpMethod.POST, path: `${exports.path}`, access: [core_1.Access.USER], validator: order_repo_db_interface_1.CREATE, response: order_repo_db_interface_1.RESPONSE_FIELDS_DETAILS },
|
|
33
|
-
{ method: core_1.HttpMethod.PUT, path: `${exports.path}/{id}`, access: [core_1.Access.USER], validator: order_repo_db_interface_1.REPLACE, response: order_repo_db_interface_1.RESPONSE_FIELDS_DETAILS },
|
|
34
|
-
{ method: core_1.HttpMethod.PATCH, path: `${exports.path}/{id}`, access: [core_1.Access.USER], validator: order_repo_db_interface_1.UPDATE, response: order_repo_db_interface_1.RESPONSE_FIELDS_DETAILS },
|
|
35
|
-
{ method: core_1.HttpMethod.DELETE, path: `${exports.path}/{id}`, access: [core_1.Access.USER] },
|
|
36
|
-
];
|
|
37
|
-
// SCOPES
|
|
38
|
-
const scopeMap = new core_1.ScopeMap()
|
|
39
|
-
.set("branch", { filterField: "branchId", claimKey: "sub" })
|
|
40
|
-
.set("agent", { filterField: "agentId", claimKey: "custom:agent" })
|
|
41
|
-
.set("org", { filterField: "organizationId", claimKey: "custom:org" });
|
|
42
|
-
// INIT
|
|
43
|
-
super(exports.path, adminGroupNames);
|
|
44
|
-
this.setDynamoDB(tableName, ownerFieldName, indexMap)
|
|
45
|
-
.setOpenSearch(exports.openSearch_order.domain, exports.openSearch_order.index)
|
|
46
|
-
.setPolicies(policyList)
|
|
47
|
-
.setScopes(scopeMap)
|
|
48
|
-
.setRoleTable("Permission-dev")
|
|
49
|
-
.setRolePath("/permission/plp");
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
exports.PropertyConfig = PropertyConfig;
|
|
53
|
-
// Export default Order configuration
|
|
54
|
-
exports.CONFIG_PROPERTY = new PropertyConfig();
|
|
55
|
-
//# sourceMappingURL=property.config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"property.config.js","sourceRoot":"","sources":["../../../../src/_examples/controller/property/property.config.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityConfigImpl } from \"../../../model/base.config\";\nimport { Access as a, DynamoIndexMap, EndpointPolicy, HttpMethod as m, ScopeMap } from \"@chinggis/core\";\nimport {\n CREATE,\n REPLACE,\n RESPONSE_FIELDS_DETAILS as FIELDS_D,\n RESPONSE_FIELDS_LIST as FIELDS_L,\n UPDATE,\n} from \"../../repositories/order/order-repo-db.interface\";\n\n// OpenSearch configuration\nexport const openSearch_order = {\n domain: \"https://search-amplify-opense-1ddfdekgbbpwe-kgxh6aum57h2wc4moozm2jcvom.ap-southeast-1.es.amazonaws.com\",\n index: \"order\",\n};\nexport const path = \"/property\"; // url path base\n\n// Order configuration\nexport class PropertyConfig extends EntityConfigImpl {\n constructor() {\n // DYNAMODB\n const tableName = \"Property-dev\";\n const ownerFieldName = \"ownerId\";\n const indexMap = new DynamoIndexMap()\n .setFields(\"ownerId\")\n .set(\"byAgent\", { field: \"agentId\", rFields: [\"agentId\"] })\n .set(\"propertyByBranch\", { field: \"branchId\", rFields: [\"branchId\"] })\n .set(\"byOrg\", { field: \"organizationId\", rFields: [\"organizationId\"] });\n\n // PERMISSIONS\n const adminGroupNames = [\"adminUsers\"];\n\n const policyList: EndpointPolicy[] = [\n { method: m.GET, path: `${path}`, access: [a.USER, a.PUBLIC, a.ADMIN] },\n { method: m.GET, path: `${path}/search`, access: [a.USER], response: FIELDS_L },\n { method: m.GET, path: `${path}/search/query`, access: [a.USER], response: FIELDS_L },\n { method: m.GET, path: `${path}/search/query/total-count`, access: [a.USER] },\n { method: m.GET, path: `${path}/{id}`, access: [a.USER], response: FIELDS_D },\n { method: m.POST, path: `${path}`, access: [a.USER], validator: CREATE, response: FIELDS_D },\n { method: m.PUT, path: `${path}/{id}`, access: [a.USER], validator: REPLACE, response: FIELDS_D },\n { method: m.PATCH, path: `${path}/{id}`, access: [a.USER], validator: UPDATE, response: FIELDS_D },\n { method: m.DELETE, path: `${path}/{id}`, access: [a.USER] },\n ];\n\n // SCOPES\n const scopeMap = new ScopeMap()\n .set(\"branch\", { filterField: \"branchId\", claimKey: \"sub\" })\n .set(\"agent\", { filterField: \"agentId\", claimKey: \"custom:agent\" })\n .set(\"org\", { filterField: \"organizationId\", claimKey: \"custom:org\" });\n\n // INIT\n super(path, adminGroupNames);\n this.setDynamoDB(tableName, ownerFieldName, indexMap)\n .setOpenSearch(openSearch_order.domain, openSearch_order.index)\n .setPolicies(policyList)\n .setScopes(scopeMap)\n .setRoleTable(\"Permission-dev\")\n .setRolePath(\"/permission/plp\");\n }\n}\n\n// Export default Order configuration\nexport const CONFIG_PROPERTY = new PropertyConfig();\n"]}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { OrderService } from "../../service/order-service.interface";
|
|
2
|
-
import "../../service/order-service";
|
|
3
|
-
import { Order } from "src/_examples/model-shared/example.model";
|
|
4
|
-
import { HttpRequest } from "src/utils";
|
|
5
|
-
import { ControllerApi } from "src/controller";
|
|
6
|
-
/**
|
|
7
|
-
* Example Controller for Profile: Validator (Zod) is set centrally.
|
|
8
|
-
* Scopes are configured in PropertyConfig via ScopeMap.
|
|
9
|
-
*/
|
|
10
|
-
export declare class PropertyController extends ControllerApi<Order, OrderService> {
|
|
11
|
-
protected processCrudRequest(event: HttpRequest): Promise<any>;
|
|
12
|
-
constructor();
|
|
13
|
-
getPermission(permission: string): Promise<boolean>;
|
|
14
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
-
};
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
-
};
|
|
44
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.PropertyController = void 0;
|
|
46
|
-
const typedi_1 = __importStar(require("typedi"));
|
|
47
|
-
const property_config_1 = require("./property.config");
|
|
48
|
-
require("../../service/order-service");
|
|
49
|
-
const controller_1 = require("src/controller");
|
|
50
|
-
const property_permissions_1 = require("./property.permissions");
|
|
51
|
-
/**
|
|
52
|
-
* Example Controller for Profile: Validator (Zod) is set centrally.
|
|
53
|
-
* Scopes are configured in PropertyConfig via ScopeMap.
|
|
54
|
-
*/
|
|
55
|
-
let PropertyController = class PropertyController extends controller_1.ControllerApi {
|
|
56
|
-
processCrudRequest(event) {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
constructor() {
|
|
60
|
-
const service = typedi_1.default.get("OrderService");
|
|
61
|
-
super(service, property_config_1.CONFIG_PROPERTY.toObject());
|
|
62
|
-
}
|
|
63
|
-
async getPermission(permission) {
|
|
64
|
-
return (0, property_permissions_1.hasPropertyPermission)(permission);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
exports.PropertyController = PropertyController;
|
|
68
|
-
exports.PropertyController = PropertyController = __decorate([
|
|
69
|
-
(0, typedi_1.Service)("PropertyController"),
|
|
70
|
-
__metadata("design:paramtypes", [])
|
|
71
|
-
], PropertyController);
|
|
72
|
-
//# sourceMappingURL=property.controller.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"property.controller.js","sourceRoot":"","sources":["../../../../src/_examples/controller/property/property.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAA4C;AAG5C,uDAAoD;AAEpD,uCAAqC;AAGrC,+CAA+C;AAC/C,iEAA+D;AAE/D;;;GAGG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAmB,SAAQ,0BAAkC;IAC9D,kBAAkB,CAAC,KAAkB;QAC7C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;QACE,MAAM,OAAO,GAAiB,gBAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC5D,KAAK,CAAC,OAAO,EAAE,iCAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,UAAkB;QACpC,OAAO,IAAA,4CAAqB,EAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;CACF,CAAA;AAbY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,gBAAO,EAAC,oBAAoB,CAAC;;GACjB,kBAAkB,CAa9B","sourcesContent":["import Container, { Service } from \"typedi\";\nimport {} from \"../../../controller/base-controller\";\n\nimport { CONFIG_PROPERTY } from \"./property.config\";\nimport { OrderService } from \"../../service/order-service.interface\";\nimport \"../../service/order-service\";\nimport { Order } from \"src/_examples/model-shared/example.model\";\nimport { HttpRequest } from \"src/utils\";\nimport { ControllerApi } from \"src/controller\";\nimport { hasPropertyPermission } from \"./property.permissions\";\n\n/**\n * Example Controller for Profile: Validator (Zod) is set centrally.\n * Scopes are configured in PropertyConfig via ScopeMap.\n */\n@Service(\"PropertyController\")\nexport class PropertyController extends ControllerApi<Order, OrderService> {\n protected processCrudRequest(event: HttpRequest): Promise<any> {\n return undefined;\n }\n\n constructor() {\n const service: OrderService = Container.get(\"OrderService\");\n super(service, CONFIG_PROPERTY.toObject());\n }\n\n async getPermission(permission: string): Promise<boolean> {\n return hasPropertyPermission(permission);\n }\n}\n"]}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PROPERTY_PERMISSION_KEYS = void 0;
|
|
4
|
-
exports.hasPropertyPermission = hasPropertyPermission;
|
|
5
|
-
exports.PROPERTY_PERMISSION_KEYS = new Set([
|
|
6
|
-
"adminusers.property.branch.GET",
|
|
7
|
-
"adminusers.property.branch.POST",
|
|
8
|
-
"user.property.branch.GET",
|
|
9
|
-
"user.property.agent.GET",
|
|
10
|
-
"user.property.agent.POST",
|
|
11
|
-
"owner.property.branch.GET",
|
|
12
|
-
"owner.property.branch.POST",
|
|
13
|
-
"owner.property.agent.GET",
|
|
14
|
-
"owner.property.agent.POST",
|
|
15
|
-
]);
|
|
16
|
-
function hasPropertyPermission(permission) {
|
|
17
|
-
return exports.PROPERTY_PERMISSION_KEYS.has(permission);
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=property.permissions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"property.permissions.js","sourceRoot":"","sources":["../../../../src/_examples/controller/property/property.permissions.ts"],"names":[],"mappings":";;;AAYA,sDAEC;AAdY,QAAA,wBAAwB,GAAG,IAAI,GAAG,CAAS;IACtD,gCAAgC;IAChC,iCAAiC;IACjC,0BAA0B;IAC1B,yBAAyB;IACzB,0BAA0B;IAC1B,2BAA2B;IAC3B,4BAA4B;IAC5B,0BAA0B;IAC1B,2BAA2B;CAC5B,CAAC,CAAC;AAEH,SAAgB,qBAAqB,CAAC,UAAkB;IACtD,OAAO,gCAAwB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAClD,CAAC","sourcesContent":["export const PROPERTY_PERMISSION_KEYS = new Set<string>([\n \"adminusers.property.branch.GET\",\n \"adminusers.property.branch.POST\",\n \"user.property.branch.GET\",\n \"user.property.agent.GET\",\n \"user.property.agent.POST\",\n \"owner.property.branch.GET\",\n \"owner.property.branch.POST\",\n \"owner.property.agent.GET\",\n \"owner.property.agent.POST\",\n]);\n\nexport function hasPropertyPermission(permission: string): boolean {\n return PROPERTY_PERMISSION_KEYS.has(permission);\n}\n"]}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Permission } from "../model/role.model";
|
|
2
|
-
import { ScopeMap } from "../model/base.model";
|
|
3
|
-
import { HttpRequest } from "../utils/http/http.util";
|
|
4
|
-
import { PermissionService } from "../service/permission.service";
|
|
5
|
-
/**
|
|
6
|
-
* ControllerRole — centralized Permission CRUD + RBAC access enforcement.
|
|
7
|
-
*
|
|
8
|
-
* All caching and DB orchestration lives in PermissionService.
|
|
9
|
-
*
|
|
10
|
-
* Scope validation, scope filtering, and permission checks are centralized here
|
|
11
|
-
* so that ControllerApi (and any other consumer) delegates without duplicating logic.
|
|
12
|
-
*/
|
|
13
|
-
export declare class ControllerRole {
|
|
14
|
-
protected readonly permissionService: PermissionService;
|
|
15
|
-
constructor(roleTableName: string);
|
|
16
|
-
addPermission(input: {
|
|
17
|
-
role: string;
|
|
18
|
-
resource: string;
|
|
19
|
-
scope: string;
|
|
20
|
-
method: Permission["method"];
|
|
21
|
-
}): Promise<Permission>;
|
|
22
|
-
updatePermission(id: string, updates: Partial<Pick<Permission, "role" | "resource" | "scope" | "method">>): Promise<Permission>;
|
|
23
|
-
deletePermission(id: string): Promise<boolean>;
|
|
24
|
-
getPermission(id: string): Promise<Permission | null>;
|
|
25
|
-
listPermissions(): Promise<Permission[]>;
|
|
26
|
-
addRole(userPoolId: string, groupName: string, description?: string): Promise<{
|
|
27
|
-
groupName: string;
|
|
28
|
-
description?: string;
|
|
29
|
-
}>;
|
|
30
|
-
assignRole(userPoolId: string, username: string, groupName: string): Promise<void>;
|
|
31
|
-
hasPermission(role: string, resource: string, scope: string, method: string): Promise<boolean>;
|
|
32
|
-
getPermissionByKey(permissionKey: string): Promise<Permission | null>;
|
|
33
|
-
/**
|
|
34
|
-
* Centralized RBAC check: validates scope, checks permission via DB, applies scope filter.
|
|
35
|
-
*
|
|
36
|
-
* Only runs when both `role` and `scope` are present in the request.
|
|
37
|
-
* When either is absent, scope filters are cleared to block user injection.
|
|
38
|
-
*
|
|
39
|
-
* @param req The parsed HTTP request
|
|
40
|
-
* @param resource The resource name (e.g. "property")
|
|
41
|
-
* @param scopeMap The scope configuration from EntityConfig
|
|
42
|
-
*/
|
|
43
|
-
checkRbacAccess(req: HttpRequest, resource: string, scopeMap: ScopeMap): Promise<void>;
|
|
44
|
-
/** Extract user role from JWT groups. */
|
|
45
|
-
private extractRole;
|
|
46
|
-
/** Resolve and validate the scope query param against the ScopeMap. */
|
|
47
|
-
private resolveScope;
|
|
48
|
-
/**
|
|
49
|
-
* Apply scope-based data filter from identity claims.
|
|
50
|
-
* Clears ALL scope-controlled filter fields first (block injection),
|
|
51
|
-
* then sets only the matched scope's claim value.
|
|
52
|
-
*/
|
|
53
|
-
private applyScopeFilter;
|
|
54
|
-
/** Clear all scope-controlled filter fields — prevents user injection when no RBAC applies. */
|
|
55
|
-
private removeScopeFilter;
|
|
56
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ControllerRole = void 0;
|
|
4
|
-
const exception_1 = require("../exception");
|
|
5
|
-
const permission_service_1 = require("../service/permission.service");
|
|
6
|
-
const cognito_1 = require("../function/cognito");
|
|
7
|
-
/**
|
|
8
|
-
* ControllerRole — centralized Permission CRUD + RBAC access enforcement.
|
|
9
|
-
*
|
|
10
|
-
* All caching and DB orchestration lives in PermissionService.
|
|
11
|
-
*
|
|
12
|
-
* Scope validation, scope filtering, and permission checks are centralized here
|
|
13
|
-
* so that ControllerApi (and any other consumer) delegates without duplicating logic.
|
|
14
|
-
*/
|
|
15
|
-
class ControllerRole {
|
|
16
|
-
permissionService;
|
|
17
|
-
constructor(roleTableName) {
|
|
18
|
-
this.permissionService = new permission_service_1.PermissionService(roleTableName);
|
|
19
|
-
}
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
// CRUD
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
async addPermission(input) {
|
|
24
|
-
return this.permissionService.createPermission(input);
|
|
25
|
-
}
|
|
26
|
-
async updatePermission(id, updates) {
|
|
27
|
-
return this.permissionService.updatePermission(id, updates);
|
|
28
|
-
}
|
|
29
|
-
async deletePermission(id) {
|
|
30
|
-
return this.permissionService.deletePermission(id);
|
|
31
|
-
}
|
|
32
|
-
async getPermission(id) {
|
|
33
|
-
if (!id)
|
|
34
|
-
throw new exception_1.ErrorHttp({ code: 400, error: "BadRequest" }, "Permission id is required");
|
|
35
|
-
return this.permissionService.getPermissionById(id);
|
|
36
|
-
}
|
|
37
|
-
async listPermissions() {
|
|
38
|
-
return this.permissionService.listPermissions();
|
|
39
|
-
}
|
|
40
|
-
// ---------------------------------------------------------------------------
|
|
41
|
-
// Role (Cognito group)
|
|
42
|
-
// ---------------------------------------------------------------------------
|
|
43
|
-
async addRole(userPoolId, groupName, description) {
|
|
44
|
-
return (0, cognito_1.createGroup)(userPoolId, groupName, description);
|
|
45
|
-
}
|
|
46
|
-
async assignRole(userPoolId, username, groupName) {
|
|
47
|
-
return (0, cognito_1.addUserToGroup)(userPoolId, username, groupName);
|
|
48
|
-
}
|
|
49
|
-
// ---------------------------------------------------------------------------
|
|
50
|
-
// Permission check
|
|
51
|
-
// ---------------------------------------------------------------------------
|
|
52
|
-
async hasPermission(role, resource, scope, method) {
|
|
53
|
-
return this.permissionService.hasPermission(role, resource, scope, method);
|
|
54
|
-
}
|
|
55
|
-
async getPermissionByKey(permissionKey) {
|
|
56
|
-
return this.permissionService.getPermissionByKey(permissionKey);
|
|
57
|
-
}
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
// RBAC access enforcement (used by ControllerApi)
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
/**
|
|
62
|
-
* Centralized RBAC check: validates scope, checks permission via DB, applies scope filter.
|
|
63
|
-
*
|
|
64
|
-
* Only runs when both `role` and `scope` are present in the request.
|
|
65
|
-
* When either is absent, scope filters are cleared to block user injection.
|
|
66
|
-
*
|
|
67
|
-
* @param req The parsed HTTP request
|
|
68
|
-
* @param resource The resource name (e.g. "property")
|
|
69
|
-
* @param scopeMap The scope configuration from EntityConfig
|
|
70
|
-
*/
|
|
71
|
-
async checkRbacAccess(req, resource, scopeMap) {
|
|
72
|
-
const role = this.extractRole(req);
|
|
73
|
-
const scope = this.resolveScope(req, scopeMap);
|
|
74
|
-
const method = req.methode.toUpperCase();
|
|
75
|
-
if (role && scope) {
|
|
76
|
-
const allowed = await this.permissionService.hasPermission(role, resource, scope, method);
|
|
77
|
-
if (!allowed) {
|
|
78
|
-
const key = `${role}#${resource}#${scope}`;
|
|
79
|
-
throw new exception_1.ErrorHttp({ code: 403, error: "PermissionDenied" }, `Permission denied: role="${role}" lacks "${key}.${method}"`);
|
|
80
|
-
}
|
|
81
|
-
this.applyScopeFilter(req, scope, scopeMap);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
this.removeScopeFilter(req, scopeMap);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// ---------------------------------------------------------------------------
|
|
88
|
-
// Scope helpers (private — single source of truth)
|
|
89
|
-
// ---------------------------------------------------------------------------
|
|
90
|
-
/** Extract user role from JWT groups. */
|
|
91
|
-
extractRole(req) {
|
|
92
|
-
return req.identity?.groups?.[0];
|
|
93
|
-
}
|
|
94
|
-
/** Resolve and validate the scope query param against the ScopeMap. */
|
|
95
|
-
resolveScope(req, scopeMap) {
|
|
96
|
-
if (!scopeMap?.size)
|
|
97
|
-
return undefined;
|
|
98
|
-
const scope = req.queryStringParameters?.scope || req.customQueryParameters?.scope;
|
|
99
|
-
if (!scope)
|
|
100
|
-
return undefined;
|
|
101
|
-
if (!scopeMap.has(scope)) {
|
|
102
|
-
const allowed = Array.from(scopeMap.keys()).join(", ");
|
|
103
|
-
throw new exception_1.ErrorHttp({ code: 400, error: "BadRequest" }, `Invalid scope "${scope}". Allowed: ${allowed}`);
|
|
104
|
-
}
|
|
105
|
-
return scope;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Apply scope-based data filter from identity claims.
|
|
109
|
-
* Clears ALL scope-controlled filter fields first (block injection),
|
|
110
|
-
* then sets only the matched scope's claim value.
|
|
111
|
-
*/
|
|
112
|
-
applyScopeFilter(req, scope, scopeMap) {
|
|
113
|
-
if (!req.filter)
|
|
114
|
-
req.filter = {};
|
|
115
|
-
for (const [, entry] of scopeMap) {
|
|
116
|
-
delete req.filter[entry.filterField];
|
|
117
|
-
}
|
|
118
|
-
const mapping = scopeMap.get(scope);
|
|
119
|
-
if (!mapping)
|
|
120
|
-
return;
|
|
121
|
-
const claimKey = mapping.claimKey ?? "custom:" + scope;
|
|
122
|
-
const claimValue = req.identity?.[claimKey] || req.identity?.attributes?.[claimKey];
|
|
123
|
-
if (!claimValue) {
|
|
124
|
-
throw new exception_1.ErrorHttp({ code: 403, error: "PermissionDenied" }, `Missing claim "${claimKey}" for scope "${scope}"`);
|
|
125
|
-
}
|
|
126
|
-
req.filter[mapping.filterField] = claimValue;
|
|
127
|
-
delete req.filter?.scope;
|
|
128
|
-
}
|
|
129
|
-
/** Clear all scope-controlled filter fields — prevents user injection when no RBAC applies. */
|
|
130
|
-
removeScopeFilter(req, scopeMap) {
|
|
131
|
-
if (!req.filter)
|
|
132
|
-
req.filter = {};
|
|
133
|
-
for (const [, entry] of scopeMap) {
|
|
134
|
-
delete req.filter[entry.filterField];
|
|
135
|
-
}
|
|
136
|
-
delete req.filter["scope"];
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
exports.ControllerRole = ControllerRole;
|
|
140
|
-
//# sourceMappingURL=controller-role.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"controller-role.js","sourceRoot":"","sources":["../../src/controller/controller-role.ts"],"names":[],"mappings":"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","sourcesContent":["import { ErrorHttp } from \"../exception\";\nimport { Permission } from \"../model/role.model\";\nimport { ScopeMap } from \"../model/base.model\";\nimport { HttpRequest } from \"../utils/http/http.util\";\nimport { PermissionService } from \"../service/permission.service\";\nimport { createGroup, addUserToGroup } from \"../function/cognito\";\n\n/**\n * ControllerRole — centralized Permission CRUD + RBAC access enforcement.\n *\n * All caching and DB orchestration lives in PermissionService.\n *\n * Scope validation, scope filtering, and permission checks are centralized here\n * so that ControllerApi (and any other consumer) delegates without duplicating logic.\n */\nexport class ControllerRole {\n protected readonly permissionService: PermissionService;\n\n constructor(roleTableName: string) {\n this.permissionService = new PermissionService(roleTableName);\n }\n\n // ---------------------------------------------------------------------------\n // CRUD\n // ---------------------------------------------------------------------------\n\n async addPermission(input: {\n role: string;\n resource: string;\n scope: string;\n method: Permission[\"method\"];\n }): Promise<Permission> {\n return this.permissionService.createPermission(input);\n }\n\n async updatePermission(\n id: string,\n updates: Partial<Pick<Permission, \"role\" | \"resource\" | \"scope\" | \"method\">>,\n ): Promise<Permission> {\n return this.permissionService.updatePermission(id, updates);\n }\n\n async deletePermission(id: string): Promise<boolean> {\n return this.permissionService.deletePermission(id);\n }\n\n async getPermission(id: string): Promise<Permission | null> {\n if (!id) throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Permission id is required\");\n return this.permissionService.getPermissionById(id);\n }\n\n async listPermissions(): Promise<Permission[]> {\n return this.permissionService.listPermissions();\n }\n\n // ---------------------------------------------------------------------------\n // Role (Cognito group)\n // ---------------------------------------------------------------------------\n\n async addRole(userPoolId: string, groupName: string, description?: string) {\n return createGroup(userPoolId, groupName, description);\n }\n\n async assignRole(userPoolId: string, username: string, groupName: string): Promise<void> {\n return addUserToGroup(userPoolId, username, groupName);\n }\n\n // ---------------------------------------------------------------------------\n // Permission check\n // ---------------------------------------------------------------------------\n\n async hasPermission(role: string, resource: string, scope: string, method: string): Promise<boolean> {\n return this.permissionService.hasPermission(role, resource, scope, method);\n }\n\n async getPermissionByKey(permissionKey: string): Promise<Permission | null> {\n return this.permissionService.getPermissionByKey(permissionKey);\n }\n\n // ---------------------------------------------------------------------------\n // RBAC access enforcement (used by ControllerApi)\n // ---------------------------------------------------------------------------\n\n /**\n * Centralized RBAC check: validates scope, checks permission via DB, applies scope filter.\n *\n * Only runs when both `role` and `scope` are present in the request.\n * When either is absent, scope filters are cleared to block user injection.\n *\n * @param req The parsed HTTP request\n * @param resource The resource name (e.g. \"property\")\n * @param scopeMap The scope configuration from EntityConfig\n */\n async checkRbacAccess(req: HttpRequest, resource: string, scopeMap: ScopeMap): Promise<void> {\n const role = this.extractRole(req);\n const scope = this.resolveScope(req, scopeMap);\n const method = req.methode.toUpperCase();\n\n if (role && scope) {\n const allowed = await this.permissionService.hasPermission(role, resource, scope, method);\n\n if (!allowed) {\n const key = `${role}#${resource}#${scope}`;\n throw new ErrorHttp(\n { code: 403, error: \"PermissionDenied\" },\n `Permission denied: role=\"${role}\" lacks \"${key}.${method}\"`,\n );\n }\n\n this.applyScopeFilter(req, scope, scopeMap);\n } else {\n this.removeScopeFilter(req, scopeMap);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Scope helpers (private — single source of truth)\n // ---------------------------------------------------------------------------\n\n /** Extract user role from JWT groups. */\n private extractRole(req: HttpRequest): string | undefined {\n return req.identity?.groups?.[0];\n }\n\n /** Resolve and validate the scope query param against the ScopeMap. */\n private resolveScope(req: HttpRequest, scopeMap: ScopeMap): string | undefined {\n if (!scopeMap?.size) return undefined;\n\n const scope = req.queryStringParameters?.scope || req.customQueryParameters?.scope;\n if (!scope) return undefined;\n\n if (!scopeMap.has(scope)) {\n const allowed = Array.from(scopeMap.keys()).join(\", \");\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, `Invalid scope \"${scope}\". Allowed: ${allowed}`);\n }\n\n return scope;\n }\n\n /**\n * Apply scope-based data filter from identity claims.\n * Clears ALL scope-controlled filter fields first (block injection),\n * then sets only the matched scope's claim value.\n */\n private applyScopeFilter(req: HttpRequest, scope: string, scopeMap: ScopeMap): void {\n if (!req.filter) req.filter = {};\n\n for (const [, entry] of scopeMap) {\n delete req.filter[entry.filterField];\n }\n\n const mapping = scopeMap.get(scope);\n if (!mapping) return;\n\n const claimKey = mapping.claimKey ?? \"custom:\" + scope;\n const claimValue = req.identity?.[claimKey] || req.identity?.attributes?.[claimKey];\n\n if (!claimValue) {\n throw new ErrorHttp({ code: 403, error: \"PermissionDenied\" }, `Missing claim \"${claimKey}\" for scope \"${scope}\"`);\n }\n\n req.filter[mapping.filterField] = claimValue;\n delete req.filter?.scope;\n }\n\n /** Clear all scope-controlled filter fields — prevents user injection when no RBAC applies. */\n private removeScopeFilter(req: HttpRequest, scopeMap: ScopeMap): void {\n if (!req.filter) req.filter = {};\n\n for (const [, entry] of scopeMap) {\n delete req.filter[entry.filterField];\n }\n delete req.filter[\"scope\"];\n }\n}\n"]}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { BaseEntity } from "./base.model";
|
|
2
|
-
export interface Permission extends BaseEntity {
|
|
3
|
-
role: string;
|
|
4
|
-
resource: string;
|
|
5
|
-
scope: string;
|
|
6
|
-
method: {
|
|
7
|
-
get?: boolean;
|
|
8
|
-
post?: boolean;
|
|
9
|
-
patch?: boolean;
|
|
10
|
-
put?: boolean;
|
|
11
|
-
delete?: boolean;
|
|
12
|
-
};
|
|
13
|
-
permissionKey: string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Build a fully-qualified permission key.
|
|
17
|
-
* Format: `${role}.${resource}.${scope}.${method}`
|
|
18
|
-
* Example: `OwnerRole.PropertyTable.BranchScope.GET`
|
|
19
|
-
*/
|
|
20
|
-
export declare function buildPermissionKey(role: string, resource: string, scope: string, method: string): string;
|
package/dist/model/role.model.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildPermissionKey = buildPermissionKey;
|
|
4
|
-
/**
|
|
5
|
-
* Build a fully-qualified permission key.
|
|
6
|
-
* Format: `${role}.${resource}.${scope}.${method}`
|
|
7
|
-
* Example: `OwnerRole.PropertyTable.BranchScope.GET`
|
|
8
|
-
*/
|
|
9
|
-
function buildPermissionKey(role, resource, scope, method) {
|
|
10
|
-
return `${role}.${resource}.${scope}.${method}`;
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=role.model.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"role.model.js","sourceRoot":"","sources":["../../src/model/role.model.ts"],"names":[],"mappings":";;AAqBA,gDAEC;AAPD;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,IAAY,EAAE,QAAgB,EAAE,KAAa,EAAE,MAAc;IAC9F,OAAO,GAAG,IAAI,IAAI,QAAQ,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;AAClD,CAAC","sourcesContent":["import { BaseEntity } from \"./base.model\";\n\nexport interface Permission extends BaseEntity {\n role: string; // DB Index: Manager | User etc\n resource: string; // DB Index: Property | Profile etc\n scope: string; // DB Index: Organization | Branch | Agent\n method: {\n get?: boolean;\n post?: boolean;\n patch?: boolean;\n put?: boolean;\n delete?: boolean;\n };\n permissionKey: string; // DB Index: role#resourse#scope Manager#Property#Branch\n}\n\n/**\n * Build a fully-qualified permission key.\n * Format: `${role}.${resource}.${scope}.${method}`\n * Example: `OwnerRole.PropertyTable.BranchScope.GET`\n */\nexport function buildPermissionKey(role: string, resource: string, scope: string, method: string): string {\n return `${role}.${resource}.${scope}.${method}`;\n}\n"]}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Permission } from "../model/role.model";
|
|
2
|
-
/**
|
|
3
|
-
* In-memory read-through cache for Permission entities.
|
|
4
|
-
*
|
|
5
|
-
* - Keyed by permissionKey (deterministic, namespaced).
|
|
6
|
-
* - TTL-based expiry per entry.
|
|
7
|
-
* - Survives across warm Lambda invocations (module-level singleton).
|
|
8
|
-
* - Handles concurrent fetches for the same key via in-flight dedup.
|
|
9
|
-
*/
|
|
10
|
-
export declare class PermissionCache {
|
|
11
|
-
private readonly store;
|
|
12
|
-
private readonly inflight;
|
|
13
|
-
private readonly ttlMs;
|
|
14
|
-
constructor(ttlMs?: number);
|
|
15
|
-
get(key: string): Permission | null;
|
|
16
|
-
set(key: string, value: Permission): void;
|
|
17
|
-
/**
|
|
18
|
-
* Read-through: returns cached value or calls `fetcher` exactly once.
|
|
19
|
-
* Concurrent calls for the same key share a single in-flight promise.
|
|
20
|
-
*/
|
|
21
|
-
getOrFetch(key: string, fetcher: () => Promise<Permission | null>): Promise<Permission | null>;
|
|
22
|
-
invalidate(key: string): void;
|
|
23
|
-
clear(): void;
|
|
24
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PermissionCache = void 0;
|
|
4
|
-
const DEFAULT_TTL_MS = 15 * 60 * 1000; // 15 minutes
|
|
5
|
-
/**
|
|
6
|
-
* In-memory read-through cache for Permission entities.
|
|
7
|
-
*
|
|
8
|
-
* - Keyed by permissionKey (deterministic, namespaced).
|
|
9
|
-
* - TTL-based expiry per entry.
|
|
10
|
-
* - Survives across warm Lambda invocations (module-level singleton).
|
|
11
|
-
* - Handles concurrent fetches for the same key via in-flight dedup.
|
|
12
|
-
*/
|
|
13
|
-
class PermissionCache {
|
|
14
|
-
store = new Map();
|
|
15
|
-
inflight = new Map();
|
|
16
|
-
ttlMs;
|
|
17
|
-
constructor(ttlMs = DEFAULT_TTL_MS) {
|
|
18
|
-
this.ttlMs = ttlMs;
|
|
19
|
-
}
|
|
20
|
-
get(key) {
|
|
21
|
-
const entry = this.store.get(key);
|
|
22
|
-
if (!entry)
|
|
23
|
-
return null;
|
|
24
|
-
if (Date.now() > entry.expiresAt) {
|
|
25
|
-
this.store.delete(key);
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
return entry.value;
|
|
29
|
-
}
|
|
30
|
-
set(key, value) {
|
|
31
|
-
this.store.set(key, { value, expiresAt: Date.now() + this.ttlMs });
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Read-through: returns cached value or calls `fetcher` exactly once.
|
|
35
|
-
* Concurrent calls for the same key share a single in-flight promise.
|
|
36
|
-
*/
|
|
37
|
-
async getOrFetch(key, fetcher) {
|
|
38
|
-
const cached = this.get(key);
|
|
39
|
-
if (cached)
|
|
40
|
-
return cached;
|
|
41
|
-
const existing = this.inflight.get(key);
|
|
42
|
-
if (existing)
|
|
43
|
-
return existing;
|
|
44
|
-
const promise = fetcher().then((result) => {
|
|
45
|
-
this.inflight.delete(key);
|
|
46
|
-
if (result)
|
|
47
|
-
this.set(key, result);
|
|
48
|
-
return result;
|
|
49
|
-
});
|
|
50
|
-
this.inflight.set(key, promise);
|
|
51
|
-
return promise;
|
|
52
|
-
}
|
|
53
|
-
invalidate(key) {
|
|
54
|
-
this.store.delete(key);
|
|
55
|
-
}
|
|
56
|
-
clear() {
|
|
57
|
-
this.store.clear();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
exports.PermissionCache = PermissionCache;
|
|
61
|
-
//# sourceMappingURL=permission.cache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"permission.cache.js","sourceRoot":"","sources":["../../src/service/permission.cache.ts"],"names":[],"mappings":";;;AAOA,MAAM,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAEpD;;;;;;;GAOG;AACH,MAAa,eAAe;IACT,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IACtC,QAAQ,GAAG,IAAI,GAAG,EAAsC,CAAC;IACzD,KAAK,CAAS;IAE/B,YAAY,QAAgB,cAAc;QACxC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAiB;QAChC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,OAAyC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAE9B,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACxC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,IAAI,MAAM;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAClC,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,UAAU,CAAC,GAAW;QACpB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AAnDD,0CAmDC","sourcesContent":["import { Permission } from \"../model/role.model\";\n\ninterface CacheEntry {\n value: Permission;\n expiresAt: number;\n}\n\nconst DEFAULT_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n/**\n * In-memory read-through cache for Permission entities.\n *\n * - Keyed by permissionKey (deterministic, namespaced).\n * - TTL-based expiry per entry.\n * - Survives across warm Lambda invocations (module-level singleton).\n * - Handles concurrent fetches for the same key via in-flight dedup.\n */\nexport class PermissionCache {\n private readonly store = new Map<string, CacheEntry>();\n private readonly inflight = new Map<string, Promise<Permission | null>>();\n private readonly ttlMs: number;\n\n constructor(ttlMs: number = DEFAULT_TTL_MS) {\n this.ttlMs = ttlMs;\n }\n\n get(key: string): Permission | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return null;\n }\n return entry.value;\n }\n\n set(key: string, value: Permission): void {\n this.store.set(key, { value, expiresAt: Date.now() + this.ttlMs });\n }\n\n /**\n * Read-through: returns cached value or calls `fetcher` exactly once.\n * Concurrent calls for the same key share a single in-flight promise.\n */\n async getOrFetch(key: string, fetcher: () => Promise<Permission | null>): Promise<Permission | null> {\n const cached = this.get(key);\n if (cached) return cached;\n\n const existing = this.inflight.get(key);\n if (existing) return existing;\n\n const promise = fetcher().then((result) => {\n this.inflight.delete(key);\n if (result) this.set(key, result);\n return result;\n });\n\n this.inflight.set(key, promise);\n return promise;\n }\n\n invalidate(key: string): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n}\n"]}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Permission } from "../model/role.model";
|
|
2
|
-
import { List } from "../model/base.model";
|
|
3
|
-
/**
|
|
4
|
-
* Repository layer for Permission table.
|
|
5
|
-
* Pure DB operations — no caching, no business logic.
|
|
6
|
-
*/
|
|
7
|
-
export declare class PermissionRepo {
|
|
8
|
-
private readonly db;
|
|
9
|
-
constructor(tableName: string);
|
|
10
|
-
findById(id: string): Promise<Permission | null>;
|
|
11
|
-
findByPermissionKey(permissionKey: string): Promise<Permission | null>;
|
|
12
|
-
save(permission: Partial<Permission>): Promise<Permission>;
|
|
13
|
-
update(permission: Partial<Permission>): Promise<Permission>;
|
|
14
|
-
delete(id: string): Promise<boolean>;
|
|
15
|
-
scan(): Promise<List<Partial<Permission>>>;
|
|
16
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PermissionRepo = void 0;
|
|
4
|
-
const base_db_repo_1 = require("../repositories/base-db.repo");
|
|
5
|
-
const dynamodb_model_1 = require("../model/dynamodb.model");
|
|
6
|
-
const dynamodb_utils_1 = require("../utils/dynamodb.utils");
|
|
7
|
-
function createPermissionIndexMap() {
|
|
8
|
-
const map = new dynamodb_model_1.DynamoIndexMap();
|
|
9
|
-
map.partitionKey = "id";
|
|
10
|
-
map.set("byPermissionKey", { field: "permissionKey", rFields: ["role", "resource", "scope"], fieldSeparator: "#" });
|
|
11
|
-
map.mapFields = ["method"];
|
|
12
|
-
return map;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Repository layer for Permission table.
|
|
16
|
-
* Pure DB operations — no caching, no business logic.
|
|
17
|
-
*/
|
|
18
|
-
class PermissionRepo {
|
|
19
|
-
db;
|
|
20
|
-
constructor(tableName) {
|
|
21
|
-
this.db = new base_db_repo_1.BaseRepoDBImpl();
|
|
22
|
-
this.db.setTable(tableName);
|
|
23
|
-
this.db.setIndexMap(createPermissionIndexMap());
|
|
24
|
-
}
|
|
25
|
-
async findById(id) {
|
|
26
|
-
return this.db.findById(id);
|
|
27
|
-
}
|
|
28
|
-
async findByPermissionKey(permissionKey) {
|
|
29
|
-
return this.db.findOne({
|
|
30
|
-
indexName: "byPermissionKey",
|
|
31
|
-
indexValue: permissionKey,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
async save(permission) {
|
|
35
|
-
if (!permission.id)
|
|
36
|
-
permission.id = (0, dynamodb_utils_1.generateUUID)();
|
|
37
|
-
const now = new Date().toISOString();
|
|
38
|
-
if (!permission.createdAt)
|
|
39
|
-
permission.createdAt = now;
|
|
40
|
-
permission.updatedAt = now;
|
|
41
|
-
// Build composite key: role#resource#scope
|
|
42
|
-
if (permission.role && permission.resource && permission.scope) {
|
|
43
|
-
permission.permissionKey = `${permission.role}#${permission.resource}#${permission.scope}`;
|
|
44
|
-
}
|
|
45
|
-
return this.db.save(permission);
|
|
46
|
-
}
|
|
47
|
-
async update(permission) {
|
|
48
|
-
permission.updatedAt = new Date().toISOString();
|
|
49
|
-
// Rebuild composite key if components changed
|
|
50
|
-
if (permission.role && permission.resource && permission.scope) {
|
|
51
|
-
permission.permissionKey = `${permission.role}#${permission.resource}#${permission.scope}`;
|
|
52
|
-
}
|
|
53
|
-
return this.db.update(permission);
|
|
54
|
-
}
|
|
55
|
-
async delete(id) {
|
|
56
|
-
return this.db.delete(id);
|
|
57
|
-
}
|
|
58
|
-
async scan() {
|
|
59
|
-
return this.db.scan({});
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
exports.PermissionRepo = PermissionRepo;
|
|
63
|
-
//# sourceMappingURL=permission.repo.js.map
|