Skip to content

Commit

Permalink
N21-1976 add media source to license logic (#5016)
Browse files Browse the repository at this point in the history
* add media source Id and use it for license logic
  • Loading branch information
IgorCapCoder authored May 22, 2024
1 parent 941c8a3 commit bedec82
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const schulconnexLizenzInfoResponseFactory = Factory.define<SchulconnexLi
{
target: {
uid: 'bildungscloud',
partOf: '',
},
permission: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ describe('Media Board (API)', () => {
const { studentAccount, studentUser } = UserAndAccountTestFactory.buildStudent();

const externalTool = externalToolEntityFactory.build();
const licensedUnusedExternalTool = externalToolEntityFactory.build({ medium: { mediumId: 'mediumId' } });
const licensedUnusedExternalTool = externalToolEntityFactory.withMedium().build();
const unusedExternalTool = externalToolEntityFactory.build({ medium: { mediumId: 'notLicensedByUser' } });
const schoolExternalTool = schoolExternalToolEntityFactory.build({
tool: externalTool,
Expand Down Expand Up @@ -532,6 +532,7 @@ describe('Media Board (API)', () => {
const userLicense: MediaUserLicenseEntity = mediaUserLicenseEntityFactory.build({
user: studentUser,
mediumId: 'mediumId',
mediaSourceId: 'mediaSourceId',
});

await em.persistAndFlush([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ export class MediaAvailableLineUc {
const mediaUserLicenses: MediaUserLicense[] = await this.userLicenseService.getMediaUserLicensesForUser(userId);

matchedTools = matchedTools.filter((tool: [ExternalTool, SchoolExternalTool]): boolean => {
const externalToolMediumId = tool[0]?.medium?.mediumId;
if (externalToolMediumId) {
return this.mediaUserLicenseService.hasLicenseForExternalTool(externalToolMediumId, mediaUserLicenses);
const externalToolMedium = tool[0]?.medium;
if (externalToolMedium) {
return this.mediaUserLicenseService.hasLicenseForExternalTool(externalToolMedium, mediaUserLicenses);
}
return true;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import {
SanisSonstigeGruppenzugehoerigeResponse,
schulconnexResponseFactory,
} from '@infra/schulconnex-client';
import { SchulconnexLizenzInfoResponse } from '@infra/schulconnex-client/response';
import { schulconnexLizenzInfoResponseFactory } from '@infra/schulconnex-client/testing/schulconnex-lizenz-info-response-factory';
import { GroupTypes } from '@modules/group';
import { Test, TestingModule } from '@nestjs/testing';
import { RoleName } from '@shared/domain/interface';
import { Logger } from '@src/core/logger';
import { IProvisioningFeatures, ProvisioningFeatures } from '../../config';
import { ExternalGroupDto, ExternalSchoolDto, ExternalUserDto } from '../../dto';
import { ExternalGroupDto, ExternalLicenseDto, ExternalSchoolDto, ExternalUserDto } from '../../dto';
import { SanisResponseMapper } from './sanis-response.mapper';

describe('SanisResponseMapper', () => {
Expand Down Expand Up @@ -46,11 +48,13 @@ describe('SanisResponseMapper', () => {
const externalSchoolId = 'df66c8e6-cfac-40f7-b35b-0da5d8ee680e';

const sanisResponse: SanisResponse = schulconnexResponseFactory.build();
const licenseResponse: SchulconnexLizenzInfoResponse[] = schulconnexLizenzInfoResponseFactory.build();

return {
externalUserId,
externalSchoolId,
sanisResponse,
licenseResponse,
};
};

Expand Down Expand Up @@ -305,4 +309,21 @@ describe('SanisResponseMapper', () => {
});
});
});

describe('mapToExternalLicenses', () => {
describe('when a sanis response with license is provided', () => {
it('should map the response to an ExternalLicenseDto', () => {
const { licenseResponse } = setupSanisResponse();

const result: ExternalLicenseDto[] = SanisResponseMapper.mapToExternalLicenses(licenseResponse);

expect(result).toEqual<ExternalLicenseDto[]>([
{
mediumId: 'bildungscloud',
mediaSourceId: undefined,
},
]);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,18 @@ export class SanisResponseMapper {
}

public static mapToExternalLicenses(licenseInfos: SchulconnexLizenzInfoResponse[]): ExternalLicenseDto[] {
const externalLicenseDtos: ExternalLicenseDto[] = licenseInfos.map(
(license: SchulconnexLizenzInfoResponse) =>
new ExternalLicenseDto({
mediumId: license.target.uid,
mediaSourceId: license.target.partOf,
})
);
const externalLicenseDtos: ExternalLicenseDto[] = licenseInfos.map((license: SchulconnexLizenzInfoResponse) => {
if (license.target.partOf === '') {
license.target.partOf = undefined;
}

const externalLicenseDto: ExternalLicenseDto = new ExternalLicenseDto({
mediumId: license.target.uid,
mediaSourceId: license.target.partOf,
});

return externalLicenseDto;
});

return externalLicenseDtos;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,9 @@ describe(SanisProvisioningStrategy.name, () => {
const schulconnexLizenzInfoResponses: SchulconnexLizenzInfoResponse[] =
schulconnexLizenzInfoResponseFactory.build();
const schulconnexLizenzInfoResponse = schulconnexLizenzInfoResponses[0];
const licenses: ExternalLicenseDto[] = [
new ExternalLicenseDto({
mediumId: schulconnexLizenzInfoResponse.target.uid,
mediaSourceId: schulconnexLizenzInfoResponse.target.partOf,
}),
];
const licenses: ExternalLicenseDto[] = SanisResponseMapper.mapToExternalLicenses([
schulconnexLizenzInfoResponse,
]);

httpService.get.mockReturnValue(of(createAxiosResponse(sanisResponse)));
mapper.mapToExternalUserDto.mockReturnValue(user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ export class ExternalToolMediumParams {
@IsNotEmpty()
@ApiPropertyOptional({ type: String, description: 'Publisher of the medium' })
publisher?: string;

@IsString()
@IsOptional()
@IsNotEmpty()
@ApiPropertyOptional({ type: String, description: 'The id of the media source' })
mediaSourceId?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ export class ExternalToolMediumResponse {
@ApiPropertyOptional({ type: String, description: 'Publisher of the medium' })
publisher?: string;

@ApiPropertyOptional({ type: String, description: 'The id of the media source' })
mediaSourceId?: string;

constructor(props: ExternalToolMediumResponse) {
this.mediumId = props.mediumId;
this.publisher = props.publisher;
this.mediaSourceId = props.mediaSourceId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ export interface ExternalToolMediumProps {
mediumId: string;

publisher?: string;

mediaSourceId?: string;
}

export class ExternalToolMedium {
mediumId: string;

publisher?: string;

mediaSourceId?: string;

constructor(props: ExternalToolMediumProps) {
this.mediumId = props.mediumId;
this.publisher = props.publisher;
this.mediaSourceId = props.mediaSourceId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ export class ExternalToolMediumEntity {
@Property({ nullable: true })
publisher?: string;

@Property({ nullable: true })
mediaSourceId?: string;

constructor(props: ExternalToolMediumEntity) {
this.mediumId = props.mediumId;
this.publisher = props.publisher;
this.mediaSourceId = props.mediaSourceId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export class ExternalToolEntityFactory extends BaseFactory<ExternalToolEntity, E
...medium,
mediumId: 'mediumId',
publisher: 'publisher',
mediaSourceId: 'mediaSourceId',
}),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class ExternalToolFactory extends DoBaseFactory<ExternalTool, ExternalToolProps>
medium: {
mediumId: 'mediumId',
publisher: 'publisher',
mediaSourceId: 'mediaSourceId',
...externalToolMedium,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ describe('ToolLaunchUc', () => {
const user: User = userFactory.build();
const mediaUserLicense: MediaUserLicense = mediaUserLicenseFactory.build();
const externalTool: ExternalTool = externalToolFactory.build({
medium: { mediumId: mediaUserLicense.mediumId },
medium: { mediumId: mediaUserLicense.mediumId, mediaSourceId: mediaUserLicense.mediaSourceId },
});
const schoolExternalToolId = new ObjectId().toHexString();
const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ id: schoolExternalToolId });
Expand Down Expand Up @@ -543,6 +543,7 @@ describe('ToolLaunchUc', () => {

return {
user,
externalTool,
schoolExternalTool,
contextExternalTool,
toolLaunchData,
Expand All @@ -552,11 +553,11 @@ describe('ToolLaunchUc', () => {
};

it('should check license', async () => {
const { user, contextExternalTool, mediaUserLicense } = setup();
const { user, contextExternalTool, mediaUserLicense, externalTool } = setup();

await uc.getSchoolExternalToolLaunchRequest(user.id, contextExternalTool);

expect(mediaUserLicenseService.hasLicenseForExternalTool).toHaveBeenCalledWith(mediaUserLicense.mediumId, [
expect(mediaUserLicenseService.hasLicenseForExternalTool).toHaveBeenCalledWith(externalTool.medium, [
mediaUserLicense,
]);
});
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/modules/tool/tool-launch/uc/tool-launch.uc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ export class ToolLaunchUc {
const mediaUserLicenses: MediaUserLicense[] = await this.userLicenseService.getMediaUserLicensesForUser(userId);

if (
externalTool.medium?.mediumId &&
!this.mediaUserLicenseService.hasLicenseForExternalTool(externalTool.medium.mediumId, mediaUserLicenses)
externalTool.medium &&
!this.mediaUserLicenseService.hasLicenseForExternalTool(externalTool.medium, mediaUserLicenses)
) {
throw new MissingMediaLicenseLoggableException(externalTool.medium, userId, contextExternalTool);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ExternalToolMedium } from '@modules/tool/external-tool/domain';
import { MediaUserLicense, mediaUserLicenseFactory } from '@modules/user-license';
import { MediaUserLicenseService } from '@modules/user-license/service/media-user-license.service';
import { Test, TestingModule } from '@nestjs/testing';
Expand Down Expand Up @@ -25,60 +26,94 @@ describe(MediaUserLicenseService.name, () => {
describe('hasLicenseForExternalTool', () => {
describe('when user has license', () => {
const setup = () => {
const mediumId = 'mediumId';
const mediaUserLicenses: MediaUserLicense[] = mediaUserLicenseFactory.buildList(2);
mediaUserLicenses[0].mediumId = 'mediumId';
const toolMedium: ExternalToolMedium = {
mediumId: 'mediumId',
mediaSourceId: 'mediaSourceId',
};
const medium = mediaUserLicenseFactory.build({
mediumId: toolMedium.mediumId,
mediaSourceId: toolMedium.mediaSourceId,
});
const unusedMedium = mediaUserLicenseFactory.build();
const mediaUserLicenses: MediaUserLicense[] = [medium, unusedMedium];

return {
toolMedium,
mediaUserLicenses,
};
};

it('should return true', () => {
const { toolMedium, mediaUserLicenses } = setup();

const result = service.hasLicenseForExternalTool(toolMedium, mediaUserLicenses);

expect(result).toEqual(true);
});
});

describe('when user has license without sourceId', () => {
const setup = () => {
const toolMedium: ExternalToolMedium = {
mediumId: 'mediumId',
};
const medium = mediaUserLicenseFactory.build({
mediumId: toolMedium.mediumId,
mediaSourceId: undefined,
});
const unusedMedium = mediaUserLicenseFactory.build();
const mediaUserLicenses: MediaUserLicense[] = [medium, unusedMedium];

return {
mediumId,
toolMedium,
mediaUserLicenses,
};
};

it('should return true', () => {
const { mediumId, mediaUserLicenses } = setup();
const { toolMedium, mediaUserLicenses } = setup();

const result = service.hasLicenseForExternalTool(mediumId, mediaUserLicenses);
const result = service.hasLicenseForExternalTool(toolMedium, mediaUserLicenses);

expect(result).toEqual(true);
});
});

describe('when user has not the correct license', () => {
const setup = () => {
const mediumId = 'mediumId';
const medium: ExternalToolMedium = { mediumId: 'mediumId' };
const mediaUserLicenses: MediaUserLicense[] = mediaUserLicenseFactory.buildList(2);

return {
mediumId,
medium,
mediaUserLicenses,
};
};

it('should return false', () => {
const { mediumId, mediaUserLicenses } = setup();
const { medium, mediaUserLicenses } = setup();

const result = service.hasLicenseForExternalTool(mediumId, mediaUserLicenses);
const result = service.hasLicenseForExternalTool(medium, mediaUserLicenses);

expect(result).toEqual(false);
});
});

describe('when user has no licenses', () => {
const setup = () => {
const mediumId = 'mediumId';
const medium: ExternalToolMedium = { mediumId: 'mediumId' };
const mediaUserLicenses: MediaUserLicense[] = [];

return {
mediumId,
medium,
mediaUserLicenses,
};
};

it('should return false', () => {
const { mediumId, mediaUserLicenses } = setup();
const { medium, mediaUserLicenses } = setup();

const result = service.hasLicenseForExternalTool(mediumId, mediaUserLicenses);
const result = service.hasLicenseForExternalTool(medium, mediaUserLicenses);

expect(result).toEqual(false);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { ExternalToolMedium } from '@modules/tool/external-tool/domain';
import { MediaUserLicense } from '@modules/user-license';
import { Injectable } from '@nestjs/common';

@Injectable()
export class MediaUserLicenseService {
public hasLicenseForExternalTool(externalToolMediumId: string, mediaUserLicenses: MediaUserLicense[]): boolean {
return mediaUserLicenses.some((license: MediaUserLicense) => license.mediumId === externalToolMediumId);
public hasLicenseForExternalTool(
externalToolMedium: ExternalToolMedium,
mediaUserLicenses: MediaUserLicense[]
): boolean {
return mediaUserLicenses.some(
(license: MediaUserLicense) =>
license.mediumId === externalToolMedium.mediumId && license.mediaSourceId === externalToolMedium.mediaSourceId
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class ExternalToolRepoMapper {
return new ExternalToolMedium({
mediumId: entity.mediumId,
publisher: entity.publisher,
mediaSourceId: entity.mediaSourceId,
});
}

Expand Down Expand Up @@ -137,6 +138,7 @@ export class ExternalToolRepoMapper {
return new ExternalToolMediumEntity({
mediumId: medium.mediumId,
publisher: medium.publisher,
mediaSourceId: medium.mediaSourceId,
});
}

Expand Down

0 comments on commit bedec82

Please sign in to comment.