Skip to content

Commit

Permalink
move external tool authorisation code
Browse files Browse the repository at this point in the history
  • Loading branch information
Metauriel committed Sep 27, 2024
1 parent 128d522 commit 1a53e92
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { InstanceModule } from '@modules/instance';
import { LessonModule } from '@modules/lesson';
import { ToolModule } from '@modules/tool';
import { forwardRef, Module } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { CourseGroupRepo, CourseRepo, LegacySchoolRepo, SubmissionRepo, TaskRepo, UserRepo } from '@shared/repo';
import { LoggerModule } from '@src/core/logger';
import { AuthorizationModule } from './authorization.module';
Expand All @@ -14,8 +13,7 @@ import { TeamsModule } from '../teams';
* Avoid using this module and load the needed data in your use cases and then use the normal AuthorizationModule!
*/
@Module({
// TODO: remove forwardRef
imports: [AuthorizationModule, LessonModule, TeamsModule, forwardRef(() => ToolModule), LoggerModule, InstanceModule],
imports: [AuthorizationModule, LessonModule, TeamsModule, LoggerModule, InstanceModule],
providers: [
AuthorizationHelper,
ReferenceLoader,
Expand Down
2 changes: 0 additions & 2 deletions apps/server/src/modules/authorization/authorization.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { AuthorizationHelper, AuthorizationService, RuleManager, AuthorizationIn
import {
CourseGroupRule,
CourseRule,
ExternalToolRule,
GroupRule,
InstanceRule,
LegacySchoolRule,
Expand Down Expand Up @@ -46,7 +45,6 @@ import { FeathersAuthorizationService, FeathersAuthProvider } from './feathers';
LegacySchoolRule,
SystemRule,
SchoolSystemOptionsRule,
ExternalToolRule,
InstanceRule,
],
exports: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,3 @@ export * from './group.rule';
export { SystemRule } from './system.rule';
export { SchoolSystemOptionsRule } from './school-system-options.rule';
export { InstanceRule } from './instance.rule';
export { ExternalToolRule } from './external-tool.rule';
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// TODO fix modules circular dependency
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { TeamAuthorisableService } from '@src/modules/teams/service/team-authorisable.service';
import { ExternalToolAuthorizableService } from '@modules/tool/external-tool/service';
import { LessonService } from '@modules/lesson';
import { Injectable, NotImplementedException } from '@nestjs/common';
import { AuthorizableObject } from '@shared/domain/domain-object';
Expand All @@ -23,7 +22,6 @@ export class ReferenceLoader {
private readonly lessonService: LessonService,
private readonly teamAuthorisableService: TeamAuthorisableService,
private readonly submissionRepo: SubmissionRepo,
private readonly externalToolAuthorizableService: ExternalToolAuthorizableService,
private readonly instanceService: InstanceService,
private readonly authorizationInjectionService: AuthorizationInjectionService
) {
Expand All @@ -36,7 +34,6 @@ export class ReferenceLoader {
service.injectReferenceLoader(AuthorizableReferenceType.Lesson, this.lessonService);
service.injectReferenceLoader(AuthorizableReferenceType.Team, this.teamAuthorisableService);
service.injectReferenceLoader(AuthorizableReferenceType.Submission, this.submissionRepo);
service.injectReferenceLoader(AuthorizableReferenceType.ExternalTool, this.externalToolAuthorizableService);
service.injectReferenceLoader(AuthorizableReferenceType.Instance, this.instanceService);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
UserLoginMigrationRule,
UserRule,
} from '../rules';
import { ExternalToolRule } from '../rules/external-tool.rule';
import type { AuthorizationContext, Rule } from '../type';
import { AuthorizationInjectionService } from './authorization-injection.service';

Expand All @@ -38,7 +37,6 @@ export class RuleManager {
teamRule: TeamRule,
userLoginMigrationRule: UserLoginMigrationRule,
userRule: UserRule,
externalToolRule: ExternalToolRule,
instanceRule: InstanceRule,
private readonly authorizationInjectionService: AuthorizationInjectionService
) {
Expand All @@ -55,7 +53,6 @@ export class RuleManager {
this.authorizationInjectionService.injectAuthorizationRule(teamRule);
this.authorizationInjectionService.injectAuthorizationRule(userLoginMigrationRule);
this.authorizationInjectionService.injectAuthorizationRule(userRule);
this.authorizationInjectionService.injectAuthorizationRule(externalToolRule);
this.authorizationInjectionService.injectAuthorizationRule(instanceRule);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { ContextExternalToolRule } from './authorisation/context-external-tool.r
exports: [
ContextExternalToolService,
ContextExternalToolValidationService,
ContextExternalToolAuthorizableService,
ToolReferenceService,
ToolConfigurationStatusService,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import { Test, TestingModule } from '@nestjs/testing';
import { User } from '@shared/domain/entity';
import { Permission } from '@shared/domain/interface';
import { setupEntities, userFactory } from '@shared/testing';
import { AuthorizationHelper } from '../service/authorization.helper';
import { Action } from '../type';
import { ExternalToolRule } from './external-tool.rule';
import { Action, AuthorizationHelper, AuthorizationInjectionService } from '@src/modules/authorization';

describe(ExternalToolRule.name, () => {
let module: TestingModule;
let rule: ExternalToolRule;

let authorizationHelper: DeepMocked<AuthorizationHelper>;
let injectionService: DeepMocked<AuthorizationInjectionService>;

beforeAll(async () => {
await setupEntities();
Expand All @@ -25,11 +25,16 @@ describe(ExternalToolRule.name, () => {
provide: AuthorizationHelper,
useValue: createMock<AuthorizationHelper>(),
},
{
provide: AuthorizationInjectionService,
useValue: createMock<AuthorizationInjectionService>(),
},
],
}).compile();

rule = module.get(ExternalToolRule);
authorizationHelper = module.get(AuthorizationHelper);
injectionService = module.get(AuthorizationInjectionService);
});

beforeEach(() => {
Expand All @@ -40,6 +45,13 @@ describe(ExternalToolRule.name, () => {
await module.close();
});

describe('constructor', () => {
it('should inject itself into the AuthorizationInjectionService', () => {
new ExternalToolRule(authorizationHelper, injectionService);
expect(injectionService.injectAuthorizationRule).toHaveBeenCalledWith(rule);
});
});

describe('isApplicable', () => {
describe('when the object is an external tool', () => {
const setup = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { ExternalTool } from '@modules/tool/external-tool/domain';
import { Injectable } from '@nestjs/common';
import { User } from '@shared/domain/entity';
import { AuthorizationHelper } from '../service/authorization.helper';
import { AuthorizationContext, Rule } from '../type';
import {
AuthorizationContext,
AuthorizationHelper,
AuthorizationInjectionService,
Rule,
} from '@src/modules/authorization';

@Injectable()
export class ExternalToolRule implements Rule<ExternalTool> {
constructor(private readonly authorizationHelper: AuthorizationHelper) {}
constructor(
private readonly authorizationHelper: AuthorizationHelper,
injectionService: AuthorizationInjectionService
) {
injectionService.injectAuthorizationRule(this);
}

public isApplicable(user: User, object: unknown): boolean {
const isMatched: boolean = object instanceof ExternalTool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import {
ExternalToolConfigurationService,
ExternalToolLogoService,
DatasheetPdfService,
ExternalToolAuthorizableService,
ExternalToolImageService,
],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { Test, TestingModule } from '@nestjs/testing';
import { ExternalToolRepo } from '@shared/repo';
import { externalToolFactory } from '../testing';
import { ExternalToolAuthorizableService } from './external-tool-authorizable.service';
import { AuthorizableReferenceType, AuthorizationInjectionService } from '@src/modules/authorization';

describe(ExternalToolAuthorizableService.name, () => {
let module: TestingModule;
let service: ExternalToolAuthorizableService;

let externalToolRepo: DeepMocked<ExternalToolRepo>;
let authorizationInjectionService: DeepMocked<AuthorizationInjectionService>;

beforeAll(async () => {
module = await Test.createTestingModule({
Expand All @@ -18,11 +20,16 @@ describe(ExternalToolAuthorizableService.name, () => {
provide: ExternalToolRepo,
useValue: createMock<ExternalToolRepo>(),
},
{
provide: AuthorizationInjectionService,
useValue: createMock<AuthorizationInjectionService>(),
},
],
}).compile();

service = module.get(ExternalToolAuthorizableService);
externalToolRepo = module.get(ExternalToolRepo);
authorizationInjectionService = module.get(AuthorizationInjectionService);
});

afterAll(async () => {
Expand All @@ -33,6 +40,15 @@ describe(ExternalToolAuthorizableService.name, () => {
jest.resetAllMocks();
});

describe('constructor', () => {
it('should inject itself into the AuthorizationInjectionService', () => {
expect(authorizationInjectionService.injectReferenceLoader).toHaveBeenCalledWith(
AuthorizableReferenceType.ExternalTool,
service
);
});
});

describe('findById', () => {
describe('when there is an external tool', () => {
const setup = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { AuthorizationLoaderService } from '@modules/authorization';
import {
AuthorizableReferenceType,
AuthorizationInjectionService,
AuthorizationLoaderService,
} from '@modules/authorization';
import { Injectable } from '@nestjs/common';
import { EntityId } from '@shared/domain/types';
import { ExternalToolRepo } from '@shared/repo';
import { ExternalTool } from '../domain';

@Injectable()
export class ExternalToolAuthorizableService implements AuthorizationLoaderService {
constructor(private readonly externalToolRepo: ExternalToolRepo) {}
constructor(private readonly externalToolRepo: ExternalToolRepo, injectionService: AuthorizationInjectionService) {
injectionService.injectReferenceLoader(AuthorizableReferenceType.ExternalTool, this);
}

async findById(id: EntityId): Promise<ExternalTool> {
const externalTool: ExternalTool = await this.externalToolRepo.findById(id);
Expand Down

0 comments on commit 1a53e92

Please sign in to comment.