@transmit-security/rbac 1.0.0-beta
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.
Potentially problematic release.
This version of @transmit-security/rbac might be problematic. Click here for more details.
- package/README.md +18 -0
- package/dist/src/definitions/action.js +31 -0
- package/dist/src/definitions/resources/administration-resources.js +12 -0
- package/dist/src/definitions/resources/app-resources.js +43 -0
- package/dist/src/definitions/resources/drs-resources.js +53 -0
- package/dist/src/definitions/resources/events-resources.js +20 -0
- package/dist/src/definitions/resources/idv-resources.js +32 -0
- package/dist/src/definitions/resources/index.js +30 -0
- package/dist/src/definitions/resources/oidc-resource-resources.js +9 -0
- package/dist/src/definitions/resources/orc-resources.js +26 -0
- package/dist/src/definitions/resources/organization-resources.js +12 -0
- package/dist/src/definitions/resources/service-provider-resources.js +9 -0
- package/dist/src/definitions/resources/user-resources.js +9 -0
- package/dist/src/index.js +53 -0
- package/dist/src/infra/permission-selector-builder.js +50 -0
- package/dist/src/infra/permission.js +83 -0
- package/dist/src/infra/placeHolders.js +7 -0
- package/dist/src/infra/resource-class-builder.js +277 -0
- package/dist/src/infra/resource-registry.js +22 -0
- package/dist/src/infra/resource.js +93 -0
- package/dist/src/infra/wildcard.js +6 -0
- package/dist/src/utils/is-valid-enum-value.js +8 -0
- package/package.json +38 -0
package/README.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# @transmit-security/rbac
|
2
|
+
|
3
|
+
RBAC impl of Transmt sec
|
4
|
+
|
5
|
+
### Usage
|
6
|
+
|
7
|
+
```js
|
8
|
+
import { Permission, Action, AppResourceDefinition } from '@transmit-security/rbac';
|
9
|
+
|
10
|
+
const userPermission = new Permission(Action.read, AppResourceDefinition);
|
11
|
+
|
12
|
+
if (userPermission.allows([Action.write, AppResourceDefinition.type])) {
|
13
|
+
// perform the operation
|
14
|
+
} else {
|
15
|
+
// return error
|
16
|
+
}
|
17
|
+
|
18
|
+
```
|
@@ -0,0 +1,31 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.Action = void 0;
|
4
|
+
var Action;
|
5
|
+
(function (Action) {
|
6
|
+
/** Create a resource. */
|
7
|
+
Action["create"] = "create";
|
8
|
+
/** Read a single resource. This should not allow searching or listing similar resources, only reading a specific one.
|
9
|
+
for example, this can be used for the `/users/:id` endpoint, but not for `/users` (at least not without additional actions).
|
10
|
+
*/
|
11
|
+
Action["read"] = "read";
|
12
|
+
/** Edit a single resource. This should not allow deleting that resource or creating similar resources. */
|
13
|
+
Action["edit"] = "edit";
|
14
|
+
/** Delete resources. This can be used for bulk-delete as well. */
|
15
|
+
Action["delete"] = "delete";
|
16
|
+
/** List resources. This should be used for list and search endpoints, where resource IDs or resource details are returned without
|
17
|
+
* their IDs being known to the caller. for example, if the `/users` endpoint returns a list of all user IDs, this can be used to
|
18
|
+
* guard it. but this should not be used for `/users/:id`.
|
19
|
+
*
|
20
|
+
* If an endpoint returns not just resource IDs but also some details (e.g search users which returns name and email), then the
|
21
|
+
* endpoint should be guarded by the `read` permission as well as `list`.
|
22
|
+
*/
|
23
|
+
Action["list"] = "list";
|
24
|
+
/** Execute a resource. Currently the only resources we can execute are FlexId journeys, but perhaps in the future we'll extend
|
25
|
+
* this capability to users who complain too much.
|
26
|
+
*/
|
27
|
+
Action["execute"] = "execute";
|
28
|
+
/** All actions. This grants the ability to perform any of the other actions. */
|
29
|
+
Action["all"] = "*";
|
30
|
+
})(Action || (exports.Action = Action = {}));
|
31
|
+
//# sourceMappingURL=action.js.map
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.AdministrationResourceDefinition = void 0;
|
4
|
+
exports.AdministrationResourceDefinition = {
|
5
|
+
type: 'simple',
|
6
|
+
id: 'administration',
|
7
|
+
children: {
|
8
|
+
adminUsers: { type: 'collection', id: 'admin-users', key: 'adminId' },
|
9
|
+
adminRoles: { type: 'collection', id: 'admin-roles', key: 'roleId' },
|
10
|
+
},
|
11
|
+
};
|
12
|
+
//# sourceMappingURL=administration-resources.js.map
|
@@ -0,0 +1,43 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.AppResourceDefinition = void 0;
|
4
|
+
exports.AppResourceDefinition = {
|
5
|
+
type: 'collection',
|
6
|
+
id: 'apps',
|
7
|
+
key: 'appId',
|
8
|
+
children: {
|
9
|
+
config: {
|
10
|
+
type: 'simple',
|
11
|
+
id: 'config',
|
12
|
+
children: {
|
13
|
+
idv: {
|
14
|
+
type: 'simple',
|
15
|
+
id: 'idv',
|
16
|
+
children: {
|
17
|
+
identityExperienceManagement: {
|
18
|
+
type: 'simple',
|
19
|
+
id: 'identity-experience-management',
|
20
|
+
children: {
|
21
|
+
settings: { type: 'simple', id: 'settings' },
|
22
|
+
consent: { type: 'simple', id: 'consent' },
|
23
|
+
branding: { type: 'simple', id: 'branding' },
|
24
|
+
},
|
25
|
+
},
|
26
|
+
identityRestrictionCriteria: {
|
27
|
+
type: 'simple',
|
28
|
+
id: 'identity-restriction-criteria',
|
29
|
+
},
|
30
|
+
},
|
31
|
+
},
|
32
|
+
drs: {
|
33
|
+
type: 'simple',
|
34
|
+
id: 'drs',
|
35
|
+
children: {
|
36
|
+
privateIdentifier: { type: 'simple', id: 'private-identifier' },
|
37
|
+
},
|
38
|
+
},
|
39
|
+
},
|
40
|
+
},
|
41
|
+
},
|
42
|
+
};
|
43
|
+
//# sourceMappingURL=app-resources.js.map
|
@@ -0,0 +1,53 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.drsResourceDefinition = void 0;
|
4
|
+
exports.drsResourceDefinition = {
|
5
|
+
type: 'simple',
|
6
|
+
id: 'drs',
|
7
|
+
children: {
|
8
|
+
recommendations: {
|
9
|
+
type: 'simple',
|
10
|
+
id: 'recommendations',
|
11
|
+
children: {
|
12
|
+
export: { type: 'simple', id: 'export' },
|
13
|
+
},
|
14
|
+
},
|
15
|
+
list: {
|
16
|
+
type: 'collection',
|
17
|
+
id: 'list',
|
18
|
+
key: 'listId',
|
19
|
+
children: {
|
20
|
+
items: { type: 'collection', id: 'items', key: 'itemId' },
|
21
|
+
},
|
22
|
+
},
|
23
|
+
label: {
|
24
|
+
type: 'simple',
|
25
|
+
id: 'label',
|
26
|
+
children: {
|
27
|
+
bulk: { type: 'simple', id: 'bulk' },
|
28
|
+
},
|
29
|
+
},
|
30
|
+
customActionType: { type: 'simple', id: 'custom-action-type' },
|
31
|
+
detectionSensitivityConfiguration: {
|
32
|
+
type: 'simple',
|
33
|
+
id: 'detection-sensitivity-configuration',
|
34
|
+
children: {
|
35
|
+
preview: { type: 'simple', id: 'preview' },
|
36
|
+
production: { type: 'simple', id: 'production' },
|
37
|
+
},
|
38
|
+
},
|
39
|
+
rule: {
|
40
|
+
type: 'collection',
|
41
|
+
id: 'rule',
|
42
|
+
key: 'ruleId',
|
43
|
+
children: {
|
44
|
+
preview: { type: 'simple', id: 'preview' },
|
45
|
+
production: { type: 'simple', id: 'production' },
|
46
|
+
},
|
47
|
+
},
|
48
|
+
preview: { type: 'simple', id: 'preview' },
|
49
|
+
securityInsights: { type: 'simple', id: 'security-insights' },
|
50
|
+
automatedWorkflows: { type: 'simple', id: 'automated-workflows' },
|
51
|
+
},
|
52
|
+
};
|
53
|
+
//# sourceMappingURL=drs-resources.js.map
|
@@ -0,0 +1,20 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.EventsResourceDefinition = void 0;
|
4
|
+
exports.EventsResourceDefinition = {
|
5
|
+
type: 'simple',
|
6
|
+
id: 'events',
|
7
|
+
children: {
|
8
|
+
userActivities: {
|
9
|
+
type: 'collection',
|
10
|
+
id: 'user-activities',
|
11
|
+
key: 'userActivityId',
|
12
|
+
},
|
13
|
+
adminActivities: {
|
14
|
+
type: 'collection',
|
15
|
+
id: 'admin-activities',
|
16
|
+
key: 'adminActivityId',
|
17
|
+
},
|
18
|
+
},
|
19
|
+
};
|
20
|
+
//# sourceMappingURL=events-resources.js.map
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.idvResourceDefinition = void 0;
|
4
|
+
exports.idvResourceDefinition = {
|
5
|
+
type: 'simple',
|
6
|
+
id: 'idv',
|
7
|
+
children: {
|
8
|
+
identityVerifications: {
|
9
|
+
type: 'collection',
|
10
|
+
id: 'identity-verifications',
|
11
|
+
key: 'verificationId',
|
12
|
+
children: {
|
13
|
+
status: { type: 'simple', id: 'status' },
|
14
|
+
images: { type: 'collection', id: 'images', key: 'imageId' },
|
15
|
+
result: { type: 'simple', id: 'result' },
|
16
|
+
labels: { type: 'simple', id: 'labels' },
|
17
|
+
},
|
18
|
+
},
|
19
|
+
blocklist: {
|
20
|
+
type: 'simple',
|
21
|
+
id: 'blocklist',
|
22
|
+
children: {
|
23
|
+
faces: { type: 'collection', id: 'faces', key: 'entryId' },
|
24
|
+
},
|
25
|
+
},
|
26
|
+
analytics: {
|
27
|
+
type: 'simple',
|
28
|
+
id: 'analytics',
|
29
|
+
},
|
30
|
+
},
|
31
|
+
};
|
32
|
+
//# sourceMappingURL=idv-resources.js.map
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.oidcResources = exports.serviceProviders = exports.orc = exports.drs = exports.events = exports.idv = exports.users = exports.organization = exports.administration = exports.apps = void 0;
|
4
|
+
const resource_class_builder_1 = require("../../infra/resource-class-builder");
|
5
|
+
const administration_resources_1 = require("./administration-resources");
|
6
|
+
const app_resources_1 = require("./app-resources");
|
7
|
+
const organization_resources_1 = require("./organization-resources");
|
8
|
+
const user_resources_1 = require("./user-resources");
|
9
|
+
const idv_resources_1 = require("./idv-resources");
|
10
|
+
const events_resources_1 = require("./events-resources");
|
11
|
+
const drs_resources_1 = require("./drs-resources");
|
12
|
+
const service_provider_resources_1 = require("./service-provider-resources");
|
13
|
+
const oidc_resource_resources_1 = require("./oidc-resource-resources");
|
14
|
+
const orc_resources_1 = require("./orc-resources");
|
15
|
+
/*
|
16
|
+
Resources definition are split into files for better change isolation. as
|
17
|
+
this project matures, we can consider merging all definitions into a single
|
18
|
+
file for ease of use.
|
19
|
+
*/
|
20
|
+
exports.apps = (0, resource_class_builder_1.buildResourceClass)(app_resources_1.AppResourceDefinition);
|
21
|
+
exports.administration = (0, resource_class_builder_1.buildResourceClass)(administration_resources_1.AdministrationResourceDefinition);
|
22
|
+
exports.organization = (0, resource_class_builder_1.buildResourceClass)(organization_resources_1.organizationsResourceDefinition);
|
23
|
+
exports.users = (0, resource_class_builder_1.buildResourceClass)(user_resources_1.userResourceDefinition);
|
24
|
+
exports.idv = (0, resource_class_builder_1.buildResourceClass)(idv_resources_1.idvResourceDefinition);
|
25
|
+
exports.events = (0, resource_class_builder_1.buildResourceClass)(events_resources_1.EventsResourceDefinition);
|
26
|
+
exports.drs = (0, resource_class_builder_1.buildResourceClass)(drs_resources_1.drsResourceDefinition);
|
27
|
+
exports.orc = (0, resource_class_builder_1.buildResourceClass)(orc_resources_1.orcResourceDefinitions);
|
28
|
+
exports.serviceProviders = (0, resource_class_builder_1.buildResourceClass)(service_provider_resources_1.serviceProviderResourceDefinition);
|
29
|
+
exports.oidcResources = (0, resource_class_builder_1.buildResourceClass)(oidc_resource_resources_1.oidcResourceResourceDefinition);
|
30
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.oidcResourceResourceDefinition = void 0;
|
4
|
+
exports.oidcResourceResourceDefinition = {
|
5
|
+
type: 'collection',
|
6
|
+
id: 'resources',
|
7
|
+
key: 'resourceId',
|
8
|
+
};
|
9
|
+
//# sourceMappingURL=oidc-resource-resources.js.map
|
@@ -0,0 +1,26 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.orcResourceDefinitions = void 0;
|
4
|
+
exports.orcResourceDefinitions = {
|
5
|
+
type: 'simple',
|
6
|
+
id: 'orc',
|
7
|
+
children: {
|
8
|
+
journeys: {
|
9
|
+
type: 'simple',
|
10
|
+
id: 'journeys',
|
11
|
+
},
|
12
|
+
connections: {
|
13
|
+
type: 'simple',
|
14
|
+
id: 'connections',
|
15
|
+
},
|
16
|
+
lists: {
|
17
|
+
type: 'simple',
|
18
|
+
id: 'lists',
|
19
|
+
},
|
20
|
+
identities: {
|
21
|
+
type: 'simple',
|
22
|
+
id: 'identities',
|
23
|
+
},
|
24
|
+
},
|
25
|
+
};
|
26
|
+
//# sourceMappingURL=orc-resources.js.map
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.organizationsResourceDefinition = void 0;
|
4
|
+
exports.organizationsResourceDefinition = {
|
5
|
+
type: 'simple',
|
6
|
+
id: 'organizations',
|
7
|
+
children: {
|
8
|
+
orgs: { type: 'simple', id: 'orgs' },
|
9
|
+
roles: { type: 'simple', id: 'roles' },
|
10
|
+
},
|
11
|
+
};
|
12
|
+
//# sourceMappingURL=organization-resources.js.map
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.serviceProviderResourceDefinition = void 0;
|
4
|
+
exports.serviceProviderResourceDefinition = {
|
5
|
+
type: 'collection',
|
6
|
+
id: 'service-providers',
|
7
|
+
key: 'serviceProviderId',
|
8
|
+
};
|
9
|
+
//# sourceMappingURL=service-provider-resources.js.map
|
@@ -0,0 +1,53 @@
|
|
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 __importStar = (this && this.__importStar) || function (mod) {
|
19
|
+
if (mod && mod.__esModule) return mod;
|
20
|
+
var result = {};
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
+
__setModuleDefault(result, mod);
|
23
|
+
return result;
|
24
|
+
};
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
26
|
+
exports.wildcardPrimitive = exports.wildcard = exports.resourceClassRegistry = exports.build = exports.Resource = exports.placeholder = exports.Permission = exports.Action = exports.permissions = exports.resources = void 0;
|
27
|
+
const resources = __importStar(require("./definitions/resources"));
|
28
|
+
exports.resources = resources;
|
29
|
+
const permission_selector_builder_1 = require("./infra/permission-selector-builder");
|
30
|
+
/** A reference to all the actions and resources in the RBAC system. You can
|
31
|
+
* use this instead of creating permissions and resource instances
|
32
|
+
* manually.
|
33
|
+
*
|
34
|
+
* example:
|
35
|
+
* ```
|
36
|
+
* permissions.create.Users()
|
37
|
+
* ```*/
|
38
|
+
exports.permissions = (0, permission_selector_builder_1.buildPermissionSelector)(resources);
|
39
|
+
var action_1 = require("./definitions/action");
|
40
|
+
Object.defineProperty(exports, "Action", { enumerable: true, get: function () { return action_1.Action; } });
|
41
|
+
var permission_1 = require("./infra/permission");
|
42
|
+
Object.defineProperty(exports, "Permission", { enumerable: true, get: function () { return permission_1.Permission; } });
|
43
|
+
var placeHolders_1 = require("./infra/placeHolders");
|
44
|
+
Object.defineProperty(exports, "placeholder", { enumerable: true, get: function () { return placeHolders_1.placeholder; } });
|
45
|
+
var resource_1 = require("./infra/resource");
|
46
|
+
Object.defineProperty(exports, "Resource", { enumerable: true, get: function () { return resource_1.Resource; } });
|
47
|
+
exports.build = __importStar(require("./infra/resource-class-builder"));
|
48
|
+
var resource_registry_1 = require("./infra/resource-registry");
|
49
|
+
Object.defineProperty(exports, "resourceClassRegistry", { enumerable: true, get: function () { return resource_registry_1.resourceClassRegistry; } });
|
50
|
+
var wildcard_1 = require("./infra/wildcard");
|
51
|
+
Object.defineProperty(exports, "wildcard", { enumerable: true, get: function () { return wildcard_1.wildcard; } });
|
52
|
+
Object.defineProperty(exports, "wildcardPrimitive", { enumerable: true, get: function () { return wildcard_1.wildcardPrimitive; } });
|
53
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1,50 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.buildPermissionSelector = void 0;
|
4
|
+
const action_1 = require("../definitions/action");
|
5
|
+
const permission_1 = require("./permission");
|
6
|
+
const placeHolders_1 = require("./placeHolders");
|
7
|
+
const wildcard_1 = require("./wildcard");
|
8
|
+
function buildPermissionTree(resourceClass, action, parentKeys, keyValues) {
|
9
|
+
const result = {};
|
10
|
+
let childKeys = { ...parentKeys };
|
11
|
+
let entityKeys = { ...parentKeys };
|
12
|
+
if (resourceClass.definition.type === 'collection') {
|
13
|
+
let keyValue = keyValues
|
14
|
+
? keyValues[resourceClass.definition.key]
|
15
|
+
: undefined;
|
16
|
+
if (keyValue === placeHolders_1.placeholder) {
|
17
|
+
keyValue = (0, placeHolders_1.getPlaceHolderString)(resourceClass.definition.key);
|
18
|
+
}
|
19
|
+
childKeys[resourceClass.definition.key] = keyValue || wildcard_1.wildcard;
|
20
|
+
entityKeys[resourceClass.definition.key] = keyValue || undefined;
|
21
|
+
}
|
22
|
+
Object.getOwnPropertyNames(resourceClass).forEach((propName) => {
|
23
|
+
const value = resourceClass[propName];
|
24
|
+
if (typeof value === 'function') {
|
25
|
+
if ('definition' in value) {
|
26
|
+
result[propName] = buildPermissionTree(value, action, childKeys, keyValues);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
});
|
30
|
+
childKeys['childPermission'] = resourceClass.definition.id;
|
31
|
+
const selectable = {
|
32
|
+
permission: new permission_1.Permission(action, new resourceClass(entityKeys)),
|
33
|
+
childPermission: new permission_1.Permission(action, new resourceClass(childKeys)),
|
34
|
+
};
|
35
|
+
Object.assign(result, selectable);
|
36
|
+
return result;
|
37
|
+
}
|
38
|
+
function buildPermissionSelector(resourceTree, keyValues) {
|
39
|
+
return Object.entries(action_1.Action).reduce((selector, [actionName, actionValue]) => {
|
40
|
+
const resources = Object.entries(resourceTree).reduce((acc, [key, value]) => {
|
41
|
+
const tree = buildPermissionTree(value, actionValue, {}, keyValues);
|
42
|
+
acc[key] = tree;
|
43
|
+
return acc;
|
44
|
+
}, {});
|
45
|
+
selector[actionName] = resources;
|
46
|
+
return selector;
|
47
|
+
}, {});
|
48
|
+
}
|
49
|
+
exports.buildPermissionSelector = buildPermissionSelector;
|
50
|
+
//# sourceMappingURL=permission-selector-builder.js.map
|
@@ -0,0 +1,83 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.Permission = void 0;
|
4
|
+
const action_1 = require("../definitions/action");
|
5
|
+
const is_valid_enum_value_1 = require("../utils/is-valid-enum-value");
|
6
|
+
const resource_1 = require("./resource");
|
7
|
+
class Permission {
|
8
|
+
constructor(action, resource) {
|
9
|
+
this.action = action;
|
10
|
+
this.resource = resource;
|
11
|
+
}
|
12
|
+
static parse(permissionString) {
|
13
|
+
const segments = permissionString.split(':');
|
14
|
+
if (segments.length !== 2 || segments.some((s) => s.length === 0))
|
15
|
+
return {
|
16
|
+
success: false,
|
17
|
+
error: `Invalid format - should be 'action:resource'`,
|
18
|
+
};
|
19
|
+
const action = segments[0];
|
20
|
+
if (!(0, is_valid_enum_value_1.isValidEnumValue)(action_1.Action, action))
|
21
|
+
return { success: false, error: `Invalid action: '${segments[0]}'` };
|
22
|
+
const parseRes = resource_1.Resource.parse(segments[1]);
|
23
|
+
if (!parseRes.success)
|
24
|
+
return {
|
25
|
+
success: false,
|
26
|
+
error: `Cannot parse resource: ${parseRes.error}`,
|
27
|
+
};
|
28
|
+
const { resource } = parseRes;
|
29
|
+
return {
|
30
|
+
success: true,
|
31
|
+
permission: new Permission(action, resource),
|
32
|
+
};
|
33
|
+
}
|
34
|
+
/** Checks if this permission is granted by any of the provided permissions.
|
35
|
+
*
|
36
|
+
* When permission validation fails, it's recommended to log the required and provided permissions for easy debugging.
|
37
|
+
*
|
38
|
+
* note: by default, invalid permissions are ignored. you can adjust this behavior using the options parameter, or
|
39
|
+
* parse and check the permissions yourself using `Permission.parse`.
|
40
|
+
*/
|
41
|
+
isAllowedBy(providedPermissions, options) {
|
42
|
+
for (const permission of providedPermissions) {
|
43
|
+
if (typeof permission === 'string') {
|
44
|
+
const parseRes = Permission.parse(permission);
|
45
|
+
if (!parseRes.success) {
|
46
|
+
if (options.onParsingError === 'throw') {
|
47
|
+
throw new Error(parseRes.error);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
else if (parseRes.permission.allows(this)) {
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
else if (permission.allows(this)) {
|
55
|
+
return true;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
return false;
|
59
|
+
}
|
60
|
+
/** Checks if this permission allows the operation described by the other permission.
|
61
|
+
*
|
62
|
+
* example:
|
63
|
+
* ```
|
64
|
+
* if (tokenPermission.allows(requiredPermission)) {
|
65
|
+
* // perform the operation
|
66
|
+
* } else {
|
67
|
+
* // return error
|
68
|
+
* }
|
69
|
+
* ```
|
70
|
+
*/
|
71
|
+
allows(other) {
|
72
|
+
if (this.action !== action_1.Action.all && this.action !== other.action)
|
73
|
+
return false;
|
74
|
+
if (!this.resource.owns(other.resource))
|
75
|
+
return false;
|
76
|
+
return true;
|
77
|
+
}
|
78
|
+
toString() {
|
79
|
+
return `${this.action}:${this.resource.toString()}`;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
exports.Permission = Permission;
|
83
|
+
//# sourceMappingURL=permission.js.map
|
@@ -0,0 +1,7 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getPlaceHolderString = exports.placeholder = void 0;
|
4
|
+
exports.placeholder = 'PLACEHOLDER';
|
5
|
+
const getPlaceHolderString = (key) => `[${key}]`;
|
6
|
+
exports.getPlaceHolderString = getPlaceHolderString;
|
7
|
+
//# sourceMappingURL=placeHolders.js.map
|
@@ -0,0 +1,277 @@
|
|
1
|
+
"use strict";
|
2
|
+
/*
|
3
|
+
|
4
|
+
The purpose of this file is to provide a way to build resource classes, from a
|
5
|
+
data structure that's as simple as possible.
|
6
|
+
|
7
|
+
## General idea
|
8
|
+
|
9
|
+
recommended reading:
|
10
|
+
https://cloud.google.com/apis/design/resource_names
|
11
|
+
|
12
|
+
Resource classes are typescript classes which represent a specific type of resources,
|
13
|
+
and are used to create instances of those resources for things like permission checks
|
14
|
+
or data access. At the lowest level a resource is just a string, but we want to provide
|
15
|
+
a move convenient mechanism to work with them.
|
16
|
+
|
17
|
+
Resource classes have several requirements:
|
18
|
+
|
19
|
+
1. provide a string that represents the resource
|
20
|
+
2. ensure all placeholder values are filled in when creating an instance
|
21
|
+
e.g if the resource is `apps/$appId/users/$userId`, then when creating an instance,
|
22
|
+
both `appId` and `userId` must be provided.
|
23
|
+
3. provide a way to reference a resource class (not instance) via a string
|
24
|
+
i.e if a client tells a server "I want to access the `users` resource", the server
|
25
|
+
should be able to understand which resource class that is.
|
26
|
+
4. provide a convenient way to create child resources from a parent resource
|
27
|
+
|
28
|
+
|
29
|
+
The end result is a bunch of classes that look kinda like this:
|
30
|
+
```
|
31
|
+
class Apps {
|
32
|
+
constructor(public appId: string) { }
|
33
|
+
toString() { return `apps/${this.appId}` }
|
34
|
+
|
35
|
+
users(userId: string) { return new AppUsers(this.appId, userId); }
|
36
|
+
}
|
37
|
+
|
38
|
+
class AppUsers {
|
39
|
+
constructor(public appId: string, public userId: string) { }
|
40
|
+
toString() { return `apps/${this.appId}/users/${this.userId}` }
|
41
|
+
}
|
42
|
+
```
|
43
|
+
|
44
|
+
the ONLY thing that matters is that end result. the implementation of the
|
45
|
+
builder is free to change and evolve - we can even generate the classes
|
46
|
+
at build time using a code generator, or even remove automatic generation
|
47
|
+
entirely and just write the classes manually.
|
48
|
+
|
49
|
+
## Implementation
|
50
|
+
|
51
|
+
The implementation is based on a recursive function that builds the classes
|
52
|
+
from a data structure that represents the resource.
|
53
|
+
|
54
|
+
Due to all the type manipulation, the implementation is a bit complex -
|
55
|
+
we have the types which facilitate the type manipulation, and the actual code
|
56
|
+
that builds the classes. That's 2 parallel flows of data. We try to use them
|
57
|
+
together as much as possible to get type safety, but in some cases it's
|
58
|
+
technically impossible to get type info, so we resort to `any` and make sure
|
59
|
+
that area covered by tests.
|
60
|
+
|
61
|
+
The entry point for the type definitions is the `ResourceClassFromDef` type,
|
62
|
+
which takes in a `ResourceDefNode` type and builds a class from it, with the
|
63
|
+
the collections keys and child resource if any. see the jsdoc on the type
|
64
|
+
itself for details.
|
65
|
+
|
66
|
+
The entry point for the actual code is the `buildResourceClass` function,
|
67
|
+
which takes in a `ResourceDefNode` instance and returns a class built from it,
|
68
|
+
also with the correct collection keys and child resources. here too, see the
|
69
|
+
jsdoc for details.
|
70
|
+
|
71
|
+
## Some future ideas
|
72
|
+
|
73
|
+
### non-class references
|
74
|
+
|
75
|
+
there's no real reason that `Apps.Users` (for example) has to be the users
|
76
|
+
class - all we need from it is the template, since we can build an instance
|
77
|
+
using `new Apps().users()`. Populating those props with something that holds
|
78
|
+
a template string and child objects, instead of a class, will make them easier
|
79
|
+
to explore since they won't have the other methods that functions have.
|
80
|
+
|
81
|
+
### inherently type-checked collection keys
|
82
|
+
|
83
|
+
when building the type of an anon object (`{a:"str"}`), typescript sets the
|
84
|
+
type of primitive properties to their full type even when a fixed value is
|
85
|
+
provided. so the example's type would be `{a: string}` and not `{a:"str"}`.
|
86
|
+
for this reason, users of the builder have to add `as const` to their
|
87
|
+
definitions - without it, collection keys would be just any string and not
|
88
|
+
specifically the provided key.
|
89
|
+
we could instead change the api to get collection keys as object keys, not as
|
90
|
+
strings: `{key: {userId: string}}` instead of `{key: "userId"}`. with this,
|
91
|
+
there's no need to `as const` since string fields are not used for type
|
92
|
+
inference.
|
93
|
+
|
94
|
+
|
95
|
+
### id-based resource types
|
96
|
+
|
97
|
+
instead of simple and collection resource definitions, we can use ids like
|
98
|
+
`apps` and `apps/$appId` and automatically determine if it's a collection.
|
99
|
+
see https://www.typescriptlang.org/play/?#code/C4TwDgpgBAyglgWzAGwgSQCZQLxQM7ABOcAdgOYBQokUAwgPbKoDGwc9JmAPAHICGCaBAAewCCQx58RUmQA0UANIQQ-QVBFiJUgsXIA+HFAAGAEgDeaiAF8A9KYvLVAm8YruAZgFcSrdiSgyCGAuABUNUXFJOkYWNg5uPhIQBSSQQwAfWEQUdAx9AAoKKBLpQgAuKFCKAEpK8M0oqQYmCD8EjC5SDwhCKCsFbt6lFStDYtKAfihzaghKgCJmWLb4kgWFEhdKgagAa1HtkedBaygJksrzKDnFvBzUDagtwXqzinMLqEJgr0IA8xnPhSNIUazuCjLEgEfAPaC4ILAAoLLx4Xp4BY1Ci2WylPEAPUmkI4MOWrXaAQRwWRqPR9lphEwmOxuIJRIhQA
|
100
|
+
this will make the definitions a lot simpler, but is also a bit less discoverable -
|
101
|
+
the type system won't tell you that you can create a collection that way.
|
102
|
+
can consider this when there are more resources to use as reference.
|
103
|
+
|
104
|
+
### fluent builder
|
105
|
+
|
106
|
+
instead of passing an object to the constructor, we can use a fluent builder.
|
107
|
+
this will allow greater flexibility in the future, and will avoid the need for `as const`.
|
108
|
+
downside is that it can get pretty verbose, and will require a lot of boilerplate.
|
109
|
+
|
110
|
+
|
111
|
+
*/
|
112
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
113
|
+
exports.InvalidKeyForCollection = exports.MissingKeyForCollection = exports.buildResourceClass = void 0;
|
114
|
+
const resource_1 = require("./resource");
|
115
|
+
const resource_registry_1 = require("./resource-registry");
|
116
|
+
const wildcard_1 = require("./wildcard");
|
117
|
+
function getTemplatePath(res) {
|
118
|
+
return res.type === 'simple' ? [res.id] : [res.id, `$${res.key}`];
|
119
|
+
}
|
120
|
+
function buildResourceClassCommon(source, parentDefinitions) {
|
121
|
+
const parentPath = parentDefinitions.map(getTemplatePath).flat();
|
122
|
+
const fullPath = [...parentPath, ...getTemplatePath(source)];
|
123
|
+
return {
|
124
|
+
template: fullPath,
|
125
|
+
templateStr: fullPath.join(resource_1.Resource.separator),
|
126
|
+
definition: source,
|
127
|
+
};
|
128
|
+
}
|
129
|
+
function buildResourceConstructor(source, parents) {
|
130
|
+
switch (source.type) {
|
131
|
+
case 'simple':
|
132
|
+
return class SimpleResource extends resource_1.Resource {
|
133
|
+
constructor(input) {
|
134
|
+
super(buildResourcePath([...parents, source], input));
|
135
|
+
}
|
136
|
+
};
|
137
|
+
case 'collection':
|
138
|
+
return class CollectionResource extends resource_1.Resource {
|
139
|
+
constructor(input) {
|
140
|
+
super(buildResourcePath([...parents, source], input));
|
141
|
+
}
|
142
|
+
};
|
143
|
+
}
|
144
|
+
}
|
145
|
+
/** Builds the properties that provide the child resource.
|
146
|
+
*
|
147
|
+
* e.g with `new Apps.Users({appId:"123", userId:"456"})` - this function
|
148
|
+
* had built the `Users` static property on the `Apps` class.
|
149
|
+
*
|
150
|
+
* The returned object should be merged with the parent class.
|
151
|
+
*/
|
152
|
+
function buildChildResourceStaticProperties(childClasses) {
|
153
|
+
const propMap = {};
|
154
|
+
for (const [key, childClass] of Object.entries(childClasses)) {
|
155
|
+
propMap[key] = { get: () => childClass };
|
156
|
+
}
|
157
|
+
return propMap;
|
158
|
+
}
|
159
|
+
/** Builds the methods that create child resource from a parent resource.
|
160
|
+
*
|
161
|
+
* e.g with `new Apps("someAppId").users("someUserId")` - this function
|
162
|
+
* had built the `users` method on the `Apps` class.
|
163
|
+
*
|
164
|
+
* The returned object should be merged with the parent class prototype.
|
165
|
+
*/
|
166
|
+
function buildChildResourceInstanceMethods(childClasses, definitions) {
|
167
|
+
const propMap = {};
|
168
|
+
for (const [key, childClass] of Object.entries(childClasses)) {
|
169
|
+
const childDefinition = childClass.definition;
|
170
|
+
propMap[key] = {
|
171
|
+
get() {
|
172
|
+
let input = gatherInput(this, definitions);
|
173
|
+
return childDefinition.type == 'simple'
|
174
|
+
? (childResource) => new childClass({ ...input, childResource })
|
175
|
+
: (id, childResource) => new childClass({
|
176
|
+
...input,
|
177
|
+
[childDefinition.key]: id,
|
178
|
+
childResource,
|
179
|
+
});
|
180
|
+
},
|
181
|
+
};
|
182
|
+
}
|
183
|
+
return propMap;
|
184
|
+
}
|
185
|
+
function build(source, parentDefinitions) {
|
186
|
+
/*
|
187
|
+
we're gonna do dynamic stuff here, so to maintain type safety as much as possible,
|
188
|
+
we'll create the components of a resource class separately, and then combine them.
|
189
|
+
*/
|
190
|
+
const resourceClass = buildResourceConstructor(source, parentDefinitions);
|
191
|
+
Object.assign(resourceClass, buildResourceClassCommon(source, parentDefinitions));
|
192
|
+
if (source.children) {
|
193
|
+
const childParents = [...parentDefinitions, source];
|
194
|
+
const childClassesRecord = Object.entries(source.children).reduce((acc, [key, childDefinition]) => {
|
195
|
+
acc[key] = build(childDefinition, childParents);
|
196
|
+
return acc;
|
197
|
+
}, {});
|
198
|
+
Object.defineProperties(resourceClass, buildChildResourceStaticProperties(childClassesRecord));
|
199
|
+
Object.defineProperties(resourceClass.prototype, buildChildResourceInstanceMethods(childClassesRecord, childParents));
|
200
|
+
}
|
201
|
+
resource_registry_1.resourceClassRegistry.register(resourceClass.templateStr);
|
202
|
+
return resourceClass;
|
203
|
+
}
|
204
|
+
/** returns an object with the inputs used to build it and each parent.
|
205
|
+
* simple (non-collection) resources are not included in the output since they don't have inputs.
|
206
|
+
*
|
207
|
+
* example -
|
208
|
+
* for resource `apps/123/users/456` (assuming template `apps/$appId/users/$userId`),
|
209
|
+
* this will return `{appId: "123", userId: "456"}`
|
210
|
+
*/
|
211
|
+
function gatherInput(source, definitions) {
|
212
|
+
const remainingPath = [...source.path];
|
213
|
+
return definitions.reduce((acc, def) => {
|
214
|
+
remainingPath.shift();
|
215
|
+
if (def.type === 'collection') {
|
216
|
+
const key = remainingPath.shift();
|
217
|
+
if (key === wildcard_1.wildcardPrimitive) {
|
218
|
+
acc[def.key] = wildcard_1.wildcard;
|
219
|
+
}
|
220
|
+
else {
|
221
|
+
acc[def.key] = key;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
return acc;
|
225
|
+
}, {});
|
226
|
+
}
|
227
|
+
function buildResourcePath(resources, input = {}) {
|
228
|
+
const lastResource = resources[resources.length - 1];
|
229
|
+
return resources.reduce((acc, res) => {
|
230
|
+
if (res.type === 'simple') {
|
231
|
+
if (input.childPermission === res.id ||
|
232
|
+
(res.id === lastResource.id && input.childResource)) {
|
233
|
+
return [...acc, res.id, wildcard_1.wildcardPrimitive];
|
234
|
+
}
|
235
|
+
return [...acc, res.id];
|
236
|
+
}
|
237
|
+
else {
|
238
|
+
if (!(res.key in input))
|
239
|
+
return [...acc, res.id];
|
240
|
+
const key = input[res.key];
|
241
|
+
if (key == '' || key == null)
|
242
|
+
return [...acc, res.id];
|
243
|
+
if (key === wildcard_1.wildcard)
|
244
|
+
return [...acc, res.id, wildcard_1.wildcardPrimitive];
|
245
|
+
const isValid = (0, resource_1.validateResourceSegment)(key);
|
246
|
+
if (!isValid)
|
247
|
+
throw new InvalidKeyForCollection(res.key, key);
|
248
|
+
if ((res.id === lastResource.id && input.childResource) ||
|
249
|
+
input.childPermission === res.id) {
|
250
|
+
return [...acc, res.id, key, wildcard_1.wildcardPrimitive];
|
251
|
+
}
|
252
|
+
return [...acc, res.id, key];
|
253
|
+
}
|
254
|
+
}, []);
|
255
|
+
}
|
256
|
+
/** Build a resource class from a definition.
|
257
|
+
*
|
258
|
+
* - remember to add `as const` to the input object, to get accurate auto-complete.
|
259
|
+
* - for resource names, use valid javascript identifiers - i.e adminUsers and not 'admin-users'. those identifies are mapped to properties, so non-standard names would make them harder to access.
|
260
|
+
*/
|
261
|
+
function buildResourceClass(resourceDef) {
|
262
|
+
return build(resourceDef, []);
|
263
|
+
}
|
264
|
+
exports.buildResourceClass = buildResourceClass;
|
265
|
+
class MissingKeyForCollection extends Error {
|
266
|
+
constructor(keyName) {
|
267
|
+
super(`No key for collection; keyName: '${String(keyName)}'`);
|
268
|
+
}
|
269
|
+
}
|
270
|
+
exports.MissingKeyForCollection = MissingKeyForCollection;
|
271
|
+
class InvalidKeyForCollection extends Error {
|
272
|
+
constructor(keyName, keyValue) {
|
273
|
+
super(`Invalid key for collection; keyName: '${String(keyName)}', value: '${keyValue}'`);
|
274
|
+
}
|
275
|
+
}
|
276
|
+
exports.InvalidKeyForCollection = InvalidKeyForCollection;
|
277
|
+
//# sourceMappingURL=resource-class-builder.js.map
|
@@ -0,0 +1,22 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.resourceClassRegistry = void 0;
|
4
|
+
class ResourceClassRegistry {
|
5
|
+
constructor() {
|
6
|
+
this.templates = [];
|
7
|
+
}
|
8
|
+
register(name) {
|
9
|
+
this.templates.push(name);
|
10
|
+
}
|
11
|
+
getTemplates() {
|
12
|
+
return [...this.templates];
|
13
|
+
}
|
14
|
+
}
|
15
|
+
/* not very DI-like but for this specific use case (library, registry of fixed
|
16
|
+
values) it's fine.
|
17
|
+
|
18
|
+
if we do want to play nice with DI, we'll need to have the registry provided
|
19
|
+
to the resource creation externally, and have the DI provide it.
|
20
|
+
*/
|
21
|
+
exports.resourceClassRegistry = new ResourceClassRegistry();
|
22
|
+
//# sourceMappingURL=resource-registry.js.map
|
@@ -0,0 +1,93 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.Resource = exports.validateResourceSegment = exports.segmentMatcher = void 0;
|
4
|
+
const wildcard_1 = require("./wildcard");
|
5
|
+
exports.segmentMatcher = /^[a-zA-Z0-9_-]+$/;
|
6
|
+
function validateResourceSegment(segment, options) {
|
7
|
+
if ((options === null || options === void 0 ? void 0 : options.allowWildcard) && segment === wildcard_1.wildcardPrimitive)
|
8
|
+
return true;
|
9
|
+
if (segment === undefined)
|
10
|
+
return true;
|
11
|
+
if (segment.startsWith('[') && segment.endsWith(']')) {
|
12
|
+
segment = segment.slice(1, -1); // remove template brackets
|
13
|
+
}
|
14
|
+
return exports.segmentMatcher.test(segment);
|
15
|
+
}
|
16
|
+
exports.validateResourceSegment = validateResourceSegment;
|
17
|
+
class Resource {
|
18
|
+
constructor(path) {
|
19
|
+
this.path = path;
|
20
|
+
}
|
21
|
+
static parse(str) {
|
22
|
+
const path = str.split(Resource.separator);
|
23
|
+
if (path.length === 0) {
|
24
|
+
return { success: false, error: 'Resource path is empty' };
|
25
|
+
}
|
26
|
+
const emptySegments = path.filter((segment) => segment === '');
|
27
|
+
if (emptySegments.length > 0) {
|
28
|
+
return { success: false, error: `Resource path contains empty segments` };
|
29
|
+
}
|
30
|
+
const invalidSegments = path.filter((segment) => !validateResourceSegment(segment, { allowWildcard: true }));
|
31
|
+
if (invalidSegments.length > 0) {
|
32
|
+
return {
|
33
|
+
success: false,
|
34
|
+
error: 'Resource path contains invalid segments',
|
35
|
+
invalidSegments,
|
36
|
+
validationRegex: exports.segmentMatcher,
|
37
|
+
};
|
38
|
+
}
|
39
|
+
return {
|
40
|
+
success: true,
|
41
|
+
resource: new Resource(path),
|
42
|
+
};
|
43
|
+
}
|
44
|
+
/** checks if this resource owns `other`. i.e if `other` is a subset of this resource.
|
45
|
+
*
|
46
|
+
* examples:
|
47
|
+
* - `apps/123/users` does not own `apps/123/users/456`
|
48
|
+
* - `apps/123/users/*` owns `apps/123/users/456`
|
49
|
+
* - `apps/123/users` does not own `apps/123`
|
50
|
+
* - `apps/123/users` owns `apps/123/users` (itself)
|
51
|
+
*
|
52
|
+
* it's like `israel/tel-aviv/*` owns `israel/tel-aviv/alenby`, but not the other way around.
|
53
|
+
* and `israel/tel-aviv` does not own `israel/tel-aviv/alenby`, it owns only itself.
|
54
|
+
*/
|
55
|
+
owns(other) {
|
56
|
+
const maxPathLength = Math.max(this.path.length, other.path.length);
|
57
|
+
// safeguard against unintentional global permission. should be explicit `*`
|
58
|
+
if (other.path.length === 0 || other.path[0] === '')
|
59
|
+
return false;
|
60
|
+
for (let i = 0; i < maxPathLength; i++) {
|
61
|
+
const thisSegment = this.path[i];
|
62
|
+
const otherSegment = other.path[i];
|
63
|
+
// e.g this is `apps/123` does not own `apps/123/users`.
|
64
|
+
// but 'apps/123/*' owns 'apps/123/users/567' , 'apps/*' owns 'apps/123/users/567' or 'apps/*/users' etc.
|
65
|
+
if (!thisSegment) {
|
66
|
+
if (this.path[i - 1] === wildcard_1.wildcardPrimitive) {
|
67
|
+
return true;
|
68
|
+
}
|
69
|
+
return false;
|
70
|
+
}
|
71
|
+
// if `other` ended, but `this` didn't, then `this` doesn't contain `other`.
|
72
|
+
if (!otherSegment)
|
73
|
+
return false;
|
74
|
+
// if this segment is wildcard, no need for additional checks - it's a match.
|
75
|
+
// we only check further if it's not.
|
76
|
+
if (thisSegment !== wildcard_1.wildcardPrimitive) {
|
77
|
+
// if this segment isn't wildcard, but other is, then this can't possibly contain other.
|
78
|
+
if (otherSegment === wildcard_1.wildcardPrimitive)
|
79
|
+
return false;
|
80
|
+
// if the segments don't match, we can stop checking.
|
81
|
+
if (thisSegment !== otherSegment)
|
82
|
+
return false;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
return true;
|
86
|
+
}
|
87
|
+
toString() {
|
88
|
+
return this.path.join(Resource.separator);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
exports.Resource = Resource;
|
92
|
+
Resource.separator = '/';
|
93
|
+
//# sourceMappingURL=resource.js.map
|
@@ -0,0 +1,8 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.isValidEnumValue = void 0;
|
4
|
+
function isValidEnumValue(enumType, value) {
|
5
|
+
return Object.values(enumType).includes(value);
|
6
|
+
}
|
7
|
+
exports.isValidEnumValue = isValidEnumValue;
|
8
|
+
//# sourceMappingURL=is-valid-enum-value.js.map
|
package/package.json
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"name": "@transmit-security/rbac",
|
3
|
+
"private": false,
|
4
|
+
"description": "RBAC impl of Transmt sec",
|
5
|
+
"version": "1.0.0-beta",
|
6
|
+
"main": "dist/ui.es.js",
|
7
|
+
"module": "dist/ui.es.js",
|
8
|
+
"author": "htrs-sec",
|
9
|
+
"repository": "https://www.github.com/htrs-sec/@transmit-security/rbac",
|
10
|
+
"license": "MIT",
|
11
|
+
"files": [
|
12
|
+
"dist",
|
13
|
+
"scripts"
|
14
|
+
],
|
15
|
+
"publishConfig": {
|
16
|
+
"access": "public"
|
17
|
+
},
|
18
|
+
"scripts": {
|
19
|
+
"build": "tsc"
|
20
|
+
},
|
21
|
+
"devDependencies": {
|
22
|
+
"husky": "9.1.4",
|
23
|
+
"lint-staged": "13.1.4",
|
24
|
+
"typescript": "^5.6.2"
|
25
|
+
},
|
26
|
+
"husky": {
|
27
|
+
"hooks": {
|
28
|
+
"commit-msg": "commitlint .commitlintrc.js -E HUSKY_GIT_PARAMS",
|
29
|
+
"pre-commit": "lint-staged"
|
30
|
+
}
|
31
|
+
},
|
32
|
+
"lint-staged": {
|
33
|
+
"*": [
|
34
|
+
"eden lint format",
|
35
|
+
"git add"
|
36
|
+
]
|
37
|
+
}
|
38
|
+
}
|