• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alkem-io / server / #8050

16 Aug 2024 11:21AM UTC coverage: 13.92%. First build
#8050

Pull #4411

travis-ci

Pull Request #4411: Type added to authorization policy entity

80 of 4158 branches covered (1.92%)

Branch coverage included in aggregate %.

61 of 116 new or added lines in 50 files covered. (52.59%)

1945 of 10389 relevant lines covered (18.72%)

3.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

8.46
/src/domain/common/authorization-policy/authorization.policy.service.ts
1
import { Inject, Injectable, LoggerService } from '@nestjs/common';
48✔
2
import { InjectRepository } from '@nestjs/typeorm';
48✔
3
import { FindOptionsSelect, Repository } from 'typeorm';
48✔
4
import {
48✔
5
  EntityNotFoundException,
6
  ForbiddenException,
7
  RelationshipNotFoundException,
8
} from '@common/exceptions';
9
import {
48✔
10
  AuthorizationCredential,
11
  AuthorizationPrivilege,
12
  AuthorizationRoleGlobal,
13
  LogContext,
14
} from '@common/enums';
15
import { AuthorizationPolicy } from '@domain/common/authorization-policy/authorization.policy.entity';
48✔
16
import { IAuthorizationPolicy } from './authorization.policy.interface';
17
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
48✔
18
import { CredentialsSearchInput } from '@domain/agent/credential/dto/credentials.dto.search';
19
import { IAuthorizationPolicyRuleCredential } from '../../../core/authorization/authorization.policy.rule.credential.interface';
20
import { AuthorizationPolicyRuleCredential } from '@core/authorization/authorization.policy.rule.credential';
48✔
21
import { AuthorizationService } from '@core/authorization/authorization.service';
48✔
22
import { AgentInfo } from '@core/authentication.agent.info/agent.info';
23
import { AuthorizationPolicyRuleVerifiedCredential } from '@core/authorization/authorization.policy.rule.verified.credential';
24
import { IAuthorizationPolicyRulePrivilege } from '@core/authorization/authorization.policy.rule.privilege.interface';
25
import { IAuthorizationPolicyRuleVerifiedCredential } from '@core/authorization/authorization.policy.rule.verified.credential.interface';
26
import { ICredentialDefinition } from '@domain/agent/credential/credential.definition.interface';
27
import { AuthorizationPolicyType } from '@common/enums/authorization.policy.type';
48✔
28
import { ConfigService } from '@nestjs/config';
29
import { AlkemioConfig } from '@src/types';
30
import { AuthorizationPolicyRulePrivilege } from '@core/authorization/authorization.policy.rule.privilege';
48✔
31

