Archived
2
This repository has been archived on 2023-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
definma-api/src/routes/measurement.ts

149 lines
5.8 KiB
TypeScript
Raw Normal View History

2020-05-12 12:15:36 +02:00
import express from 'express';
2020-05-12 17:15:36 +02:00
import _ from 'lodash';
2020-05-12 12:15:36 +02:00
import MeasurementModel from '../models/measurement';
import MeasurementTemplateModel from '../models/measurement_template';
2020-05-27 17:03:03 +02:00
import SampleModel from '../models/sample';
2020-05-12 12:15:36 +02:00
import MeasurementValidate from './validate/measurement';
import IdValidate from './validate/id';
import res400 from './validate/res400';
import ParametersValidate from './validate/parameters';
import globals from '../globals';
2020-05-12 12:15:36 +02:00
const router = express.Router();
router.get('/measurement/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
2020-05-27 17:03:03 +02:00
MeasurementModel.findById(req.params.id).lean().exec((err, data: any) => {
2020-05-12 12:15:36 +02:00
if (err) return next(err);
if (!data) {
return res.status(404).json({status: 'Not found'});
}
2020-05-27 17:03:03 +02:00
if (data.status ===globals.status.deleted && !req.auth(res, ['maintain', 'admin'], 'all')) return; // deleted measurements only available for maintain/admin
2020-05-12 12:15:36 +02:00
res.json(MeasurementValidate.output(data));
});
});
2020-05-12 17:15:36 +02:00
router.put('/measurement/' + IdValidate.parameter(), async (req, res, next) => {
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
const {error, value: measurement} = MeasurementValidate.input(req.body, 'change');
if (error) return res400(error, res);
const data = await MeasurementModel.findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
2020-05-14 15:36:47 +02:00
if (data instanceof Error) return;
2020-05-12 17:15:36 +02:00
if (!data) {
2020-05-28 11:47:51 +02:00
return res.status(404).json({status: 'Not found'});
2020-05-12 17:15:36 +02:00
}
2020-05-28 13:16:15 +02:00
if (data.status === globals.status.deleted) {
return res.status(403).json({status: 'Forbidden'});
}
2020-05-18 14:47:22 +02:00
2020-05-27 17:03:03 +02:00
// add properties needed for sampleIdCheck
2020-05-12 17:15:36 +02:00
measurement.measurement_template = data.measurement_template;
2020-05-27 17:03:03 +02:00
measurement.sample_id = data.sample_id;
if (!await sampleIdCheck(measurement, req, res, next)) return;
2020-05-18 14:47:22 +02:00
// check for changes
2020-05-27 17:03:03 +02:00
if (measurement.values) { // fill not changed values from database
2020-05-13 09:56:44 +02:00
measurement.values = _.assign({}, data.values, measurement.values);
if (!_.isEqual(measurement.values, data.values)) {
measurement.status = globals.status.new; // set status to new
2020-05-13 09:56:44 +02:00
}
2020-05-12 17:15:36 +02:00
}
2020-05-18 14:47:22 +02:00
2020-05-12 17:15:36 +02:00
if (!await templateCheck(measurement, 'change', res, next)) return;
await MeasurementModel.findByIdAndUpdate(req.params.id, measurement, {new: true}).lean().exec((err, data) => {
if (err) return next(err);
res.json(MeasurementValidate.output(data));
});
});
2020-05-12 17:37:01 +02:00
router.delete('/measurement/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
MeasurementModel.findById(req.params.id).lean().exec(async (err, data) => {
if (err) return next(err);
if (!data) {
2020-05-28 11:47:51 +02:00
return res.status(404).json({status: 'Not found'});
2020-05-12 17:37:01 +02:00
}
2020-05-27 17:03:03 +02:00
if (!await sampleIdCheck(data, req, res, next)) return;
await MeasurementModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).lean().exec(err => {
2020-05-12 17:37:01 +02:00
if (err) return next(err);
2020-05-28 11:47:51 +02:00
return res.json({status: 'OK'});
2020-05-12 17:37:01 +02:00
});
});
});
2020-05-28 15:03:49 +02:00
router.put('/measurement/restore/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
MeasurementModel.findByIdAndUpdate(req.params.id, {status: globals.status.new}).lean().exec((err, data) => {
if (err) return next(err);
if (!data) {
return res.status(404).json({status: 'Not found'});
}
res.json({status: 'OK'});
});
});
2020-05-12 12:15:36 +02:00
router.post('/measurement/new', async (req, res, next) => {
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
const {error, value: measurement} = MeasurementValidate.input(req.body, 'new');
if (error) return res400(error, res);
2020-05-27 17:03:03 +02:00
if (!await sampleIdCheck(measurement, req, res, next)) return;
measurement.values = await templateCheck(measurement, 'new', res, next);
if (!measurement.values) return;
2020-05-12 12:15:36 +02:00
2020-05-12 17:15:36 +02:00
measurement.status = 0;
2020-05-12 12:15:36 +02:00
await new MeasurementModel(measurement).save((err, data) => {
if (err) return next(err);
res.json(MeasurementValidate.output(data.toObject()));
});
});
module.exports = router;
2020-05-27 17:03:03 +02:00
async function sampleIdCheck (measurement, req, res, next) { // validate sample_id, returns false if invalid or user has no access for this sample
const sampleData = await SampleModel.findById(measurement.sample_id).lean().exec().catch(err => {next(err); return false;}) as any;
if (!sampleData) { // sample_id not found
res.status(400).json({status: 'Sample id not available'});
2020-05-12 12:15:36 +02:00
return false
2020-05-27 17:03:03 +02:00
}
if (sampleData.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return false; // sample does not belong to user
return true;
2020-05-12 12:15:36 +02:00
}
2020-05-27 17:03:03 +02:00
async function templateCheck (measurement, param, res, next) { // validate measurement_template and values, returns values, true if values are {} or false if invalid, param for 'new'/'change'
2020-05-12 12:15:36 +02:00
const templateData = await MeasurementTemplateModel.findById(measurement.measurement_template).lean().exec().catch(err => {next(err); return false;}) as any;
if (!templateData) { // template not found
res.status(400).json({status: 'Measurement template not available'});
return false
}
2020-05-27 17:03:03 +02:00
// fill not given values for new measurements
if (param === 'new') {
if (Object.keys(measurement.values).length === 0) {
res.status(400).json({status: 'At least one value is required'});
return false
}
const fillValues = {}; // initialize not given values with null
templateData.parameters.forEach(parameter => {
fillValues[parameter.name] = null;
});
measurement.values = _.assign({}, fillValues, measurement.values);
}
2020-05-12 12:15:36 +02:00
// validate values
2020-05-27 17:03:03 +02:00
const {error, value} = ParametersValidate.input(measurement.values, templateData.parameters, 'null');
2020-05-12 12:15:36 +02:00
if (error) {res400(error, res); return false;}
2020-05-27 17:03:03 +02:00
return value || true;
2020-05-12 12:15:36 +02:00
}