From 8315fc0d3ba63a07bec516b0733dd381089e4bc6 Mon Sep 17 00:00:00 2001 From: VLE2FE Date: Thu, 14 May 2020 15:36:47 +0200 Subject: [PATCH] PUT finished --- src/models/measurement_template.ts | 2 +- src/models/treatment_template.ts | 2 +- src/routes/condition.ts | 4 +- src/routes/material.ts | 4 +- src/routes/measurement.ts | 4 +- src/routes/sample.spec.ts | 26 +++++++ src/routes/sample.ts | 44 ++++++----- src/routes/template.spec.ts | 117 +++++++++++++++++------------ src/routes/template.ts | 58 +++++++------- src/routes/validate/template.ts | 8 +- src/routes/validate/user.ts | 2 +- 11 files changed, 162 insertions(+), 109 deletions(-) diff --git a/src/models/measurement_template.ts b/src/models/measurement_template.ts index 1b0f6e9..080f42b 100644 --- a/src/models/measurement_template.ts +++ b/src/models/measurement_template.ts @@ -1,7 +1,7 @@ import mongoose from 'mongoose'; const MeasurementTemplateSchema = new mongoose.Schema({ - name: {type: String, index: {unique: true}}, + name: String, version: Number, parameters: [{ name: String, diff --git a/src/models/treatment_template.ts b/src/models/treatment_template.ts index 8fc4af8..154ae79 100644 --- a/src/models/treatment_template.ts +++ b/src/models/treatment_template.ts @@ -1,7 +1,7 @@ import mongoose from 'mongoose'; const TreatmentTemplateSchema = new mongoose.Schema({ - name: {type: String, index: {unique: true}}, + name: String, version: Number, number_prefix: String, parameters: [{ diff --git a/src/routes/condition.ts b/src/routes/condition.ts index 8acc2f2..89ddce0 100644 --- a/src/routes/condition.ts +++ b/src/routes/condition.ts @@ -34,9 +34,7 @@ router.put('/condition/' + IdValidate.parameter(), async (req, res, next) => { if (error) return res400(error, res); const data = await ConditionModel.findById(req.params.id).lean().exec().catch(err => {next(err);}) as any; - if (data instanceof Error) { - return; - } + if (data instanceof Error) return; if (!data) { res.status(404).json({status: 'Not found'}); } diff --git a/src/routes/material.ts b/src/routes/material.ts index a912f5e..1c33591 100644 --- a/src/routes/material.ts +++ b/src/routes/material.ts @@ -104,9 +104,7 @@ module.exports = router; async function nameCheck (material, res, next) { // check if name was already taken const materialData = await MaterialModel.findOne({name: material.name}).lean().exec().catch(err => {next(err); return false;}) as any; - if (materialData instanceof Error) { - return false; - } + if (materialData instanceof Error) return false; if (materialData) { // could not find material_id res.status(400).json({status: 'Material name already taken'}); return false; diff --git a/src/routes/measurement.ts b/src/routes/measurement.ts index 4aa89c1..bb69b3f 100644 --- a/src/routes/measurement.ts +++ b/src/routes/measurement.ts @@ -32,9 +32,7 @@ router.put('/measurement/' + IdValidate.parameter(), async (req, res, next) => { if (error) return res400(error, res); const data = await MeasurementModel.findById(req.params.id).lean().exec().catch(err => {next(err);}) as any; - if (data instanceof Error) { - return; - } + if (data instanceof Error) return; if (!data) { res.status(404).json({status: 'Not found'}); } diff --git a/src/routes/sample.spec.ts b/src/routes/sample.spec.ts index 99f6344..42c8435 100644 --- a/src/routes/sample.spec.ts +++ b/src/routes/sample.spec.ts @@ -124,6 +124,32 @@ describe('/sample', () => { }); }); }); + it('keeps unchanged notes', done => { + TestHelper.request(server, done, { + method: 'put', + url: '/sample/400000000000000000000002', + auth: {basic: 'janedoe'}, + httpStatus: 200, + req: {notes: {comment: 'Stoff gesperrt', sample_references: []}} + }).end((err, res) => { + if (err) return done(err); + should(res.body).be.eql({_id: '400000000000000000000002', number: '21', type: 'granulate', color: 'natural', batch: '1560237365', material_id: '100000000000000000000001', note_id: '500000000000000000000001', user_id: '000000000000000000000002'}); + SampleModel.findById('400000000000000000000002').lean().exec((err, data: any) => { + if (err) return done (err); + should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v'); + should(data).have.property('_id'); + should(data).have.property('number', '21'); + should(data).have.property('color', 'natural'); + should(data).have.property('type', 'granulate'); + should(data).have.property('batch', '1560237365'); + should(data.material_id.toString()).be.eql('100000000000000000000001'); + should(data.user_id.toString()).be.eql('000000000000000000000002'); + should(data).have.property('status', 10); + should(data.note_id.toString()).be.eql('500000000000000000000001'); + done(); + }); + }); + }); it('changes the given properties', done => { TestHelper.request(server, done, { method: 'put', diff --git a/src/routes/sample.ts b/src/routes/sample.ts index a6e9ced..6acb7d2 100644 --- a/src/routes/sample.ts +++ b/src/routes/sample.ts @@ -46,25 +46,31 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => { if (!await materialCheck(sample, res, next, sampleData.material_id)) return; } - if (sample.hasOwnProperty('notes') && sampleData.note_id !== null) { // deal with old notes data - NoteModel.findById(sampleData.note_id).lean().exec((err, data: any) => { - if (err) return console.error(err); - if (data.hasOwnProperty('custom_fields')) { // update note_fields - customFieldsChange(Object.keys(data.custom_fields), -1); + if (sample.hasOwnProperty('notes')) { + let newNotes = true; + if (sampleData.note_id !== null) { // old notes data exists + const data = await NoteModel.findById(sampleData.note_id).lean().exec().catch(err => {next(err);}) as any; + if (data instanceof Error) return; + newNotes = !_.isEqual(_.pick(IdValidate.stringify(data), _.keys(sample.notes)), sample.notes); + if (newNotes) { + if (data.hasOwnProperty('custom_fields')) { // update note_fields + customFieldsChange(Object.keys(data.custom_fields), -1); + } + NoteModel.findByIdAndDelete(sampleData.note_id).lean().exec(err => { // delete old notes + if (err) return console.error(err); + }); } - NoteModel.findByIdAndDelete(sampleData.note_id).lean().exec(err => { // delete old notes - if (err) return console.error(err); - }) - }); - } - if (sample.hasOwnProperty('notes') && Object.keys(sample.notes).length > 0) { // save new notes - if (!await sampleRefCheck(sample, res, next)) return; - if (sample.notes.hasOwnProperty('custom_fields') && Object.keys(sample.notes.custom_fields).length > 0) { // new custom_fields - customFieldsChange(Object.keys(sample.notes.custom_fields), 1); } - let data = await new NoteModel(sample.notes).save().catch(err => { return next(err)}); // save new notes - delete sample.notes; - sample.note_id = data._id; + + if (_.keys(sample.notes).length > 0 && newNotes) { // save new notes + if (!await sampleRefCheck(sample, res, next)) return; + if (sample.notes.hasOwnProperty('custom_fields') && Object.keys(sample.notes.custom_fields).length > 0) { // new custom_fields + customFieldsChange(Object.keys(sample.notes.custom_fields), 1); + } + let data = await new NoteModel(sample.notes).save().catch(err => { return next(err)}); // save new notes + delete sample.notes; + sample.note_id = data._id; + } } // check for changes @@ -160,9 +166,7 @@ async function numberCheck (sample, res, next) { // validate number, returns fa async function materialCheck (sample, res, next, id = sample.material_id) { // validate material_id and color, returns false if invalid const materialData = await MaterialModel.findById(id).lean().exec().catch(err => {next(err); return false;}) as any; - if (materialData instanceof Error) { - return false; - } + if (materialData instanceof Error) return false; if (!materialData) { // could not find material_id res.status(400).json({status: 'Material not available'}); return false; diff --git a/src/routes/template.spec.ts b/src/routes/template.spec.ts index e89e238..c42430b 100644 --- a/src/routes/template.spec.ts +++ b/src/routes/template.spec.ts @@ -1,4 +1,5 @@ import should from 'should/as-function'; +import _ from 'lodash'; import TemplateTreatmentModel from '../models/treatment_template'; import TemplateMeasurementModel from '../models/measurement_template'; import TestHelper from "../test/helper"; @@ -130,8 +131,7 @@ describe('/template', () => { req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]} }).end((err, res) => { if (err) return done(err); - should(res.body).be.eql({_id: '200000000000000000000001', name: 'heat aging', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {min: 1}}]}); - TemplateTreatmentModel.findById('200000000000000000000001').lean().exec((err, data:any) => { + TemplateTreatmentModel.findById(res.body._id).lean().exec((err, data:any) => { if (err) return done(err); should(data).have.only.keys('_id', 'name', 'version', 'number_prefix', 'parameters', '__v'); should(data).have.property('name', 'heat aging'); @@ -154,17 +154,15 @@ describe('/template', () => { req: {name: 'heat aging'} }).end((err, res) => { if (err) return done(err); - should(res.body).be.eql({_id: '200000000000000000000001', name: 'heat aging', version: 2, number_prefix: 'A', parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}); - TemplateTreatmentModel.find({name: 'heat aging'}).lean().exec((err, data:any) => { + TemplateTreatmentModel.findById(res.body._id).lean().exec((err, data:any) => { if (err) return done(err); - should(data).have.lengthOf(1); - should(data[0]).have.only.keys('_id', 'name', 'version', 'number_prefix', 'parameters', '__v'); - should(data[0]).have.property('name', 'heat aging'); - should(data[0]).have.property('version', 2); - should(data[0]).have.property('number_prefix', 'A'); - should(data[0]).have.property('parameters').have.lengthOf(1); - should(data[0].parameters[0]).have.property('name', 'material'); - should(data[0].parameters[1]).have.property('name', 'weeks'); + should(data).have.only.keys('_id', 'name', 'version', 'number_prefix', 'parameters', '__v'); + should(data).have.property('name', 'heat aging'); + should(data).have.property('version', 2); + should(data).have.property('number_prefix', 'A'); + should(data).have.property('parameters').have.lengthOf(2); + should(data.parameters[0]).have.property('name', 'material'); + should(data.parameters[1]).have.property('name', 'weeks'); done(); }); }); @@ -175,8 +173,11 @@ describe('/template', () => { url: '/template/treatment/200000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'time', range: {values: [1, 2, 5]}}]}, - res: {_id: '200000000000000000000001', name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {values: [1, 2, 5]}}]} + req: {parameters: [{name: 'time', range: {values: [1, 2, 5]}}]} + }).end((err, res) => { + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {values: [1, 2, 5]}}]}); + done(); }); }); it('supports min max ranges', done => { @@ -185,8 +186,11 @@ describe('/template', () => { url: '/template/treatment/200000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'time', range: {min: 1, max: 11}}]}, - res: {_id: '200000000000000000000001', name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {min: 1, max: 11}}]} + req: {parameters: [{name: 'time', range: {min: 1, max: 11}}]} + }).end((err, res) => { + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {min: 1, max: 11}}]}); + done(); }); }); it('supports array type ranges', done => { @@ -195,8 +199,12 @@ describe('/template', () => { url: '/template/treatment/200000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'time', range: {type: 'array'}}]}, - res: {_id: '200000000000000000000001', name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {type: 'array'}}]} + req: {parameters: [{name: 'time', range: {type: 'array'}}]} + }).end((err, res) => { + console.log(res.body); + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {type: 'array'}}]}); + done(); }); }); it('supports empty ranges', done => { @@ -205,8 +213,11 @@ describe('/template', () => { url: '/template/treatment/200000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'time', range: {}}]}, - res: {_id: '200000000000000000000001', name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {}}]} + req: {parameters: [{name: 'time', range: {}}]} + }).end((err, res) => { + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {}}]}); + done(); }); }); it('rejects not specified parameters', done => { @@ -216,7 +227,7 @@ describe('/template', () => { auth: {basic: 'admin'}, httpStatus: 400, req: {name: 'heat treatment', parameters: [{name: 'material', range: {xx: 5}}]}, - res: {} + res: {status: 'Invalid body format', details: '"parameters[0].range.xx" is not allowed'} }); }) it('rejects an invalid id', done => { @@ -478,7 +489,7 @@ describe('/template', () => { url: '/template/measurement/300000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 200, - res: {_id: '300000000000000000000001', name: 'spectrum', version: 1, parameters: [{name: 'dpt', range: {}}]} + res: {_id: '300000000000000000000001', name: 'spectrum', version: 1, parameters: [{name: 'dpt', range: { type: 'array'}}]} }); }); it('rejects an API key', done => { @@ -514,7 +525,7 @@ describe('/template', () => { auth: {basic: 'admin'}, httpStatus: 200, req: {}, - res: {_id: '300000000000000000000001', name: 'spectrum', version: 1, parameters: [{name: 'dpt', range: {}}]} + res: {_id: '300000000000000000000001', name: 'spectrum', version: 1, parameters: [{name: 'dpt', range: { type: 'array'}}]} }); }); it('keeps unchanged properties', done => { @@ -523,7 +534,7 @@ describe('/template', () => { url: '/template/measurement/300000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {name: 'spectrum', parameters: [{name: 'dpt', range: {}}]}, + req: {name: 'spectrum', parameters: [{name: 'dpt', range: { type: 'array'}}]}, res: {_id: '300000000000000000000001', name: 'spectrum', version: 1, parameters: [{name: 'dpt', range: {type: 'array'}}]} }); }); @@ -546,18 +557,17 @@ describe('/template', () => { req: {name: 'IR spectrum', parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]}, }).end((err, res) => { if (err) return done(err); - should(res.body).be.eql({_id: '300000000000000000000001', name: 'IR spectrum', parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]}); - TemplateMeasurementModel.findById('300000000000000000000001').lean().exec((err, data:any) => { + should(_.omit(res.body, '_id')).be.eql({name: 'IR spectrum', version: 2, parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]}); + TemplateMeasurementModel.findById(res.body._id).lean().exec((err, data:any) => { if (err) return done(err); - should(data).have.lengthOf(1); - should(data[0]).have.only.keys('_id', 'name', 'version', 'parameters', '__v'); - should(data[0]).have.property('name', 'IR spectrum'); - should(data[0]).have.property('version', 2); - should(data[0]).have.property('parameters').have.lengthOf(1); - should(data[0].parameters[0]).have.property('name', 'data point table'); - should(data[0].parameters[0]).have.property('range'); - should(data[0].parameters[0].range).have.property('min', 0); - should(data[0].parameters[0].range).have.property('max', 1000); + should(data).have.only.keys('_id', 'name', 'version', 'parameters', '__v'); + should(data).have.property('name', 'IR spectrum'); + should(data).have.property('version', 2); + should(data).have.property('parameters').have.lengthOf(1); + should(data.parameters[0]).have.property('name', 'data point table'); + should(data.parameters[0]).have.property('range'); + should(data.parameters[0].range).have.property('min', 0); + should(data.parameters[0].range).have.property('max', 1000); done(); }); }); @@ -571,10 +581,9 @@ describe('/template', () => { req: {name: 'IR spectrum'}, }).end((err, res) => { if (err) return done(err); - should(res.body).be.eql({_id: '300000000000000000000001', name: 'IR spectrum', parameters: [{name: 'dpt', range: {type: 'array'}}]}); - TemplateMeasurementModel.findById('300000000000000000000001').lean().exec((err, data:any) => { + should(_.omit(res.body, '_id')).be.eql({name: 'IR spectrum', version: 2, parameters: [{name: 'dpt', range: {type: 'array'}}]}); + TemplateMeasurementModel.findById(res.body._id).lean().exec((err, data:any) => { if (err) return done(err); - should(data).have.lengthOf(1); should(data).have.only.keys('_id', 'name', 'version', 'parameters', '__v'); should(data).have.property('name', 'IR spectrum'); should(data).have.property('version', 2); @@ -592,8 +601,11 @@ describe('/template', () => { url: '/template/measurement/300000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'dpt', range: {values: [1, 2, 5]}}]}, - res: {_id: '300000000000000000000001', name: 'spectrum', version: 2, parameters: [{name: 'dpt', range: {values: [1, 2, 5]}}]} + req: {parameters: [{name: 'dpt', range: {values: [1, 2, 5]}}]} + }).end((err, res) => { + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'spectrum', version: 2, parameters: [{name: 'dpt', range: {values: [1, 2, 5]}}]}); + done(); }); }); it('supports min max ranges', done => { @@ -602,18 +614,24 @@ describe('/template', () => { url: '/template/measurement/300000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'dpt', range: {min: 0, max: 1000}}]}, - res: {_id: '300000000000000000000001', name: 'spectrum', version: 2, parameters: [{name: 'dpt', range: {min: 0, max: 1000}}]} + req: {parameters: [{name: 'dpt', range: {min: 0, max: 1000}}]} + }).end((err, res) => { + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'spectrum', version: 2, parameters: [{name: 'dpt', range: {min: 0, max: 1000}}]}); + done(); }); }); - it('supports min max ranges', done => { + it('supports array type ranges', done => { TestHelper.request(server, done, { method: 'put', url: '/template/measurement/300000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'dpt', range: {type: 'array'}}]}, - res: {_id: '300000000000000000000001', name: 'spectrum', version: 2, parameters: [{name: 'dpt', range: {type: 'array'}}]} + req: {parameters: [{name: 'dpt2', range: {type: 'array'}}]} + }).end((err, res) => { + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'spectrum', version: 2, parameters: [{name: 'dpt2', range: {type: 'array'}}]}); + done(); }); }); it('supports empty ranges', done => { @@ -622,8 +640,11 @@ describe('/template', () => { url: '/template/measurement/300000000000000000000002', auth: {basic: 'admin'}, httpStatus: 200, - req: {parameters: [{name: 'weight %', range: {}}]}, - res: {_id: '300000000000000000000002', name: 'kf', version: 2, parameters: [{name: 'weight %', range: {}}]} + req: {parameters: [{name: 'weight %', range: {}}]} + }).end((err, res) => { + if (err) return done(err); + should(_.omit(res.body, '_id')).be.eql({name: 'kf', version: 3, parameters: [{name: 'weight %', range: {}}]}); + done(); }); }); it('rejects not specified parameters', done => { @@ -633,7 +654,7 @@ describe('/template', () => { auth: {basic: 'admin'}, httpStatus: 400, req: {parameters: [{name: 'dpt'}], range: {xx: 33}}, - res: {} + res: {status: 'Invalid body format', details: '"parameters[0].range" is required'} }); }); it('rejects an invalid id', done => { diff --git a/src/routes/template.ts b/src/routes/template.ts index 6c3212b..dac7a01 100644 --- a/src/routes/template.ts +++ b/src/routes/template.ts @@ -35,39 +35,32 @@ router.get('/template/:collection(measurement|treatment)/' + IdValidate.paramete }); }); -router.put('/template/:collection(measurement|treatment)/' + IdValidate.parameter(), (req, res, next) => { +router.put('/template/:collection(measurement|treatment)/' + IdValidate.parameter(), async (req, res, next) => { if (!req.auth(res, ['maintain', 'admin'], 'basic')) return; + const {error, value: template} = TemplateValidate.input(req.body, 'change', req.params.collection); + if (error) return res400(error, res); - model(req).findOne({name: req.params.name}).lean().exec((err, data) => { - if (err) next (err); - const templateState = data? 'change': 'new'; - const {error, value: template} = TemplateValidate.input(req.body, templateState, req.params.collection); - if (error) return res400(error, res); + const templateData = await model(req).findById(req.params.id).lean().exec().catch(err => {next(err);}) as any; + if (templateData instanceof Error) return; + if (!templateData) { + res.status(404).json({status: 'Not found'}); + } - if (template.hasOwnProperty('name') && template.name !== req.params.name) { - model(req).find({name: template.name}).lean().exec((err, data) => { - if (err) next (err); - if (data.length > 0) { - res.status(400).json({status: 'Template name already taken'}); - return; - } - else { - f(); - } - }); - } - else { - f(); - } + if (_.has(template, 'number_prefix') && template.number_prefix !== templateData.number_prefix) { // got new number_prefix + if (!await numberPrefixCheck(template, req, res, next)) return; + } - function f() { // to resolve async - model(req).findOneAndUpdate({name: req.params.name}, template, {new: true, upsert: true}).lean().exec((err, data) => { - if (err) return next(err); - res.json(TemplateValidate.output(data, req.params.collection)); - }); - } - }); + if (!_.isEqual(_.pick(templateData, _.keys(template)), template)) { // data was changed + template.version = templateData.version + 1; + await new (model(req))(_.assign({}, _.omit(templateData, ['_id', '__v']), template)).save((err, data) => { + if (err) next (err); + res.json(TemplateValidate.output(data.toObject(), req.params.collection)); + }); + } + else { + res.json(TemplateValidate.output(templateData, req.params.collection)); + } }); // router.delete('/template/:collection(measurement|treatment)/:name', (req, res, next) => { @@ -89,6 +82,15 @@ router.put('/template/:collection(measurement|treatment)/' + IdValidate.paramete module.exports = router; +async function numberPrefixCheck (template, req, res, next) { + const data = await model(req).findOne({number_prefix: template.number_prefix}).lean().exec().catch(err => {next(err); return false;}) as any; + if (data) { + res.status(400).json({status: 'Number prefix already taken'}); + return false + } + return true; +} + function model (req) { return req.params.collection === 'treatment' ? TemplateTreatmentModel : TemplateMeasurementModel; } \ No newline at end of file diff --git a/src/routes/validate/template.ts b/src/routes/validate/template.ts index 440c515..7cb461d 100644 --- a/src/routes/validate/template.ts +++ b/src/routes/validate/template.ts @@ -27,10 +27,16 @@ export default class TemplateValidate { min: joi.number(), - max: joi.number() + max: joi.number(), + + type: joi.string() + .valid('array') }) .oxor('values', 'min') .oxor('values', 'max') + .oxor('type', 'values') + .oxor('type', 'min') + .oxor('type', 'max') .required() }) ) diff --git a/src/routes/validate/user.ts b/src/routes/validate/user.ts index 024d1a9..4472aa8 100644 --- a/src/routes/validate/user.ts +++ b/src/routes/validate/user.ts @@ -5,7 +5,7 @@ import IdValidate from './id'; export default class UserValidate { // validate input for user private static user = { - name: Joi.string() + name: Joi.string() // TODO: check allowed characters .alphanum() .lowercase() .max(128),