Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 37 additions & 5 deletions src/api/middlewares/is-auth.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
//require("dotenv").config();
const jwt = require("jsonwebtoken");
const Professor = require("../../models/professor");
const Student = require('../../models/student');
const log = require('debug')('is-auth');
const logVerifyToken = log.extend('verifyToken');
const logVerifyStudent = log.extend('verifyStudent');

exports.verifyToken=(req,res,next)=>{

let query = req.header('authorization').split(' ');

let token = query[1]; //Authenticate

//The exception thrown by the split method is handled sending a meessage to client
let token;
try {
let query = req.header('authorization').split(' ');
token = query[1]; //Authenticate
}catch(err) {
logVerifyToken(err);
return res.status(503).json({
ok: false,
err
});
}
jwt.verify(token,process.env.JWT_SECRET,(error,decoded)=>{
//decoded is the payload
logVerifyToken(error);
if(error){
return res.status(500).json({
ok:false,
Expand Down Expand Up @@ -37,4 +49,24 @@ exports.verifyProfesssor = async (req,res,next) => {
error:'El usuario no es profesor'
});
}
}

exports.verifyStudent = async (req, res, next) => {
let id=req.id;
try {
const student= await Student.findOne({
where:{
userId:id
}
});
logVerifyStudent(`Student row: ${student}`)
next();
} catch(error){
logVerifyStudent(`Error: ${error}`)
return res.status(500).json({
ok:false,
message: 'User is not a student',
error
});
}
}
9 changes: 9 additions & 0 deletions src/api/routes/enrollment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const { Router } = require('express');
const auth = require('../middlewares/is-auth');
const EnrollmentController = require("../../controllers/enrollmentController");

const router = Router();

router.get('/', [auth.verifyToken, auth.verifyStudent],EnrollmentController.enrollStudentInACourse);

module.exports = router;
1 change: 1 addition & 0 deletions src/api/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = function(app) {
{ path: "/answer", file: "./answers" },
{ path: "/question", file: "./questions" },
{ path: "/exam", file: "./exams" },
{ path: "/enrollment", file: './enrollment'}
];

routes.forEach(route => {
Expand Down
35 changes: 35 additions & 0 deletions src/controllers/enrollmentController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const LOG = require("debug")("error:data");
const Enrollment = require('../models/enrollment');

class EnrollmentController {


static async enrollStudentInACourse(req, res, next) {
LOG(`StudentId: ${req.query.studentId}`);
LOG(`courseId: ${req.query.courseId}`);
const studentId = req.query.studentId;
const courseId = req.query.courseId;

try {
const enrollment = await Enrollment.create({
studentId,
courseId,
calification: 85
});
return res.status(201).json({
ok: true,
message: `You have enrolled to course with id ${courseId}`,
});
}catch(err) {
e(err);
return res.status(400).json({
ok: false,
message: `Something wrong happen enrolling in a course`,
err
});
}

}
}

module.exports = EnrollmentController;
18 changes: 12 additions & 6 deletions src/models/enrollment.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
const Sequelize = require("sequelize");
const {sequelize} = require("../../config/db/mysql");
const { Student } = require("./student");
const Course = require("./course");

const Enrollment = sequelize.define('enrollments',
{
{
studentId: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: 'students', key: 'id' }
},
courseId: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: 'courses', key: 'id' }
},
calification: {
type: Sequelize.DOUBLE,
allowNull: false
Expand All @@ -13,9 +21,7 @@ const Enrollment = sequelize.define('enrollments',
{ timestamps: false }
);


Enrollment.belongsTo(Course);
Enrollment.belongsTo(Student);
Enrollment.removeAttribute('id');//Remove the default field named 'id'

module.exports = Enrollment

17 changes: 13 additions & 4 deletions src/models/student.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const Sequelize = require("sequelize");
const { sequelize } = require("../../config/db/mysql");
const Course = require("./course");

const Student = sequelize.define("students", {
id: {
Expand All @@ -9,6 +8,19 @@ const Student = sequelize.define("students", {
primaryKey: true,
autoIncrement:true
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: 'users', key: 'id' }
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
},
deletedAt: {
type: Sequelize.DATE,
allowNull: true,
Expand All @@ -17,7 +29,4 @@ const Student = sequelize.define("students", {
paranoid:true
});


Student.hasMany(Course);

module.exports = Student;
2 changes: 1 addition & 1 deletion src/services/studentService.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class StudentService {
} catch (err) {

e(err);
return new Error('An error has ocurred');
return new Error(err);
}

}
Expand Down
116 changes: 116 additions & 0 deletions tests/rest/enrollment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
const chai = require("chai");
const chaiHttp = require("chai-http");
const { expect } = require("chai");

const app = require("../../src/index");
const { generateValidToken } = require("../../src/services/generateToken");
const StudentService = require('../../src/services/studentService');
const User = require("../../src/models/user");
const Student = require('../../src/models/student');
const Enrollment = require('../../src/models/enrollment');
const { sequelize } = require("../../config/db/mysql");
const log = require('debug')('enrollmenTest');
const logCleanTables = log.extend('cleanTables');
const server = require('../../src/index');


//1. Para que un estudiante pueda enrolarse al curso este debe existir y haber iniciado sesión
//2. Un estudiante no puede enrolarse al mismo curso más de 1 vez
//3. Un estudiante tendrá accesos al curso cuando el profesor lo haya autorizado
//4. Un estudiante NO puede desenrolarse de un curso
//5. Un profesor puede desenrolar de un curso a un estudiante
//6. Solo los estudiantes pueden visualizar los cursos?

chai.use(chaiHttp);
describe('Enrollment Tests', () => {
describe('A student can enroll to a course', () => {
const existentCourseId = 5;
let student, token;
before(async function(){
student = await StudentService.createStudent({firstname: 'Rigoberto', lastname: 'Pérez', email: 'ed2@gmail.com', password: 'cisco123'});
token = generateValidToken(student);
});

it.only('should return true if the course exists', (done) => {
chai.request(app)
.get("/api/v1/enrollment")
.query({studentId: student.id, courseId: existentCourseId})
.set( 'Authorization', `Bearer ${token}` )
.end(function(err, res) {
if (err) done(err);
expect(res).to.have.property('ok', true);
expect(res).to.have.status(201);

done();
});
});

after(function(){
const starterPromise = Promise.resolve();
const asyncThingsToDo = [
'DELETE_ENROLLMENT_ROWS',
'DELETE_STUDENT_ROWS',
'DELETE_USER_ROWS',
'ALTER_AUTOINCREMENT_STUDENT',
'ALTER_AUTOINCREMENT_USER',
'CLOSE_DB_CONNECTION',
'CLOSE_SERVER_CONNECTION'
];


asyncThingsToDo.reduce(async (previous, task) => {
try {
const log = await previous;
logCleanTables(log);
} catch(err) {
logCleanTables(err)
}
return cleanTables(task);
},starterPromise);

});

function cleanTables(task) {
switch(task) {
case 'DELETE_ENROLLMENT_ROWS':
logCleanTables('Inside DELETE_ENROLLMENT_ROWS');
return Enrollment.destroy({
where: {
studentId: student.id,
courseId: existentCourseId
},
force: true
}).then(num => `Enrollment rows deleted ${num}`);
case 'DELETE_STUDENT_ROWS':
logCleanTables('Inside DELETE_STUDENT_ROWS');
return Student.destroy({
where: {
id: student.id
},
force: true
}).then(num => `Student rows deleted ${num}`);
case 'DELETE_USER_ROWS':
logCleanTables('Inside DELETE_USER_ROWS');
return User.destroy({
where: {
id: student.userId
},
force: true
}).then(num => `User rows deleted ${num}`);
case 'ALTER_AUTOINCREMENT_STUDENT':
logCleanTables('Inside ALTER_AUTOINCREMENT_STUDENT');
return sequelize.query(`ALTER TABLE students AUTO_INCREMENT ${student.id}`)
//.then(result => result);
case 'ALTER_AUTOINCREMENT_USER':
logCleanTables('Inside ALTER_AUTOINCREMENT_USER');
return sequelize.query(`ALTER TABLE users AUTO_INCREMENT ${student.userId}`)
//.then(result => result);
case 'CLOSE_DB_CONNECTION':
return sequelize.close();
case 'CLOSE_SERVER_CONNECTION':
return server.close();
}
}
});
});