|
| 1 | +import * as cedarWasm from '@cedar-policy/cedar-wasm/nodejs'; |
1 | 2 | import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; |
| 3 | +import { IGlobalDatabaseContext } from '../../common/application/global-database-context.interface.js'; |
| 4 | +import { BaseType } from '../../common/data-injection.tokens.js'; |
2 | 5 | import { AccessLevelEnum } from '../../enums/index.js'; |
3 | 6 | import { Messages } from '../../exceptions/text/messages.js'; |
4 | 7 | import { Cacher } from '../../helpers/cache/cacher.js'; |
5 | | -import { IGlobalDatabaseContext } from '../../common/application/global-database-context.interface.js'; |
6 | | -import { BaseType } from '../../common/data-injection.tokens.js'; |
7 | 8 | import { GroupEntity } from '../group/group.entity.js'; |
8 | 9 | import { ITablePermissionData } from '../permission/permission.interface.js'; |
9 | | -import { CedarAction, CedarResourceType, CEDAR_ACTION_TYPE, CEDAR_USER_TYPE } from './cedar-action-map.js'; |
| 10 | +import { IUserAccessRepository } from '../user-access/repository/user-access.repository.interface.js'; |
| 11 | +import { CEDAR_ACTION_TYPE, CEDAR_USER_TYPE, CedarAction, CedarResourceType } from './cedar-action-map.js'; |
10 | 12 | import { buildCedarEntities } from './cedar-entity-builder.js'; |
11 | 13 | import { CEDAR_SCHEMA } from './cedar-schema.js'; |
12 | | -import * as cedarWasm from '@cedar-policy/cedar-wasm/nodejs'; |
13 | | -import { IUserAccessRepository } from '../user-access/repository/user-access.repository.interface.js'; |
14 | 14 |
|
15 | 15 | interface EvalContext { |
16 | 16 | userGroups: Array<GroupEntity>; |
@@ -58,6 +58,69 @@ export class CedarPermissionsService implements IUserAccessRepository { |
58 | 58 | return AccessLevelEnum.none; |
59 | 59 | } |
60 | 60 |
|
| 61 | + async getUserConnectionAccessLevelsForMultipleConnections( |
| 62 | + userId: string, |
| 63 | + connectionIds: Array<string>, |
| 64 | + ): Promise<Map<string, AccessLevelEnum>> { |
| 65 | + const result = new Map<string, AccessLevelEnum>(); |
| 66 | + if (connectionIds.length === 0) return result; |
| 67 | + |
| 68 | + const allGroups = await this.globalDbContext.groupRepository.findAllUserGroupsInConnections(connectionIds, userId); |
| 69 | + |
| 70 | + const groupsByConnection = new Map<string, Array<GroupEntity>>(); |
| 71 | + for (const group of allGroups) { |
| 72 | + const connId = group.connection?.id; |
| 73 | + if (!connId) continue; |
| 74 | + if (!groupsByConnection.has(connId)) { |
| 75 | + groupsByConnection.set(connId, []); |
| 76 | + } |
| 77 | + groupsByConnection.get(connId).push(group); |
| 78 | + } |
| 79 | + |
| 80 | + for (const connectionId of connectionIds) { |
| 81 | + const userGroups = groupsByConnection.get(connectionId); |
| 82 | + if (!userGroups || userGroups.length === 0) { |
| 83 | + result.set(connectionId, AccessLevelEnum.none); |
| 84 | + continue; |
| 85 | + } |
| 86 | + |
| 87 | + const policies = userGroups.map((g) => g.cedarPolicy).filter(Boolean); |
| 88 | + if (policies.length === 0) { |
| 89 | + result.set(connectionId, AccessLevelEnum.none); |
| 90 | + continue; |
| 91 | + } |
| 92 | + |
| 93 | + const entities = buildCedarEntities(userId, userGroups, connectionId); |
| 94 | + if ( |
| 95 | + this.evaluatePolicies( |
| 96 | + userId, |
| 97 | + CedarAction.ConnectionEdit, |
| 98 | + CedarResourceType.Connection, |
| 99 | + connectionId, |
| 100 | + policies, |
| 101 | + entities, |
| 102 | + ) |
| 103 | + ) { |
| 104 | + result.set(connectionId, AccessLevelEnum.edit); |
| 105 | + } else if ( |
| 106 | + this.evaluatePolicies( |
| 107 | + userId, |
| 108 | + CedarAction.ConnectionRead, |
| 109 | + CedarResourceType.Connection, |
| 110 | + connectionId, |
| 111 | + policies, |
| 112 | + entities, |
| 113 | + ) |
| 114 | + ) { |
| 115 | + result.set(connectionId, AccessLevelEnum.readonly); |
| 116 | + } else { |
| 117 | + result.set(connectionId, AccessLevelEnum.none); |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + return result; |
| 122 | + } |
| 123 | + |
61 | 124 | async checkUserConnectionRead(cognitoUserName: string, connectionId: string): Promise<boolean> { |
62 | 125 | const ctx = await this.loadContext(connectionId, cognitoUserName); |
63 | 126 | if (!ctx) return false; |
@@ -372,5 +435,4 @@ export class CedarPermissionsService implements IUserAccessRepository { |
372 | 435 |
|
373 | 436 | return { userGroups, policies }; |
374 | 437 | } |
375 | | - |
376 | 438 | } |
0 commit comments