@nu-art/permissions-backend 0.400.5

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.
Files changed (65) hide show
  1. package/PermissionKey_BE.d.ts +13 -0
  2. package/PermissionKey_BE.js +48 -0
  3. package/_entity/permission-access-level/ModuleBE_PermissionAccessLevelDB.d.ts +18 -0
  4. package/_entity/permission-access-level/ModuleBE_PermissionAccessLevelDB.js +55 -0
  5. package/_entity/permission-access-level/index.d.ts +2 -0
  6. package/_entity/permission-access-level/index.js +2 -0
  7. package/_entity/permission-access-level/module-pack.d.ts +1 -0
  8. package/_entity/permission-access-level/module-pack.js +3 -0
  9. package/_entity/permission-api/ModuleBE_PermissionAPIDB.d.ts +12 -0
  10. package/_entity/permission-api/ModuleBE_PermissionAPIDB.js +62 -0
  11. package/_entity/permission-api/index.d.ts +2 -0
  12. package/_entity/permission-api/index.js +2 -0
  13. package/_entity/permission-api/module-pack.d.ts +1 -0
  14. package/_entity/permission-api/module-pack.js +3 -0
  15. package/_entity/permission-domain/ModuleBE_PermissionDomainDB.d.ts +15 -0
  16. package/_entity/permission-domain/ModuleBE_PermissionDomainDB.js +25 -0
  17. package/_entity/permission-domain/index.d.ts +2 -0
  18. package/_entity/permission-domain/index.js +2 -0
  19. package/_entity/permission-domain/module-pack.d.ts +1 -0
  20. package/_entity/permission-domain/module-pack.js +3 -0
  21. package/_entity/permission-group/ModuleBE_PermissionGroupDB.d.ts +14 -0
  22. package/_entity/permission-group/ModuleBE_PermissionGroupDB.js +62 -0
  23. package/_entity/permission-group/index.d.ts +2 -0
  24. package/_entity/permission-group/index.js +2 -0
  25. package/_entity/permission-group/module-pack.d.ts +1 -0
  26. package/_entity/permission-group/module-pack.js +3 -0
  27. package/_entity/permission-project/ModuleBE_PermissionProjectDB.d.ts +10 -0
  28. package/_entity/permission-project/ModuleBE_PermissionProjectDB.js +12 -0
  29. package/_entity/permission-project/index.d.ts +2 -0
  30. package/_entity/permission-project/index.js +2 -0
  31. package/_entity/permission-project/module-pack.d.ts +1 -0
  32. package/_entity/permission-project/module-pack.js +3 -0
  33. package/_entity/permission-user/ModuleBE_PermissionUserAPI.d.ts +8 -0
  34. package/_entity/permission-user/ModuleBE_PermissionUserAPI.js +13 -0
  35. package/_entity/permission-user/ModuleBE_PermissionUserDB.d.ts +36 -0
  36. package/_entity/permission-user/ModuleBE_PermissionUserDB.js +222 -0
  37. package/_entity/permission-user/index.d.ts +3 -0
  38. package/_entity/permission-user/index.js +3 -0
  39. package/_entity/permission-user/module-pack.d.ts +2 -0
  40. package/_entity/permission-user/module-pack.js +3 -0
  41. package/_entity.d.ts +12 -0
  42. package/_entity.js +18 -0
  43. package/consts.d.ts +7 -0
  44. package/consts.js +5 -0
  45. package/core/module-pack.d.ts +3 -0
  46. package/core/module-pack.js +32 -0
  47. package/core/utils.d.ts +25 -0
  48. package/core/utils.js +85 -0
  49. package/index.d.ts +4 -0
  50. package/index.js +22 -0
  51. package/modules/ModuleBE_Permissions.d.ts +77 -0
  52. package/modules/ModuleBE_Permissions.js +357 -0
  53. package/modules/ModuleBE_PermissionsAssert.d.ts +48 -0
  54. package/modules/ModuleBE_PermissionsAssert.js +242 -0
  55. package/modules/consts.d.ts +11 -0
  56. package/modules/consts.js +29 -0
  57. package/modules/index.d.ts +1 -0
  58. package/modules/index.js +19 -0
  59. package/package.json +85 -0
  60. package/permissions.d.ts +22 -0
  61. package/permissions.js +154 -0
  62. package/shared.d.ts +1 -0
  63. package/shared.js +19 -0
  64. package/types.d.ts +28 -0
  65. package/types.js +1 -0
