@nu-art/permissions-backend 0.500.0 → 0.500.6
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/RequirePermission.d.ts +22 -10
- package/RequirePermission.js +24 -15
- package/_entity/access-group/ModuleBE_AccessGroupDB.d.ts +13 -0
- package/_entity/access-group/ModuleBE_AccessGroupDB.js +36 -0
- package/_entity/access-group/module-pack.d.ts +1 -0
- package/_entity/access-group/module-pack.js +3 -0
- package/_entity/permission-scope/ModuleBE_PermissionScopeDB.d.ts +6 -0
- package/_entity/permission-scope/ModuleBE_PermissionScopeDB.js +8 -0
- package/_entity/permission-scope/module-pack.d.ts +1 -0
- package/_entity/permission-scope/module-pack.js +3 -0
- package/_entity/user-permissions/ModuleBE_UserPermissionsAPI.d.ts +9 -0
- package/_entity/{permission-user/ModuleBE_PermissionUserAPI.js → user-permissions/ModuleBE_UserPermissionsAPI.js} +17 -16
- package/_entity/user-permissions/ModuleBE_UserPermissionsDB.d.ts +6 -0
- package/_entity/user-permissions/ModuleBE_UserPermissionsDB.js +8 -0
- package/_entity/user-permissions/module-pack.d.ts +2 -0
- package/_entity/user-permissions/module-pack.js +3 -0
- package/assertion-types.d.ts +9 -0
- package/consts.d.ts +7 -4
- package/consts.js +4 -2
- package/core/function-permission-registry.d.ts +5 -6
- package/core/function-permission-registry.js +10 -0
- package/core/module-pack.js +6 -7
- package/document-access-api.d.ts +6 -0
- package/document-access-api.js +49 -0
- package/document-access-enforcement.d.ts +9 -0
- package/document-access-enforcement.js +137 -0
- package/index.d.ts +12 -6
- package/index.js +12 -6
- package/modules/ModuleBE_Permissions.d.ts +63 -78
- package/modules/ModuleBE_Permissions.js +494 -441
- package/modules/ModuleBE_PermissionsAssert.d.ts +6 -54
- package/modules/ModuleBE_PermissionsAssert.js +60 -285
- package/package.json +14 -12
- package/PermissionKey_BE.d.ts +0 -16
- package/PermissionKey_BE.js +0 -59
- package/_entity/permission-access-level/ModuleBE_PermissionAccessLevelDB.d.ts +0 -13
- package/_entity/permission-access-level/ModuleBE_PermissionAccessLevelDB.js +0 -49
- package/_entity/permission-access-level/index.d.ts +0 -2
- package/_entity/permission-access-level/index.js +0 -2
- package/_entity/permission-access-level/module-pack.d.ts +0 -1
- package/_entity/permission-access-level/module-pack.js +0 -3
- package/_entity/permission-api/ModuleBE_PermissionAPIDB.d.ts +0 -10
- package/_entity/permission-api/ModuleBE_PermissionAPIDB.js +0 -62
- package/_entity/permission-api/index.d.ts +0 -2
- package/_entity/permission-api/index.js +0 -2
- package/_entity/permission-api/module-pack.d.ts +0 -1
- package/_entity/permission-api/module-pack.js +0 -3
- package/_entity/permission-domain/ModuleBE_PermissionDomainDB.d.ts +0 -9
- package/_entity/permission-domain/ModuleBE_PermissionDomainDB.js +0 -22
- package/_entity/permission-domain/index.d.ts +0 -2
- package/_entity/permission-domain/index.js +0 -2
- package/_entity/permission-domain/module-pack.d.ts +0 -1
- package/_entity/permission-domain/module-pack.js +0 -3
- package/_entity/permission-group/ModuleBE_PermissionGroupDB.d.ts +0 -12
- package/_entity/permission-group/ModuleBE_PermissionGroupDB.js +0 -65
- package/_entity/permission-group/index.d.ts +0 -2
- package/_entity/permission-group/index.js +0 -2
- package/_entity/permission-group/module-pack.d.ts +0 -1
- package/_entity/permission-group/module-pack.js +0 -3
- package/_entity/permission-project/ModuleBE_PermissionProjectDB.d.ts +0 -8
- package/_entity/permission-project/ModuleBE_PermissionProjectDB.js +0 -12
- package/_entity/permission-project/index.d.ts +0 -2
- package/_entity/permission-project/index.js +0 -2
- package/_entity/permission-project/module-pack.d.ts +0 -1
- package/_entity/permission-project/module-pack.js +0 -3
- package/_entity/permission-user/ModuleBE_PermissionUserAPI.d.ts +0 -9
- package/_entity/permission-user/ModuleBE_PermissionUserDB.d.ts +0 -34
- package/_entity/permission-user/ModuleBE_PermissionUserDB.js +0 -241
- package/_entity/permission-user/index.d.ts +0 -3
- package/_entity/permission-user/index.js +0 -3
- package/_entity/permission-user/module-pack.d.ts +0 -2
- package/_entity/permission-user/module-pack.js +0 -3
- package/_entity.d.ts +0 -12
- package/_entity.js +0 -18
- package/core/external-api-paths.d.ts +0 -13
- package/core/external-api-paths.js +0 -13
- package/core/utils.d.ts +0 -25
- package/core/utils.js +0 -85
- package/modules/consts.d.ts +0 -11
- package/modules/consts.js +0 -29
- package/modules/index.d.ts +0 -2
- package/modules/index.js +0 -20
- package/permissions-wire.d.ts +0 -46
- package/permissions-wire.js +0 -47
- package/permissions.d.ts +0 -22
- package/permissions.js +0 -152
- package/types.d.ts +0 -28
- /package/{types.js → assertion-types.js} +0 -0
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DB_PermissionAPI, DatabaseDef_PermissionAPI, DatabaseDef_PermissionProject } from '@nu-art/permissions-shared';
|
|
3
|
-
import { Transaction } from 'firebase-admin/firestore';
|
|
4
|
-
export declare class ModuleBE_PermissionAPIDB_Class extends ModuleBE_BaseDB<DatabaseDef_PermissionAPI> {
|
|
5
|
-
constructor();
|
|
6
|
-
protected preWriteProcessing(instance: DB_PermissionAPI, originalDbInstance: DatabaseDef_PermissionAPI['dbType'], t?: Transaction): Promise<void>;
|
|
7
|
-
registerApis(projectId: DatabaseDef_PermissionProject['id'], routes: string[]): Promise<DB_PermissionAPI[]>;
|
|
8
|
-
apiUpsert(): unknown;
|
|
9
|
-
}
|
|
10
|
-
export declare const ModuleBE_PermissionAPIDB: ModuleBE_PermissionAPIDB_Class;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DBDef_PermissionAPI } from '@nu-art/permissions-shared';
|
|
3
|
-
import { dbObjectToId, filterInstances } from '@nu-art/ts-common';
|
|
4
|
-
import { ModuleBE_PermissionAccessLevelDB } from '../permission-access-level/index.js';
|
|
5
|
-
import { MemKey_AccountId } from '@nu-art/user-account-backend';
|
|
6
|
-
import { ModuleBE_PermissionProjectDB } from '../permission-project/index.js';
|
|
7
|
-
import { HttpCodes } from '@nu-art/ts-common/core/exceptions/http-codes';
|
|
8
|
-
import { trimStartingForwardSlash } from '@nu-art/permissions-shared';
|
|
9
|
-
export class ModuleBE_PermissionAPIDB_Class extends ModuleBE_BaseDB {
|
|
10
|
-
constructor() {
|
|
11
|
-
super(DBDef_PermissionAPI);
|
|
12
|
-
this.registerVersionUpgradeProcessor('1.0.0', async (instances) => {
|
|
13
|
-
}); // adjustment made in pre-write requires us to do this in order to upgrade the data
|
|
14
|
-
}
|
|
15
|
-
async preWriteProcessing(instance, originalDbInstance, t) {
|
|
16
|
-
await ModuleBE_PermissionProjectDB.query.uniqueAssert(instance.projectId);
|
|
17
|
-
// clean '/' from api path start
|
|
18
|
-
instance.path = trimStartingForwardSlash(instance.path);
|
|
19
|
-
// set who created this
|
|
20
|
-
instance._auditorId = MemKey_AccountId.get();
|
|
21
|
-
const accessLevelIds = new Set();
|
|
22
|
-
const duplicateAccessLevelIds = new Set();
|
|
23
|
-
//Check for duplicated Unique IDs
|
|
24
|
-
instance.accessLevelIds?.forEach(id => {
|
|
25
|
-
const duplicate = accessLevelIds.has(id);
|
|
26
|
-
accessLevelIds.add(id);
|
|
27
|
-
if (duplicate)
|
|
28
|
-
duplicateAccessLevelIds.add(id);
|
|
29
|
-
});
|
|
30
|
-
if (duplicateAccessLevelIds.size)
|
|
31
|
-
throw HttpCodes._4XX.BAD_REQUEST('Could not update permission api', `Trying to create API with duplicate access levels: ${duplicateAccessLevelIds}`);
|
|
32
|
-
// Verify all AccessLevels actually exist, and assign _accessLevels
|
|
33
|
-
if (instance.accessLevelIds?.length) {
|
|
34
|
-
const dbAccessLevels = filterInstances(await ModuleBE_PermissionAccessLevelDB.query.all(instance.accessLevelIds));
|
|
35
|
-
if (dbAccessLevels.length !== instance.accessLevelIds.length) {
|
|
36
|
-
const dbAccessLevelIds = dbAccessLevels.map(dbObjectToId);
|
|
37
|
-
throw HttpCodes._4XX.NOT_FOUND('Could not update permission api', `Asked to assign an api non existing accessLevels: ${instance.accessLevelIds.filter(id => !dbAccessLevelIds.includes(id))}`);
|
|
38
|
-
}
|
|
39
|
-
dbAccessLevels.forEach(accessLevel => {
|
|
40
|
-
if (!instance._accessLevels)
|
|
41
|
-
instance._accessLevels = {};
|
|
42
|
-
instance._accessLevels[accessLevel.domainId] = accessLevel.value;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
instance._accessLevels = {};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
registerApis(projectId, routes) {
|
|
50
|
-
return this.runTransaction(async (transaction) => {
|
|
51
|
-
const existingProjectApis = await this.query.custom({ where: { projectId } }, transaction);
|
|
52
|
-
const apisToAdd = routes
|
|
53
|
-
.filter(path => !existingProjectApis.find(api => api.path === path))
|
|
54
|
-
.map(path => ({ path, projectId, _auditorId: MemKey_AccountId.get() }));
|
|
55
|
-
return this.set.all(apisToAdd, transaction);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
apiUpsert() {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
export const ModuleBE_PermissionAPIDB = new ModuleBE_PermissionAPIDB_Class();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const ModulePackBE_PermissionAPI: (import("./ModuleBE_PermissionAPIDB.js").ModuleBE_PermissionAPIDB_Class | import("@nu-art/db-api-backend").ModuleBE_BaseApi_Class<import("@nu-art/permissions-shared").DatabaseDef_PermissionAPI>)[];
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DatabaseDef_PermissionDomain, DB_PermissionDomain } from '@nu-art/permissions-shared';
|
|
3
|
-
import { Transaction } from 'firebase-admin/firestore';
|
|
4
|
-
export declare class ModuleBE_PermissionDomainDB_Class extends ModuleBE_BaseDB<DatabaseDef_PermissionDomain> {
|
|
5
|
-
constructor();
|
|
6
|
-
protected assertDeletion(transaction: Transaction, dbInstance: DB_PermissionDomain): Promise<void>;
|
|
7
|
-
protected preWriteProcessing(dbInstance: DB_PermissionDomain, originalDbInstance: DatabaseDef_PermissionDomain['dbType'], t?: Transaction): Promise<void>;
|
|
8
|
-
}
|
|
9
|
-
export declare const ModuleBE_PermissionDomainDB: ModuleBE_PermissionDomainDB_Class;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DBDef_PermissionDomain } from '@nu-art/permissions-shared';
|
|
3
|
-
import { ApiException } from '@nu-art/ts-common';
|
|
4
|
-
import { MemKey_AccountId } from '@nu-art/user-account-backend';
|
|
5
|
-
import { ModuleBE_PermissionAccessLevelDB } from '../permission-access-level/index.js';
|
|
6
|
-
import { ModuleBE_PermissionProjectDB } from '../permission-project/index.js';
|
|
7
|
-
export class ModuleBE_PermissionDomainDB_Class extends ModuleBE_BaseDB {
|
|
8
|
-
constructor() {
|
|
9
|
-
super(DBDef_PermissionDomain);
|
|
10
|
-
}
|
|
11
|
-
async assertDeletion(transaction, dbInstance) {
|
|
12
|
-
const accessLevels = await ModuleBE_PermissionAccessLevelDB.query.custom({ where: { domainId: dbInstance._id } });
|
|
13
|
-
if (accessLevels.length) {
|
|
14
|
-
throw new ApiException(403, 'You trying delete domain that associated with accessLevels, you need delete the accessLevels first');
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
async preWriteProcessing(dbInstance, originalDbInstance, t) {
|
|
18
|
-
await ModuleBE_PermissionProjectDB.query.uniqueAssert(dbInstance.projectId, t);
|
|
19
|
-
dbInstance._auditorId = MemKey_AccountId.get();
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export const ModuleBE_PermissionDomainDB = new ModuleBE_PermissionDomainDB_Class();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const ModulePackBE_PermissionDomain: (import("./ModuleBE_PermissionDomainDB.js").ModuleBE_PermissionDomainDB_Class | import("@nu-art/db-api-backend").ModuleBE_BaseApi_Class<import("@nu-art/permissions-shared").DatabaseDef_PermissionDomain>)[];
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DB_PermissionGroup, DatabaseDef_PermissionGroup } from '@nu-art/permissions-shared';
|
|
3
|
-
import { Transaction } from 'firebase-admin/firestore';
|
|
4
|
-
import { CollectionActionType, PostWriteProcessingData } from '@nu-art/firebase-backend/firestore-v3/FirestoreCollectionV3';
|
|
5
|
-
export declare class ModuleBE_PermissionGroupDB_Class extends ModuleBE_BaseDB<DatabaseDef_PermissionGroup> {
|
|
6
|
-
constructor();
|
|
7
|
-
protected preWriteProcessing(instance: DB_PermissionGroup, originalDbInstance: DatabaseDef_PermissionGroup['dbType'], t?: Transaction): Promise<void>;
|
|
8
|
-
protected postWriteProcessing(data: PostWriteProcessingData<DatabaseDef_PermissionGroup['dbType']>, actionType: CollectionActionType): Promise<void>;
|
|
9
|
-
private clearUnused;
|
|
10
|
-
private upgrade_100_101;
|
|
11
|
-
}
|
|
12
|
-
export declare const ModuleBE_PermissionGroupDB: ModuleBE_PermissionGroupDB_Class;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DBDef_PermissionGroup } from '@nu-art/permissions-shared';
|
|
3
|
-
import { getActionProcessor } from '../../permissions-wire.js';
|
|
4
|
-
import { _keys, ApiException, batchActionParallel, dbObjectToId, filterDuplicates, filterInstances, reduceToMap } from '@nu-art/ts-common';
|
|
5
|
-
import { ModuleBE_PermissionAccessLevelDB } from '../permission-access-level/index.js';
|
|
6
|
-
import { MemKey_AccountId, SlackReporter } from '@nu-art/user-account-backend';
|
|
7
|
-
import { ModuleBE_PermissionUserDB } from '../permission-user/index.js';
|
|
8
|
-
import { _EmptyQuery } from '@nu-art/firebase-shared';
|
|
9
|
-
export class ModuleBE_PermissionGroupDB_Class extends ModuleBE_BaseDB {
|
|
10
|
-
constructor() {
|
|
11
|
-
super(DBDef_PermissionGroup);
|
|
12
|
-
const processor = getActionProcessor();
|
|
13
|
-
if (processor)
|
|
14
|
-
processor.registerAction({
|
|
15
|
-
key: 'clear-unused-permission-groups',
|
|
16
|
-
group: 'Permissions',
|
|
17
|
-
description: 'Clears all permission groups that aren\'t in use',
|
|
18
|
-
processor: this.clearUnused
|
|
19
|
-
}, this);
|
|
20
|
-
this.registerVersionUpgradeProcessor('1.0.0', this.upgrade_100_101);
|
|
21
|
-
}
|
|
22
|
-
async preWriteProcessing(instance, originalDbInstance, t) {
|
|
23
|
-
instance._auditorId = MemKey_AccountId.get();
|
|
24
|
-
const dbLevels = filterInstances(await ModuleBE_PermissionAccessLevelDB.query.all(instance.accessLevelIds, t));
|
|
25
|
-
if (dbLevels.length < instance.accessLevelIds.length) {
|
|
26
|
-
const dbAccessLevelIds = dbLevels.map(dbObjectToId);
|
|
27
|
-
throw new ApiException(404, `Asked to assign a group non existing accessLevels: ${instance.accessLevelIds.filter(id => !dbAccessLevelIds.includes(id))}`);
|
|
28
|
-
}
|
|
29
|
-
// Find if there is more than one access level with the same domainId.
|
|
30
|
-
const duplicationMap = dbLevels.reduce((map, level) => {
|
|
31
|
-
if (map[level.domainId] === undefined)
|
|
32
|
-
map[level.domainId] = 0;
|
|
33
|
-
else
|
|
34
|
-
map[level.domainId]++;
|
|
35
|
-
return map;
|
|
36
|
-
}, {});
|
|
37
|
-
// Get all domainIds that appear more than once in this group
|
|
38
|
-
const duplicateDomainIds = filterInstances(_keys(duplicationMap)
|
|
39
|
-
.map(domainId => duplicationMap[domainId] > 1 ? domainId : undefined));
|
|
40
|
-
if (duplicateDomainIds.length > 0)
|
|
41
|
-
throw new ApiException(400, `Can't add a group with more than one access level per domain: ${duplicateDomainIds}, group: ${instance.label}`);
|
|
42
|
-
instance._levelsMap = reduceToMap(dbLevels, dbLevel => dbLevel.domainId, dbLevel => dbLevel.value);
|
|
43
|
-
}
|
|
44
|
-
async postWriteProcessing(data, actionType) {
|
|
45
|
-
const deleted = data.deleted ? (Array.isArray(data.deleted) ? data.deleted : [data.deleted]) : [];
|
|
46
|
-
const updated = data.updated ? (Array.isArray(data.updated) ? data.updated : [data.updated]) : [];
|
|
47
|
-
const groupIds = filterDuplicates([...deleted, ...updated].map(dbObjectToId));
|
|
48
|
-
const users = await batchActionParallel(groupIds, 10, async (ids) => await ModuleBE_PermissionUserDB.query.custom({ where: { __groupIds: { $aca: ids } } }));
|
|
49
|
-
await ModuleBE_PermissionUserDB.rotateSession(users.map(dbObjectToId));
|
|
50
|
-
}
|
|
51
|
-
clearUnused = async () => {
|
|
52
|
-
let report = 'Report for refactor action *Clean Unused Permission Groups*:\n\n';
|
|
53
|
-
const allPermissionUsers = await ModuleBE_PermissionUserDB.query.custom(_EmptyQuery);
|
|
54
|
-
const allGroups = await this.query.custom(_EmptyQuery);
|
|
55
|
-
const usedGroupIds = allPermissionUsers.map(user => user.__groupIds ?? []).flat();
|
|
56
|
-
const unusedGroups = allGroups.filter(group => !usedGroupIds.includes(group._id));
|
|
57
|
-
report += `Cleared ${unusedGroups.length} groups: ${unusedGroups.map(group => group.label).join(',\n')}`;
|
|
58
|
-
await this.delete.allItems(unusedGroups);
|
|
59
|
-
await new SlackReporter(report).sendReportToChannel();
|
|
60
|
-
};
|
|
61
|
-
upgrade_100_101 = async (items) => {
|
|
62
|
-
items.forEach(group => group.uiLabel = group.label);
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
export const ModuleBE_PermissionGroupDB = new ModuleBE_PermissionGroupDB_Class();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const ModulePackBE_PermissionGroup: (import("./ModuleBE_PermissionGroupDB.js").ModuleBE_PermissionGroupDB_Class | import("@nu-art/db-api-backend").ModuleBE_BaseApi_Class<import("@nu-art/permissions-shared").DatabaseDef_PermissionGroup>)[];
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DB_PermissionProject, DatabaseDef_PermissionProject } from '@nu-art/permissions-shared';
|
|
3
|
-
import { Transaction } from 'firebase-admin/firestore';
|
|
4
|
-
export declare class ModuleBE_PermissionProjectDB_Class extends ModuleBE_BaseDB<DatabaseDef_PermissionProject> {
|
|
5
|
-
constructor();
|
|
6
|
-
protected preWriteProcessing(dbInstance: DB_PermissionProject, originalDbInstance: DatabaseDef_PermissionProject['dbType'], t?: Transaction): Promise<void>;
|
|
7
|
-
}
|
|
8
|
-
export declare const ModuleBE_PermissionProjectDB: ModuleBE_PermissionProjectDB_Class;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DBDef_PermissionProject } from '@nu-art/permissions-shared';
|
|
3
|
-
import { MemKey_AccountId } from '@nu-art/user-account-backend';
|
|
4
|
-
export class ModuleBE_PermissionProjectDB_Class extends ModuleBE_BaseDB {
|
|
5
|
-
constructor() {
|
|
6
|
-
super(DBDef_PermissionProject);
|
|
7
|
-
}
|
|
8
|
-
async preWriteProcessing(dbInstance, originalDbInstance, t) {
|
|
9
|
-
dbInstance._auditorId = MemKey_AccountId.get();
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
export const ModuleBE_PermissionProjectDB = new ModuleBE_PermissionProjectDB_Class();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const ModulePackBE_PermissionProject: (import("./ModuleBE_PermissionProjectDB.js").ModuleBE_PermissionProjectDB_Class | import("@nu-art/db-api-backend").ModuleBE_BaseApi_Class<import("@nu-art/permissions-shared").DatabaseDef_PermissionProject>)[];
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { createApisForDBModule } from '@nu-art/db-api-backend';
|
|
2
|
-
import { ModuleBE_PermissionProjectDB } from './ModuleBE_PermissionProjectDB.js';
|
|
3
|
-
export const ModulePackBE_PermissionProject = [ModuleBE_PermissionProjectDB, createApisForDBModule(ModuleBE_PermissionProjectDB)];
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseApi_Class } from '@nu-art/db-api-backend';
|
|
2
|
-
import { API_PermissionUser, DatabaseDef_PermissionUser } from '@nu-art/permissions-shared';
|
|
3
|
-
declare class ModuleBE_PermissionUserAPI_Class extends ModuleBE_BaseApi_Class<DatabaseDef_PermissionUser> {
|
|
4
|
-
constructor();
|
|
5
|
-
init(): void;
|
|
6
|
-
assignPermissions(body: API_PermissionUser['assignPermissions']['Body']): Promise<void>;
|
|
7
|
-
}
|
|
8
|
-
export declare const ModuleBE_PermissionUserAPI: ModuleBE_PermissionUserAPI_Class;
|
|
9
|
-
export {};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { DB_PermissionUser, DatabaseDef_PermissionUser, Request_AssignPermissions, User_Group, type PerformProjectSetup } from '@nu-art/permissions-shared';
|
|
3
|
-
import { DB_BaseObject, UniqueId } from '@nu-art/ts-common';
|
|
4
|
-
import { OnNewUserRegistered, OnUserLogin } from '@nu-art/user-account-backend';
|
|
5
|
-
import { Transaction } from 'firebase-admin/firestore';
|
|
6
|
-
import { UI_Account } from '@nu-art/user-account-shared';
|
|
7
|
-
import { CollectionActionType } from '@nu-art/firebase-backend/firestore-v3/FirestoreCollectionV3';
|
|
8
|
-
import { PostWriteProcessingDataShape } from '@nu-art/db-api-backend';
|
|
9
|
-
export declare class ModuleBE_PermissionUserDB_Class extends ModuleBE_BaseDB<DatabaseDef_PermissionUser> implements OnNewUserRegistered, OnUserLogin, PerformProjectSetup {
|
|
10
|
-
private defaultPermissionGroups?;
|
|
11
|
-
constructor();
|
|
12
|
-
__performProjectSetup(): {
|
|
13
|
-
priority: number;
|
|
14
|
-
processor: () => Promise<void>;
|
|
15
|
-
};
|
|
16
|
-
__onUserLogin(account: UI_Account, transaction: Transaction): Promise<void>;
|
|
17
|
-
__onNewUserRegistered(account: UI_Account, transaction: Transaction): Promise<void>;
|
|
18
|
-
protected preWriteProcessing(instance: DB_PermissionUser, originalDbInstance: DatabaseDef_PermissionUser['dbType'], t?: Transaction): Promise<void>;
|
|
19
|
-
protected postWriteProcessing(data: PostWriteProcessingDataShape<DatabaseDef_PermissionUser['dbType']>, actionType: CollectionActionType): Promise<void>;
|
|
20
|
-
insertIfNotExist: (uiAccount: UI_Account & DB_BaseObject, transaction: Transaction) => Promise<DB_PermissionUser | (Omit<DB_PermissionUser, "_id" | "__created" | "__updated" | "_v" | ("_auditorId" | "__groupIds")> & Partial<import("@nu-art/ts-common").SubsetObjectByKeys<DB_PermissionUser, "_id" | "__created" | "__updated" | "_v" | ("_auditorId" | "__groupIds")>> & Partial<import("@nu-art/db-api-shared").DB_Object>)>;
|
|
21
|
-
assignPermissions(body: Request_AssignPermissions): Promise<void>;
|
|
22
|
-
setDefaultPermissionGroups: (groupsGetter: () => Promise<User_Group[]>) => void;
|
|
23
|
-
clearDefaultPermissionGroups: () => void;
|
|
24
|
-
/**
|
|
25
|
-
* The system requires to perform action, which in other cases can also be done by a human.
|
|
26
|
-
* This requires system features to identify as a bot user, or "Service Account"
|
|
27
|
-
*
|
|
28
|
-
* @param serviceAccounts - List of Accounts to create
|
|
29
|
-
* @private
|
|
30
|
-
*/
|
|
31
|
-
private createSystemServiceAccount;
|
|
32
|
-
rotateSession(accountIds: UniqueId[]): Promise<void>;
|
|
33
|
-
}
|
|
34
|
-
export declare const ModuleBE_PermissionUserDB: ModuleBE_PermissionUserDB_Class;
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import { ModuleBE_BaseDB } from '@nu-art/db-api-backend';
|
|
2
|
-
import { MemKey_ServerApi } from '@nu-art/http-server';
|
|
3
|
-
import { DBDef_PermissionUser, toPermissionGroupId } from '@nu-art/permissions-shared';
|
|
4
|
-
import { getGlobalEnvConfigRef, getServiceAccountsProvider } from '../../permissions-wire.js';
|
|
5
|
-
import { _keys, ApiException, batchAction, batchActionParallel, dbObjectToId, exists, filterDuplicates, filterInstances, filterKeys, JwtTools, merge, Year } from '@nu-art/ts-common';
|
|
6
|
-
import { ModuleBE_PermissionGroupDB } from '../permission-group/ModuleBE_PermissionGroupDB.js';
|
|
7
|
-
import { MemKey_AccountId, ModuleBE_AccountDB, ModuleBE_SessionDB } from '@nu-art/user-account-backend';
|
|
8
|
-
import { MemKey_UserPermissions } from '../../consts.js';
|
|
9
|
-
export class ModuleBE_PermissionUserDB_Class extends ModuleBE_BaseDB {
|
|
10
|
-
defaultPermissionGroups;
|
|
11
|
-
constructor() {
|
|
12
|
-
super(DBDef_PermissionUser);
|
|
13
|
-
}
|
|
14
|
-
__performProjectSetup() {
|
|
15
|
-
return {
|
|
16
|
-
priority: 200,
|
|
17
|
-
processor: async () => {
|
|
18
|
-
const accounts = await ModuleBE_AccountDB.query.where({});
|
|
19
|
-
// Permission user _id is 1:1 with account _id; query.all expects permission user ids.
|
|
20
|
-
const permissionUserIds = accounts.map(dbObjectToId);
|
|
21
|
-
const permissionsUser = await this.query.all(permissionUserIds);
|
|
22
|
-
const usersToUpsert = [];
|
|
23
|
-
const usersToDelete = [];
|
|
24
|
-
permissionsUser.forEach((user, index) => {
|
|
25
|
-
if (exists(user)) {
|
|
26
|
-
// Same 1:1 design: account id and permission user id are the same value.
|
|
27
|
-
if (!exists(accounts.find(account => account._id === user._id)))
|
|
28
|
-
usersToDelete.push(user);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
usersToUpsert.push({
|
|
32
|
-
_id: accounts[index]._id,
|
|
33
|
-
groups: [],
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
await this.set.all(usersToUpsert);
|
|
37
|
-
await this.delete.all(usersToDelete);
|
|
38
|
-
// This stage updates the rtdb's config- which is why it's last. Changing the rtdb's config kills the server.
|
|
39
|
-
const provider = getServiceAccountsProvider();
|
|
40
|
-
const serviceAccounts = provider ? await provider() : [];
|
|
41
|
-
await this.createSystemServiceAccount(serviceAccounts);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
async __onUserLogin(account, transaction) {
|
|
46
|
-
await this.insertIfNotExist(account, transaction);
|
|
47
|
-
}
|
|
48
|
-
async __onNewUserRegistered(account, transaction) {
|
|
49
|
-
await this.insertIfNotExist(account, transaction);
|
|
50
|
-
}
|
|
51
|
-
// protected async canDeleteDocument(transaction: FirestoreTransaction, dbInstances: DB_PermissionUser[]) {
|
|
52
|
-
// const conflicts: DB_PermissionUser[] = [];
|
|
53
|
-
// const accounts = await ModuleBE_AccountDB.query.custom(_EmptyQuery);
|
|
54
|
-
//
|
|
55
|
-
// for (const item of dbInstances) {
|
|
56
|
-
// const account = accounts.find(acc => acc._id === item.accountId);
|
|
57
|
-
// if (account)
|
|
58
|
-
// conflicts.push(item);
|
|
59
|
-
// }
|
|
60
|
-
//
|
|
61
|
-
// if (conflicts.length)
|
|
62
|
-
// throw new ApiException<DB_EntityDependency<any>[]>(422, 'permission users are connected to accounts').setErrorBody({
|
|
63
|
-
// type: 'has-dependencies',
|
|
64
|
-
// body: conflicts.map(conflict => ({collectionKey: 'User', conflictingIds: [conflict._id]}))
|
|
65
|
-
// });
|
|
66
|
-
// }
|
|
67
|
-
async preWriteProcessing(instance, originalDbInstance, t) {
|
|
68
|
-
instance._auditorId = MemKey_AccountId.get();
|
|
69
|
-
instance.__groupIds = filterDuplicates(instance.groups.map(group => group.groupId) || []);
|
|
70
|
-
if (!instance.__groupIds.length)
|
|
71
|
-
return;
|
|
72
|
-
// Get all groups the user has from the collection
|
|
73
|
-
const dbGroups = filterInstances(await ModuleBE_PermissionGroupDB.query.all(instance.__groupIds, t));
|
|
74
|
-
// Verify all groups actually existing in the collection
|
|
75
|
-
if (instance.__groupIds.length !== dbGroups.length) {
|
|
76
|
-
const dbGroupIds = dbGroups.map(dbObjectToId);
|
|
77
|
-
throw new ApiException(422, `Trying to assign a user to a permission-group that does not exist: ${instance.__groupIds.filter(groupId => !dbGroupIds.includes(groupId))}`);
|
|
78
|
-
}
|
|
79
|
-
//todo check for duplications in data
|
|
80
|
-
}
|
|
81
|
-
async postWriteProcessing(data, actionType) {
|
|
82
|
-
const deleted = data.deleted ? (Array.isArray(data.deleted) ? data.deleted : [data.deleted]) : [];
|
|
83
|
-
const updated = data.updated ? (Array.isArray(data.updated) ? data.updated : [data.updated]) : [];
|
|
84
|
-
const before = data.before ? (Array.isArray(data.before) ? data.before : [data.before]) : [];
|
|
85
|
-
const beforeIds = before.map(b => b._id);
|
|
86
|
-
const accountIdToInvalidate = filterDuplicates(filterInstances([...deleted, ...updated].map(i => i._id))).filter(id => beforeIds.includes(id));
|
|
87
|
-
await this.rotateSession(accountIdToInvalidate);
|
|
88
|
-
}
|
|
89
|
-
insertIfNotExist = async (uiAccount, transaction) => {
|
|
90
|
-
const create = async (transaction) => {
|
|
91
|
-
const defaultPermissionGroups = ModuleBE_PermissionUserDB.defaultPermissionGroups ? await ModuleBE_PermissionUserDB.defaultPermissionGroups() : [];
|
|
92
|
-
const permissionGroups = ModuleBE_PermissionUserDB.defaultPermissionGroups
|
|
93
|
-
? filterInstances(await ModuleBE_PermissionGroupDB.query.all(defaultPermissionGroups.map(item => item.groupId)))
|
|
94
|
-
: [];
|
|
95
|
-
this.logInfo(`Received ${defaultPermissionGroups.length} groups to assign, ${permissionGroups.length} of which exist`);
|
|
96
|
-
// Permission user _id is 1:1 with account _id (design); cast required across brands.
|
|
97
|
-
const permissionUserId = uiAccount._id;
|
|
98
|
-
const permissionsUserToCreate = {
|
|
99
|
-
_id: permissionUserId,
|
|
100
|
-
groups: permissionGroups.map(group => ({ groupId: group._id })),
|
|
101
|
-
_auditorId: MemKey_AccountId.get()
|
|
102
|
-
};
|
|
103
|
-
return ModuleBE_PermissionUserDB.create.item(permissionsUserToCreate, transaction);
|
|
104
|
-
};
|
|
105
|
-
return ModuleBE_PermissionUserDB.collection.uniqueGetOrCreate({ _id: uiAccount._id }, create, transaction);
|
|
106
|
-
};
|
|
107
|
-
async assignPermissions(body) {
|
|
108
|
-
if (!body.targetAccountIds.length)
|
|
109
|
-
throw new ApiException(400, `Asked to modify permissions but provided no users to modify permissions of.`);
|
|
110
|
-
// Permission user id is 1:1 with account id (design); cast required across brands.
|
|
111
|
-
const permissionUserIds = body.targetAccountIds;
|
|
112
|
-
const usersToGiveTo = filterInstances(await this.query.all(permissionUserIds));
|
|
113
|
-
// console.log('assignPermissions target accounts ');
|
|
114
|
-
// console.log(await this.query.custom(_EmptyQuery));
|
|
115
|
-
if (!usersToGiveTo.length || usersToGiveTo.length !== body.targetAccountIds.length) {
|
|
116
|
-
const dbUserIds = usersToGiveTo.map(dbObjectToId);
|
|
117
|
-
throw new ApiException(404, `Asked to give permissions to non-existent user accounts: ${body.targetAccountIds.filter(id => !dbUserIds.includes(id))}`);
|
|
118
|
-
}
|
|
119
|
-
const dbGroups = filterInstances(await ModuleBE_PermissionGroupDB.query.all(body.permissionGroupIds));
|
|
120
|
-
if (dbGroups.length !== body.permissionGroupIds.length) {
|
|
121
|
-
const dbGroupIds = dbGroups.map(dbObjectToId);
|
|
122
|
-
throw new ApiException(404, `Asked to give users non-existing permission groups: ${body.permissionGroupIds.filter(id => !dbGroupIds.includes(id))}`);
|
|
123
|
-
}
|
|
124
|
-
const myUserPermissions = MemKey_UserPermissions.get();
|
|
125
|
-
const permissionsToGive = dbGroups.reduce((map, group) => {
|
|
126
|
-
// Gather the highest permissions for each domain, from all groups
|
|
127
|
-
_keys(group._levelsMap || []).forEach(domainId => {
|
|
128
|
-
if (map[domainId] === undefined)
|
|
129
|
-
map[domainId] = 0;
|
|
130
|
-
if (map[domainId] < group._levelsMap[domainId])
|
|
131
|
-
map[domainId] = group._levelsMap[domainId];
|
|
132
|
-
});
|
|
133
|
-
return map;
|
|
134
|
-
}, {});
|
|
135
|
-
const failedDomains = _keys(permissionsToGive).filter(domainId => {
|
|
136
|
-
const tooLowPermission = myUserPermissions[domainId] < permissionsToGive[domainId];
|
|
137
|
-
this.logError(`${myUserPermissions[domainId]} < ${permissionsToGive[domainId]} === ${tooLowPermission}`);
|
|
138
|
-
const noPermissionInThisDomain = myUserPermissions[domainId] === undefined;
|
|
139
|
-
return noPermissionInThisDomain || tooLowPermission;
|
|
140
|
-
});
|
|
141
|
-
if (failedDomains.length)
|
|
142
|
-
throw new ApiException(403, `Attempted to give higher permissions than current user has: ${failedDomains}`);
|
|
143
|
-
const groupIds = dbGroups.map(group => ({ groupId: group._id }));
|
|
144
|
-
const usersToUpdate = usersToGiveTo.map(user => {
|
|
145
|
-
user.groups = groupIds;
|
|
146
|
-
return user;
|
|
147
|
-
});
|
|
148
|
-
await this.set.multi(usersToUpdate);
|
|
149
|
-
}
|
|
150
|
-
setDefaultPermissionGroups = (groupsGetter) => {
|
|
151
|
-
this.defaultPermissionGroups = groupsGetter;
|
|
152
|
-
};
|
|
153
|
-
clearDefaultPermissionGroups = () => {
|
|
154
|
-
delete this.defaultPermissionGroups;
|
|
155
|
-
};
|
|
156
|
-
/**
|
|
157
|
-
* The system requires to perform action, which in other cases can also be done by a human.
|
|
158
|
-
* This requires system features to identify as a bot user, or "Service Account"
|
|
159
|
-
*
|
|
160
|
-
* @param serviceAccounts - List of Accounts to create
|
|
161
|
-
* @private
|
|
162
|
-
*/
|
|
163
|
-
async createSystemServiceAccount(serviceAccounts) {
|
|
164
|
-
this.logInfoBold('Creating Service Accounts: ', serviceAccounts);
|
|
165
|
-
// @ts-ignore
|
|
166
|
-
const tokenCreator = ModuleBE_AccountDB.token.create;
|
|
167
|
-
const envConfigRef = getGlobalEnvConfigRef();
|
|
168
|
-
const updatedConfig = {};
|
|
169
|
-
//Run over all service accounts
|
|
170
|
-
for (const serviceAccount of serviceAccounts) {
|
|
171
|
-
// Create account if it doesn't already exist
|
|
172
|
-
const accountsToRequest = filterKeys({
|
|
173
|
-
type: 'service',
|
|
174
|
-
email: serviceAccount.email,
|
|
175
|
-
description: serviceAccount.description
|
|
176
|
-
});
|
|
177
|
-
let account;
|
|
178
|
-
//Get or create service account
|
|
179
|
-
try {
|
|
180
|
-
account = await ModuleBE_AccountDB.impl.querySafeAccount({ email: serviceAccount.email });
|
|
181
|
-
}
|
|
182
|
-
catch (e) {
|
|
183
|
-
this.logInfo('NOTICE: querySafeAccount failed, creating accounts');
|
|
184
|
-
account = await ModuleBE_AccountDB.account.create(accountsToRequest);
|
|
185
|
-
}
|
|
186
|
-
// Assign permissions groups to service account; permission user _id is 1:1 with account _id
|
|
187
|
-
const permissionsUser = await ModuleBE_PermissionUserDB.query.uniqueAssert({ _id: account._id });
|
|
188
|
-
permissionsUser.groups = serviceAccount.groupIds?.map(gid => ({ groupId: toPermissionGroupId(gid) })) || [];
|
|
189
|
-
await ModuleBE_PermissionUserDB.set.item(permissionsUser);
|
|
190
|
-
//Service accounts are only allowed to have one session... but this isn't the defined place to be a cop about it
|
|
191
|
-
const sessions = await ModuleBE_AccountDB.account.getSessions(account);
|
|
192
|
-
//If we have a valid session(not expired) we use its JWT instead of creating a new one
|
|
193
|
-
let validSession;
|
|
194
|
-
for (const session of sessions.sessions) {
|
|
195
|
-
if (await JwtTools.isJwtActive(session.sessionIdJwt)) {
|
|
196
|
-
validSession = session;
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
this.logError(serviceAccount.ttl);
|
|
201
|
-
const token = validSession?.sessionIdJwt ? { token: validSession?.sessionIdJwt } : await tokenCreator({
|
|
202
|
-
accountId: account._id,
|
|
203
|
-
ttl: serviceAccount.ttl ?? Year
|
|
204
|
-
});
|
|
205
|
-
updatedConfig[serviceAccount.moduleName] = {
|
|
206
|
-
serviceAccount: filterKeys({
|
|
207
|
-
token,
|
|
208
|
-
description: serviceAccount.description,
|
|
209
|
-
accountId: account._id,
|
|
210
|
-
email: account.email
|
|
211
|
-
})
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
if (_keys(updatedConfig).length > 0 && envConfigRef)
|
|
215
|
-
MemKey_ServerApi.get().addPostCallAction(async () => {
|
|
216
|
-
const currentConfig = await envConfigRef.get({});
|
|
217
|
-
await envConfigRef.set(merge(currentConfig, updatedConfig));
|
|
218
|
-
this.logInfoBold('Created Service Accounts for', _keys(updatedConfig));
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
async rotateSession(accountIds) {
|
|
222
|
-
if (!accountIds.length)
|
|
223
|
-
return;
|
|
224
|
-
//Collect all sessions connected to account
|
|
225
|
-
const sessions = await batchActionParallel(accountIds, 10, async (ids) => await ModuleBE_SessionDB.query.custom({ where: { accountId: { $in: ids } } }));
|
|
226
|
-
//TODO - Make sure new logic in ModuleBE_SessionDB that deletes expired sessions happens before this code, this will be redundant
|
|
227
|
-
//Filter to sessions that aren't expired
|
|
228
|
-
const validSessions = filterInstances(await Promise.all(sessions.map(async (session) => {
|
|
229
|
-
const isExpired = await JwtTools.isJwtExpired(session.sessionIdJwt);
|
|
230
|
-
return isExpired ? undefined : session;
|
|
231
|
-
})));
|
|
232
|
-
//TODO END
|
|
233
|
-
this.logWarning(`#### Rotating ${validSessions.length} Sessions! ####`);
|
|
234
|
-
await batchAction(validSessions, 500, async (sessions) => {
|
|
235
|
-
await this.runTransaction(async (t) => {
|
|
236
|
-
await Promise.all(sessions.map(session => ModuleBE_SessionDB._session.rotate.reissue.bySession(session, t)));
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
export const ModuleBE_PermissionUserDB = new ModuleBE_PermissionUserDB_Class();
|
package/_entity.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
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';
|