32
@Injectable()
33
export class AuthorizationPolicyService {
×
34
  private readonly authChunkSize: number;
×
35
  constructor(
36
    @InjectRepository(AuthorizationPolicy)
×
37
    private authorizationPolicyRepository: Repository<AuthorizationPolicy>,
38
    private authorizationService: AuthorizationService,
39
    @Inject(WINSTON_MODULE_NEST_PROVIDER)
40
    private readonly logger: LoggerService,
41
    private readonly configService: ConfigService<AlkemioConfig, true>
42
  ) {
43
    this.authChunkSize = this.configService.get('authorization.chunk', {
44
      infer: true,
×
45
    });
46
  }
47

48
  public authorizationSelectOptions: FindOptionsSelect<AuthorizationPolicy> = {
49
    id: true,
50
    credentialRules: true,
51
    privilegeRules: true,
52
    verifiedCredentialRules: true,
53
  };
54

55
  createCredentialRule(
56
    grantedPrivileges: AuthorizationPrivilege[],
57
    criterias: ICredentialDefinition[],
×
58
    name: string
59
  ): IAuthorizationPolicyRuleCredential {
×
60
    return {
×
61
      grantedPrivileges,
62
      criterias,
63
      cascade: true,
64
      name,
65
    };
×
66
  }
67

68
  createCredentialRuleUsingTypesOnly(
×
69
    grantedPrivileges: AuthorizationPrivilege[],
70
    createntialTypes: AuthorizationCredential[],
71
    name: string
72
  ): IAuthorizationPolicyRuleCredential {
73
    const criterias: ICredentialDefinition[] = [];
74

75
    for (const credentialType of createntialTypes) {
76
      const criteria: ICredentialDefinition = {
77
        type: credentialType,
78
        resourceID: '',
79
      };
80

81
      criterias.push(criteria);
×
82
    }
83

×
84
    return {
85
      grantedPrivileges,
×
86
      criterias,
87
      cascade: true,
×
88
      name,
×
89
    };
90
  }
×
91

×
92
  private createCredentialRuleGlobalAdmins(
93
    grantedPrivileges: AuthorizationPrivilege[],
×
94
    globalRoles: AuthorizationRoleGlobal[],
×
95
    name: string
96
  ): IAuthorizationPolicyRuleCredential {
×
97
    const criterias: ICredentialDefinition[] = [];
98

99
    for (const globalRole of globalRoles) {
100
      let credType: AuthorizationCredential;
101
      switch (globalRole) {
102
        case AuthorizationRoleGlobal.GLOBAL_ADMIN:
×
103
          credType = AuthorizationCredential.GLOBAL_ADMIN;
104
          break;
105
        case AuthorizationRoleGlobal.GLOBAL_COMMUNITY_READ:
106
          credType = AuthorizationCredential.GLOBAL_COMMUNITY_READ;
107
          break;
×
108
        case AuthorizationRoleGlobal.GLOBAL_SUPPORT:
109
          credType = AuthorizationCredential.GLOBAL_SUPPORT;
110
          break;
×
111
        default:
112
          throw new ForbiddenException(
113
            `Authorization: invalid global role encountered: ${globalRole}`,
114
            LogContext.AUTH
115
          );
116
      }
117

118
      const criteria: ICredentialDefinition = {
119
        type: credType,
120
        resourceID: '',
121
      };
122

NEW
123
      criterias.push(criteria);
×
124
    }
125

126
    return {
×
127
      grantedPrivileges,
128
      criterias,
129
      cascade: true,
130
      name,
131
    };
132
  }
×
133

×
134
  createGlobalRolesAuthorizationPolicy(
135
    globalRoles: AuthorizationRoleGlobal[],
×
136
    privileges: AuthorizationPrivilege[],
137
    name: string
138
  ): IAuthorizationPolicy {
139
    const authorization = new AuthorizationPolicy(
140
      AuthorizationPolicyType.IN_MEMORY
141
    );
×
142
    const rule = this.createCredentialRuleGlobalAdmins(
×
143
      privileges,
144
      globalRoles,
145
      name
146
    );
147

×
148
    const rules = [rule];
×
149
    this.appendCredentialAuthorizationRules(authorization, rules);
×
150

×
151
    return authorization;
152
  }
153

154
  public reset(
155
    authorizationPolicy: IAuthorizationPolicy | undefined
156
  ): IAuthorizationPolicy {
157
    if (!authorizationPolicy) {
×
158
      throw new RelationshipNotFoundException(
159
        'Undefined Authorization Policy supplied',
160
        LogContext.AUTH
×
161
      );
×
162
    }
163
    authorizationPolicy.credentialRules = [];
164
    authorizationPolicy.verifiedCredentialRules = [];
165
    authorizationPolicy.privilegeRules = [];
×
166
    return authorizationPolicy;
167
  }
168

169
  async getAuthorizationPolicyOrFail(
170
    authorizationPolicyID: string
171
  ): Promise<IAuthorizationPolicy> {
×
172
    const authorizationPolicy =
173
      await this.authorizationPolicyRepository.findOneBy({
174
        id: authorizationPolicyID,
175
      });
176
    if (!authorizationPolicy)
177
      throw new EntityNotFoundException(
178
        `Not able to locate Authorization Policy with the specified ID: ${authorizationPolicyID}`,
179
        LogContext.AUTH
×
180
      );
181
    return authorizationPolicy;
182
  }
183

×
184
  async delete(
185
    authorizationPolicy: IAuthorizationPolicy
186
  ): Promise<IAuthorizationPolicy> {
187
    return await this.authorizationPolicyRepository.remove(
×
188
      authorizationPolicy as AuthorizationPolicy
189
    );
190
  }
191

192
  async save(
193
    authorizationPolicy: IAuthorizationPolicy
194
  ): Promise<IAuthorizationPolicy> {
195
    return this.authorizationPolicyRepository.save(authorizationPolicy);
×
196
  }
×
197

198
  async saveAll(authorizationPolicies: IAuthorizationPolicy[]): Promise<void> {
199
    if (authorizationPolicies.length > 500)
×
200
      this.logger.warn?.(
201
        `Saving ${authorizationPolicies.length} authorization policies of type ${authorizationPolicies[0].type}`,
202
        LogContext.AUTH
203
      );
204
    else {
205
      this.logger.verbose?.(
×
206
        `Saving ${authorizationPolicies.length} authorization policies`,
×
207
        LogContext.AUTH
208
      );
209
    }
210

×
211
    await this.authorizationPolicyRepository.save(authorizationPolicies, {
212
      chunk: this.authChunkSize,
213
    });
214
  }
215

216
  cloneAuthorizationPolicy(
217
    originalAuthorization: IAuthorizationPolicy | undefined
218
  ): IAuthorizationPolicy {
219
    this.validateAuthorization(originalAuthorization);
×
220
    const clonedAuthorization: IAuthorizationPolicy = JSON.parse(
×
221
      JSON.stringify(originalAuthorization)
222
    );
223
    return clonedAuthorization;
×
224
  }
225

226
  validateAuthorization(
227
    authorization: IAuthorizationPolicy | undefined
×
228
  ): IAuthorizationPolicy {
229
    if (!authorization)
230
      throw new ForbiddenException(
231
        'Authorization: no definition provided',
×
232
        LogContext.AUTH
×
233
      );
×
234
    return authorization;
235
  }
236

237
  appendCredentialAuthorizationRule(
238
    authorization: IAuthorizationPolicy | undefined,
239
    credentialCriteria: CredentialsSearchInput,
240
    grantedPrivileges: AuthorizationPrivilege[],
×
241
    name: string
242
  ): IAuthorizationPolicy {
×
243
    const auth = this.validateAuthorization(authorization);
244
    const rules = auth.credentialRules;
245
    const newRule = new AuthorizationPolicyRuleCredential(
×
246
      grantedPrivileges,
×
247
      {
248
        type: credentialCriteria.type,
249
        resourceID: credentialCriteria.resourceID || '',
×
250
      },
×
251
      name
252
    );
253
    rules.push(newRule);
254
    auth.credentialRules = rules;
255
    return auth;
256
  }
257

×
258
  public appendCredentialRuleRegisteredAccess(
×
259
    authorization: IAuthorizationPolicy | undefined,
260
    privilege: AuthorizationPrivilege,
261
    cascade = true
×
262
  ): IAuthorizationPolicy {
×
263
    const auth = this.validateAuthorization(authorization);
264

×
265
    const newRule = this.createCredentialRuleUsingTypesOnly(
×
266
      [privilege],
267
      [AuthorizationCredential.GLOBAL_REGISTERED],
268
      `Anonymous agent granted '${privilege}' registered access`
269
    );
270
    newRule.cascade = cascade;
271
    auth.credentialRules.push(newRule);
272
    return auth;
×
273
  }
274

275
  public appendCredentialRuleAnonymousAccess(
×
276
    authorization: IAuthorizationPolicy | undefined,
277
    privilege: AuthorizationPrivilege,
278
    cascade = true
×
279
  ): IAuthorizationPolicy {
×
280
    const auth = this.validateAuthorization(authorization);
281

282
    const newRule = this.createCredentialRuleUsingTypesOnly(
×
283
      [privilege],
×
284
      [AuthorizationCredential.GLOBAL_ANONYMOUS],
285
      `Anonymous agent granted '${privilege}' anonymous access`
286
    );
287
    newRule.cascade = cascade;
288
    auth.credentialRules.push(newRule);
289
    return auth;
290
  }
×
291

×
292
  /**
×
293
   * Returns GLOBAL_ANONYMOUS and GLOBAL_REGISTERED credential definitions.
294
   */
295
  public getCredentialDefinitionsAnonymousRegistered(): ICredentialDefinition[] {
296
    return [
297
      { type: AuthorizationCredential.GLOBAL_ANONYMOUS, resourceID: '' },
298
      { type: AuthorizationCredential.GLOBAL_REGISTERED, resourceID: '' },
299
    ];
300
  }
301

×
302
  public appendCredentialRuleAnonymousRegisteredAccess(
×
303
    authorization: IAuthorizationPolicy | undefined,
×
304
    privilege: AuthorizationPrivilege,
305
    cascade = true
306
  ): IAuthorizationPolicy {
307
    const auth = this.validateAuthorization(authorization);
308

NEW
309
    const newRule = this.createCredentialRuleUsingTypesOnly(
×
310
      [privilege],
311
      [
×
312
        AuthorizationCredential.GLOBAL_ANONYMOUS,
×
313
        AuthorizationCredential.GLOBAL_REGISTERED,
314
      ],
×
315
      `Anonymous agent granted '${privilege}' anonymous registered access`
316
    );
×
317
    newRule.cascade = cascade;
318
    auth.credentialRules.push(newRule);
319
    return auth;
×
320
  }
×
321

×
322
  appendCredentialAuthorizationRules(
×
323
    authorization: IAuthorizationPolicy | undefined,
324
    additionalRules: IAuthorizationPolicyRuleCredential[]
325
  ): IAuthorizationPolicy {
×
326
    const auth = this.validateAuthorization(authorization);
327

328
    const existingRules = auth.credentialRules;
329
    for (const additionalRule of additionalRules) {
×
330
      existingRules.push(additionalRule);
331
    }
332

×
333
    auth.credentialRules = existingRules;
×
334
    return auth;
×
335
  }
336

×
337
  appendPrivilegeAuthorizationRules(
338
    authorization: IAuthorizationPolicy | undefined,
×
339
    privilegeRules: IAuthorizationPolicyRulePrivilege[]
340
  ): IAuthorizationPolicy {
341
    const auth = this.validateAuthorization(authorization);
342
    const existingRules = auth.privilegeRules;
343
    for (const additionalRule of privilegeRules) {
344
      existingRules.push(additionalRule);
×
345
    }
346
    auth.privilegeRules = existingRules;
347
    return auth;
×
348
  }
349

350
  public appendPrivilegeAuthorizationRuleMapping(
351
    authorization: IAuthorizationPolicy | undefined,
352
    sourcePrivilege: AuthorizationPrivilege,
353
    grantedPrivileges: AuthorizationPrivilege[],
×
354
    name: string
355
  ): IAuthorizationPolicy {
356
    const auth = this.validateAuthorization(authorization);
×
357
    const existingRules = auth.privilegeRules;
358
    const newPrivilegeRule = new AuthorizationPolicyRulePrivilege(
359
      grantedPrivileges,
360
      sourcePrivilege,
361
      name
362
    );
×
363
    existingRules.push(newPrivilegeRule);
364

365
    auth.privilegeRules = existingRules;
×
366
    return auth;
367
  }
368

369
  appendVerifiedCredentialAuthorizationRules(
370
    authorization: IAuthorizationPolicy | undefined,
371
    additionalRules: AuthorizationPolicyRuleVerifiedCredential[]
372
  ): IAuthorizationPolicy {
×
373
    const auth = this.validateAuthorization(authorization);
374

×
375
    const existingRules = auth.verifiedCredentialRules;
376
    for (const additionalRule of additionalRules) {
377
      existingRules.push(additionalRule);
378
    }
379

380
    auth.verifiedCredentialRules = existingRules;
381
    return auth;
382
  }
383

384
  inheritParentAuthorization(
385
    childAuthorization: IAuthorizationPolicy | undefined,
386
    parentAuthorization: IAuthorizationPolicy | undefined
387
  ): IAuthorizationPolicy {
388
    // TODO: remove this
389
    // create a new child definition if one is not provided, a temporary fix
390
    let child = childAuthorization;
391
    if (!child) {
392
      this.logger.error(
393
        `Encountered undefined child authorization policy, parent authorization: ${JSON.stringify(
394
          parentAuthorization
395
        )}`,
396
        LogContext.AUTH
397
      );
398
      child = new AuthorizationPolicy(AuthorizationPolicyType.UNKNOWN);
399
    }
400
    const parent = this.validateAuthorization(parentAuthorization);
401
    const resetAuthPolicy = this.reset(child);
402

403
    // (a) Inherit the credential rules
404
    const inheritedRules = parent.credentialRules;
405

406
    const newRules: IAuthorizationPolicyRuleCredential[] = [];
407
    for (const inheritedRule of inheritedRules) {
408
      if (inheritedRule.cascade) {
409
        newRules.push(inheritedRule);
410
      }
411
    }
412
    resetAuthPolicy.credentialRules = newRules;
413

414
    // (b) Inherit the verified credential rules
415
    const inheritedVCRules = parent.verifiedCredentialRules;
416

417
    const newVcRules: IAuthorizationPolicyRuleVerifiedCredential[] = [];
418
    for (const inheritedVcRule of inheritedVCRules) {
419
      newVcRules.push(inheritedVcRule);
420
    }
421
    resetAuthPolicy.verifiedCredentialRules = newVcRules;
422

423
    return resetAuthPolicy;
424
  }
425

426
  getCredentialRules(
427
    authorization: IAuthorizationPolicy
428
  ): IAuthorizationPolicyRuleCredential[] {
429
    return authorization.credentialRules;
430
  }
431

432
  getVerifiedCredentialRules(
433
    authorization: IAuthorizationPolicy
434
  ): IAuthorizationPolicyRuleVerifiedCredential[] {
435
    return authorization.verifiedCredentialRules;
436
  }
437

438
  getPrivilegeRules(
439
    authorization: IAuthorizationPolicy
440
  ): IAuthorizationPolicyRulePrivilege[] {
441
    return authorization.privilegeRules ?? [];
442
  }
443

444
  getAgentPrivileges(
445
    agentInfo: AgentInfo,
446
    authorizationPolicy: IAuthorizationPolicy
447
  ): AuthorizationPrivilege[] {
448
    if (!agentInfo || !agentInfo.credentials) return [];
449

450
    return this.authorizationService.getGrantedPrivileges(
451
      agentInfo.credentials,
452
      agentInfo.verifiedCredentials,
453
      authorizationPolicy
454
    );
455
  }
456
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc