@nu-art/permissions-backend 0.401.8 → 0.500.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/PermissionKey_BE.d.ts +9 -6
- package/PermissionKey_BE.js +20 -9
- package/RequirePermission.d.ts +21 -0
- package/RequirePermission.js +47 -0
- package/_entity/permission-access-level/ModuleBE_PermissionAccessLevelDB.d.ts +5 -9
- package/_entity/permission-access-level/ModuleBE_PermissionAccessLevelDB.js +1 -7
- package/_entity/permission-access-level/module-pack.d.ts +1 -1
- package/_entity/permission-access-level/module-pack.js +2 -2
- package/_entity/permission-api/ModuleBE_PermissionAPIDB.d.ts +6 -8
- package/_entity/permission-api/ModuleBE_PermissionAPIDB.js +4 -4
- package/_entity/permission-api/module-pack.d.ts +1 -1
- package/_entity/permission-api/module-pack.js +2 -2
- package/_entity/permission-domain/ModuleBE_PermissionDomainDB.d.ts +4 -10
- package/_entity/permission-domain/ModuleBE_PermissionDomainDB.js +1 -4
- package/_entity/permission-domain/module-pack.d.ts +1 -1
- package/_entity/permission-domain/module-pack.js +2 -2
- package/_entity/permission-group/ModuleBE_PermissionGroupDB.d.ts +5 -7
- package/_entity/permission-group/ModuleBE_PermissionGroupDB.js +10 -7
- package/_entity/permission-group/module-pack.d.ts +1 -1
- package/_entity/permission-group/module-pack.js +2 -2
- package/_entity/permission-project/ModuleBE_PermissionProjectDB.d.ts +4 -6
- package/_entity/permission-project/ModuleBE_PermissionProjectDB.js +1 -1
- package/_entity/permission-project/module-pack.d.ts +1 -1
- package/_entity/permission-project/module-pack.js +2 -2
- package/_entity/permission-user/ModuleBE_PermissionUserAPI.d.ts +4 -3
- package/_entity/permission-user/ModuleBE_PermissionUserAPI.js +63 -10
- package/_entity/permission-user/ModuleBE_PermissionUserDB.d.ts +8 -10
- package/_entity/permission-user/ModuleBE_PermissionUserDB.js +33 -18
- package/core/external-api-paths.d.ts +13 -0
- package/core/external-api-paths.js +13 -0
- package/core/function-permission-registry.d.ts +25 -0
- package/core/function-permission-registry.js +50 -0
- package/core/utils.d.ts +4 -4
- package/core/utils.js +7 -7
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/modules/ModuleBE_Permissions.d.ts +10 -4
- package/modules/ModuleBE_Permissions.js +365 -264
- package/modules/ModuleBE_PermissionsAssert.d.ts +20 -3
- package/modules/ModuleBE_PermissionsAssert.js +271 -205
- package/modules/consts.d.ts +2 -2
- package/modules/consts.js +5 -5
- package/modules/index.d.ts +1 -0
- package/modules/index.js +1 -0
- package/package.json +13 -12
- package/permissions-wire.d.ts +46 -0
- package/permissions-wire.js +47 -0
- package/permissions.js +29 -31
- package/types.d.ts +3 -3
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Module, StringMap, TypedMap } from '@nu-art/ts-common';
|
|
2
|
-
import { ServerApi_Middleware } from '@nu-art/
|
|
2
|
+
import type { ServerApi_Middleware } from '@nu-art/http-server';
|
|
3
|
+
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
3
4
|
import { CollectSessionData } from '@nu-art/user-account-backend';
|
|
4
|
-
import { Base_AccessLevel, DB_PermissionAccessLevel, DB_PermissionAPI, DomainToLevelValueMap, SessionData_StrictMode } from '@nu-art/permissions-shared';
|
|
5
|
+
import { API_PermissionsAssert, Base_AccessLevel, DB_PermissionAccessLevel, DB_PermissionAPI, DomainToLevelValueMap, SessionData_StrictMode } from '@nu-art/permissions-shared';
|
|
5
6
|
import { PermissionKey_BE } from '../PermissionKey_BE.js';
|
|
7
|
+
import type { FunctionPermissionDef } from '../core/function-permission-registry.js';
|
|
6
8
|
export type UserCalculatedAccessLevel = {
|
|
7
9
|
[domainId: string]: number;
|
|
8
10
|
};
|
|
@@ -27,9 +29,24 @@ export declare class ModuleBE_PermissionsAssert_Class extends Module<Config> imp
|
|
|
27
29
|
readonly CustomMiddleware: (keys: string[], action: (projectId: string, customFields: StringMap) => Promise<void>) => ServerApi_Middleware;
|
|
28
30
|
__collectSessionData(): Promise<SessionData_StrictMode>;
|
|
29
31
|
init(): void;
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Path-based sync filter; use function-based permissions instead. API collection deprecated.
|
|
34
|
+
* Returns a filter for sync manager. The app must call SyncManager.setModuleFilter(ModuleBE_PermissionsAssert.getPermissionsAssertSyncFilter()) when using a sync manager.
|
|
35
|
+
*/
|
|
36
|
+
getPermissionsAssertSyncFilter(): (dbModules: (ModuleBE_BaseDB<any>)[]) => Promise<(ModuleBE_BaseDB<any>)[]>;
|
|
37
|
+
assertUserPermissions(body: API_PermissionsAssert['assertUserPermissions']['Body']): Promise<API_PermissionsAssert['assertUserPermissions']['Response']>;
|
|
30
38
|
private assertPermission;
|
|
31
|
-
|
|
39
|
+
/**
|
|
40
|
+
* @deprecated Path-based API permission; use function-based permissions and assertFunctionPermission(def) instead. API collection deprecated.
|
|
41
|
+
*/
|
|
42
|
+
assertPathPermissions(projectId: string, path: string): Promise<void>;
|
|
32
43
|
assertUserPassesAccessLevels(domainToLevelValueMap: DomainToLevelValueMap, userPermissions: TypedMap<number>): void;
|
|
44
|
+
/**
|
|
45
|
+
* Asserts that the user has at least the required level for the function-permission def (from @RequirePermission).
|
|
46
|
+
* Call this before invoking a handler when getRequirePermissionDef(handler) returns a def.
|
|
47
|
+
*/
|
|
48
|
+
assertFunctionPermission(def: FunctionPermissionDef): void;
|
|
49
|
+
/** @deprecated Path-based API lookup; API collection deprecated. Use function-based permissions. */
|
|
33
50
|
getApiDetails(_path: string, projectId: string): Promise<{
|
|
34
51
|
dbApi: DB_PermissionAPI;
|
|
35
52
|
requestPermissions: DB_PermissionAccessLevel[];
|
|
@@ -16,227 +16,293 @@
|
|
|
16
16
|
* See the License for the specific language governing permissions and
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
20
|
+
var useValue = arguments.length > 2;
|
|
21
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
22
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
23
|
+
}
|
|
24
|
+
return useValue ? value : void 0;
|
|
25
|
+
};
|
|
26
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
27
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
28
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
29
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
30
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
31
|
+
var _, done = false;
|
|
32
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
33
|
+
var context = {};
|
|
34
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
35
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
36
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
37
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
38
|
+
if (kind === "accessor") {
|
|
39
|
+
if (result === void 0) continue;
|
|
40
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
41
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
42
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
43
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
44
|
+
}
|
|
45
|
+
else if (_ = accept(result)) {
|
|
46
|
+
if (kind === "field") initializers.unshift(_);
|
|
47
|
+
else descriptor[key] = _;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
51
|
+
done = true;
|
|
52
|
+
};
|
|
53
|
+
import { _keys, ApiException, arrayToMap, BadImplementationException, batchActionParallel, exists, filterDuplicates, filterInstances, ImplementationMissingException, Module } from '@nu-art/ts-common';
|
|
54
|
+
import { ApiHandler } from '@nu-art/http-server';
|
|
55
|
+
import { HttpMethod } from '@nu-art/api-types';
|
|
56
|
+
import { MemKey_AccountId } from '@nu-art/user-account-backend';
|
|
23
57
|
import { ApiDef_PermissionsAssert } from '@nu-art/permissions-shared';
|
|
24
|
-
import { MemKey_HttpRequestBody, MemKey_HttpRequestMethod, MemKey_HttpRequestQuery, MemKey_HttpRequestUrl } from '@nu-art/
|
|
58
|
+
import { MemKey_HttpRequestBody, MemKey_HttpRequestMethod, MemKey_HttpRequestQuery, MemKey_HttpRequestUrl } from '@nu-art/http-server';
|
|
25
59
|
import { MemKey_UserPermissions, SessionKey_Permissions_BE } from '../consts.js';
|
|
26
60
|
import { PermissionKey_BE } from '../PermissionKey_BE.js';
|
|
27
61
|
import { ModuleBE_PermissionAccessLevelDB, ModuleBE_PermissionAPIDB } from '../_entity.js';
|
|
62
|
+
import { RuntimeBE_Modules } from '@nu-art/db-api-backend';
|
|
28
63
|
/**
|
|
29
64
|
* [DomainId uniqueString]: accessLevel's numerical value
|
|
30
65
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return this.assertUserPermissions(projectId, MemKey_HttpRequestUrl.get());
|
|
42
|
-
})();
|
|
43
|
-
};
|
|
44
|
-
LoadPermissionsMiddleware = async () => {
|
|
45
|
-
try {
|
|
46
|
-
MemKey_UserPermissions.get();
|
|
66
|
+
let ModuleBE_PermissionsAssert_Class = (() => {
|
|
67
|
+
let _classSuper = Module;
|
|
68
|
+
let _instanceExtraInitializers = [];
|
|
69
|
+
let _assertUserPermissions_decorators;
|
|
70
|
+
return class ModuleBE_PermissionsAssert_Class extends _classSuper {
|
|
71
|
+
static {
|
|
72
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
73
|
+
_assertUserPermissions_decorators = [ApiHandler(ApiDef_PermissionsAssert.assertUserPermissions)];
|
|
74
|
+
__esDecorate(this, null, _assertUserPermissions_decorators, { kind: "method", name: "assertUserPermissions", static: false, private: false, access: { has: obj => "assertUserPermissions" in obj, get: obj => obj.assertUserPermissions }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
75
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
47
76
|
}
|
|
48
|
-
|
|
49
|
-
|
|
77
|
+
projectId = __runInitializers(this, _instanceExtraInitializers);
|
|
78
|
+
_keys = {};
|
|
79
|
+
permissionKeys = {};
|
|
80
|
+
// constructor() {
|
|
81
|
+
// super();
|
|
82
|
+
// this.setMinLevel(LogLevel.Debug);
|
|
83
|
+
// }
|
|
84
|
+
Middleware = (keys = []) => async () => {
|
|
85
|
+
await this.CustomMiddleware(keys, async (projectId) => {
|
|
86
|
+
return this.assertPathPermissions(projectId, MemKey_HttpRequestUrl.get());
|
|
87
|
+
})();
|
|
88
|
+
};
|
|
89
|
+
LoadPermissionsMiddleware = async () => {
|
|
90
|
+
try {
|
|
91
|
+
MemKey_UserPermissions.get();
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
MemKey_UserPermissions.set(SessionKey_Permissions_BE.get().domainToValueMap);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
CustomMiddleware = (keys, action) => async () => {
|
|
98
|
+
const customFields = {};
|
|
99
|
+
let object;
|
|
100
|
+
const reqMethod = MemKey_HttpRequestMethod.get();
|
|
101
|
+
switch (reqMethod) {
|
|
102
|
+
case HttpMethod.POST:
|
|
103
|
+
case HttpMethod.PATCH:
|
|
104
|
+
case HttpMethod.PUT:
|
|
105
|
+
object = MemKey_HttpRequestBody.get();
|
|
106
|
+
break;
|
|
107
|
+
case HttpMethod.GET:
|
|
108
|
+
case HttpMethod.DELETE:
|
|
109
|
+
object = MemKey_HttpRequestQuery.get();
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
throw new BadImplementationException(`Generic custom fields cannot be extracted on api with method: ${reqMethod}`);
|
|
113
|
+
}
|
|
114
|
+
_keys(object).filter(key => keys.includes(key)).forEach(key => {
|
|
115
|
+
const oElement = object[key];
|
|
116
|
+
if (oElement === undefined || oElement === null)
|
|
117
|
+
return;
|
|
118
|
+
if (typeof oElement !== 'string')
|
|
119
|
+
return;
|
|
120
|
+
customFields[key] = oElement;
|
|
121
|
+
});
|
|
122
|
+
const projectId = this.projectId;
|
|
123
|
+
await action(projectId, customFields);
|
|
124
|
+
};
|
|
125
|
+
async __collectSessionData() {
|
|
126
|
+
return { key: 'strictMode', value: { isStrictMode: this.isStrictMode() } };
|
|
50
127
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
128
|
+
init() {
|
|
129
|
+
super.init();
|
|
130
|
+
_keys(this._keys).forEach(key => this.permissionKeys[key] = new PermissionKey_BE(key));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* @deprecated Path-based sync filter; use function-based permissions instead. API collection deprecated.
|
|
134
|
+
* Returns a filter for sync manager. The app must call SyncManager.setModuleFilter(ModuleBE_PermissionsAssert.getPermissionsAssertSyncFilter()) when using a sync manager.
|
|
135
|
+
*/
|
|
136
|
+
getPermissionsAssertSyncFilter() {
|
|
137
|
+
const assert = this;
|
|
138
|
+
return async (dbModules) => {
|
|
139
|
+
const userPermissions = MemKey_UserPermissions.get();
|
|
140
|
+
const mapDbNameToApiModules = arrayToMap(RuntimeBE_Modules(), (item) => item.dbModule.dbDef.dbKey);
|
|
141
|
+
const paths = dbModules.map(module => {
|
|
142
|
+
const apiModule = mapDbNameToApiModules[module.dbDef.dbKey];
|
|
143
|
+
if (!apiModule)
|
|
144
|
+
return undefined;
|
|
145
|
+
return apiModule.crudApiDef?.query?.path;
|
|
146
|
+
});
|
|
147
|
+
const _allApis = await ModuleBE_PermissionAPIDB.query.where({});
|
|
148
|
+
const apis = _allApis.filter(_api => paths.includes(_api.path));
|
|
149
|
+
const mapPathToDBApi = arrayToMap(apis, api => api.path);
|
|
150
|
+
return dbModules.filter((dbModule, index) => {
|
|
151
|
+
const path = paths[index];
|
|
152
|
+
if (!path)
|
|
153
|
+
return false;
|
|
154
|
+
const dbApi = mapPathToDBApi[path];
|
|
155
|
+
if (!dbApi)
|
|
156
|
+
return !ModuleBE_PermissionsAssert.isStrictMode();
|
|
157
|
+
const accessLevels = dbApi._accessLevels;
|
|
158
|
+
return _keys(accessLevels).reduce((hasAccess, domainId) => {
|
|
159
|
+
if (!hasAccess)
|
|
160
|
+
return false;
|
|
161
|
+
const userDomainAccessValue = userPermissions[domainId];
|
|
162
|
+
const apiRequiredAccessValue = accessLevels[domainId];
|
|
163
|
+
if (!userDomainAccessValue)
|
|
164
|
+
return false;
|
|
165
|
+
if (!exists(userDomainAccessValue) || userDomainAccessValue < apiRequiredAccessValue) {
|
|
166
|
+
assert.logErrorBold(`${(userDomainAccessValue ?? 0)} < ${apiRequiredAccessValue} === ${(userDomainAccessValue ?? 0) < apiRequiredAccessValue}`);
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
return hasAccess;
|
|
170
|
+
}, true);
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async assertUserPermissions(body) {
|
|
175
|
+
return this.assertPermission(body);
|
|
176
|
+
}
|
|
177
|
+
assertPermission = async (body) => {
|
|
178
|
+
await ModuleBE_PermissionsAssert.assertPathPermissions(body.projectId, body.path);
|
|
179
|
+
return { userId: MemKey_AccountId.get() };
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* @deprecated Path-based API permission; use function-based permissions and assertFunctionPermission(def) instead. API collection deprecated.
|
|
183
|
+
*/
|
|
184
|
+
async assertPathPermissions(projectId, path) {
|
|
185
|
+
// [DomainId]: accessLevel's numerical value
|
|
90
186
|
const userPermissions = MemKey_UserPermissions.get();
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
// this.logWarningBold(`no dbApi ${path}`);
|
|
114
|
-
return !ModuleBE_PermissionsAssert.isStrictMode();
|
|
187
|
+
const apiDetails = await this.getApiDetails(path, projectId);
|
|
188
|
+
this.logDebug('______________________________');
|
|
189
|
+
this.logDebug(userPermissions);
|
|
190
|
+
this.logDebug('______________________________');
|
|
191
|
+
this.logDebug(apiDetails?.dbApi);
|
|
192
|
+
this.logDebug('______________________________');
|
|
193
|
+
if (!apiDetails || !apiDetails.dbApi.accessLevelIds) {
|
|
194
|
+
if (!this.config.strictMode)
|
|
195
|
+
return;
|
|
196
|
+
throw new ApiException(403, `No permissions configuration specified for api: ${projectId ? `${projectId}--` : ''}${path}`);
|
|
197
|
+
}
|
|
198
|
+
//_accessLevels is a map[domain id <> access level numeric value]
|
|
199
|
+
this.assertUserPassesAccessLevels(apiDetails.dbApi._accessLevels, userPermissions);
|
|
200
|
+
}
|
|
201
|
+
assertUserPassesAccessLevels(domainToLevelValueMap, userPermissions) {
|
|
202
|
+
_keys(domainToLevelValueMap).forEach(domainId => {
|
|
203
|
+
const userDomainPermission = userPermissions[domainId];
|
|
204
|
+
if (!exists(userDomainPermission))
|
|
205
|
+
throw new ApiException(403, 'Missing Access For This Domain');
|
|
206
|
+
if (userDomainPermission < domainToLevelValueMap[domainId]) {
|
|
207
|
+
this.logErrorBold(`for domain - userAccessLevel <> expectedAccessLevel: "${domainId}" ${(userDomainPermission ?? 0)} <> ${domainToLevelValueMap[domainId]}`);
|
|
208
|
+
throw new ApiException(403, 'Action Forbidden');
|
|
115
209
|
}
|
|
116
|
-
const accessLevels = dbApi._accessLevels;
|
|
117
|
-
return _keys(accessLevels).reduce((hasAccess, domainId) => {
|
|
118
|
-
if (!hasAccess)
|
|
119
|
-
return false;
|
|
120
|
-
const userDomainAccessValue = userPermissions[domainId];
|
|
121
|
-
const apiRequiredAccessValue = accessLevels[domainId];
|
|
122
|
-
if (!userDomainAccessValue)
|
|
123
|
-
return false;
|
|
124
|
-
if (!exists(userDomainAccessValue) || userDomainAccessValue < apiRequiredAccessValue) {
|
|
125
|
-
this.logErrorBold(`${(userDomainAccessValue ?? 0)} < ${apiRequiredAccessValue} === ${(userDomainAccessValue ?? 0) < apiRequiredAccessValue}`);
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
return hasAccess;
|
|
129
|
-
}, true);
|
|
130
210
|
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
this.logDebug('______________________________');
|
|
142
|
-
this.logDebug(userPermissions);
|
|
143
|
-
this.logDebug('______________________________');
|
|
144
|
-
this.logDebug(apiDetails?.dbApi);
|
|
145
|
-
this.logDebug('______________________________');
|
|
146
|
-
if (!apiDetails || !apiDetails.dbApi.accessLevelIds) {
|
|
147
|
-
if (!this.config.strictMode)
|
|
148
|
-
return;
|
|
149
|
-
throw new ApiException(403, `No permissions configuration specified for api: ${projectId ? `${projectId}--` : ''}${path}`);
|
|
150
|
-
}
|
|
151
|
-
//_accessLevels is a map[domain id <> access level numeric value]
|
|
152
|
-
this.assertUserPassesAccessLevels(apiDetails.dbApi._accessLevels, userPermissions);
|
|
153
|
-
}
|
|
154
|
-
assertUserPassesAccessLevels(domainToLevelValueMap, userPermissions) {
|
|
155
|
-
_keys(domainToLevelValueMap).forEach(domainId => {
|
|
156
|
-
const userDomainPermission = userPermissions[domainId];
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Asserts that the user has at least the required level for the function-permission def (from @RequirePermission).
|
|
214
|
+
* Call this before invoking a handler when getRequirePermissionDef(handler) returns a def.
|
|
215
|
+
*/
|
|
216
|
+
assertFunctionPermission(def) {
|
|
217
|
+
if (def.domainId === undefined || def.levelValue === undefined)
|
|
218
|
+
throw new ApiException(503, `Function permission "${def.scopeKey}/${def.value}" not yet provisioned; run project setup to create domains/levels from registry.`);
|
|
219
|
+
const userPermissions = MemKey_UserPermissions.get();
|
|
220
|
+
const userDomainPermission = userPermissions[def.domainId];
|
|
157
221
|
if (!exists(userDomainPermission))
|
|
158
222
|
throw new ApiException(403, 'Missing Access For This Domain');
|
|
159
|
-
if (userDomainPermission <
|
|
160
|
-
this.logErrorBold(`
|
|
223
|
+
if (userDomainPermission < def.levelValue) {
|
|
224
|
+
this.logErrorBold(`function permission - userLevel < required: "${def.scopeKey}/${def.value}" ${userDomainPermission} < ${def.levelValue}`);
|
|
161
225
|
throw new ApiException(403, 'Action Forbidden');
|
|
162
226
|
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
227
|
+
}
|
|
228
|
+
/** @deprecated Path-based API lookup; API collection deprecated. Use function-based permissions. */
|
|
229
|
+
async getApiDetails(_path, projectId) {
|
|
230
|
+
let path = _path.substring(0, (_path + '?').indexOf('?')); //Get raw path without query
|
|
231
|
+
if (path.at(0) === '/')
|
|
232
|
+
path = path.substring(1);
|
|
233
|
+
this.logDebug(`Fetching Permission API for path: ${path} and project id: ${projectId}`);
|
|
234
|
+
const dbApi = (await ModuleBE_PermissionAPIDB.query.custom({
|
|
235
|
+
where: {
|
|
236
|
+
path,
|
|
237
|
+
projectId
|
|
238
|
+
}
|
|
239
|
+
}))[0];
|
|
240
|
+
if (!dbApi)
|
|
241
|
+
return undefined;
|
|
242
|
+
const requestPermissions = await this.getAccessLevels(dbApi.accessLevelIds || []);
|
|
243
|
+
return {
|
|
244
|
+
dbApi,
|
|
245
|
+
requestPermissions
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
async getApisDetails(urls, projectId) {
|
|
249
|
+
const paths = urls.map(_path => _path.substring(0, (_path + '?').indexOf('?')));
|
|
250
|
+
const apiDbs = await batchActionParallel(paths, 10, elements => ModuleBE_PermissionAPIDB.query.custom({
|
|
251
|
+
where: {
|
|
252
|
+
projectId,
|
|
253
|
+
path: { $in: elements }
|
|
254
|
+
}
|
|
255
|
+
}));
|
|
256
|
+
return Promise.all(paths.map(async (path) => {
|
|
257
|
+
const apiDb = apiDbs.find(_apiDb => _apiDb.path === path);
|
|
258
|
+
if (!apiDb)
|
|
259
|
+
return;
|
|
260
|
+
try {
|
|
261
|
+
const requestPermissions = await this.getAccessLevels(apiDb.accessLevelIds);
|
|
262
|
+
return ({
|
|
263
|
+
apiDb,
|
|
264
|
+
requestPermissions
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
}));
|
|
271
|
+
}
|
|
272
|
+
async getAccessLevels(_accessLevelIds) {
|
|
273
|
+
const accessLevelIds = filterDuplicates(_accessLevelIds || []);
|
|
274
|
+
const requestPermissions = filterInstances(await ModuleBE_PermissionAccessLevelDB.query.all(accessLevelIds));
|
|
275
|
+
const idNotFound = accessLevelIds.find(lId => !requestPermissions.find(r => r._id === lId));
|
|
276
|
+
if (idNotFound)
|
|
277
|
+
throw new ApiException(404, `Could not find api level with _id: ${idNotFound}`);
|
|
278
|
+
return requestPermissions;
|
|
279
|
+
}
|
|
280
|
+
setProjectId = (projectId) => {
|
|
281
|
+
this.projectId = projectId;
|
|
182
282
|
};
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
}));
|
|
207
|
-
}
|
|
208
|
-
async getAccessLevels(_accessLevelIds) {
|
|
209
|
-
const accessLevelIds = filterDuplicates(_accessLevelIds || []);
|
|
210
|
-
const requestPermissions = filterInstances(await ModuleBE_PermissionAccessLevelDB.query.all(accessLevelIds));
|
|
211
|
-
const idNotFound = accessLevelIds.find(lId => !requestPermissions.find(r => r._id === lId));
|
|
212
|
-
if (idNotFound)
|
|
213
|
-
throw new ApiException(404, `Could not find api level with _id: ${idNotFound}`);
|
|
214
|
-
return requestPermissions;
|
|
215
|
-
}
|
|
216
|
-
setProjectId = (projectId) => {
|
|
217
|
-
this.projectId = projectId;
|
|
283
|
+
getRegEx(value) {
|
|
284
|
+
if (!value)
|
|
285
|
+
return new RegExp(`^${value}$`, 'g');
|
|
286
|
+
let regExValue = value;
|
|
287
|
+
const startRegEx = '^';
|
|
288
|
+
const endRegEx = '$';
|
|
289
|
+
if (value[0] !== startRegEx)
|
|
290
|
+
regExValue = startRegEx + regExValue;
|
|
291
|
+
if (value[value.length - 1] !== endRegEx)
|
|
292
|
+
regExValue = regExValue + endRegEx;
|
|
293
|
+
return new RegExp(regExValue, 'g');
|
|
294
|
+
}
|
|
295
|
+
registerPermissionKeys(keys) {
|
|
296
|
+
keys.forEach(key => {
|
|
297
|
+
if (this._keys[key])
|
|
298
|
+
throw new ImplementationMissingException(`Registered PermissionKey '${key}' more than once!`);
|
|
299
|
+
this._keys[key] = true;
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
isStrictMode() {
|
|
303
|
+
return !!this.config.strictMode;
|
|
304
|
+
}
|
|
218
305
|
};
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return new RegExp(`^${value}$`, 'g');
|
|
222
|
-
let regExValue = value;
|
|
223
|
-
const startRegEx = '^';
|
|
224
|
-
const endRegEx = '$';
|
|
225
|
-
if (value[0] !== startRegEx)
|
|
226
|
-
regExValue = startRegEx + regExValue;
|
|
227
|
-
if (value[value.length - 1] !== endRegEx)
|
|
228
|
-
regExValue = regExValue + endRegEx;
|
|
229
|
-
return new RegExp(regExValue, 'g');
|
|
230
|
-
}
|
|
231
|
-
registerPermissionKeys(keys) {
|
|
232
|
-
keys.forEach(key => {
|
|
233
|
-
if (this._keys[key])
|
|
234
|
-
throw new ImplementationMissingException(`Registered PermissionKey '${key}' more than once!`);
|
|
235
|
-
this._keys[key] = true;
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
isStrictMode() {
|
|
239
|
-
return !!this.config.strictMode;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
306
|
+
})();
|
|
307
|
+
export { ModuleBE_PermissionsAssert_Class };
|
|
242
308
|
export const ModuleBE_PermissionsAssert = new ModuleBE_PermissionsAssert_Class();
|
package/modules/consts.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { DefaultDef_Package } from '../types.js';
|
|
2
2
|
export declare const Domain_PermissionAssignment: Readonly<{
|
|
3
|
-
_id: "
|
|
3
|
+
_id: import("@nu-art/db-api-shared").DB_UniqueId<"permissions--domain">;
|
|
4
4
|
namespace: "Permissions Assignment";
|
|
5
5
|
}>;
|
|
6
6
|
export declare const Permissions_PermissionAssignment: DefaultDef_Package;
|
|
7
7
|
export declare const Domain_PermissionManagement: Readonly<{
|
|
8
|
-
_id: "
|
|
8
|
+
_id: import("@nu-art/db-api-shared").DB_UniqueId<"permissions--domain">;
|
|
9
9
|
namespace: "Permissions Management";
|
|
10
10
|
}>;
|
|
11
11
|
export declare const Permissions_PermissionManagement: DefaultDef_Package;
|
package/modules/consts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DBDef_PermissionAccessLevel, DBDef_PermissionAPI, DBDef_PermissionDomain, DBDef_PermissionGroup, DBDef_PermissionProject, DBDef_PermissionUser, DomainNamespace_PermissionAssignment, DomainNamespace_PermissionManagement, DuplicateDefaultAccessLevels } from '@nu-art/permissions-shared';
|
|
1
|
+
import { DBDef_PermissionAccessLevel, DBDef_PermissionAPI, DBDef_PermissionDomain, DBDef_PermissionGroup, DBDef_PermissionProject, DBDef_PermissionUser, DomainNamespace_PermissionAssignment, DomainNamespace_PermissionManagement, DuplicateDefaultAccessLevels, toPermissionDomainId } from '@nu-art/permissions-shared';
|
|
2
2
|
export const Domain_PermissionAssignment = Object.freeze({
|
|
3
|
-
_id: '1f41541c4514b50140ae62c1f7097029',
|
|
3
|
+
_id: toPermissionDomainId('1f41541c4514b50140ae62c1f7097029'),
|
|
4
4
|
namespace: DomainNamespace_PermissionAssignment
|
|
5
5
|
});
|
|
6
6
|
export const Permissions_PermissionAssignment = {
|
|
@@ -8,13 +8,13 @@ export const Permissions_PermissionAssignment = {
|
|
|
8
8
|
domains: [
|
|
9
9
|
{
|
|
10
10
|
...Domain_PermissionAssignment,
|
|
11
|
-
levels:
|
|
11
|
+
levels: DuplicateDefaultAccessLevels(Domain_PermissionAssignment._id),
|
|
12
12
|
dbNames: [DBDef_PermissionUser.dbKey, DBDef_PermissionGroup.dbKey]
|
|
13
13
|
}
|
|
14
14
|
]
|
|
15
15
|
};
|
|
16
16
|
export const Domain_PermissionManagement = Object.freeze({
|
|
17
|
-
_id: '1f41541c4514b50140ae62c1f7097029',
|
|
17
|
+
_id: toPermissionDomainId('1f41541c4514b50140ae62c1f7097029'),
|
|
18
18
|
namespace: DomainNamespace_PermissionManagement
|
|
19
19
|
});
|
|
20
20
|
export const Permissions_PermissionManagement = {
|
|
@@ -22,7 +22,7 @@ export const Permissions_PermissionManagement = {
|
|
|
22
22
|
domains: [
|
|
23
23
|
{
|
|
24
24
|
...Domain_PermissionManagement,
|
|
25
|
-
levels:
|
|
25
|
+
levels: DuplicateDefaultAccessLevels(Domain_PermissionManagement._id),
|
|
26
26
|
dbNames: [DBDef_PermissionProject.dbKey, DBDef_PermissionDomain.dbKey, DBDef_PermissionAccessLevel.dbKey, DBDef_PermissionAPI.dbKey]
|
|
27
27
|
}
|
|
28
28
|
]
|
package/modules/index.d.ts
CHANGED
package/modules/index.js
CHANGED