Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bc 4572 rewrite courses to nest #4358

Merged
merged 27 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d50c42e
change name of lesson entity, add method in lesson repo and in lesson…
WojciechGrancow Aug 24, 2023
8706f36
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Aug 24, 2023
6303028
modification in repos: lesson, course, coursegroup and add methon in …
WojciechGrancow Aug 27, 2023
a4d0aa2
add method for course service
WojciechGrancow Sep 6, 2023
47c8b9b
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 7, 2023
a4bd6e0
add service for courseGroup
WojciechGrancow Sep 7, 2023
87d4c2b
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 8, 2023
72515d5
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 11, 2023
6b320ce
tests for services
WojciechGrancow Sep 11, 2023
9a13d4e
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 11, 2023
07cd9d2
small changes
WojciechGrancow Sep 12, 2023
f5e62e2
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 12, 2023
8ce31fe
change lesson into lesoonEntity in one test
WojciechGrancow Sep 12, 2023
b38facb
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 12, 2023
8d46269
add method to course and courseGroup entity
WojciechGrancow Sep 13, 2023
c357481
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 13, 2023
87d7d74
fixes after review
WojciechGrancow Sep 14, 2023
96e3fad
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 14, 2023
e83413e
fix tests in courseGroup entity
WojciechGrancow Sep 14, 2023
1fa2f6d
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 18, 2023
83e1f76
changes in testcases after review
WojciechGrancow Sep 18, 2023
d997841
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 19, 2023
acf1de9
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 19, 2023
738f7d9
Merge branch 'BC-4572-rewrite-courses-to-nest' of https://github.com/…
WojciechGrancow Sep 19, 2023
fcda3c5
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 19, 2023
b4fc890
Merge branch 'main' into BC-4572-rewrite-courses-to-nest
WojciechGrancow Sep 20, 2023
828175f
merge with main
WojciechGrancow Sep 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/server/src/modules/copy-helper/mapper/copy.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EntityId, Lesson, Task } from '@shared/domain';
import { EntityId, LessonEntity, Task } from '@shared/domain';
import { LessonCopyApiParams } from '@src/modules/learnroom/controller/dto/lesson/lesson-copy.params';
import { LessonCopyParentParams } from '@src/modules/lesson/types';
import { TaskCopyApiParams } from '@src/modules/task/controller/dto/task-copy.params';
Expand All @@ -15,7 +15,7 @@ export class CopyMapper {
});

if (copyStatus.copyEntity) {
const copyEntity = copyStatus.copyEntity as Lesson | Task;
const copyEntity = copyStatus.copyEntity as LessonEntity | Task;
dto.id = copyEntity.id;
dto.destinationCourseId = copyEntity.course?.id;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Lesson, Submission, Task } from '@shared/domain';
import { LessonEntity, Submission, Task } from '@shared/domain';

export type EntitiesWithFiles = Task | Lesson | Submission;
export type EntityWithEmbeddedFiles = Task | Lesson;
export type EntitiesWithFiles = Task | LessonEntity | Submission;
export type EntityWithEmbeddedFiles = Task | LessonEntity;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Lesson, Submission, Task } from '@shared/domain';
import { LessonEntity, Submission, Task } from '@shared/domain';
import { FileRecordParentType } from '@shared/infra/rabbitmq';
import { CopyFileDto, FileDto } from '../dto';
import { EntitiesWithFiles, ICopyFileDomainObjectProps, IFileDomainObjectProps } from '../interfaces';
Expand Down Expand Up @@ -60,7 +60,7 @@ export class FilesStorageClientMapper {
}

