Merge pull request #41 in ~VLE2FE/definma-api from develop to master
* commit 'c891933d11976a6efd2a6593168d58f1933b519e': implemented /model/files updated to new model format
This commit is contained in:
		| @@ -73,6 +73,32 @@ | ||||
|       500: | ||||
|         $ref: 'api.yaml#/components/responses/500' | ||||
|  | ||||
| /model/files: | ||||
|   get: | ||||
|     summary: list all stored models | ||||
|     description: 'Auth: basic, levels: dev, admin' | ||||
|     tags: | ||||
|       - /model | ||||
|     responses: | ||||
|       200: | ||||
|         description: model details list | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               properties: | ||||
|                 name: | ||||
|                   type: string | ||||
|                   example: model_VN_A3WG6_V1 | ||||
|                 size: | ||||
|                   type: number | ||||
|                   example: 4177449 | ||||
|       401: | ||||
|         $ref: 'api.yaml#/components/responses/401' | ||||
|       403: | ||||
|         $ref: 'api.yaml#/components/responses/403' | ||||
|       500: | ||||
|         $ref: 'api.yaml#/components/responses/500' | ||||
|  | ||||
| /model/file/{name}: | ||||
|   parameters: | ||||
|     - $ref: 'api.yaml#/components/parameters/Name' | ||||
|   | ||||
| @@ -26,11 +26,10 @@ describe('/model', () => { | ||||
|           should(group).have.only.keys('group', 'models'); | ||||
|           should(group).have.property('group').be.type('string'); | ||||
|           should(group.models).matchEach(model => { | ||||
|             should(model).have.only.keys('_id', 'name', 'url', 'label'); | ||||
|             should(model).have.only.keys('_id', 'name', 'url'); | ||||
|             should(model).have.property('_id').be.type('string'); | ||||
|             should(model).have.property('name').be.type('string'); | ||||
|             should(model).have.property('url').be.type('string'); | ||||
|             should(model).have.property('label').be.type('string'); | ||||
|           }); | ||||
|         }); | ||||
|         done(); | ||||
| @@ -48,7 +47,7 @@ describe('/model', () => { | ||||
|         should(res.body).matchEach(group => { | ||||
|           should(group).have.only.keys('group', 'models'); | ||||
|           should(group).have.property('group').be.type('string'); | ||||
|           should(group).have.property('models', [{_id: '120000000000000000000001', name: 'Model A', url: 'http://model-a.com', label: 'ml/g'}]); | ||||
|           should(group).have.property('models', [{_id: '120000000000000000000001', name: 'Model A', url: 'http://model-a.com'}]); | ||||
|         }); | ||||
|         done(); | ||||
|       }); | ||||
| @@ -77,7 +76,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 200, | ||||
|         req: {name: 'Model C', url: 'http://model-c.com', label: 'ml/g'} | ||||
|         req: {name: 'Model C', url: 'http://model-c.com'} | ||||
|       }).end((err, res) => { | ||||
|         if (err) return done(err); | ||||
|         should(res.body).be.eql({status: 'OK'}); | ||||
| @@ -85,7 +84,6 @@ describe('/model', () => { | ||||
|           if (err) return done(err); | ||||
|           const model = res.models.find(e => e.name === 'Model C'); | ||||
|           should(model).have.property('url', 'http://model-c.com'); | ||||
|           should(model).have.property('label', 'ml/g'); | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
| @@ -96,7 +94,7 @@ describe('/model', () => { | ||||
|         url: '/model/classification', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 200, | ||||
|         req: {name: 'Model 0.1', url: 'http://model-0-1.com', label: 'group'} | ||||
|         req: {name: 'Model 0.1', url: 'http://model-0-1.com'} | ||||
|       }).end((err, res) => { | ||||
|         if (err) return done(err); | ||||
|         should(res.body).be.eql({status: 'OK'}); | ||||
| @@ -104,10 +102,9 @@ describe('/model', () => { | ||||
|           if (err) return done(err); | ||||
|           should(res).have.only.keys('_id', 'group', 'models', '__v'); | ||||
|           should(res).have.property('group', 'classification'); | ||||
|           should(res.models[0]).have.only.keys('_id', 'name', 'url', 'label'); | ||||
|           should(res.models[0]).have.only.keys('_id', 'name', 'url'); | ||||
|           should(res.models[0]).have.property('name', 'Model 0.1'); | ||||
|           should(res.models[0]).have.property('url', 'http://model-0-1.com'); | ||||
|           should(res.models[0]).have.property('label', 'group'); | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
| @@ -118,7 +115,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 200, | ||||
|         req: {name: 'Model A', url: 'http://model-a-new.com', label: 'ml/cm3'} | ||||
|         req: {name: 'Model A', url: 'http://model-a-new.com'} | ||||
|       }).end((err, res) => { | ||||
|         if (err) return done(err); | ||||
|         should(res.body).be.eql({status: 'OK'}); | ||||
| @@ -126,26 +123,6 @@ describe('/model', () => { | ||||
|           if (err) return done(err); | ||||
|           const model = res.models.find(e => e.name === 'Model A'); | ||||
|           should(model).have.property('url', 'http://model-a-new.com'); | ||||
|           should(model).have.property('label', 'ml/cm3'); | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
|     it('accepts an empty label', done => { | ||||
|       TestHelper.request(server, done, { | ||||
|         method: 'post', | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 200, | ||||
|         req: {name: 'Model C', url: 'http://model-c.com', label: ''} | ||||
|       }).end((err, res) => { | ||||
|         if (err) return done(err); | ||||
|         should(res.body).be.eql({status: 'OK'}); | ||||
|         ModelModel.findOne({group: 'VN'}).lean().exec((err, res) => { | ||||
|           if (err) return done(err); | ||||
|           const model = res.models.find(e => e.name === 'Model C'); | ||||
|           should(model).have.property('url', 'http://model-c.com'); | ||||
|           should(model).have.property('label', ''); | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
| @@ -156,7 +133,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 400, | ||||
|         req: {name: '', url: 'http://model-c.com', label: 'ml/g'}, | ||||
|         req: {name: '', url: 'http://model-c.com'}, | ||||
|         res:{status: 'Invalid body format', details: '"name" is not allowed to be empty'} | ||||
|       }); | ||||
|     }); | ||||
| @@ -166,7 +143,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 400, | ||||
|         req: {url: 'http://model-c.com', label: 'ml/g'}, | ||||
|         req: {url: 'http://model-c.com'}, | ||||
|         res:{status: 'Invalid body format', details: '"name" is required'} | ||||
|       }); | ||||
|     }); | ||||
| @@ -176,7 +153,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 400, | ||||
|         req: {name: 'Model C', url: 'model-c', label: 'ml/g'}, | ||||
|         req: {name: 'Model C', url: 'model-c'}, | ||||
|         res:{status: 'Invalid body format', details: '"url" must be a valid uri'} | ||||
|       }); | ||||
|     }); | ||||
| @@ -186,7 +163,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'admin'}, | ||||
|         httpStatus: 400, | ||||
|         req: {name: 'Model C', label: 'ml/g'}, | ||||
|         req: {name: 'Model C'}, | ||||
|         res:{status: 'Invalid body format', details: '"url" is required'} | ||||
|       }); | ||||
|     }); | ||||
| @@ -196,7 +173,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {basic: 'janedoe'}, | ||||
|         httpStatus: 403, | ||||
|         req: {name: 'Model C', url: 'http://model-c.com', label: 'ml/g'} | ||||
|         req: {name: 'Model C', url: 'http://model-c.com'} | ||||
|       }); | ||||
|     }); | ||||
|     it('rejects an API key', done => { | ||||
| @@ -205,7 +182,7 @@ describe('/model', () => { | ||||
|         url: '/model/VN', | ||||
|         auth: {key: 'admin'}, | ||||
|         httpStatus: 401, | ||||
|         req: {name: 'Model C', url: 'http://model-c.com', label: 'ml/g'} | ||||
|         req: {name: 'Model C', url: 'http://model-c.com'} | ||||
|       }); | ||||
|     }); | ||||
|     it('rejects an unauthorized request', done => { | ||||
| @@ -213,7 +190,7 @@ describe('/model', () => { | ||||
|         method: 'post', | ||||
|         url: '/model/VN', | ||||
|         httpStatus: 401, | ||||
|         req: {name: 'Model C', url: 'http://model-c.com', label: 'ml/g'} | ||||
|         req: {name: 'Model C', url: 'http://model-c.com'} | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| @@ -232,10 +209,9 @@ describe('/model', () => { | ||||
|           if (err) return done(err); | ||||
|           should(res).have.only.keys('_id', 'group', 'models'); | ||||
|           should(res).have.property('group', 'VN'); | ||||
|           should(res.models[0]).have.only.keys('_id', 'name', 'url', 'label'); | ||||
|           should(res.models[0]).have.only.keys('_id', 'name', 'url'); | ||||
|           should(res.models[0]).have.property('name', 'Model B'); | ||||
|           should(res.models[0]).have.property('url', 'http://model-b.com'); | ||||
|           should(res.models[0]).have.property('label', 'ml/g'); | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
| @@ -297,6 +273,32 @@ describe('/model', () => { | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('GET /model/files', () => { | ||||
|     it('rejects a write user', done => { | ||||
|       TestHelper.request(server, done, { | ||||
|         method: 'get', | ||||
|         url: '/model/files', | ||||
|         auth: {basic: 'janedoe'}, | ||||
|         httpStatus: 403, | ||||
|       }); | ||||
|     }); | ||||
|     it('rejects an API key', done => { | ||||
|       TestHelper.request(server, done, { | ||||
|         method: 'get', | ||||
|         url: '/model/files', | ||||
|         auth: {key: 'admin'}, | ||||
|         httpStatus: 401, | ||||
|       }); | ||||
|     }); | ||||
|     it('rejects an unauthorized request', done => { | ||||
|       TestHelper.request(server, done, { | ||||
|         method: 'get', | ||||
|         url: '/model/files', | ||||
|         httpStatus: 401, | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('GET /model/file/{name}', (() => { | ||||
|     it('returns the binary data', done => { | ||||
|       TestHelper.request(server, done, { | ||||
|   | ||||
| @@ -33,7 +33,6 @@ router.post('/model/:group', (req, res, next) => { | ||||
|   if (!req.auth(res, ['dev', 'admin'], 'basic')) return; | ||||
|  | ||||
|   const {error, value: model} = ModelValidate.input(req.body); | ||||
|   console.log(error); | ||||
|   if (error) return res400(error, res); | ||||
|  | ||||
|   ModelModel.findOne({group: req.params.group}).lean().exec((err, data) => { | ||||
| @@ -96,6 +95,15 @@ router.delete('/model/:group(((?!file)[^\\/]+?))/:name', (req, res, next) => { | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| router.get('/model/files', (req, res, next) => { | ||||
|   if (!req.auth(res, ['dev', 'admin'], 'basic')) return; | ||||
|  | ||||
|   ModelFileModel.find().exec((err, data) => { | ||||
|     if (err) return next(err); | ||||
|     res.json(data.map(e => ModelValidate.fileOutput(e))); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| router.get('/model/file/:name', (req, res, next) => { | ||||
|   if (!req.auth(res, ['dev', 'admin'], 'all')) return; | ||||
|  | ||||
|   | ||||
| @@ -16,11 +16,6 @@ export default class ModelValidate {  // validate input for model | ||||
|         url: Joi.string() | ||||
|           .uri() | ||||
|           .max(512) | ||||
|           .required(), | ||||
|  | ||||
|         label: Joi.string() | ||||
|           .allow('') | ||||
|           .max(128) | ||||
|           .required() | ||||
|       }) | ||||
|   }; | ||||
| @@ -37,4 +32,11 @@ export default class ModelValidate {  // validate input for model | ||||
|     }).validate(data, {stripUnknown: true}); | ||||
|     return error !== undefined? null : value; | ||||
|   } | ||||
|  | ||||
|   static fileOutput (data) { | ||||
|     return { | ||||
|       name: data.name, | ||||
|       size: data.data.length | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -736,14 +736,12 @@ | ||||
|           { | ||||
|             "_id": {"$oid":"120000000000000000000001"}, | ||||
|             "name": "Model A", | ||||
|             "url": "http://model-a.com", | ||||
|             "label": "ml/g" | ||||
|             "url": "http://model-a.com" | ||||
|           }, | ||||
|           { | ||||
|             "_id": {"$oid":"120000000000000000000002"}, | ||||
|             "name": "Model B", | ||||
|             "url": "http://model-b.com", | ||||
|             "label": "ml/g" | ||||
|             "url": "http://model-b.com" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
| @@ -753,8 +751,7 @@ | ||||
|           { | ||||
|             "_id": {"$oid":"120000000000000000000003"}, | ||||
|             "name": "Model 1", | ||||
|             "url": "http://model-1.com", | ||||
|             "label": "weight %" | ||||
|             "url": "http://model-1.com" | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Veit Lukas (PEA4-Fe)
					Veit Lukas (PEA4-Fe)