license handling in set working

parent 6c3b3172
......@@ -96,53 +96,10 @@ module.exports = {
if (!params.number)
return res.badRequest();
// Check license
License.findOne({ number: params.number })
.then((l) => {
if (!l)
return res.badRequest("Invalid license");
if (l.activation_ts)
return res.badRequest("The license is already active");
// License ok, check student
Student.findOne(params.id_stu)
.then((s) => {
if (!s)
return res.badRequest("Student not found");
// Check if the student has a previous license
License.findOne({ student: s.id})
.then((l_old) => {
var left = 0;
if (l_old) {
// He had a license, if not expired, get remaining time
left = l_old.expiration_ts - new Date();
left = left < 0 ? 0 : left;
License.destroy({id: l_old.id}).exec((err) => {
if (err) throw err;
});
}
// Compute parameters for license to activate
var now = new Date();
l.student = s.id;
l.activation_ts = now;
l.expiration_ts = new Date(new Date(now.getFullYear(), now.getMonth()+l.duration, now.getDate()+1).getTime() + left);
l.save((err) => {
if (err)
return res.serverError(err);
delete l.student;
delete l.id;
return res.ok(l);
});
});
})
.catch((err) => {
return res.serverError(err);
});
})
.catch(() => {
return res.serverError();
License.activate(req.license, req.body.id_stu, function(err, license) {
if (err)
return res.badRequest(err);
return res.ok(license);
});
}
};
......@@ -49,10 +49,12 @@ module.exports = {
Student.findOne({
username: req.body.username
})
.populate('license')
.then(function (student) {
if (student) {
if (bcrypt.compareSync(req.body.password, student.password)) {
student.isStudent = true;
student.license = student.license[0];
res.ok({
user: student,
token: sailsTokenAuth.issueToken(student, sails.config.jwt.expiresInMinutes),
......@@ -100,7 +102,9 @@ module.exports = {
* }
*/
getInfo: function (req, res) {
Student.findOne({id: req.params.id_stu}).populate('lastInstruction')
Student.findOne({id: req.params.id_stu})
.populate('lastInstruction')
.populate('license')
.then(function (student) {
if (!student)
throw new Error("student not found");
......@@ -108,13 +112,6 @@ module.exports = {
student.current_method = student.lastInstruction[0] ? student.lastInstruction[0].met_name : "no_method";
student.current_instruction = student.lastInstruction[0] ? student.lastInstruction[0].ins_name : "no_instruction";
// recover last instruction to complete student info
var stu_last_inst = VStuLastInstruction.findOne({student: student.id})
.then(function (stu_last_inst) {
return stu_last_inst;
})
.error(err => {throw err});
// determine supervision level of the requester on the student
var stu_sup = StuSup.findOne({id_stu: student.id, id_sup: req.token.id})
.then(function (stu_sup) {
......@@ -122,13 +119,9 @@ module.exports = {
})
.error(err => {throw err});
return [student, stu_last_inst, stu_sup];
return [student, stu_sup];
})
.spread(function (student, stu_last_inst, stu_sup) {
if (stu_last_inst) {
student.current_method = stu_last_inst.met_name;
student.current_instruction = stu_last_inst.ins_name;
}
.spread(function (student, stu_sup) {
// requester has no relation
student.supervision = -1;
......@@ -207,17 +200,34 @@ module.exports = {
res.badRequest();
}
Student.findOne(req.params.id_stu).then(function(stu) {
Student.findOne(req.params.id_stu)
.populate('license')
.then(function(stu) {
var k;
if (!stu)
throw new Error("Student not found");
// Update license
if (req.body.license_number)
if (!stu.license[0] || req.body.license_number != stu.license[0].number) {
License.activate(req.body.license_number, stu.id, function(err, license) {
if (err)
return res.badRequest(err);
});
}
// copy attributes
for (k in req.body) stu[k] = req.body[k];
if (!req.body.password) // to avoid change password when no one is provided
delete stu.password;
// delete license attribute as this has been already handled
delete stu.license;
stu.save().then(function (saved) {
res.ok(stu);
res.ok(saved);
// Send websocket message
sails.hooks.events.broadcastEvent(
......
......@@ -47,6 +47,71 @@ module.exports = {
columnName: "number",
size: 16,
unique: true
},
toJSON: function () {
var l = this.toObject();
delete l.id;
return l;
}
},
/**
Class methods
*/
/**
Activates a license
@param {number} number License number
@param {ID} id_stu ID of the student the license is associated to
@param {function} callback Callback function with prototype: function(err, license)
*/
activate: function(number, id_stu, callback) {
// Check license
License.findOne({ number: number })
.then((l) => {
if (!l)
throw new Error("Invalid license");
if (l.activation_ts)
throw new Error("The license is already active");
// License ok, check student
Student.findOne(id_stu)
.then((s) => {
if (!s)
throw new Error("Student not found");
// Check if the student has a previous license
License.findOne({ student: s.id })
.then((l_old) => {
var left = 0;
if (l_old) {
// He had a license, if not expired, get remaining time
left = l_old.expiration_ts - new Date();
left = left < 0 ? 0 : left;
License.destroy({id: l_old.id}).exec((err) => {
if (err) throw err;
});
}
// Compute parameters for license to activate
var now = new Date();
l.student = s.id;
l.activation_ts = now;
l.expiration_ts = new Date(new Date(now.getFullYear(), now.getMonth()+l.duration, now.getDate()+1).getTime() + left);
l.save((err) => {
if (err)
throw err;
delete l.student;
delete l.id;
callback(null, l);
});
});
})
.catch((err) => {
throw err;
});
})
.catch((err) => {
callback(err, null);
});
}
}
......@@ -88,11 +88,16 @@ module.exports = {
collection: 'stupicto',
via: 'student'
},
// Relación con VStuLastInstruction [1 Student to 1 StuPicto]
// Relación con VStuLastInstruction [1 Student to 1 VStuLastInstruction]
lastInstruction: {
collection: 'vstulastinstruction',
via: 'student'
},
// Relación con licencias
license: {
collection: 'license',
via: 'student'
},
/**
* This "extra" property allow us to adapt the server to the student needs
......@@ -109,6 +114,7 @@ module.exports = {
toJSON: function () {
var student = this.toObject();
student.pic = sails.config.pictogram.urls.getStudentAvatarUrl(student.pic);
student.license = student.license[0] ? student.license[0] : null;
student.attributes = Student.getValidAttributes(student.attributes);
delete student.password;
return student;
......
......@@ -29,7 +29,7 @@
"angular-chart.js": "latest",
"ng-lodash": "~0.3.0",
"bootstrap-filestyle": "~1.2.1",
"jquery.maskedinput": "~1.4.1"
"ngMask": "angular-mask#~3.1.1"
},
"resolutions": {
"angular": ">=1 <1.3.0",
......
......@@ -131,8 +131,12 @@
"legend": "Legend",
"legend_size": "Legend size",
"licenses": "Licenses",
"license_already_activated": "License already activated",
"license_created": "License created",
"license_expires": "License expires on ",
"license_invalid": "Invalid license number",
"licenses_left": "{{number}} licenses left",
"license_missing": "Account without license",
"license_number": "License number",
"light_up": "Light up",
"link": "Link",
......
......@@ -132,8 +132,12 @@
"legend_size": "Tamaño de la leyenda",
"licenses": "Licencias",
"licenses_left": "{{number}} licencias disponibles",
"license_already_activated": "Licencia ya activada previamente",
"license_expires": "La licencia expira el ",
"license_created": "Licencia creada",
"license_invalid": "Licencia inválida",
"license_number": "Número de licencia",
"license_missing": "Cuenta sin licencia",
"light_up": "Iluminar",
"link": "Vincular",
"loading_pictos": "Cargando pictos",
......
......@@ -17,7 +17,8 @@ var dashboardApp = angular.module('dashboardApp', [
'ngSanitize',
'ngToast',
'chart.js',
'ngLodash'
'ngLodash',
'ngMask'
]);
/* Main constants */
......
......@@ -23,9 +23,6 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
input: false
});
// Set mask for license number input field
$("#setup_license").mask("****-****-****-****");
/**
* Updates the student picture
* @param {Angular file array} $files Image to be uploaded
......@@ -91,14 +88,11 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
if ($scope.formUser.password_confirm === $scope.formUser.password) {
password = $scope.formUser.password;
} else {
$translate('password_match').then(function (translation) {
ngToast.danger({ content: translation });
});
ngToast.danger({ content: $translate.instant('password_match') });
return;
}
}
attrs = {
birthdate: $scope.formUser.birthdate,
country: $scope.formUser.country,
......@@ -108,16 +102,17 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
notes: $scope.formUser.notes,
surname: $scope.formUser.surname,
username: $scope.formUser.username,
license_number: $scope.formUser.license_number
};
if (password)
attrs.password = password;
// Update student data
$http.put(config.backend + '/stu/' + $scope.studentData.id, attrs)
.success(function (data) {
$translate('student_updated').then(function (translation) {
ngToast.success({ content: translation });
});
ngToast.success({ content: $translate.instant('student_updated') });
$scope.formUser.birthdate = data.birthdate;
$scope.formUser.country = data.country;
$scope.formUser.gender = data.gender;
......@@ -126,17 +121,28 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
$scope.formUser.notes = data.notes;
$scope.formUser.surname = data.surname;
$scope.formUser.username = data.username;
$scope.formUser.license_number = data.license ? data.license.number : '';
$scope.studentData.license = data.license ? data.license : null;
if (data.license) {
moment.locale($translate.use().substr(0, 2));
$scope.expiration_date = moment($scope.studentData.license.expiration_ts).format('L');
}
// websocket emit vocabulary delete action
// websocket emit update action
delete data.license;
io.socket.post('/stu/config', {
action: 'update',
attributes: data
}, function () {});
})
.error(function () {
$translate.danger('student_not_updated', function (translation) {
ngToast.danger({ content: translation });
});
.error(function (err) {
console.log(err);
if (err.message.search('nvalid license'))
ngToast.danger({ content: $translate.instant('license_invalid') });
else if (err.message.search('is already active'))
ngToast.danger({ content: $translate.instant('license_already_activated') });
else
ngToast.danger({ content: $translate.instant('student_not_updated') });
});
};
......
......@@ -28,6 +28,9 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
lang: '',
notes: '',
attributes: {},
license: {
number: ''
},
office: {
id: '',
name: ''
......@@ -99,6 +102,7 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
$scope.studentData.current_method = data.current_method;
$scope.studentData.current_instruction = data.current_instruction;
$scope.studentData.supervision = data.supervision; // supervision level on student: 0->admin, 1->tutor, 2->therapist
$scope.studentData.license = data.license;
// Setup section: Fill formUser (data able to be modified) from studentData parent object
// It must go here to assign the values when studentData is recovered
......@@ -111,6 +115,11 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
$scope.formUser.gender = $scope.studentData.gender;
$scope.formUser.lang = $scope.studentData.lang;
$scope.formUser.notes = $scope.studentData.notes;
if ($scope.studentData.license) {
$scope.formUser.license_number = $scope.studentData.license.number;
moment.locale($translate.use().substr(0, 2));
$scope.expiration_date = moment($scope.studentData.license.expiration_ts).format('L');
}
// Subscribe to student's socket room
io.socket.post('/stu/subscribe', {
......
......@@ -35,7 +35,14 @@
<input type="password" class="form-control" id="setup_password2" placeholder="{{ 'password_confirm' | translate }}" ng-model="formUser.password_confirm"/>
</div>
<div class="form-group">
<input type="text" class="form-control" style="text-transform: uppercase" id="setup_license" placeholder="{{ 'license_number' | translate }}" required ng-model="formUser.license"/>
<input type="text" id="setup_license" mask="9999-9999-9999-9999" clean="true" placeholder="{{ 'license_number' | translate }}" ng-model="formUser.license_number" required>
<br/>
<span ng-show="studentData.license" class="text-info">
({{ 'license_expires' | translate }} {{ expiration_date }})
</span>
<span ng-show="!studentData.license" class="text-danger">
{{ 'license_missing' | translate }}
</span>
</div>
</fieldset>
......
......@@ -26,7 +26,7 @@ module.exports = function (grunt) {
'assets/app/bower_components/ng-lodash/build/ng-lodash.js',
'assets/app/bower_components/ng-file-upload/angular-file-upload-shim.js',
'assets/app/bower_components/bootstrap-filestyle/src/bootstrap-filestyle.min.js',
'assets/app/bower_components/jquery.maskedinput/dist/jquery.maskedinput.min.js',
'assets/app/bower_components/ngMask/dist/ngMask.min.js',
'assets/scripts/lib/sails.io.js'
];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment