mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 10:19:20 +03:00
added students to course
This commit is contained in:
parent
a96ad1e7b5
commit
a9715971e4
@ -2,7 +2,9 @@ import { Exception } from '@adonisjs/core/build/standalone';
|
|||||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
import Course from 'App/Models/Course';
|
import Course from 'App/Models/Course';
|
||||||
import User from 'App/Models/User';
|
import User from 'App/Models/User';
|
||||||
|
import AddCourseToUserValidator from 'App/Validators/AddCourseToUserValidator';
|
||||||
import CreateCourseValidator from 'App/Validators/CreateCourseValidator';
|
import CreateCourseValidator from 'App/Validators/CreateCourseValidator';
|
||||||
|
import DelCourseFromUserValidator from 'App/Validators/DelCourseFromUserValidator';
|
||||||
import UpdateCourseValidator from 'App/Validators/UpdateCourseValidator';
|
import UpdateCourseValidator from 'App/Validators/UpdateCourseValidator';
|
||||||
|
|
||||||
export default class CoursesController {
|
export default class CoursesController {
|
||||||
@ -95,8 +97,16 @@ export default class CoursesController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Students of Course with "id"
|
* Show Students of Course with "id"
|
||||||
|
* GET /courses/:id/students
|
||||||
*/
|
*/
|
||||||
public async showStudents({ response, params }: HttpContextContract) {}
|
public async showStudents({ response, params }: HttpContextContract) {
|
||||||
|
const course = await this.Course.query().preload('students').where('id', params.id).firstOrFail();
|
||||||
|
|
||||||
|
return response.ok({
|
||||||
|
message: `Fetched students from course with id: "${course.id}"`,
|
||||||
|
data: course.students,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new Course in a system
|
* Create new Course in a system
|
||||||
@ -178,4 +188,58 @@ export default class CoursesController {
|
|||||||
data: course,
|
data: course,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach student to course
|
||||||
|
* POST /courses/:id/attach-student
|
||||||
|
*/
|
||||||
|
async attachStudent({ response, request, params }: HttpContextContract) {
|
||||||
|
try {
|
||||||
|
const payload = await request.validate(AddCourseToUserValidator);
|
||||||
|
const student = await this.User.findOrFail(payload.student_id);
|
||||||
|
const course = await this.Course.findOrFail(params.id);
|
||||||
|
|
||||||
|
await course.load('students');
|
||||||
|
await student.load('roles');
|
||||||
|
|
||||||
|
const studentRoles = student.roles.map(r => r.slug);
|
||||||
|
|
||||||
|
if (!studentRoles.includes('student')) {
|
||||||
|
throw new Exception(`User cannot be attached to the course without "student" role.`, 400, 'E_USER_ROLE');
|
||||||
|
}
|
||||||
|
|
||||||
|
await course.related('students').attach([student.id]);
|
||||||
|
|
||||||
|
return response.ok({
|
||||||
|
message: 'Student attached',
|
||||||
|
data: 'SUCCESS',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.code === '23505')
|
||||||
|
throw new Exception('Student already attached to that course', 400, 'E_STUDENT_ATTACHED');
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detach student from course
|
||||||
|
*/
|
||||||
|
async detachStudent({ response, request, params }: HttpContextContract) {
|
||||||
|
const payload = await request.validate(DelCourseFromUserValidator);
|
||||||
|
const course = await this.Course.query().preload('students').where('id', params.id).firstOrFail();
|
||||||
|
const candidate = course.students.find(student => student.id === payload.student_id);
|
||||||
|
|
||||||
|
if (!candidate) {
|
||||||
|
throw new Exception('Student not attached to that course', 400, 'E_STUDENT_NOT_ATTACHED');
|
||||||
|
}
|
||||||
|
|
||||||
|
const student = await this.User.findOrFail(payload.student_id);
|
||||||
|
await course.related('students').detach([student.id]);
|
||||||
|
|
||||||
|
return response.ok({
|
||||||
|
message: 'Student detached',
|
||||||
|
data: 'SUCCESS',
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,7 +122,7 @@ export default class UsersController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach array of roles to user
|
* Attach array of roles to user
|
||||||
* POST /users/:id/attach_roles
|
* POST /users/:id/attach-roles
|
||||||
*/
|
*/
|
||||||
public async attachRoles({ request, response, params }: HttpContextContract) {
|
public async attachRoles({ request, response, params }: HttpContextContract) {
|
||||||
await request.validate(AddRoleToUserValidator);
|
await request.validate(AddRoleToUserValidator);
|
||||||
@ -141,7 +141,7 @@ export default class UsersController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach array of roles from user
|
* Detach array of roles from user
|
||||||
* DELETE /users/:id/detach_roles
|
* DELETE /users/:id/detach-roles
|
||||||
*/
|
*/
|
||||||
public async detachRoles({ request, response, params }: HttpContextContract) {
|
public async detachRoles({ request, response, params }: HttpContextContract) {
|
||||||
await request.validate(DelRoleFromUserValidator);
|
await request.validate(DelRoleFromUserValidator);
|
||||||
|
|||||||
@ -1,10 +1,20 @@
|
|||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { BaseModel, beforeCreate, BelongsTo, belongsTo, column, HasMany, hasMany } from '@ioc:Adonis/Lucid/Orm';
|
import {
|
||||||
import Category from './Category';
|
BaseModel,
|
||||||
import Lesson from './Lesson';
|
beforeCreate,
|
||||||
import User from './User';
|
BelongsTo,
|
||||||
|
belongsTo,
|
||||||
|
column,
|
||||||
|
HasMany,
|
||||||
|
hasMany,
|
||||||
|
ManyToMany,
|
||||||
|
manyToMany,
|
||||||
|
} from '@ioc:Adonis/Lucid/Orm';
|
||||||
|
import Category from 'App/Models/Category';
|
||||||
|
import Lesson from 'App/Models/Lesson';
|
||||||
|
import User from 'App/Models/User';
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
|
|
||||||
export default class Course extends BaseModel {
|
export default class Course extends BaseModel {
|
||||||
@ -38,6 +48,11 @@ export default class Course extends BaseModel {
|
|||||||
})
|
})
|
||||||
public lessons: HasMany<typeof Lesson>;
|
public lessons: HasMany<typeof Lesson>;
|
||||||
|
|
||||||
|
@manyToMany(() => User, {
|
||||||
|
pivotTable: 'users_courses',
|
||||||
|
})
|
||||||
|
public students: ManyToMany<typeof User>;
|
||||||
|
|
||||||
@column.dateTime({ autoCreate: true })
|
@column.dateTime({ autoCreate: true })
|
||||||
public createdAt: DateTime;
|
public createdAt: DateTime;
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import Hash from '@ioc:Adonis/Core/Hash';
|
|||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import Role from 'App/Models/Role';
|
import Role from 'App/Models/Role';
|
||||||
import Contact from 'App/Models/Contact';
|
import Contact from 'App/Models/Contact';
|
||||||
|
import Course from 'App/Models/Course';
|
||||||
|
|
||||||
export default class User extends BaseModel {
|
export default class User extends BaseModel {
|
||||||
@column({ isPrimary: true })
|
@column({ isPrimary: true })
|
||||||
@ -43,6 +44,11 @@ export default class User extends BaseModel {
|
|||||||
})
|
})
|
||||||
public roles: ManyToMany<typeof Role>;
|
public roles: ManyToMany<typeof Role>;
|
||||||
|
|
||||||
|
@manyToMany(() => Course, {
|
||||||
|
pivotTable: 'users_courses',
|
||||||
|
})
|
||||||
|
public courses: ManyToMany<typeof Course>;
|
||||||
|
|
||||||
@column.dateTime({ autoCreate: true, serializeAs: null })
|
@column.dateTime({ autoCreate: true, serializeAs: null })
|
||||||
public createdAt: DateTime;
|
public createdAt: DateTime;
|
||||||
|
|
||||||
|
|||||||
12
app/Validators/AddCourseToUserValidator.ts
Normal file
12
app/Validators/AddCourseToUserValidator.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { schema, rules } from '@ioc:Adonis/Core/Validator';
|
||||||
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
|
||||||
|
export default class AddCourseToUserValidator {
|
||||||
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
|
public schema = schema.create({
|
||||||
|
student_id: schema.string({}, [rules.exists({ table: 'users', column: 'id' })]),
|
||||||
|
});
|
||||||
|
|
||||||
|
public messages = {};
|
||||||
|
}
|
||||||
12
app/Validators/DelCourseFromUserValidator.ts
Normal file
12
app/Validators/DelCourseFromUserValidator.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { schema, rules } from '@ioc:Adonis/Core/Validator';
|
||||||
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
|
||||||
|
export default class DelCourseFromUserValidator {
|
||||||
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
|
public schema = schema.create({
|
||||||
|
student_id: schema.string({}, [rules.exists({ table: 'users', column: 'id' })]),
|
||||||
|
});
|
||||||
|
|
||||||
|
public messages = {};
|
||||||
|
}
|
||||||
18
database/migrations/1627750162275_users_courses.ts
Normal file
18
database/migrations/1627750162275_users_courses.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import BaseSchema from '@ioc:Adonis/Lucid/Schema';
|
||||||
|
|
||||||
|
export default class UsersCourses extends BaseSchema {
|
||||||
|
protected tableName = 'users_courses';
|
||||||
|
|
||||||
|
public async up() {
|
||||||
|
this.schema.createTable(this.tableName, table => {
|
||||||
|
table.increments('id');
|
||||||
|
table.string('user_id', 21).unsigned().references('users.id').onDelete('CASCADE');
|
||||||
|
table.string('course_id', 21).unsigned().references('courses.id').onDelete('CASCADE');
|
||||||
|
table.unique(['user_id', 'course_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down() {
|
||||||
|
this.schema.dropTable(this.tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -72,9 +72,17 @@ Route.group(() => {
|
|||||||
.middleware('role:admin,teacher,student')
|
.middleware('role:admin,teacher,student')
|
||||||
.as('showCourseLessons');
|
.as('showCourseLessons');
|
||||||
|
|
||||||
Route.get('courses/:id/students', 'CourseController.showStudents')
|
Route.get('courses/:id/students', 'CoursesController.showStudents')
|
||||||
.middleware('role:admin,teacher,student')
|
.middleware('role:admin,teacher,student')
|
||||||
.as('showCourseStudents');
|
.as('showCourseStudents');
|
||||||
|
|
||||||
|
Route.post('courses/:id/attach-student', 'CoursesController.attachStudent')
|
||||||
|
.middleware('role:admin,teacher')
|
||||||
|
.as('attachUserCourse');
|
||||||
|
|
||||||
|
Route.delete('courses/:id/detach-student', 'CoursesController.detachStudent')
|
||||||
|
.middleware('role:admin,teacher')
|
||||||
|
.as('detachUserCourse');
|
||||||
}).middleware('auth');
|
}).middleware('auth');
|
||||||
})
|
})
|
||||||
.prefix('/api/v1')
|
.prefix('/api/v1')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user