Skip to content

Commit

Permalink
Merge pull request #49 from SAIG-KMITL/feat/chapter-module-service
Browse files Browse the repository at this point in the history
Implement comprehensive features for course, exam, chat, and user management
  • Loading branch information
Dangkeys authored Nov 27, 2024
2 parents 2c151c2 + 176c0f2 commit c268790
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/chapter/chapter.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { Folder } from 'src/file/enums/folder.enum';
import { FileInterceptor } from '@nestjs/platform-express';
import { EnrollmentService } from 'src/enrollment/enrollment.service';
import { Public } from 'src/shared/decorators/public.decorator';
import { VideoGuard } from './guards/video.guard';

@Controller('chapter')
@ApiTags('Chapters')
Expand All @@ -57,21 +58,27 @@ export class ChapterController {
private readonly chapterService: ChapterService,
private readonly courseModuleService: CourseModuleService,
private readonly fileService: FileService,
private readonly enrollmentService: EnrollmentService,
) { }

@Get(':id/video')
@ApiParam({
name: 'id',
type: String,
description: 'Course id',
description: 'chapter id',
})
@Public()
@ApiResponse({
status: HttpStatus.OK,
description: 'Get chapter video',
type: StreamableFile,
})
@ApiQuery({
name: 'token',
type: String,
required: false,
description: 'Access token',
})
@UseGuards(VideoGuard)
async getVideo(
@Param(
'id',
Expand Down
76 changes: 76 additions & 0 deletions src/chapter/guards/video.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
NotFoundException,
ForbiddenException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { JwtPayloadDto } from 'src/auth/dtos/jwt-payload.dto';
import { ConfigService } from '@nestjs/config';
import { GLOBAL_CONFIG } from 'src/shared/constants/global-config.constant';
import { AuthenticatedRequest } from 'src/auth/interfaces/authenticated-request.interface';
import { EnrollmentService } from 'src/enrollment/enrollment.service';
import { Role } from 'src/shared/enums';
import { InjectRepository } from '@nestjs/typeorm';
import { Chapter } from '../chapter.entity';
import { Repository } from 'typeorm';

@Injectable()
export class VideoGuard implements CanActivate {
constructor(
@InjectRepository(Chapter)
private readonly chapterRepository: Repository<Chapter>,
private readonly jwtService: JwtService,
private readonly configService: ConfigService,
private readonly enrollmentService: EnrollmentService,
) {}

async canActivate(context: ExecutionContext): Promise<boolean> {
const request: AuthenticatedRequest = context.switchToHttp().getRequest();
const chapterId = request.params.id;
const chapter = await this.chapterRepository.findOne({
where: { id: chapterId },
relations: {
module: {
course: {
teacher: true,
},
},
}
});
if (!chapter) throw new NotFoundException('Chapter not found');
if (chapter.isPreview) return true;
const token = request.query.token as string;
if (!token) throw new UnauthorizedException('Unauthorized access');
try {
request.user = await this.jwtService.verifyAsync<JwtPayloadDto>(token, {
secret: this.configService.getOrThrow<string>(
GLOBAL_CONFIG.JWT_ACCESS_SECRET,
),
});
} catch (error) {
throw new UnauthorizedException('Unauthorized access');
}
const userId = request.user.id;
const courseId = chapter.module.course.id;
switch (request.user.role) {
case Role.TEACHER:
if (chapter.module.course.teacher.id !== userId)
throw new ForbiddenException('Insufficient permissions');
break;
case Role.STUDENT:
const enrollment = await this.enrollmentService.findOne({
course: { id: courseId },
user: { id: userId },
});
if (!enrollment)
throw new ForbiddenException('Insufficient permissions');
break;
default:
throw new ForbiddenException('Insufficient permissions');
}
return true;
}
}

0 comments on commit c268790

Please sign in to comment.