Archived
2

added GET /sample/number/{number} route

This commit is contained in:
VLE2FE
2020-07-20 16:31:48 +02:00
parent cd81cbf4bd
commit 1a784ade85
7 changed files with 508 additions and 164 deletions

View File

@ -13,11 +13,16 @@ function flatten (data) { // flatten object: {a: {b: true}} -> {a.b: true}
result[prop] = cur;
}
else if (Array.isArray(cur)) {
let l = 0;
for(let i = 0, l = cur.length; i < l; i++)
recurse(cur[i], prop + "[" + i + "]");
if (l == 0)
result[prop] = [];
if (cur.length && (Object(cur[0]) !== cur || Object.keys(cur[0]).length === 0)) { // array of non-objects
result[prop] = '[' + cur.join(', ') + ']';
}
else {
let l = 0;
for(let i = 0, l = cur.length; i < l; i++)
recurse(cur[i], prop + "[" + i + "]");
if (l == 0)
result[prop] = [];
}
}
else {
let isEmpty = true;

View File

@ -1343,6 +1343,67 @@ describe('/sample', () => {
});
});
describe('GET /sample/number/{number}', () => {
it('returns the right sample', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/sample/number/33',
auth: {basic: 'janedoe'},
httpStatus: 200,
res: {_id: '400000000000000000000003', number: '33', type: 'part', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], user: 'admin'}
});
});
it('works with an API key', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/sample/number/33',
auth: {key: 'janedoe'},
httpStatus: 200,
res: {_id: '400000000000000000000003', number: '33', type: 'part', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], user: 'admin'}
});
});
it('returns a deleted sample for a maintain/admin user', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/sample/number/Rng33',
auth: {basic: 'admin'},
httpStatus: 200,
res: {_id: '400000000000000000000005', number: 'Rng33', type: 'granulate', color: 'black', batch: '1653000308', condition: {condition_template: '200000000000000000000003'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {}, measurements: [], user: 'admin'}
});
});
it('returns 403 for a write user when requesting a deleted sample', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/sample/number/Rng33',
auth: {basic: 'janedoe'},
httpStatus: 403
});
});
it('returns 404 for an unknown sample', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/sample/number/Rng883',
auth: {basic: 'janedoe'},
httpStatus: 404
});
});
it('rejects an invalid id', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/sample/number/xx-xx',
auth: {basic: 'janedoe'},
httpStatus: 404
});
});
it('rejects unauthorized requests', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/sample/number/33',
httpStatus: 401
});
});
});
describe('PUT /sample/restore/{id}', () => {
it('sets the status', done => {
TestHelper.request(server, done, {

View File

@ -242,6 +242,13 @@ router.get('/samples', async (req, res, next) => {
&& e !== filters.sort[0] // field was not in sort
);
if (fieldsToAdd.find(e => e === 'notes')) { // add notes
queryPtr.push(
{$lookup: {from: 'notes', localField: 'note_id', foreignField: '_id', as: 'notes'}},
{$addFields: {notes: { $arrayElemAt: ['$notes', 0]}}}
);
}
if (fieldsToAdd.find(e => /material\./.test(e)) && !materialAdded) { // add material, was not added already
queryPtr.push(
{$lookup: {from: 'materials', localField: 'material_id', foreignField: '_id', as: 'material'}},
@ -387,26 +394,7 @@ router.get('/sample/' + IdValidate.parameter(), (req, res, next) => {
SampleModel.findById(req.params.id).populate('material_id').populate('user_id', 'name').populate('note_id').exec(async (err, sampleData: any) => {
if (err) return next(err);
if (sampleData) {
await sampleData.populate('material_id.group_id').populate('material_id.supplier_id').execPopulate().catch(err => next(err));
if (sampleData instanceof Error) return;
sampleData = sampleData.toObject();
if (sampleData.status === globals.status.deleted && !req.auth(res, ['maintain', 'admin'], 'all')) return; // deleted samples only available for maintain/admin
sampleData.material = sampleData.material_id; // map data to right keys
sampleData.material.group = sampleData.material.group_id.name;
sampleData.material.supplier = sampleData.material.supplier_id.name;
sampleData.user = sampleData.user_id.name;
sampleData.notes = sampleData.note_id ? sampleData.note_id : {};
MeasurementModel.find({sample_id: mongoose.Types.ObjectId(req.params.id), status: {$ne: globals.status.deleted}}).lean().exec((err, data) => {
sampleData.measurements = data;
res.json(SampleValidate.output(sampleData, 'details'));
});
}
else {
res.status(404).json({status: 'Not found'});
}
await sampleReturn(sampleData, req, res, next);
});
});
@ -514,6 +502,15 @@ router.delete('/sample/' + IdValidate.parameter(), (req, res, next) => {
});
});
router.get('/sample/number/:number', (req, res, next) => {
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
SampleModel.findOne({number: req.params.number}).populate('material_id').populate('user_id', 'name').populate('note_id').exec(async (err, sampleData: any) => {
if (err) return next(err);
await sampleReturn(sampleData, req, res, next);
});
});
router.put('/sample/restore/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
@ -769,4 +766,27 @@ function filterQueries (filters) {
function dateToOId (date) { // convert date to ObjectId
return mongoose.Types.ObjectId(Math.floor(date / 1000).toString(16) + '0000000000000000');
}
async function sampleReturn (sampleData, req, res, next) {
if (sampleData) {
console.log(sampleData);
await sampleData.populate('material_id.group_id').populate('material_id.supplier_id').execPopulate().catch(err => next(err));
if (sampleData instanceof Error) return;
sampleData = sampleData.toObject();
if (sampleData.status === globals.status.deleted && !req.auth(res, ['maintain', 'admin'], 'all')) return; // deleted samples only available for maintain/admin
sampleData.material = sampleData.material_id; // map data to right keys
sampleData.material.group = sampleData.material.group_id.name;
sampleData.material.supplier = sampleData.material.supplier_id.name;
sampleData.user = sampleData.user_id.name;
sampleData.notes = sampleData.note_id ? sampleData.note_id : {};
MeasurementModel.find({sample_id: sampleData._id, status: {$ne: globals.status.deleted}}).lean().exec((err, data) => {
sampleData.measurements = data;
res.json(SampleValidate.output(sampleData, 'details'));
});
}
else {
res.status(404).json({status: 'Not found'});
}
}

View File

@ -70,13 +70,14 @@ export default class SampleValidate {
private static fieldKeys = [
...SampleValidate.sortKeys,
'condition',
'notes',
'material_id',
'material',
'note_id',
'user_id',
'material._id',
'material.numbers',
'measurements.spectrum.dpt'
'measurements.spectrum.dpt',
];
static input (data, param) { // validate input, set param to 'new' to make all attributes required
@ -134,6 +135,7 @@ export default class SampleValidate {
material_id: IdValidate.get(),
material: MaterialValidate.outputV().append({number: Joi.string().max(128).allow('')}),
note_id: IdValidate.get().allow(null),
notes: this.sample.notes,
user_id: IdValidate.get(),
added: this.sample.added
};