mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 18:29:15 +03:00
fix: remove course files from drive after deleting user or category
This commit is contained in:
parent
30fb10b338
commit
7149a0f3eb
28
app/Helpers/CourseHelper.ts
Normal file
28
app/Helpers/CourseHelper.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import Course from 'App/Models/Course';
|
||||||
|
|
||||||
|
export type FileEntry = {
|
||||||
|
path: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class CourseHelper {
|
||||||
|
public static getVideoFileNames(course: Course): Array<FileEntry | null> {
|
||||||
|
const data = course.lessons.map(l => {
|
||||||
|
if (!l.video) return null;
|
||||||
|
return { path: 'videos/', name: l.video.name };
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getMaterialFileNames(course: Course): FileEntry[] {
|
||||||
|
const data = course.lessons.map(l => l.materials.map(m => ({ path: 'materials/', name: m.name }))).flat();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getImageFileName(course: Course): FileEntry | null {
|
||||||
|
if (!course.image) return null;
|
||||||
|
const data = { path: 'images/courses/', name: course.image.name };
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,6 +32,32 @@ export default class CourseRepository {
|
|||||||
this.Course = Course;
|
this.Course = Course;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of courses by teacher id
|
||||||
|
*
|
||||||
|
* @param id Teacher id
|
||||||
|
* @returns Array of courses
|
||||||
|
*/
|
||||||
|
public async getByTeacherId(id: string | number): Promise<Course[]> {
|
||||||
|
const data = await this.Course.query()
|
||||||
|
.preload('lessons', q => q.preload('video').preload('materials'))
|
||||||
|
.where('teacher_id', id);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of courses by category id
|
||||||
|
*
|
||||||
|
* @param id Category id
|
||||||
|
* @returns Array of courses
|
||||||
|
*/
|
||||||
|
public async getByCategoryId(id: string | number): Promise<Course[]> {
|
||||||
|
const data = await this.Course.query()
|
||||||
|
.preload('lessons', q => q.preload('video').preload('materials'))
|
||||||
|
.where('category_id', id);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set status on course
|
* Set status on course
|
||||||
*
|
*
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import HttpStatusEnum from 'App/Datatypes/Enums/HttpStatusEnum';
|
|||||||
* Repositories
|
* Repositories
|
||||||
*/
|
*/
|
||||||
import CategoryRepository from 'App/Repositories/CategoryRepository';
|
import CategoryRepository from 'App/Repositories/CategoryRepository';
|
||||||
|
import CourseRepository from 'App/Repositories/CourseRepository';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validators
|
* Validators
|
||||||
@ -17,12 +18,27 @@ import CategoryRepository from 'App/Repositories/CategoryRepository';
|
|||||||
import CreateCategoryValidator from 'App/Validators/Category/CreateCategoryValidator';
|
import CreateCategoryValidator from 'App/Validators/Category/CreateCategoryValidator';
|
||||||
import UpdateCategoryValidator from 'App/Validators/Category/UpdateCategoryValidator';
|
import UpdateCategoryValidator from 'App/Validators/Category/UpdateCategoryValidator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services
|
||||||
|
*/
|
||||||
|
import CourseService from 'App/Services/CourseService';
|
||||||
|
|
||||||
@inject()
|
@inject()
|
||||||
export default class CategoryService {
|
export default class CategoryService {
|
||||||
private categoryRepository: CategoryRepository;
|
private categoryRepository: CategoryRepository;
|
||||||
|
|
||||||
constructor(categoryRepository: CategoryRepository) {
|
private courseRepository: CourseRepository;
|
||||||
|
|
||||||
|
private courseService: CourseService;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
categoryRepository: CategoryRepository,
|
||||||
|
courseRepository: CourseRepository,
|
||||||
|
courseService: CourseService
|
||||||
|
) {
|
||||||
this.categoryRepository = categoryRepository;
|
this.categoryRepository = categoryRepository;
|
||||||
|
this.courseRepository = courseRepository;
|
||||||
|
this.courseService = courseService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,7 +110,7 @@ export default class CategoryService {
|
|||||||
* @returns Deleted category
|
* @returns Deleted category
|
||||||
*/
|
*/
|
||||||
public async deleteCategory(id: string | number): Promise<IResponse> {
|
public async deleteCategory(id: string | number): Promise<IResponse> {
|
||||||
const data = await this.categoryRepository.delete(id);
|
const data = await this.categoryRepository.getById(id);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return {
|
return {
|
||||||
@ -108,6 +124,10 @@ export default class CategoryService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const courses = await this.courseRepository.getByCategoryId(id);
|
||||||
|
await this.courseService.deleteAllFiles(courses);
|
||||||
|
await this.categoryRepository.delete(id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
status: HttpStatusEnum.OK,
|
status: HttpStatusEnum.OK,
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
|||||||
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
|
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
|
||||||
import Course from 'App/Models/Course';
|
import Course from 'App/Models/Course';
|
||||||
import Drive from '@ioc:Adonis/Core/Drive';
|
import Drive from '@ioc:Adonis/Core/Drive';
|
||||||
|
import CourseHelper, { FileEntry } from 'App/Helpers/CourseHelper';
|
||||||
|
|
||||||
@inject()
|
@inject()
|
||||||
export default class CourseService {
|
export default class CourseService {
|
||||||
@ -720,6 +721,32 @@ export default class CourseService {
|
|||||||
data: { count },
|
data: { count },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function will delete all associated course files on disk
|
||||||
|
*
|
||||||
|
* @param courses List of courses
|
||||||
|
*/
|
||||||
|
public async deleteAllFiles(courses: Course[]): Promise<void> {
|
||||||
|
/**
|
||||||
|
* Collect file names
|
||||||
|
*/
|
||||||
|
const images = courses.map(course => CourseHelper.getImageFileName(course)).filter(Boolean) as FileEntry[];
|
||||||
|
const videos = courses
|
||||||
|
.map(course => CourseHelper.getVideoFileNames(course))
|
||||||
|
.flat()
|
||||||
|
.filter(Boolean) as FileEntry[];
|
||||||
|
const materials = courses.map(course => CourseHelper.getMaterialFileNames(course)).flat();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove files from disk
|
||||||
|
*/
|
||||||
|
const promises = videos
|
||||||
|
.concat(images, materials)
|
||||||
|
.map(file => Drive.delete(`${file.path}${file.name.substring(file.name.lastIndexOf('/') + 1)}`));
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new Ioc().make(CourseService);
|
new Ioc().make(CourseService);
|
||||||
|
|||||||
@ -22,22 +22,48 @@ import Role from 'App/Models/Role';
|
|||||||
import RoleRepository from 'App/Repositories/RoleRepository';
|
import RoleRepository from 'App/Repositories/RoleRepository';
|
||||||
import UserRepository from 'App/Repositories/UserRepository';
|
import UserRepository from 'App/Repositories/UserRepository';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services
|
||||||
|
*/
|
||||||
|
import CourseService from './CourseService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validators
|
* Validators
|
||||||
*/
|
*/
|
||||||
import CreateUserValidator from 'App/Validators/User/CreateUserValidator';
|
import CreateUserValidator from 'App/Validators/User/CreateUserValidator';
|
||||||
import UpdateUserValidator from 'App/Validators/User/UpdateUserValidator';
|
import UpdateUserValidator from 'App/Validators/User/UpdateUserValidator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datatypes
|
||||||
|
*/
|
||||||
import RoleEnum from 'App/Datatypes/Enums/RoleEnum';
|
import RoleEnum from 'App/Datatypes/Enums/RoleEnum';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers
|
||||||
|
*/
|
||||||
|
import RoleHelper from 'App/Helpers/RoleHelper';
|
||||||
|
import CourseRepository from 'App/Repositories/CourseRepository';
|
||||||
|
|
||||||
@inject()
|
@inject()
|
||||||
export default class UserService {
|
export default class UserService {
|
||||||
private userRepository: UserRepository;
|
private userRepository: UserRepository;
|
||||||
|
|
||||||
private roleRepository: RoleRepository;
|
private roleRepository: RoleRepository;
|
||||||
|
|
||||||
constructor(userRepository: UserRepository, roleRepository: RoleRepository) {
|
private courseRepository: CourseRepository;
|
||||||
|
|
||||||
|
private courseService: CourseService;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
userRepository: UserRepository,
|
||||||
|
roleRepository: RoleRepository,
|
||||||
|
courseRepository: CourseRepository,
|
||||||
|
courseService: CourseService
|
||||||
|
) {
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.roleRepository = roleRepository;
|
this.roleRepository = roleRepository;
|
||||||
|
this.courseRepository = courseRepository;
|
||||||
|
this.courseService = courseService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -213,6 +239,12 @@ export default class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await ctx.bouncer.with('RolePolicy').authorize('manage', user.roles.map(r => r.slug) as [RoleEnum]);
|
await ctx.bouncer.with('RolePolicy').authorize('manage', user.roles.map(r => r.slug) as [RoleEnum]);
|
||||||
|
|
||||||
|
if (RoleHelper.userContainRoles(user.roles, [RoleEnum.TEACHER, RoleEnum.ADMIN])) {
|
||||||
|
const courses = await this.courseRepository.getByTeacherId(id);
|
||||||
|
await this.courseService.deleteAllFiles(courses);
|
||||||
|
}
|
||||||
|
|
||||||
await this.userRepository.delete(id);
|
await this.userRepository.delete(id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user