@@ -0,0 +1,222 @@
1
+ import { MemKey_ServerApi, ModuleBE_BaseDB, Storm, } from '@nu-art/thunderstorm-backend';
2
+ import { DBDef_PermissionUser } from '@nu-art/permissions-shared';
3
+ import { _keys, ApiException, asOptionalArray, batchActionParallel, dbObjectToId, exists, filterDuplicates, filterInstances, filterKeys, flatArray, JwtTools, merge, Year } from '@nu-art/ts-common';
4
+ import { ModuleBE_PermissionGroupDB } from '../permission-group/ModuleBE_PermissionGroupDB.js';
5
+ import { MemKey_AccountId, ModuleBE_AccountDB, ModuleBE_SessionDB } from '@nu-art/user-account-backend';
6
+ import { MemKey_UserPermissions } from '../../consts.js';
7
+ import { dispatcher_collectServiceAccounts } from '@nu-art/thunderstorm-backend/modules/_tdb/service-accounts';
8
+ export class ModuleBE_PermissionUserDB_Class extends ModuleBE_BaseDB {
9
+ defaultPermissionGroups;
10
+ constructor() {
11
+ super(DBDef_PermissionUser);
12
+ }
13
+ __performProjectSetup() {
14
+ return {
15
+ priority: 4,
16
+ processor: async () => {
17
+ const accounts = await ModuleBE_AccountDB.query.where({});
18
+ const permissionsUser = await this.query.all(accounts.map(dbObjectToId));
19
+ const usersToUpsert = [];
20
+ const usersToDelete = [];
21
+ permissionsUser.forEach((user, index) => {
22
+ if (exists(user)) {
23
+ if (!exists(accounts.find(account => account._id === user._id)))
24
+ usersToDelete.push(user);
25
+ return;
26
+ }
27
+ usersToUpsert.push({
28
+ _id: accounts[index]._id,
29
+ groups: [],
30
+ });
31
+ });
32
+ await this.set.all(usersToUpsert);
33
+ await this.delete.all(usersToDelete);
34
+ // This stage updates the rtdb's config- which is why it's last. Changing the rtdb's config kills the server.
35
+ const serviceAccounts = flatArray(dispatcher_collectServiceAccounts.dispatchModule());
36
+ await this.createSystemServiceAccount(serviceAccounts);
37
+ }
38
+ };
39
+ }
40
+ async __onUserLogin(account, transaction) {
41
+ await this.insertIfNotExist(account, transaction);
42
+ }
43
+ async __onNewUserRegistered(account, transaction) {
44
+ await this.insertIfNotExist(account, transaction);
45
+ }
46
+ // protected async canDeleteDocument(transaction: FirestoreTransaction, dbInstances: DB_PermissionUser[]) {
47
+ // const conflicts: DB_PermissionUser[] = [];
48
+ // const accounts = await ModuleBE_AccountDB.query.custom(_EmptyQuery);
49
+ //
50
+ // for (const item of dbInstances) {
51
+ // const account = accounts.find(acc => acc._id === item.accountId);
52
+ // if (account)
53
+ // conflicts.push(item);
54
+ // }
55
+ //
56
+ // if (conflicts.length)
57
+ // throw new ApiException<DB_EntityDependency<any>[]>(422, 'permission users are connected to accounts').setErrorBody({
58
+ // type: 'has-dependencies',
59
+ // body: conflicts.map(conflict => ({collectionKey: 'User', conflictingIds: [conflict._id]}))
60
+ // });
61
+ // }
62
+ async preWriteProcessing(instance, originalDbInstance, t) {
63
+ instance._auditorId = MemKey_AccountId.get();
64
+ instance.__groupIds = filterDuplicates(instance.groups.map(group => group.groupId) || []);
65
+ if (!instance.__groupIds.length)
66
+ return;
67
+ // Get all groups the user has from the collection
68
+ const dbGroups = filterInstances(await ModuleBE_PermissionGroupDB.query.all(instance.__groupIds, t));
69
+ // Verify all groups actually existing in the collection
70
+ if (instance.__groupIds.length !== dbGroups.length) {
71
+ const dbGroupIds = dbGroups.map(dbObjectToId);
72
+ throw new ApiException(422, `Trying to assign a user to a permission-group that does not exist: ${instance.__groupIds.filter(groupId => !dbGroupIds.includes(groupId))}`);
73
+ }
74
+ //todo check for duplications in data
75
+ }
76
+ async postWriteProcessing(data, actionType) {
77
+ const deleted = asOptionalArray(data.deleted) ?? [];
78
+ const updated = asOptionalArray(data.updated) ?? [];
79
+ const beforeIds = (asOptionalArray(data.before) ?? []).map(before => before?._id);
80
+ const accountIdToInvalidate = filterDuplicates(filterInstances([...deleted, ...updated].map(i => i?._id))).filter(id => beforeIds.includes(id));
81
+ await this.invalidateSession(accountIdToInvalidate);
82
+ }
83
+ insertIfNotExist = async (uiAccount, transaction) => {
84
+ const create = async (transaction) => {
85
+ const defaultPermissionGroups = ModuleBE_PermissionUserDB.defaultPermissionGroups ? await ModuleBE_PermissionUserDB.defaultPermissionGroups() : [];
86
+ const permissionGroups = ModuleBE_PermissionUserDB.defaultPermissionGroups
87
+ ? filterInstances(await ModuleBE_PermissionGroupDB.query.all(defaultPermissionGroups.map(item => item.groupId)))
88
+ : [];
89
+ this.logInfo(`Received ${defaultPermissionGroups.length} groups to assign, ${permissionGroups.length} of which exist`);
90
+ const permissionsUserToCreate = {
91
+ _id: uiAccount._id,
92
+ groups: permissionGroups.map(group => ({ groupId: group._id })),
93
+ _auditorId: MemKey_AccountId.get()
94
+ };
95
+ return ModuleBE_PermissionUserDB.create.item(permissionsUserToCreate, transaction);
96
+ };
97
+ return ModuleBE_PermissionUserDB.collection.uniqueGetOrCreate({ _id: uiAccount._id }, create, transaction);
98
+ };
99
+ async assignPermissions(body) {
100
+ if (!body.targetAccountIds.length)
101
+ throw new ApiException(400, `Asked to modify permissions but provided no users to modify permissions of.`);
102
+ const usersToGiveTo = filterInstances(await this.query.all(body.targetAccountIds));
103
+ // console.log('assignPermissions target accounts ');
104
+ // console.log(await this.query.custom(_EmptyQuery));
105
+ if (!usersToGiveTo.length || usersToGiveTo.length !== body.targetAccountIds.length) {
106
+ const dbUserIds = usersToGiveTo.map(dbObjectToId);
107
+ throw new ApiException(404, `Asked to give permissions to non-existent user accounts: ${body.targetAccountIds.filter(id => !dbUserIds.includes(id))}`);
108
+ }
109
+ const dbGroups = filterInstances(await ModuleBE_PermissionGroupDB.query.all(body.permissionGroupIds));
110
+ if (dbGroups.length !== body.permissionGroupIds.length) {
111
+ const dbGroupIds = dbGroups.map(dbObjectToId);
112
+ throw new ApiException(404, `Asked to give users non-existing permission groups: ${body.permissionGroupIds.filter(id => !dbGroupIds.includes(id))}`);
113
+ }
114
+ const myUserPermissions = MemKey_UserPermissions.get();
115
+ const permissionsToGive = dbGroups.reduce((map, group) => {
116
+ // Gather the highest permissions for each domain, from all groups
117
+ _keys(group._levelsMap || []).forEach(domainId => {
118
+ if (map[domainId] === undefined)
119
+ map[domainId] = 0;
120
+ if (map[domainId] < group._levelsMap[domainId])
121
+ map[domainId] = group._levelsMap[domainId];
122
+ });
123
+ return map;
124
+ }, {});
125
+ const failedDomains = _keys(permissionsToGive).filter(domainId => {
126
+ const tooLowPermission = myUserPermissions[domainId] < permissionsToGive[domainId];
127
+ this.logError(`${myUserPermissions[domainId]} < ${permissionsToGive[domainId]} === ${tooLowPermission}`);
128
+ const noPermissionInThisDomain = myUserPermissions[domainId] === undefined;
129
+ return noPermissionInThisDomain || tooLowPermission;
130
+ });
131
+ if (failedDomains.length)
132
+ throw new ApiException(403, `Attempted to give higher permissions than current user has: ${failedDomains}`);
133
+ const groupIds = dbGroups.map(group => ({ groupId: group._id }));
134
+ const usersToUpdate = usersToGiveTo.map(user => {
135
+ user.groups = groupIds;
136
+ return user;
137
+ });
138
+ await this.set.multi(usersToUpdate);
139
+ }
140
+ setDefaultPermissionGroups = (groupsGetter) => {
141
+ this.defaultPermissionGroups = groupsGetter;
142
+ };
143
+ clearDefaultPermissionGroups = () => {
144
+ delete this.defaultPermissionGroups;
145
+ };
146
+ /**
147
+ * The system requires to perform action, which in other cases can also be done by a human.
148
+ * This requires system features to identify as a bot user, or "Service Account"
149
+ *
150
+ * @param serviceAccounts - List of Accounts to create
151
+ * @private
152
+ */
153
+ async createSystemServiceAccount(serviceAccounts) {
154
+ this.logInfoBold('Creating Service Accounts: ', serviceAccounts);
155
+ // @ts-ignore
156
+ const tokenCreator = ModuleBE_AccountDB.token.create;
157
+ // @ts-ignore
158
+ const invalidateAccount = ModuleBE_AccountDB.token.invalidateAll;
159
+ const envConfigRef = Storm.getInstance().getGlobalEnvConfigRef();
160
+ const updatedConfig = {};
161
+ //Run over all service accounts
162
+ for (const serviceAccount of serviceAccounts) {
163
+ // Create account if it doesn't already exist
164
+ const accountsToRequest = filterKeys({
165
+ type: 'service',
166
+ email: serviceAccount.email,
167
+ description: serviceAccount.description
168
+ });
169
+ let account;
170
+ //Get or create service account
171
+ try {
172
+ account = await ModuleBE_AccountDB.impl.querySafeAccount({ email: serviceAccount.email });
173
+ }
174
+ catch (e) {
175
+ this.logInfo('NOTICE: querySafeAccount failed, creating accounts');
176
+ account = await ModuleBE_AccountDB.account.create(accountsToRequest);
177
+ }
178
+ // Assign permissions groups to service account
179
+ const permissionsUser = await ModuleBE_PermissionUserDB.query.uniqueAssert({ _id: account._id });
180
+ permissionsUser.groups = serviceAccount.groupIds?.map(groupId => ({ groupId })) || [];
181
+ await ModuleBE_PermissionUserDB.set.item(permissionsUser);
182
+ //Service accounts are only allowed to have one session... but this isn't the defined place to be a cop about it
183
+ const sessions = await ModuleBE_AccountDB.account.getSessions(account);
184
+ //If we have a valid session(not expired) we use its JWT instead of creating a new one
185
+ let validSession;
186
+ for (const session of sessions.sessions) {
187
+ if (await JwtTools.isJwtActive(session.sessionIdJwt)) {
188
+ validSession = session;
189
+ break;
190
+ }
191
+ }
192
+ this.logError(serviceAccount.ttl);
193
+ const token = validSession?.sessionIdJwt ? { token: validSession?.sessionIdJwt } : await tokenCreator({
194
+ accountId: account._id,
195
+ ttl: serviceAccount.ttl ?? Year
196
+ });
197
+ updatedConfig[serviceAccount.moduleName] = {
198
+ serviceAccount: filterKeys({
199
+ token,
200
+ description: serviceAccount.description,
201
+ accountId: account._id,
202
+ email: account.email
203
+ })
204
+ };
205
+ }
206
+ if (_keys(updatedConfig).length > 0)
207
+ MemKey_ServerApi.get().addPostCallAction(async () => {
208
+ const currentConfig = await envConfigRef.get({});
209
+ await envConfigRef.set(merge(currentConfig, updatedConfig));
210
+ this.logInfoBold('Created Service Accounts for', _keys(updatedConfig));
211
+ });
212
+ }
213
+ async invalidateSession(accountIds) {
214
+ if (!accountIds.length)
215
+ return;
216
+ const sessions = await batchActionParallel(accountIds, 10, async (ids) => await ModuleBE_SessionDB.query.custom({ where: { accountId: { $in: ids } } }));
217
+ await this.runTransaction(async (t) => {
218
+ await Promise.all(sessions.map(session => ModuleBE_SessionDB._session.invalidate.bySession(session, t)));
219
+ });
220
+ }
221
+ }
222
+ export const ModuleBE_PermissionUserDB = new ModuleBE_PermissionUserDB_Class();
@@ -0,0 +1,3 @@
1
+ export * from './ModuleBE_PermissionUserDB.js';
2
+ export * from './ModuleBE_PermissionUserAPI.js';
3
+ export * from './module-pack.js';
@@ -0,0 +1,3 @@
1
+ export * from './ModuleBE_PermissionUserDB.js';
2
+ export * from './ModuleBE_PermissionUserAPI.js';
3
+ export * from './module-pack.js';
@@ -0,0 +1,2 @@
1
+ import { Module } from '@nu-art/ts-common';
2
+ export declare const ModulePackBE_PermissionUser: Module[];
@@ -0,0 +1,3 @@
1
+ import { ModuleBE_PermissionUserDB } from './ModuleBE_PermissionUserDB.js';
2
+ import { ModuleBE_PermissionUserAPI } from './ModuleBE_PermissionUserAPI.js';
3
+ export const ModulePackBE_PermissionUser = [ModuleBE_PermissionUserDB, ModuleBE_PermissionUserAPI];
package/_entity.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export * from './_entity/permission-access-level/index.js';
2
+ export * from './_entity/permission-access-level/index.js';
3
+ export * from './_entity/permission-api/index.js';
4
+ export * from './_entity/permission-api/index.js';
5
+ export * from './_entity/permission-project/index.js';
6
+ export * from './_entity/permission-project/index.js';
7
+ export * from './_entity/permission-domain/index.js';
8
+ export * from './_entity/permission-domain/index.js';
9
+ export * from './_entity/permission-group/index.js';
10
+ export * from './_entity/permission-group/index.js';
11
+ export * from './_entity/permission-user/index.js';
12
+ export * from './_entity/permission-user/index.js';
package/_entity.js ADDED
@@ -0,0 +1,18 @@
1
+ //Access Level
2
+ export * from './_entity/permission-access-level/index.js';
3
+ export * from './_entity/permission-access-level/index.js';
4
+ //API
5
+ export * from './_entity/permission-api/index.js';
6
+ export * from './_entity/permission-api/index.js';
7
+ //Project
8
+ export * from './_entity/permission-project/index.js';
9
+ export * from './_entity/permission-project/index.js';
10
+ //Domain
11
+ export * from './_entity/permission-domain/index.js';
12
+ export * from './_entity/permission-domain/index.js';
13
+ //Group
14
+ export * from './_entity/permission-group/index.js';
15
+ export * from './_entity/permission-group/index.js';
16
+ //User
17
+ export * from './_entity/permission-user/index.js';
18
+ export * from './_entity/permission-user/index.js';
package/consts.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { SessionKey_BE } from '@nu-art/user-account-backend';
2
+ import { MemKey } from '@nu-art/ts-common/mem-storage/MemStorage';
3
+ import { TypedMap } from '@nu-art/ts-common';
4
+ import { SessionData_Permissions, SessionData_StrictMode } from '@nu-art/permissions-shared';
5
+ export declare const SessionKey_Permissions_BE: SessionKey_BE<SessionData_Permissions>;
6
+ export declare const SessionKey_StrictMode_BE: SessionKey_BE<SessionData_StrictMode>;
7
+ export declare const MemKey_UserPermissions: MemKey<TypedMap<number>>;
package/consts.js ADDED
@@ -0,0 +1,5 @@
1
+ import { SessionKey_BE } from '@nu-art/user-account-backend';
2
+ import { MemKey } from '@nu-art/ts-common/mem-storage/MemStorage';
3
+ export const SessionKey_Permissions_BE = new SessionKey_BE('permissions');
4
+ export const SessionKey_StrictMode_BE = new SessionKey_BE('strictMode');
5
+ export const MemKey_UserPermissions = new MemKey('user-permissions'); //[domainId]: access level numerical value
@@ -0,0 +1,3 @@
1
+ import { Module } from '@nu-art/ts-common';
2
+ export declare const ModulePackBE_Permissions: Module[];
3
+ export * from '../modules/ModuleBE_PermissionsAssert.js';
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Permissions management system, define access level for each of
3
+ * your server apis, and restrict users by giving them access levels
4
+ *
5
+ * Copyright (C) 2020 Adam van der Kruk aka TacB0sS
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ import { ModuleBE_PermissionsAssert } from '../modules/ModuleBE_PermissionsAssert.js';
20
+ import { ModuleBE_Permissions } from '../modules/ModuleBE_Permissions.js';
21
+ import { ModulePackBE_PermissionAccessLevel, ModulePackBE_PermissionAPI, ModulePackBE_PermissionDomain, ModulePackBE_PermissionGroup, ModulePackBE_PermissionProject, ModulePackBE_PermissionUser } from '../_entity.js';
22
+ export const ModulePackBE_Permissions = [
23
+ ...ModulePackBE_PermissionAccessLevel,
24
+ ...ModulePackBE_PermissionAPI,
25
+ ...ModulePackBE_PermissionProject,
26
+ ...ModulePackBE_PermissionDomain,
27
+ ...ModulePackBE_PermissionGroup,
28
+ ...ModulePackBE_PermissionUser,
29
+ ModuleBE_PermissionsAssert,
30
+ ModuleBE_Permissions,
31
+ ];
32
+ export * from '../modules/ModuleBE_PermissionsAssert.js';
@@ -0,0 +1,25 @@
1
+ import { TypedMap, UniqueId } from '@nu-art/ts-common';
2
+ import { DefaultDef_Group, PreDBAccessLevel } from '@nu-art/permissions-shared';
3
+ import { PermissionKey_BE } from '../PermissionKey_BE.js';
4
+ import { DefaultDef_Domain, DefaultDef_Package } from '../types.js';
5
+ export declare const Permissions_abTest: (seed: UniqueId, namespace: string, permutations: string[]) => DefaultDef_Package;
6
+ /**
7
+ * Generate automatic BE permission keys for a domain
8
+ * @param accessLevels the relevant access levels to generate keys for
9
+ * @param keyByLevelMapper the key name mapper by access level name
10
+ * @param domainId the domain id to apply in the resolver
11
+ */
12
+ export declare const generatePermissionKeys: <Key extends string | number | symbol>(accessLevels: PreDBAccessLevel[], keyByLevelMapper: TypedMap<string>, domainId: UniqueId) => { [key in Key]: PermissionKey_BE<string>; };
13
+ /**
14
+ * Automatic generator for domain default definitions,
15
+ * @param key MUST NEVER CHANGE! the key is the "key" to uniqueness of the entire permission decleration
16
+ * @param namespace The name space of the current generated domain definitions
17
+ * @param preDBAccessLevels The access levels to create (can be default or custom)
18
+ * @param permissionKeysByLevel The permission key name for each access level
19
+ * @param dbNames List of db names (optional)
20
+ */
21
+ export declare const generateDomainDefaults: <Key extends string | number | symbol>(key: string, namespace: string, preDBAccessLevels: PreDBAccessLevel[], permissionKeysByLevel: { [key in Key]: string; }, dbNames?: string[]) => {
22
+ domain: DefaultDef_Domain;
23
+ groups: DefaultDef_Group[];
24
+ keys: { [key in Key]: PermissionKey_BE<string>; };
25
+ };
package/core/utils.js ADDED
@@ -0,0 +1,85 @@
1
+ import { _values, md5 } from '@nu-art/ts-common';
2
+ import { CreateDefaultAccessLevels, DefaultAccessLevel_NoAccess, DefaultAccessLevel_Read } from '@nu-art/permissions-shared';
3
+ import { defaultValueResolverV2, PermissionKey_BE } from '../PermissionKey_BE.js';
4
+ export const Permissions_abTest = (seed, namespace, permutations) => {
5
+ const domains = permutations.map(permutation => {
6
+ const name = `${namespace}/${permutation}`;
7
+ const domain = {
8
+ _id: md5(`${seed}${name}`),
9
+ namespace: name,
10
+ permissionKeys: permutations.map(permutation => {
11
+ const initialDataResolver = () => defaultValueResolverV2(domain._id, DefaultAccessLevel_Read.name);
12
+ return new PermissionKey_BE(`${namespace}/${permutation}`, initialDataResolver);
13
+ }),
14
+ levels: CreateDefaultAccessLevels(seed, [DefaultAccessLevel_NoAccess, DefaultAccessLevel_Read]),
15
+ };
16
+ return domain;
17
+ });
18
+ const groups = permutations.map((permutation, index) => {
19
+ const name = `${namespace}/${permutation}`;
20
+ const domain = domains[index];
21
+ const group = {
22
+ _id: md5(`${domain._id}/${name}`),
23
+ name,
24
+ uiLabel: name,
25
+ accessLevels: {
26
+ [domain._id]: DefaultAccessLevel_Read.name,
27
+ }
28
+ };
29
+ return group;
30
+ });
31
+ const Permission_Package = {
32
+ name: namespace,
33
+ domains: domains,
34
+ groups: groups
35
+ };
36
+ return Permission_Package;
37
+ };
38
+ /**
39
+ * Generate automatic BE permission keys for a domain
40
+ * @param accessLevels the relevant access levels to generate keys for
41
+ * @param keyByLevelMapper the key name mapper by access level name
42
+ * @param domainId the domain id to apply in the resolver
43
+ */
44
+ export const generatePermissionKeys = (accessLevels, keyByLevelMapper, domainId) => {
45
+ return accessLevels.reduce((mapper, currentAccessLevel) => {
46
+ // declare default
47
+ const key = keyByLevelMapper[currentAccessLevel.name];
48
+ // update acc mapper
49
+ mapper[currentAccessLevel.name] = new PermissionKey_BE(key, () => defaultValueResolverV2(domainId, currentAccessLevel.name));
50
+ return mapper;
51
+ }, {});
52
+ };
53
+ /**
54
+ * Automatic generator for domain default definitions,
55
+ * @param key MUST NEVER CHANGE! the key is the "key" to uniqueness of the entire permission decleration
56
+ * @param namespace The name space of the current generated domain definitions
57
+ * @param preDBAccessLevels The access levels to create (can be default or custom)
58
+ * @param permissionKeysByLevel The permission key name for each access level
59
+ * @param dbNames List of db names (optional)
60
+ */
61
+ export const generateDomainDefaults = (key, namespace, preDBAccessLevels, permissionKeysByLevel, dbNames) => {
62
+ // Generate the new domain id
63
+ const newDomainId = md5(`domain/${key}`);
64
+ // Get all default db ready access levels using the provided ones
65
+ const accessLevels = CreateDefaultAccessLevels(newDomainId, preDBAccessLevels);
66
+ const keyDefinitions = generatePermissionKeys(preDBAccessLevels, permissionKeysByLevel, newDomainId);
67
+ return {
68
+ domain: {
69
+ _id: newDomainId,
70
+ namespace,
71
+ permissionKeys: _values(keyDefinitions),
72
+ levels: accessLevels,
73
+ dbNames
74
+ },
75
+ groups: accessLevels.map(accessLevel => ({
76
+ _id: md5(`${key}/${accessLevel.name}`),
77
+ name: `${namespace}/${accessLevel.name}`,
78
+ uiLabel: `${namespace}/${accessLevel.name}`,
79
+ accessLevels: {
80
+ [namespace]: accessLevel.name
81
+ }
82
+ })),
83
+ keys: keyDefinitions
84
+ };
85
+ };
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './core/module-pack.js';
2
+ export * from './modules/index.js';
3
+ export * from './_entity.js';
4
+ export * from './types.js';
package/index.js ADDED
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Permissions management system, define access level for each of
3
+ * your server apis, and restrict users by giving them access levels
4
+ *
5
+ * Copyright (C) 2020 Adam van der Kruk aka TacB0sS
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ export * from './core/module-pack.js';
20
+ export * from './modules/index.js';
21
+ export * from './_entity.js';
22
+ export * from './types.js';
@@ -0,0 +1,77 @@
1
+ import { Module, TypedMap } from '@nu-art/ts-common';
2
+ import { DB_PermissionGroup, DB_PermissionProject, DefaultDef_Group, SessionData_Permissions } from '@nu-art/permissions-shared';
3
+ import { BaseSessionClaims, CollectSessionData } from '@nu-art/user-account-backend';
4
+ import { PerformProjectSetup } from '@nu-art/thunderstorm-backend/modules/action-processor/Action_SetupProject';
5
+ import { DefaultDef_Project } from '../types.js';
6
+ export interface CollectPermissionsProjects {
7
+ __collectPermissionsProjects(): DefaultDef_Project;
8
+ }
9
+ export declare const PermissionGroup_Permissions_SuperAdmin: DefaultDef_Group;
10
+ export declare const PermissionGroup_Permissions_Viewer: DefaultDef_Group;
11
+ export declare const PermissionGroup_Permissions_Editor: DefaultDef_Group;
12
+ export declare const PermissionGroup_Account_Manager: DefaultDef_Group;
13
+ export declare const PermissionGroup_Account_Admin: DefaultDef_Group;
14
+ export declare const PermissionGroup_Account_Viewer: DefaultDef_Group;
15
+ export declare const PermissionGroups_Permissions: DefaultDef_Group[];
16
+ export declare const PermissionProject_Permissions: DefaultDef_Project;
17
+ declare class ModuleBE_Permissions_Class extends Module implements CollectSessionData<SessionData_Permissions>, PerformProjectSetup {
18
+ protected init(): void;
19
+ __collectSessionData(data: BaseSessionClaims): Promise<SessionData_Permissions>;
20
+ getUserPermissionMap: (userGroups: DB_PermissionGroup[]) => Promise<TypedMap<number>>;
21
+ toggleStrictMode: () => Promise<void>;
22
+ __performProjectSetup(): {
23
+ priority: number;
24
+ processor: () => Promise<void>;
25
+ };
26
+ createPermissionProjects(projects: DefaultDef_Project[]): Promise<void>;
27
+ /**
28
+ * Creates All the DB_PermissionProject
29
+ *
30
+ * @param projects - predefined permissions projects
31
+ */
32
+ createProjects(projects: DefaultDef_Project[]): Promise<TypedMap<DB_PermissionProject>>;
33
+ /**
34
+ * Creates All the DB_PermissionDomains
35
+ *
36
+ * @param projects - predefined permissions projects
37
+ * @param map_nameToDBProject
38
+ */
39
+ private createDomains;
40
+ /**
41
+ * Creates All the DB_PermissionAccessLevel
42
+ *
43
+ * @param projects - predefined permissions projects
44
+ * @param map_nameToDbDomain
45
+ */
46
+ private createAccessLevels;
47
+ /**
48
+ * Creates All the DB_PermissionGroup
49
+ *
50
+ * @param projects - predefined permissions projects
51
+ * @param map_nameToDbDomain
52
+ * @param domainNameToLevelNameToDBAccessLevel
53
+ */
54
+ private createGroups;
55
+ /**
56
+ * Creates All the DB_PermissionApi
57
+ *
58
+ * @param projects - predefined permissions projects
59
+ * @param domainNameToLevelNameToDBAccessLevel
60
+ */
61
+ private createApis;
62
+ /**
63
+ * Creates permission keys associated with the given projects.
64
+ *
65
+ * @param projects - An array of projects.
66
+ */
67
+ private createPermissionsKeys;
68
+ /**
69
+ * If no "Super Admin" user is defined in the system!
70
+ * The first user to press the create project button will become the "Super Admin" of the system
71
+ *
72
+ * If a "Super Admin" already exists in the system, a 403 will be thrown
73
+ */
74
+ private assignSuperAdmin;
75
+ }
76
+ export declare const ModuleBE_Permissions: ModuleBE_Permissions_Class;
77
+ export {};