static mapEntityToParentType(entity: EntitiesWithFiles): FileRecordParentType {
if (entity instanceof Lesson) return FileRecordParentType.Lesson;
if (entity instanceof LessonEntity) return FileRecordParentType.Lesson;

if (entity instanceof Task) return FileRecordParentType.Task;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
Course,
isLesson,
isTask,
Lesson,
LessonEntity,
LessonBoardElement,
Task,
TaskBoardElement,
Expand Down Expand Up @@ -92,7 +92,7 @@ export class BoardCopyService {
return statuses;
}

private async copyLesson(originalLesson: Lesson, user: User, destinationCourse: Course): Promise<CopyStatus> {
private async copyLesson(originalLesson: LessonEntity, user: User, destinationCourse: Course): Promise<CopyStatus> {
return this.lessonCopyService.copyLesson({
originalLessonId: originalLesson.id,
user,
Expand All @@ -115,7 +115,7 @@ export class BoardCopyService {
const taskElement = new TaskBoardElement({ target: status.copyEntity });
references.push(taskElement);
}
if (status.copyEntity instanceof Lesson) {
if (status.copyEntity instanceof LessonEntity) {
const lessonElement = new LessonBoardElement({ target: status.copyEntity });
references.push(lessonElement);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { ComponentType, Course, IComponentProperties, IComponentTextProperties, Lesson, Task } from '@shared/domain';
import {
ComponentType,
Course,
IComponentProperties,
IComponentTextProperties,
LessonEntity,
Task,
} from '@shared/domain';
import { courseFactory, lessonFactory, setupEntities, taskFactory } from '@shared/testing';
import { CommonCartridgeExportService } from '@src/modules/learnroom/service/common-cartridge-export.service';
import { CourseService } from '@src/modules/learnroom/service/course.service';
Expand All @@ -17,7 +24,7 @@ describe('CommonCartridgeExportService', () => {
let taskServiceMock: DeepMocked<TaskService>;

let course: Course;
let lessons: Lesson[];
let lessons: LessonEntity[];
let tasks: Task[];

beforeAll(async () => {
Expand Down
43 changes: 40 additions & 3 deletions apps/server/src/modules/learnroom/service/course.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { Course } from '@shared/domain';
import { CourseRepo } from '@shared/repo';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { CourseRepo, UserRepo } from '@shared/repo';
import { courseFactory, setupEntities, userFactory } from '@shared/testing';
import { CourseService } from './course.service';

describe('CourseService', () => {
let module: TestingModule;
let courseRepo: DeepMocked<CourseRepo>;
let courseService: CourseService;
let userRepo: DeepMocked<UserRepo>;

beforeAll(async () => {
await setupEntities();
module = await Test.createTestingModule({
providers: [
CourseService,
{
provide: UserRepo,
useValue: createMock<UserRepo>(),
},
{
provide: CourseRepo,
useValue: createMock<CourseRepo>(),
Expand All @@ -21,14 +28,15 @@ describe('CourseService', () => {
}).compile();
courseRepo = module.get(CourseRepo);
courseService = module.get(CourseService);
userRepo = module.get(UserRepo);
});

afterAll(async () => {
await module.close();
});

beforeEach(() => {
courseRepo.findById.mockClear();
jest.clearAllMocks();
});

describe('findById', () => {
Expand All @@ -41,4 +49,33 @@ describe('CourseService', () => {
expect(courseRepo.findById).toBeCalledWith(courseId);
});
});

describe('when deleting by userId', () => {
const setup = () => {
const user = userFactory.buildWithId();
const course1 = courseFactory.buildWithId({ students: [user] });
const course2 = courseFactory.buildWithId({ teachers: [user] });
const course3 = courseFactory.buildWithId({ substitutionTeachers: [user] });
const allCourses = [course1, course2, course3];

userRepo.findById.mockResolvedValue(user);
courseRepo.findAllByUserId.mockResolvedValue([allCourses, allCourses.length]);

return {
user,
};
};

it('should call courseRepo.findAllByUserId', async () => {
const { user } = setup();
await courseService.deleteUserDataFromCourse(user.id);
expect(courseRepo.findAllByUserId).toBeCalledWith(user.id);
});

it('should update courses without deleted user', async () => {
const { user } = setup();
const result = await courseService.deleteUserDataFromCourse(user.id);
expect(result).toEqual(3);
});
});
});
18 changes: 18 additions & 0 deletions apps/server/src/modules/learnroom/service/course.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,22 @@ export class CourseService {
async findById(courseId: EntityId): Promise<Course> {
return this.repo.findById(courseId);
}

public async deleteUserDataFromCourse(userId: EntityId): Promise<number> {
const [courses, count] = await this.repo.findAllByUserId(userId);

const updatedCourses = courses.map(
(course: Course) =>
({
...course,
students: course.students.remove((u) => u.id === userId),
teachers: course.teachers.remove((u) => u.id === userId),
substitutionTeachers: course.substitutionTeachers.remove((u) => u.id === userId),
WojciechGrancow marked this conversation as resolved.
Show resolved Hide resolved
} as unknown as Course)
);

await this.repo.save(updatedCourses);

return count;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { CourseGroupRepo, UserRepo } from '@shared/repo';
import { courseGroupFactory, setupEntities, userFactory } from '@shared/testing';
import { CourseGroupService } from './coursegroup.service';

describe('CourseGroupService', () => {
let module: TestingModule;
let courseGroupRepo: DeepMocked<CourseGroupRepo>;
let courseGroupService: CourseGroupService;
let userRepo: DeepMocked<UserRepo>;

beforeAll(async () => {
await setupEntities();
module = await Test.createTestingModule({
providers: [
CourseGroupService,
{
provide: UserRepo,
useValue: createMock<UserRepo>(),
},
{
provide: CourseGroupRepo,
useValue: createMock<CourseGroupRepo>(),
},
],
}).compile();
courseGroupRepo = module.get(CourseGroupRepo);
courseGroupService = module.get(CourseGroupService);
userRepo = module.get(UserRepo);
});

afterAll(async () => {
await module.close();
});

beforeEach(() => {
jest.clearAllMocks();
});

describe('when deleting by userId', () => {
const setup = () => {
const user = userFactory.buildWithId();
const courseGroup1 = courseGroupFactory.buildWithId({ students: [user] });
const courseGroup2 = courseGroupFactory.buildWithId({ students: [user] });

userRepo.findById.mockResolvedValue(user);
courseGroupRepo.findByUserId.mockResolvedValue([[courseGroup1, courseGroup2], 2]);

return {
user,
};
};

it('should call courseGroupRepo.findByUserId', async () => {
const { user } = setup();

await courseGroupService.deleteUserDataFromCourseGroup(user.id);

expect(courseGroupRepo.findByUserId).toBeCalledWith(user.id);
});

it('should update courses without deleted user', async () => {
const { user } = setup();

const result = await courseGroupService.deleteUserDataFromCourseGroup(user.id);

expect(result).toEqual(2);
});
});
});
24 changes: 24 additions & 0 deletions apps/server/src/modules/learnroom/service/coursegroup.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Injectable } from '@nestjs/common';
import { CourseGroup, EntityId } from '@shared/domain';
import { CourseGroupRepo } from '@shared/repo';

@Injectable()
export class CourseGroupService {
constructor(private readonly repo: CourseGroupRepo) {}

public async deleteUserDataFromCourseGroup(userId: EntityId): Promise<number> {
const [courseGroups, count] = await this.repo.findByUserId(userId);

const updatedCourseGroups = courseGroups.map(
(courseGroup: CourseGroup) =>
({
...courseGroup,
students: courseGroup.students.remove((u) => u.id === userId),
WojciechGrancow marked this conversation as resolved.
Show resolved Hide resolved
} as unknown as CourseGroup)
);

await this.repo.save(updatedCourseGroups);

return count;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Configuration } from '@hpi-schul-cloud/commons/lib';
import { IConfig } from '@hpi-schul-cloud/commons/lib/interfaces/IConfig';
import { Test, TestingModule } from '@nestjs/testing';
import { Board, Course, Lesson, Task, TaskWithStatusVo, User } from '@shared/domain';
import { Board, Course, LessonEntity, Task, TaskWithStatusVo, User } from '@shared/domain';
import {
boardFactory,
columnboardBoardElementFactory,
Expand Down Expand Up @@ -44,7 +44,7 @@ describe(RoomBoardDTOFactory.name, () => {
throw new Error('Please write a mock for RoomsAuthorisationService.hasTaskReadPermission');
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
hasLessonReadPermission(user: User, lesson: Lesson): boolean {
hasLessonReadPermission(user: User, lesson: LessonEntity): boolean {
throw new Error('Please write a mock for RoomsAuthorisationService.hasLessonReadPermission');
},
},
Expand Down Expand Up @@ -204,7 +204,7 @@ describe(RoomBoardDTOFactory.name, () => {
let substitutionTeacher: User;
let board: Board;
let room: Course;
let lessons: Lesson[];
let lessons: LessonEntity[];

beforeEach(() => {
teacher = userFactory.buildWithId();
Expand Down Expand Up @@ -243,7 +243,7 @@ describe(RoomBoardDTOFactory.name, () => {
let substitutionTeacher: User;
let board: Board;
let room: Course;
let lesson: Lesson;
let lesson: LessonEntity;
const inOneDay = new Date(Date.now() + 8.64e7);

beforeEach(() => {
Expand Down Expand Up @@ -325,7 +325,7 @@ describe(RoomBoardDTOFactory.name, () => {
let substitutionTeacher: User;
let board: Board;
let room: Course;
let lessons: Lesson[];
let lessons: LessonEntity[];

beforeEach(() => {
teacher = userFactory.buildWithId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ColumnBoardTarget,
Course,
ITaskStatus,
Lesson,
LessonEntity,
Permission,
Task,
TaskWithStatusVo,
Expand Down Expand Up @@ -73,7 +73,7 @@ class DtoCreator {
}

if (element.boardElementType === BoardElementType.Lesson) {
result = this.roomsAuthorisationService.hasLessonReadPermission(this.user, element.target as Lesson);
result = this.roomsAuthorisationService.hasLessonReadPermission(this.user, element.target as LessonEntity);
}

if (element instanceof ColumnboardBoardElement && this.isColumnBoardFeatureFlagActive()) {
Expand Down Expand Up @@ -139,7 +139,7 @@ class DtoCreator {

private mapLessonElement(element: BoardElement): RoomBoardElementDTO {
const type = RoomBoardElementTypes.LESSON;
const lesson = element.target as Lesson;
const lesson = element.target as LessonEntity;
const content: LessonMetaData = {
id: lesson.id,
name: lesson.name,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable, NotImplementedException } from '@nestjs/common';
import { Course, Lesson, Task, User } from '@shared/domain';
import { Course, LessonEntity, Task, User } from '@shared/domain';

export enum TaskParentPermission {
read,
Expand Down Expand Up @@ -42,7 +42,7 @@ export class RoomsAuthorisationService {
return hasPermission;
}

hasLessonReadPermission(user: User, lesson: Lesson): boolean {
hasLessonReadPermission(user: User, lesson: LessonEntity): boolean {
let hasCoursePermission = false;
hasCoursePermission = this.hasCourseReadPermission(user, lesson.course);
if (lesson.hidden) {
Expand Down
Loading