diff --git a/api/material.yaml b/api/material.yaml index 9775b29..d184a3f 100644 --- a/api/material.yaml +++ b/api/material.yaml @@ -2,7 +2,30 @@ get: summary: lists all materials description: 'Auth: all, levels: read, write, maintain, dev, admin' - x-doc: returns only materials with status 10 # TODO: methods /materials/new|deleted + x-doc: returns only materials with status 10 + tags: + - /material + responses: + 200: + description: all material details + content: + application/json: + schema: + type: array + items: + $ref: 'api.yaml#/components/schemas/Material' + 401: + $ref: 'api.yaml#/components/responses/401' + 500: + $ref: 'api.yaml#/components/responses/500' + +/materials/{group}: + parameters: + - $ref: 'api.yaml#/components/parameters/Group' + get: + summary: lists all new/deleted materials + description: 'Auth: basic, levels: maintain, admin' + x-doc: returns materials with status 0/-1 tags: - /material responses: diff --git a/api/parameters.yaml b/api/parameters.yaml index ba8d046..b4586f7 100644 --- a/api/parameters.yaml +++ b/api/parameters.yaml @@ -5,10 +5,20 @@ Id: schema: type: string example: 5ea0450ed851c30a90e70894 + Name: name: name description: has to be URL encoded in: path required: true schema: - type: string \ No newline at end of file + type: string + +Group: + name: group + description: 'possible values: new, deleted' + in: path + required: true + schema: + type: string + example: deleted \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index fc1b149..c40ed24 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import mongoSanitize from 'mongo-sanitize'; import api from './api'; import db from './db'; +// TODO: overall commenting/documentation review // tell if server is running in debug or production environment console.info(process.env.NODE_ENV === 'production' ? '===== PRODUCTION =====' : process.env.NODE_ENV === 'test' ? '' :'===== DEVELOPMENT ====='); diff --git a/src/routes/material.spec.ts b/src/routes/material.spec.ts index 8b212aa..df58310 100644 --- a/src/routes/material.spec.ts +++ b/src/routes/material.spec.ts @@ -76,6 +76,101 @@ describe('/material', () => { }); }); + describe('GET /materials/{group}', () => { + it('returns all new materials', done => { + TestHelper.request(server, done, { + method: 'get', + url: '/materials/new', + auth: {basic: 'admin'}, + httpStatus: 200 + }).end((err, res) => { + if (err) return done(err); + const json = require('../test/db.json'); + let asyncCounter = res.body.length; + should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 0).length); + should(res.body).matchEach(material => { + should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers'); + should(material).have.property('_id').be.type('string'); + should(material).have.property('name').be.type('string'); + should(material).have.property('supplier').be.type('string'); + should(material).have.property('group').be.type('string'); + should(material).have.property('mineral').be.type('number'); + should(material).have.property('glass_fiber').be.type('number'); + should(material).have.property('carbon_fiber').be.type('number'); + should(material.numbers).matchEach(number => { + should(number).have.only.keys('color', 'number'); + should(number).have.property('color').be.type('string'); + should(number).have.property('number').be.type('string'); + }); + MaterialModel.findById(material._id).lean().exec((err, data) => { + should(data).have.property('status', 0); + if (--asyncCounter === 0) { + done(); + } + }); + }); + }); + }); + it('returns all deleted materials', done => { + TestHelper.request(server, done, { + method: 'get', + url: '/materials/deleted', + auth: {basic: 'admin'}, + httpStatus: 200 + }).end((err, res) => { + if (err) return done(err); + const json = require('../test/db.json'); + let asyncCounter = res.body.length; + should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === -1).length); + should(res.body).matchEach(material => { + should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers'); + should(material).have.property('_id').be.type('string'); + should(material).have.property('name').be.type('string'); + should(material).have.property('supplier').be.type('string'); + should(material).have.property('group').be.type('string'); + should(material).have.property('mineral').be.type('number'); + should(material).have.property('glass_fiber').be.type('number'); + should(material).have.property('carbon_fiber').be.type('number'); + should(material.numbers).matchEach(number => { + should(number).have.only.keys('color', 'number'); + should(number).have.property('color').be.type('string'); + should(number).have.property('number').be.type('string'); + }); + MaterialModel.findById(material._id).lean().exec((err, data) => { + should(data).have.property('status', -1); + if (--asyncCounter === 0) { + done(); + } + }); + }); + done(); + }); + }); + it('rejects requests from a write user', done => { + TestHelper.request(server, done, { + method: 'get', + url: '/materials/new', + auth: {basic: 'janedoe'}, + httpStatus: 403 + }); + }); + it('rejects an API key', done => { + TestHelper.request(server, done, { + method: 'get', + url: '/materials/deleted', + auth: {key: 'admin'}, + httpStatus: 401 + }); + }); + it('rejects unauthorized requests', done => { + TestHelper.request(server, done, { + method: 'get', + url: '/materials/new', + httpStatus: 401 + }); + }); + }); + describe('GET /material/{id}', () => { it('returns the right material', done => { TestHelper.request(server, done, { diff --git a/src/routes/material.ts b/src/routes/material.ts index 1c33591..2de50a8 100644 --- a/src/routes/material.ts +++ b/src/routes/material.ts @@ -21,6 +21,23 @@ router.get('/materials', (req, res, next) => { }); }); +router.get('/materials/:group(new|deleted)', (req, res, next) => { + if (!req.auth(res, ['maintain', 'admin'], 'basic')) return; + + let status; + switch (req.params.group) { + case 'new': status = 0; + break; + case 'deleted': status = -1; + break; + } + MaterialModel.find({status: status}).lean().exec((err, data) => { + if (err) return next(err); + console.log(data); + res.json(_.compact(data.map(e => MaterialValidate.output(e)))); // validate all and filter null values from validation errors + }); +}); + router.get('/material/' + IdValidate.parameter(), (req, res, next) => { if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return; diff --git a/src/test/db.json b/src/test/db.json index 7154863..b78f8e7 100644 --- a/src/test/db.json +++ b/src/test/db.json @@ -230,7 +230,7 @@ "number": "" } ], - "status": 10, + "status": 0, "__v": 0 } ],