diff --git a/api/material.yaml b/api/material.yaml index c32c1ab..8e3a039 100644 --- a/api/material.yaml +++ b/api/material.yaml @@ -40,7 +40,7 @@ 500: $ref: 'api.yaml#/components/responses/500' put: - summary: TODO change material + summary: change material description: 'Auth: basic, levels: write, maintain, dev, admin' tags: - /material @@ -79,8 +79,6 @@ responses: 200: $ref: 'api.yaml#/components/responses/Ok' - 400: - $ref: 'api.yaml#/components/responses/400' 401: $ref: 'api.yaml#/components/responses/401' 403: diff --git a/src/routes/material.spec.ts b/src/routes/material.spec.ts index bb82bc1..e98da67 100644 --- a/src/routes/material.spec.ts +++ b/src/routes/material.spec.ts @@ -130,6 +130,16 @@ describe('/material', () => { res: {_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}]} }); }); + it('returns keeps unchanged properties', done => { + TestHelper.request(server, done, { + method: 'put', + url: '/material/100000000000000000000001', + auth: {basic: 'janedoe'}, + httpStatus: 200, + req: {name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}]}, + res: {_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}]} + }); + }); it('changes the given properties', done => { TestHelper.request(server, done, { method: 'put', @@ -140,9 +150,11 @@ describe('/material', () => { , }).end(err => { if (err) return done(err); - MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => { + MaterialModel.findById('100000000000000000000001').lean().exec((err, data:any) => { if (err) return done(err); - should(data).be.eql({_id: '100000000000000000000002', name: 'UltramidTKR4355G7', supplier: 'BASF', group: 'PA6/6T', mineral: 0, glass_fiber: 35, carbon_fiber: 0, numbers: [{color: 'black', number: 5514212901}, {color: 'signalviolet', number: 5514612901}], __v: 0} + data._id = data._id.toString(); + data.numbers = data.numbers.map(e => {return {color: e.color, number: e.number}}); + should(data).be.eql({_id: '100000000000000000000001', name: 'UltramidTKR4355G7_2', supplier: 'BASF', group: 'PA6/6T', mineral: '0', glass_fiber: '35', carbon_fiber: '0', numbers: [{color: 'black', number: 5514212901}, {color: 'signalviolet', number: 5514612901}], __v: 0} ); done(); }); @@ -154,7 +166,7 @@ describe('/material', () => { url: '/material/100000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 400, - req: {name: 'UltramidTKR4355G7'}, + req: {name: 'Ultramid T KR 4355 G7'}, res: {status: 'Material name already taken'} }); }); @@ -173,9 +185,8 @@ describe('/material', () => { method: 'put', url: '/material/10000000000000000000000x', auth: {basic: 'admin'}, - httpStatus: 400, + httpStatus: 404, req: {}, - res: {status: 'Invalid id'} }); }); it('rejects an API key', done => { @@ -227,7 +238,7 @@ describe('/material', () => { should(res.body).be.eql({status: 'OK'}); MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => { if (err) return done(err); - should(data).have.lengthOf(0); + should(data).be.null(); done(); }); }); @@ -238,8 +249,7 @@ describe('/material', () => { method: 'delete', url: '/material/10000000000000000000000x', auth: {basic: 'admin'}, - httpStatus: 400, - res: {status: 'Invalid id'} + httpStatus: 404 }); }); it('rejects an API key', done => { diff --git a/src/routes/material.ts b/src/routes/material.ts index 42911e3..f193b9f 100644 --- a/src/routes/material.ts +++ b/src/routes/material.ts @@ -31,6 +31,58 @@ router.get('/material/' + IdValidate.parameter(), (req, res, next) => { }); }); +router.put('/material/' + IdValidate.parameter(), (req, res, next) => { + if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return; + + const {error, value: material} = MaterialValidate.input(req.body, 'change'); + if(error !== undefined) { + res.status(400).json({status: 'Invalid body format'}); + return; + } + + if (material.hasOwnProperty('name')) { + MaterialModel.find({name: material.name}).lean().exec((err, data) => { + if(err) next(err); + if (data.length > 0 && data[0]._id != req.params.id) { + res.status(400).json({status: 'Material name already taken'}); + return; + } + else { + f(); + } + }); + } + else { + f(); + } + + function f() { // to resolve async + MaterialModel.findByIdAndUpdate(req.params.id, material).lean().exec((err, data) => { + if (err) next(err); + if (data) { + res.json(MaterialValidate.output(data)); + } + else { + res.status(404).json({status: 'Not found'}); + } + }); + } +}); + +router.delete('/material/' + IdValidate.parameter(), (req, res, next) => { + if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return; + + MaterialModel.findByIdAndDelete(req.params.id).lean().exec((err, data) => { + if (err) next(err); + if (data) { + res.json({status: 'OK'}) + } + else { + res.status(404).json({status: 'Not found'}); + } + }); +}); + router.post('/material/new', (req, res, next) => { if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return; @@ -52,8 +104,8 @@ router.post('/material/new', (req, res, next) => { if(err) next(err); res.json(MaterialValidate.output(data.toObject())); }); - }) -}) + }); +}); module.exports = router; \ No newline at end of file diff --git a/src/routes/user.ts b/src/routes/user.ts index aabb8a2..c60dd7b 100644 --- a/src/routes/user.ts +++ b/src/routes/user.ts @@ -67,7 +67,7 @@ router.put('/user:username([/](?!key|new).?*|/?)', (req, res, next) => { // thi UserModel.findOneAndUpdate({name: username}, user, {new: true}).lean().exec( (err, data:any) => { if (err) next(err); if (data) { - res.json(UserValidate.output(data)); // validate all and filter null values from validation errors + res.json(UserValidate.output(data)); } else { res.status(404).json({status: 'Not found'}); diff --git a/static/styles/swagger.css b/static/styles/swagger.css index b86a643..ac69d38 100644 --- a/static/styles/swagger.css +++ b/static/styles/swagger.css @@ -197,6 +197,10 @@ body:after { margin-top: 5px; } +.opblock-section .opblock-section-request-body > div > div { + padding-top: 18px; +} + /*response element positions*/ .swagger-ui .model-example { position: relative;