small material changes for easier UI implementation
This commit is contained in:
		@@ -24,11 +24,12 @@ describe('/material', () => {
 | 
			
		||||
        const json = require('../test/db.json');
 | 
			
		||||
        should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 'validated').length);
 | 
			
		||||
        should(res.body).matchEach(material => {
 | 
			
		||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'properties', 'numbers');
 | 
			
		||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'properties', 'numbers', 'status');
 | 
			
		||||
          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('status', 'validated');
 | 
			
		||||
          should(material.properties).have.property('material_template').be.type('string');
 | 
			
		||||
          should(material.numbers).be.instanceof(Array);
 | 
			
		||||
        });
 | 
			
		||||
@@ -46,11 +47,12 @@ describe('/material', () => {
 | 
			
		||||
        const json = require('../test/db.json');
 | 
			
		||||
        should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 'validated').length);
 | 
			
		||||
        should(res.body).matchEach(material => {
 | 
			
		||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'properties', 'numbers');
 | 
			
		||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'properties', 'numbers', 'status');
 | 
			
		||||
          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('status', 'validated');
 | 
			
		||||
          should(material.properties).have.property('material_template').be.type('string');
 | 
			
		||||
          should(material.numbers).be.instanceof(Array);
 | 
			
		||||
        });
 | 
			
		||||
@@ -60,7 +62,7 @@ describe('/material', () => {
 | 
			
		||||
    it('allows filtering by state', done => {
 | 
			
		||||
      TestHelper.request(server, done, {
 | 
			
		||||
        method: 'get',
 | 
			
		||||
        url: '/materials?status=new',
 | 
			
		||||
        url: '/materials?status[]=new',
 | 
			
		||||
        auth: {basic: 'janedoe'},
 | 
			
		||||
        httpStatus: 200
 | 
			
		||||
      }).end((err, res) => {
 | 
			
		||||
@@ -68,24 +70,57 @@ describe('/material', () => {
 | 
			
		||||
        const json = require('../test/db.json');
 | 
			
		||||
        should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 'new').length);
 | 
			
		||||
        should(res.body).matchEach(material => {
 | 
			
		||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'properties', 'numbers');
 | 
			
		||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'properties', 'numbers', 'status');
 | 
			
		||||
          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('status', 'new');
 | 
			
		||||
          should(material.properties).have.property('material_template').be.type('string');
 | 
			
		||||
          should(material.numbers).be.instanceof(Array);
 | 
			
		||||
        });
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    it('allows filtering by deleted state for admins', done => {
 | 
			
		||||
      TestHelper.request(server, done, {
 | 
			
		||||
        method: 'get',
 | 
			
		||||
        url: '/materials?status[]=deleted',
 | 
			
		||||
        auth: {basic: 'admin'},
 | 
			
		||||
        httpStatus: 200
 | 
			
		||||
      }).end((err, res) => {
 | 
			
		||||
        if (err) return done(err);
 | 
			
		||||
        const json = require('../test/db.json');
 | 
			
		||||
        should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 'deleted').length);
 | 
			
		||||
        should(res.body).matchEach(material => {
 | 
			
		||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'properties', 'numbers', 'status');
 | 
			
		||||
          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('status', 'deleted');
 | 
			
		||||
          should(material.properties).have.property('material_template').be.type('string');
 | 
			
		||||
          should(material.numbers).be.instanceof(Array);
 | 
			
		||||
        });
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    it('rejects filtering by deleted state for a write user', done => {
 | 
			
		||||
      TestHelper.request(server, done, {
 | 
			
		||||
        method: 'get',
 | 
			
		||||
        url: '/materials?status[]=deleted',
 | 
			
		||||
        auth: {basic: 'janedoe'},
 | 
			
		||||
        httpStatus: 400,
 | 
			
		||||
        res: {status: 'Invalid body format', details: '"status[0]" must be one of [validated, new]'}
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    it('rejects an invalid state name', done => {
 | 
			
		||||
      TestHelper.request(server, done, {
 | 
			
		||||
        method: 'get',
 | 
			
		||||
        url: '/materials?status=xxx',
 | 
			
		||||
        url: '/materials?status[]=xxx',
 | 
			
		||||
        auth: {basic: 'janedoe'},
 | 
			
		||||
        httpStatus: 400,
 | 
			
		||||
        res: {status: 'Invalid body format', details: '"status" must be one of [validated, new, all]'}
 | 
			
		||||
        res: {status: 'Invalid body format', details: '"status[0]" must be one of [validated, new]'}
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    it('rejects unauthorized requests', done => {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,8 @@ const router = express.Router();
 | 
			
		||||
router.get('/materials', (req, res, next) => {
 | 
			
		||||
  if (!req.auth(res, ['read', 'write', 'dev', 'admin'], 'all')) return;
 | 
			
		||||
 | 
			
		||||
  const {error, value: filters} = MaterialValidate.query(req.query);
 | 
			
		||||
  const {error, value: filters} =
 | 
			
		||||
    MaterialValidate.query(req.query, ['dev', 'admin'].indexOf(req.authDetails.level) >= 0);
 | 
			
		||||
  if (error) return res400(error, res);
 | 
			
		||||
 | 
			
		||||
  let conditions;
 | 
			
		||||
@@ -38,11 +39,12 @@ router.get('/materials', (req, res, next) => {
 | 
			
		||||
    conditions = {status: globals.status.val};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  MaterialModel.find(conditions).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
 | 
			
		||||
  MaterialModel.find(conditions).sort({name: 1}).populate('group_id').populate('supplier_id')
 | 
			
		||||
    .lean().exec((err, data) => {
 | 
			
		||||
    if (err) return next(err);
 | 
			
		||||
 | 
			
		||||
    // validate all and filter null values from validation errors
 | 
			
		||||
    res.json(_.compact(data.map(e => MaterialValidate.output(e))));
 | 
			
		||||
    res.json(_.compact(data.map(e => MaterialValidate.output(e, true))));
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,10 @@ export default class MaterialValidate {  // validate input for material
 | 
			
		||||
      .items(
 | 
			
		||||
        Joi.string()
 | 
			
		||||
          .max(64)
 | 
			
		||||
      )
 | 
			
		||||
      ),
 | 
			
		||||
 | 
			
		||||
    status: Joi.string()
 | 
			
		||||
      .valid(...Object.values(globals.status))
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static input (data, param) {  // validate input, set param to 'new' to make all attributes required
 | 
			
		||||
@@ -47,18 +50,22 @@ export default class MaterialValidate {  // validate input for material
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static output (data) {  // validate output and strip unwanted properties, returns null if not valid
 | 
			
		||||
  static output (data, status = false) {  // validate output and strip unwanted properties, returns null if not valid
 | 
			
		||||
    data = IdValidate.stringify(data);
 | 
			
		||||
    data.group = data.group_id.name;
 | 
			
		||||
    data.supplier = data.supplier_id.name;
 | 
			
		||||
    const {value, error} = Joi.object({
 | 
			
		||||
    const validate: any = {
 | 
			
		||||
      _id: IdValidate.get(),
 | 
			
		||||
      name: this.material.name,
 | 
			
		||||
      supplier: this.material.supplier,
 | 
			
		||||
      group: this.material.group,
 | 
			
		||||
      properties: this.material.properties,
 | 
			
		||||
      numbers: this.material.numbers
 | 
			
		||||
    }).validate(data, {stripUnknown: true});
 | 
			
		||||
    };
 | 
			
		||||
    if (status) {
 | 
			
		||||
      validate.status = this.material.status;
 | 
			
		||||
    }
 | 
			
		||||
    const {value, error} = Joi.object(validate).validate(data, {stripUnknown: true});
 | 
			
		||||
    return error !== undefined? null : value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -83,9 +90,13 @@ export default class MaterialValidate {  // validate input for material
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static query (data) {
 | 
			
		||||
  static query (data, dev = false) {
 | 
			
		||||
    const acceptedStatuses = [globals.status.val, globals.status.new];
 | 
			
		||||
    if (dev) {  // dev and admin can also access deleted samples
 | 
			
		||||
      acceptedStatuses.push(globals.status.del)
 | 
			
		||||
    }
 | 
			
		||||
    return Joi.object({
 | 
			
		||||
      status: Joi.string().valid(globals.status.val, globals.status.new, 'all')
 | 
			
		||||
      status: Joi.array().items(Joi.string().valid(...acceptedStatuses)).default([globals.status.val])
 | 
			
		||||
    }).validate(data);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user