implemented changelog
This commit is contained in:
parent
74080d0902
commit
ca29cef48c
@ -5,6 +5,7 @@
|
|||||||
<w>cfenv</w>
|
<w>cfenv</w>
|
||||||
<w>dfopdb</w>
|
<w>dfopdb</w>
|
||||||
<w>janedoe</w>
|
<w>janedoe</w>
|
||||||
|
<w>pagesize</w>
|
||||||
<w>testcomment</w>
|
<w>testcomment</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
@ -62,7 +62,7 @@ tags:
|
|||||||
|
|
||||||
paths:
|
paths:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: 'others.yaml'
|
- $ref: 'root.yaml'
|
||||||
- $ref: 'sample.yaml'
|
- $ref: 'sample.yaml'
|
||||||
- $ref: 'material.yaml'
|
- $ref: 'material.yaml'
|
||||||
- $ref: 'measurement.yaml'
|
- $ref: 'measurement.yaml'
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
/:
|
|
||||||
get:
|
|
||||||
summary: Root method
|
|
||||||
description: 'Auth: none'
|
|
||||||
tags:
|
|
||||||
- /
|
|
||||||
security: []
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: Server is working
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
example: 'API server up and running!'
|
|
||||||
500:
|
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
|
||||||
|
|
||||||
/authorized:
|
|
||||||
get:
|
|
||||||
summary: Checks authorization
|
|
||||||
description: 'Auth: all, levels: read, write, maintain, dev, admin'
|
|
||||||
tags:
|
|
||||||
- /
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: Authorized
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
example: 'Authorization successful'
|
|
||||||
method:
|
|
||||||
type: string
|
|
||||||
example: 'basic'
|
|
||||||
401:
|
|
||||||
$ref: 'api.yaml#/components/responses/401'
|
|
||||||
500:
|
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
|
102
api/root.yaml
Normal file
102
api/root.yaml
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/:
|
||||||
|
get:
|
||||||
|
summary: Root method
|
||||||
|
description: 'Auth: none'
|
||||||
|
tags:
|
||||||
|
- /
|
||||||
|
security: []
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Server is working
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: 'API server up and running!'
|
||||||
|
500:
|
||||||
|
$ref: 'api.yaml#/components/responses/500'
|
||||||
|
|
||||||
|
/authorized:
|
||||||
|
get:
|
||||||
|
summary: Checks authorization
|
||||||
|
description: 'Auth: all, levels: read, write, maintain, dev, admin'
|
||||||
|
tags:
|
||||||
|
- /
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Authorized
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: 'Authorization successful'
|
||||||
|
method:
|
||||||
|
type: string
|
||||||
|
example: 'basic'
|
||||||
|
401:
|
||||||
|
$ref: 'api.yaml#/components/responses/401'
|
||||||
|
500:
|
||||||
|
$ref: 'api.yaml#/components/responses/500'
|
||||||
|
|
||||||
|
/changelog/{timestamp}/{page}/{pagesize}:
|
||||||
|
parameters:
|
||||||
|
- name: timestamp
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: 1970-01-01T00:00:00.000Z
|
||||||
|
- name: page
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 3
|
||||||
|
- name: pagesize
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 30
|
||||||
|
get:
|
||||||
|
summary: get changelog
|
||||||
|
description: 'Auth: basic, levels: maintain, admin<br>Displays all logs older than timestamp, sorted by date descending, page defaults to 0, pagesize defaults to 25<br>Avoid using high page numbers for older logs, better use an older timestamp'
|
||||||
|
tags:
|
||||||
|
- /
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Changelog
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
date:
|
||||||
|
type: string
|
||||||
|
example: 1970-01-01T00:00:00.000Z
|
||||||
|
action:
|
||||||
|
type: string
|
||||||
|
example: PUT /sample/400000000000000000000001
|
||||||
|
collection:
|
||||||
|
type: string
|
||||||
|
example: samples
|
||||||
|
conditions:
|
||||||
|
type: object
|
||||||
|
example:
|
||||||
|
_id: '400000000000000000000001'
|
||||||
|
data:
|
||||||
|
type: object
|
||||||
|
example:
|
||||||
|
type: part
|
||||||
|
status: 0
|
||||||
|
401:
|
||||||
|
$ref: 'api.yaml#/components/responses/401'
|
||||||
|
403:
|
||||||
|
$ref: 'api.yaml#/components/responses/403'
|
||||||
|
404:
|
||||||
|
$ref: 'api.yaml#/components/responses/404'
|
||||||
|
500:
|
||||||
|
$ref: 'api.yaml#/components/responses/500'
|
23
src/db.ts
23
src/db.ts
@ -1,5 +1,7 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import cfenv from 'cfenv';
|
import cfenv from 'cfenv';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import ChangelogModel from './models/changelog';
|
||||||
|
|
||||||
// mongoose.set('debug', true); // enable mongoose debug
|
// mongoose.set('debug', true); // enable mongoose debug
|
||||||
|
|
||||||
@ -112,6 +114,27 @@ export default class db {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// changelog entry
|
||||||
|
static log(req, thisOrCollection, conditions = null, data = null) { // expects (req, this (from query helper)) or (req, collection, conditions, data)
|
||||||
|
if (! (conditions || data)) { // (req, this)
|
||||||
|
data = thisOrCollection._update ? _.cloneDeep(thisOrCollection._update) : {}; // replace undefined with {}
|
||||||
|
Object.keys(data).forEach(key => {
|
||||||
|
if (key[0] === '$') {
|
||||||
|
data[key.substr(1)] = data[key];
|
||||||
|
delete data[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new ChangelogModel({action: req.method + ' ' + req.url, collectionName: thisOrCollection._collection.collectionName, conditions: thisOrCollection._conditions, data: data, user_id: req.authDetails.id ? req.authDetails.id : null}).save(err => {
|
||||||
|
if (err) console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else { // (req, collection, conditions, data)
|
||||||
|
new ChangelogModel({action: req.method + ' ' + req.url, collectionName: thisOrCollection, conditions: conditions, data: data, user_id: req.authDetails.id ? req.authDetails.id : null}).save(err => {
|
||||||
|
if (err) console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static oidResolve (object: any) { // resolve $oid fields to actual ObjectIds recursively
|
private static oidResolve (object: any) { // resolve $oid fields to actual ObjectIds recursively
|
||||||
Object.keys(object).forEach(key => {
|
Object.keys(object).forEach(key => {
|
||||||
if (object[key] !== null && object[key].hasOwnProperty('$oid')) { // found oid, replace
|
if (object[key] !== null && object[key].hasOwnProperty('$oid')) { // found oid, replace
|
||||||
|
@ -5,7 +5,6 @@ import mongoSanitize from 'mongo-sanitize';
|
|||||||
import api from './api';
|
import api from './api';
|
||||||
import db from './db';
|
import db from './db';
|
||||||
|
|
||||||
// TODO: changelog
|
|
||||||
// TODO: check executing index.js/move everything needed into dist
|
// TODO: check executing index.js/move everything needed into dist
|
||||||
// TODO: validation: VZ, Humidity: min/max value, DPT: filename
|
// TODO: validation: VZ, Humidity: min/max value, DPT: filename
|
||||||
// TODO: add multiple samples at once (only GUI)
|
// TODO: add multiple samples at once (only GUI)
|
||||||
|
11
src/models/changelog.ts
Normal file
11
src/models/changelog.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
|
||||||
|
const ChangelogSchema = new mongoose.Schema({
|
||||||
|
action: String,
|
||||||
|
collectionName: String,
|
||||||
|
conditions: Object,
|
||||||
|
data: Object,
|
||||||
|
user_id: mongoose.Schema.Types.ObjectId
|
||||||
|
}, {minimize: false});
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('changelog', ChangelogSchema);
|
@ -1,13 +1,20 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const ConditionTemplateSchema = new mongoose.Schema({
|
const ConditionTemplateSchema = new mongoose.Schema({
|
||||||
first_id: mongoose.Schema.Types.ObjectId,
|
first_id: mongoose.Schema.Types.ObjectId,
|
||||||
name: String,
|
name: String,
|
||||||
version: Number,
|
version: Number,
|
||||||
parameters: [{
|
parameters: [new mongoose.Schema({
|
||||||
name: String,
|
name: String,
|
||||||
range: mongoose.Schema.Types.Mixed
|
range: mongoose.Schema.Types.Mixed
|
||||||
}]
|
} ,{ _id : false })]
|
||||||
}, {minimize: false}); // to allow empty objects
|
}, {minimize: false}); // to allow empty objects
|
||||||
|
|
||||||
export default mongoose.model('condition_template', ConditionTemplateSchema);
|
// changelog query helper
|
||||||
|
ConditionTemplateSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('condition_template', ConditionTemplateSchema);
|
@ -1,14 +1,15 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import MaterialSupplierModel from '../models/material_suppliers';
|
import MaterialSupplierModel from '../models/material_suppliers';
|
||||||
import MaterialGroupsModel from '../models/material_groups';
|
import MaterialGroupsModel from '../models/material_groups';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const MaterialSchema = new mongoose.Schema({
|
const MaterialSchema = new mongoose.Schema({
|
||||||
name: {type: String, index: {unique: true}},
|
name: {type: String, index: {unique: true}},
|
||||||
supplier_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialSupplierModel},
|
supplier_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialSupplierModel},
|
||||||
group_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialGroupsModel},
|
group_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialGroupsModel},
|
||||||
mineral: String,
|
mineral: Number,
|
||||||
glass_fiber: String,
|
glass_fiber: Number,
|
||||||
carbon_fiber: String,
|
carbon_fiber: Number,
|
||||||
numbers: [{
|
numbers: [{
|
||||||
color: String,
|
color: String,
|
||||||
number: String
|
number: String
|
||||||
@ -16,4 +17,10 @@ const MaterialSchema = new mongoose.Schema({
|
|||||||
status: Number
|
status: Number
|
||||||
}, {minimize: false});
|
}, {minimize: false});
|
||||||
|
|
||||||
export default mongoose.model('material', MaterialSchema);
|
// changelog query helper
|
||||||
|
MaterialSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('material', MaterialSchema);
|
@ -1,7 +1,14 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const MaterialGroupsSchema = new mongoose.Schema({
|
const MaterialGroupsSchema = new mongoose.Schema({
|
||||||
name: {type: String, index: {unique: true}}
|
name: {type: String, index: {unique: true}}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default mongoose.model('material_groups', MaterialGroupsSchema);
|
// changelog query helper
|
||||||
|
MaterialGroupsSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('material_groups', MaterialGroupsSchema);
|
@ -1,7 +1,14 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const MaterialSuppliersSchema = new mongoose.Schema({
|
const MaterialSuppliersSchema = new mongoose.Schema({
|
||||||
name: {type: String, index: {unique: true}}
|
name: {type: String, index: {unique: true}}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default mongoose.model('material_suppliers', MaterialSuppliersSchema);
|
// changelog query helper
|
||||||
|
MaterialSuppliersSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('material_suppliers', MaterialSuppliersSchema);
|
@ -1,6 +1,7 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import SampleModel from './sample';
|
import SampleModel from './sample';
|
||||||
import MeasurementTemplateModel from './measurement_template';
|
import MeasurementTemplateModel from './measurement_template';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -11,4 +12,10 @@ const MeasurementSchema = new mongoose.Schema({
|
|||||||
status: Number
|
status: Number
|
||||||
}, {minimize: false});
|
}, {minimize: false});
|
||||||
|
|
||||||
export default mongoose.model('measurement', MeasurementSchema);
|
// changelog query helper
|
||||||
|
MeasurementSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('measurement', MeasurementSchema);
|
@ -1,13 +1,20 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const MeasurementTemplateSchema = new mongoose.Schema({
|
const MeasurementTemplateSchema = new mongoose.Schema({
|
||||||
first_id: mongoose.Schema.Types.ObjectId,
|
first_id: mongoose.Schema.Types.ObjectId,
|
||||||
name: String,
|
name: String,
|
||||||
version: Number,
|
version: Number,
|
||||||
parameters: [{
|
parameters: [new mongoose.Schema({
|
||||||
name: String,
|
name: String,
|
||||||
range: mongoose.Schema.Types.Mixed
|
range: mongoose.Schema.Types.Mixed
|
||||||
}]
|
} ,{ _id : false })]
|
||||||
}, {minimize: false}); // to allow empty objects
|
}, {minimize: false}); // to allow empty objects
|
||||||
|
|
||||||
export default mongoose.model('measurement_template', MeasurementTemplateSchema);
|
// changelog query helper
|
||||||
|
MeasurementTemplateSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('measurement_template', MeasurementTemplateSchema);
|
@ -1,4 +1,5 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const NoteSchema = new mongoose.Schema({
|
const NoteSchema = new mongoose.Schema({
|
||||||
comment: String,
|
comment: String,
|
||||||
@ -9,4 +10,10 @@ const NoteSchema = new mongoose.Schema({
|
|||||||
custom_fields: mongoose.Schema.Types.Mixed
|
custom_fields: mongoose.Schema.Types.Mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
export default mongoose.model('note', NoteSchema);
|
// changelog query helper
|
||||||
|
NoteSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('note', NoteSchema);
|
@ -1,8 +1,15 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const NoteFieldSchema = new mongoose.Schema({
|
const NoteFieldSchema = new mongoose.Schema({
|
||||||
name: {type: String, index: {unique: true}},
|
name: {type: String, index: {unique: true}},
|
||||||
qty: Number
|
qty: Number
|
||||||
});
|
});
|
||||||
|
|
||||||
export default mongoose.model('note_field', NoteFieldSchema);
|
// changelog query helper
|
||||||
|
NoteFieldSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('note_field', NoteFieldSchema);
|
@ -3,6 +3,7 @@ import mongoose from 'mongoose';
|
|||||||
import MaterialModel from './material';
|
import MaterialModel from './material';
|
||||||
import NoteModel from './note';
|
import NoteModel from './note';
|
||||||
import UserModel from './user';
|
import UserModel from './user';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const SampleSchema = new mongoose.Schema({
|
const SampleSchema = new mongoose.Schema({
|
||||||
number: {type: String, index: {unique: true}},
|
number: {type: String, index: {unique: true}},
|
||||||
@ -16,4 +17,10 @@ const SampleSchema = new mongoose.Schema({
|
|||||||
status: Number
|
status: Number
|
||||||
}, {minimize: false});
|
}, {minimize: false});
|
||||||
|
|
||||||
export default mongoose.model('sample', SampleSchema);
|
// changelog query helper
|
||||||
|
SampleSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('sample', SampleSchema);
|
@ -1,4 +1,5 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const UserSchema = new mongoose.Schema({
|
const UserSchema = new mongoose.Schema({
|
||||||
name: {type: String, index: {unique: true}},
|
name: {type: String, index: {unique: true}},
|
||||||
@ -10,4 +11,10 @@ const UserSchema = new mongoose.Schema({
|
|||||||
device_name: String
|
device_name: String
|
||||||
});
|
});
|
||||||
|
|
||||||
export default mongoose.model('user', UserSchema);
|
// changelog query helper
|
||||||
|
UserSchema.query.log = function <Q extends mongoose.DocumentQuery<any, any>> (req) {
|
||||||
|
db.log(req, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mongoose.model<any, mongoose.Model<any, any>>('user', UserSchema);
|
@ -307,7 +307,6 @@ describe('/material', () => {
|
|||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {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'}]}
|
req: {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'}]}
|
||||||
,
|
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).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'}]});
|
should(res.body).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'}]});
|
||||||
@ -317,7 +316,7 @@ describe('/material', () => {
|
|||||||
data.group_id = data.group_id.toString();
|
data.group_id = data.group_id.toString();
|
||||||
data.supplier_id = data.supplier_id.toString();
|
data.supplier_id = data.supplier_id.toString();
|
||||||
data.numbers = data.numbers.map(e => {return {color: e.color, number: e.number}});
|
data.numbers = data.numbers.map(e => {return {color: e.color, number: e.number}});
|
||||||
should(data).be.eql({_id: '100000000000000000000001', name: 'UltramidTKR4355G7_2', supplier_id: '110000000000000000000002', group_id: '900000000000000000000002', mineral: '0', glass_fiber: '35', carbon_fiber: '0', numbers: [{color: 'black', number: '5514212901'}, {color: 'signalviolet', number: '5514612901'}], status: 0, __v: 0});
|
should(data).be.eql({_id: '100000000000000000000001', name: 'UltramidTKR4355G7_2', supplier_id: '110000000000000000000002', group_id: '900000000000000000000002', mineral: 0, glass_fiber: 35, carbon_fiber: 0, numbers: [{color: 'black', number: '5514212901'}, {color: 'signalviolet', number: '5514612901'}], status: 0, __v: 0});
|
||||||
MaterialGroupModel.find({name: 'PA6/6T'}).lean().exec((err, data) => {
|
MaterialGroupModel.find({name: 'PA6/6T'}).lean().exec((err, data) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.lengthOf(1);
|
should(data).have.lengthOf(1);
|
||||||
@ -332,6 +331,24 @@ describe('/material', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/material/100000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {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'}]},
|
||||||
|
log: {
|
||||||
|
collection: 'materials',
|
||||||
|
dataAdd: {
|
||||||
|
group_id: '900000000000000000000002',
|
||||||
|
supplier_id: '110000000000000000000002',
|
||||||
|
status: 0
|
||||||
|
},
|
||||||
|
dataIgn: ['supplier', 'group']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('accepts a color without number', done => {
|
it('accepts a color without number', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -469,6 +486,18 @@ describe('/material', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'delete',
|
||||||
|
url: '/material/100000000000000000000002',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
log: {
|
||||||
|
collection: 'materials',
|
||||||
|
dataAdd: { status: -1}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects deleting a material referenced by samples', done => {
|
it('rejects deleting a material referenced by samples', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
@ -537,6 +566,21 @@ describe('/material', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/material/restore/100000000000000000000008',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {},
|
||||||
|
log: {
|
||||||
|
collection: 'materials',
|
||||||
|
dataAdd: {
|
||||||
|
status: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -592,6 +636,21 @@ describe('/material', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/material/validate/100000000000000000000007',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {},
|
||||||
|
log: {
|
||||||
|
collection: 'materials',
|
||||||
|
dataAdd: {
|
||||||
|
status: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -669,9 +728,9 @@ describe('/material', () => {
|
|||||||
should(materialData).have.lengthOf(1);
|
should(materialData).have.lengthOf(1);
|
||||||
should(materialData[0]).have.only.keys('_id', 'name', 'supplier_id', 'group_id', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', 'status', '__v');
|
should(materialData[0]).have.only.keys('_id', 'name', 'supplier_id', 'group_id', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', 'status', '__v');
|
||||||
should(materialData[0]).have.property('name', 'Crastin CE 2510');
|
should(materialData[0]).have.property('name', 'Crastin CE 2510');
|
||||||
should(materialData[0]).have.property('mineral', '0');
|
should(materialData[0]).have.property('mineral', 0);
|
||||||
should(materialData[0]).have.property('glass_fiber', '30');
|
should(materialData[0]).have.property('glass_fiber', 30);
|
||||||
should(materialData[0]).have.property('carbon_fiber', '0');
|
should(materialData[0]).have.property('carbon_fiber', 0);
|
||||||
should(materialData[0]).have.property('status',globals.status.new);
|
should(materialData[0]).have.property('status',globals.status.new);
|
||||||
should(materialData[0].numbers).have.lengthOf(0);
|
should(materialData[0].numbers).have.lengthOf(0);
|
||||||
MaterialGroupModel.findById(materialData[0].group_id).lean().exec((err, data) => {
|
MaterialGroupModel.findById(materialData[0].group_id).lean().exec((err, data) => {
|
||||||
@ -686,6 +745,20 @@ describe('/material', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/material/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {name: 'Crastin CE 2510', supplier: 'Du Pont', group: 'PBT', mineral: 0, glass_fiber: 30, carbon_fiber: 0, numbers: []},
|
||||||
|
log: {
|
||||||
|
collection: 'materials',
|
||||||
|
dataAdd: {status: 0},
|
||||||
|
dataIgn: ['group_id', 'supplier_id', 'group', 'supplier']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('accepts a color without number', done => {
|
it('accepts a color without number', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
@ -714,9 +787,9 @@ describe('/material', () => {
|
|||||||
should(data[0]).have.only.keys('_id', 'name', 'supplier_id', 'group_id', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', 'status', '__v');
|
should(data[0]).have.only.keys('_id', 'name', 'supplier_id', 'group_id', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', 'status', '__v');
|
||||||
should(data[0]).have.property('_id');
|
should(data[0]).have.property('_id');
|
||||||
should(data[0]).have.property('name', 'Crastin CE 2510');
|
should(data[0]).have.property('name', 'Crastin CE 2510');
|
||||||
should(data[0]).have.property('mineral', '0');
|
should(data[0]).have.property('mineral', 0);
|
||||||
should(data[0]).have.property('glass_fiber', '30');
|
should(data[0]).have.property('glass_fiber', 30);
|
||||||
should(data[0]).have.property('carbon_fiber', '0');
|
should(data[0]).have.property('carbon_fiber', 0);
|
||||||
should(data[0]).have.property('status',globals.status.new);
|
should(data[0]).have.property('status',globals.status.new);
|
||||||
should(_.omit(data[0].numbers[0], '_id')).be.eql({color: 'black', number: ''});
|
should(_.omit(data[0].numbers[0], '_id')).be.eql({color: 'black', number: ''});
|
||||||
done();
|
done();
|
||||||
|
@ -10,6 +10,7 @@ import IdValidate from './validate/id';
|
|||||||
import res400 from './validate/res400';
|
import res400 from './validate/res400';
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import globals from '../globals';
|
import globals from '../globals';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -67,11 +68,11 @@ router.put('/material/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
if (!await nameCheck(material, res, next)) return;
|
if (!await nameCheck(material, res, next)) return;
|
||||||
}
|
}
|
||||||
if (material.hasOwnProperty('group')) {
|
if (material.hasOwnProperty('group')) {
|
||||||
material = await groupResolve(material, next);
|
material = await groupResolve(material, req, next);
|
||||||
if (!material) return;
|
if (!material) return;
|
||||||
}
|
}
|
||||||
if (material.hasOwnProperty('supplier')) {
|
if (material.hasOwnProperty('supplier')) {
|
||||||
material = await supplierResolve(material, next);
|
material = await supplierResolve(material, req, next);
|
||||||
if (!material) return;
|
if (!material) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ router.put('/material/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
material.status = globals.status.new; // set status to new
|
material.status = globals.status.new; // set status to new
|
||||||
}
|
}
|
||||||
|
|
||||||
await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
|
await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).log(req).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(MaterialValidate.output(data));
|
res.json(MaterialValidate.output(data));
|
||||||
});
|
});
|
||||||
@ -96,7 +97,7 @@ router.delete('/material/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
if (data.length) {
|
if (data.length) {
|
||||||
return res.status(400).json({status: 'Material still in use'});
|
return res.status(400).json({status: 'Material still in use'});
|
||||||
}
|
}
|
||||||
MaterialModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
|
MaterialModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).log(req).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
if (data) {
|
if (data) {
|
||||||
res.json({status: 'OK'});
|
res.json({status: 'OK'});
|
||||||
@ -127,15 +128,16 @@ router.post('/material/new', async (req, res, next) => {
|
|||||||
if (error) return res400(error, res);
|
if (error) return res400(error, res);
|
||||||
|
|
||||||
if (!await nameCheck(material, res, next)) return;
|
if (!await nameCheck(material, res, next)) return;
|
||||||
material = await groupResolve(material, next);
|
material = await groupResolve(material, req, next);
|
||||||
if (!material) return;
|
if (!material) return;
|
||||||
material = await supplierResolve(material, next);
|
material = await supplierResolve(material, req, next);
|
||||||
if (!material) return;
|
if (!material) return;
|
||||||
|
|
||||||
|
|
||||||
material.status = globals.status.new; // set status to new
|
material.status = globals.status.new; // set status to new
|
||||||
await new MaterialModel(material).save(async (err, data) => {
|
await new MaterialModel(material).save(async (err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
db.log(req, 'materials', {_id: data._id}, data.toObject());
|
||||||
await data.populate('group_id').populate('supplier_id').execPopulate().catch(err => next(err));
|
await data.populate('group_id').populate('supplier_id').execPopulate().catch(err => next(err));
|
||||||
if (data instanceof Error) return;
|
if (data instanceof Error) return;
|
||||||
res.json(MaterialValidate.output(data.toObject()));
|
res.json(MaterialValidate.output(data.toObject()));
|
||||||
@ -176,16 +178,16 @@ async function nameCheck (material, res, next) { // check if name was already t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function groupResolve (material, next) {
|
async function groupResolve (material, req, next) {
|
||||||
const groupData = await MaterialGroupModel.findOneAndUpdate({name: material.group}, {name: material.group}, {upsert: true, new: true}).lean().exec().catch(err => next(err)) as any;
|
const groupData = await MaterialGroupModel.findOneAndUpdate({name: material.group}, {name: material.group}, {upsert: true, new: true}).log(req).lean().exec().catch(err => next(err)) as any;
|
||||||
if (groupData instanceof Error) return false;
|
if (groupData instanceof Error) return false;
|
||||||
material.group_id = groupData._id;
|
material.group_id = groupData._id;
|
||||||
delete material.group;
|
delete material.group;
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function supplierResolve (material, next) {
|
async function supplierResolve (material, req, next) {
|
||||||
const supplierData = await MaterialSupplierModel.findOneAndUpdate({name: material.supplier}, {name: material.supplier}, {upsert: true, new: true}).lean().exec().catch(err => next(err)) as any;
|
const supplierData = await MaterialSupplierModel.findOneAndUpdate({name: material.supplier}, {name: material.supplier}, {upsert: true, new: true}).log(req).lean().exec().catch(err => next(err)) as any;
|
||||||
if (supplierData instanceof Error) return false;
|
if (supplierData instanceof Error) return false;
|
||||||
material.supplier_id = supplierData._id;
|
material.supplier_id = supplierData._id;
|
||||||
delete material.supplier;
|
delete material.supplier;
|
||||||
@ -193,7 +195,7 @@ async function supplierResolve (material, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setStatus (status, req, res, next) { // set measurement status
|
function setStatus (status, req, res, next) { // set measurement status
|
||||||
MaterialModel.findByIdAndUpdate(req.params.id, {status: status}).lean().exec((err, data) => {
|
MaterialModel.findByIdAndUpdate(req.params.id, {status: status}).log(req).lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
@ -138,6 +138,23 @@ describe('/measurement', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/measurement/800000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {values: {dpt: [[1,2],[3,4],[5,6]]}},
|
||||||
|
log: {
|
||||||
|
collection: 'measurements',
|
||||||
|
dataAdd: {
|
||||||
|
measurement_template: '300000000000000000000001',
|
||||||
|
sample_id: '400000000000000000000001',
|
||||||
|
status: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('allows changing only one value', done => {
|
it('allows changing only one value', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -296,7 +313,7 @@ describe('/measurement', () => {
|
|||||||
method: 'delete',
|
method: 'delete',
|
||||||
url: '/measurement/800000000000000000000001',
|
url: '/measurement/800000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({status: 'OK'});
|
should(res.body).be.eql({status: 'OK'});
|
||||||
@ -307,6 +324,20 @@ describe('/measurement', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'delete',
|
||||||
|
url: '/measurement/800000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
log: {
|
||||||
|
collection: 'measurements',
|
||||||
|
dataAdd: {
|
||||||
|
status: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
@ -383,6 +414,21 @@ describe('/measurement', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/measurement/restore/800000000000000000000004',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {},
|
||||||
|
log: {
|
||||||
|
collection: 'measurements',
|
||||||
|
dataAdd: {
|
||||||
|
status: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -438,6 +484,21 @@ describe('/measurement', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/measurement/validate/800000000000000000000003',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {},
|
||||||
|
log: {
|
||||||
|
collection: 'measurements',
|
||||||
|
dataAdd: {
|
||||||
|
status: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -517,6 +578,21 @@ describe('/measurement', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/measurement/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {sample_id: '400000000000000000000001', values: {'weight %': 0.8, 'standard deviation': 0.1}, measurement_template: '300000000000000000000002'},
|
||||||
|
log: {
|
||||||
|
collection: 'measurements',
|
||||||
|
dataAdd: {
|
||||||
|
status: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an invalid sample id', done => {
|
it('rejects an invalid sample id', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
@ -9,6 +9,7 @@ import IdValidate from './validate/id';
|
|||||||
import res400 from './validate/res400';
|
import res400 from './validate/res400';
|
||||||
import ParametersValidate from './validate/parameters';
|
import ParametersValidate from './validate/parameters';
|
||||||
import globals from '../globals';
|
import globals from '../globals';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -56,7 +57,7 @@ router.put('/measurement/' + IdValidate.parameter(), async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!await templateCheck(measurement, 'change', res, next)) return;
|
if (!await templateCheck(measurement, 'change', res, next)) return;
|
||||||
await MeasurementModel.findByIdAndUpdate(req.params.id, measurement, {new: true}).lean().exec((err, data) => {
|
await MeasurementModel.findByIdAndUpdate(req.params.id, measurement, {new: true}).log(req).lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(MeasurementValidate.output(data));
|
res.json(MeasurementValidate.output(data));
|
||||||
});
|
});
|
||||||
@ -71,7 +72,7 @@ router.delete('/measurement/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
return res.status(404).json({status: 'Not found'});
|
return res.status(404).json({status: 'Not found'});
|
||||||
}
|
}
|
||||||
if (!await sampleIdCheck(data, req, res, next)) return;
|
if (!await sampleIdCheck(data, req, res, next)) return;
|
||||||
await MeasurementModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).lean().exec(err => {
|
await MeasurementModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).log(req).lean().exec(err => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
return res.json({status: 'OK'});
|
return res.json({status: 'OK'});
|
||||||
});
|
});
|
||||||
@ -103,6 +104,7 @@ router.post('/measurement/new', async (req, res, next) => {
|
|||||||
measurement.status = 0;
|
measurement.status = 0;
|
||||||
await new MeasurementModel(measurement).save((err, data) => {
|
await new MeasurementModel(measurement).save((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
db.log(req, 'measurements', {_id: data._id}, data.toObject());
|
||||||
res.json(MeasurementValidate.output(data.toObject()));
|
res.json(MeasurementValidate.output(data.toObject()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -156,7 +158,7 @@ async function templateCheck (measurement, param, res, next) { // validate meas
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setStatus (status, req, res, next) { // set measurement status
|
function setStatus (status, req, res, next) { // set measurement status
|
||||||
MeasurementModel.findByIdAndUpdate(req.params.id, {status: status}).lean().exec((err, data) => {
|
MeasurementModel.findByIdAndUpdate(req.params.id, {status: status}).log(req).lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import TestHelper from "../test/helper";
|
import TestHelper from "../test/helper";
|
||||||
|
import should from 'should/as-function';
|
||||||
import db from '../db';
|
import db from '../db';
|
||||||
|
|
||||||
|
|
||||||
@ -20,6 +21,121 @@ describe('/', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('GET /changelog/{timestamp}/{page}/{pagesize}', () => {
|
||||||
|
it('returns the first page', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/0/2',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body).have.lengthOf(2);
|
||||||
|
should(res.body[0].date).be.eql('1979-07-28T06:04:51.000Z');
|
||||||
|
should(res.body[1].date).be.eql('1979-07-28T06:04:50.000Z');
|
||||||
|
should(res.body).matchEach(log => {
|
||||||
|
should(log).have.only.keys('date', 'action', 'collection', 'conditions', 'data');
|
||||||
|
should(log).have.property('action', 'PUT /sample/400000000000000000000001');
|
||||||
|
should(log).have.property('collection', 'samples');
|
||||||
|
should(log).have.property('conditions', {_id: '400000000000000000000001'});
|
||||||
|
should(log).have.property('data', {type: 'part', status: 0});
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns another page', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/1/2',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body).have.lengthOf(1);
|
||||||
|
should(res.body[0].date).be.eql('1979-07-28T06:04:49.000Z');
|
||||||
|
should(res.body).matchEach(log => {
|
||||||
|
should(log).have.only.keys('date', 'action', 'collection', 'conditions', 'data');
|
||||||
|
should(log).have.property('action', 'PUT /sample/400000000000000000000001');
|
||||||
|
should(log).have.property('collection', 'samples');
|
||||||
|
should(log).have.property('conditions', {_id: '400000000000000000000001'});
|
||||||
|
should(log).have.property('data', {type: 'part', status: 0});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns an empty array for a page with no results', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/10/2',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body).have.lengthOf(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects timestamps pre unix epoch', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1879-07-28T06:04:51.000Z/10/2',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 400,
|
||||||
|
res: {status: 'Invalid body format', details: '"timestamp" must be larger than or equal to "1970-01-01T00:00:00.000Z"'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects invalid timestamps', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-14-28T06:04:51.000Z/10/2',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 400,
|
||||||
|
res: {status: 'Invalid body format', details: '"timestamp" must be in ISO 8601 date format'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects negative page numbers', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/-10/2',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 400,
|
||||||
|
res: {status: 'Invalid body format', details: '"page" must be larger than or equal to 0'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects negative pagesizes', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/10/-2',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 400,
|
||||||
|
res: {status: 'Invalid body format', details: '"pagesize" must be larger than or equal to 0'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects request from a write user', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/10/2',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 403
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects requests from an API key', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/10/2',
|
||||||
|
auth: {key: 'admin'},
|
||||||
|
httpStatus: 401
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects unauthorized requests', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/changelog/1979-07-28T06:04:51.000Z/10/2',
|
||||||
|
httpStatus: 401
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Unknown routes', () => {
|
describe('Unknown routes', () => {
|
||||||
it('return a 404 message', done => {
|
it('return a 404 message', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import globals from '../globals';
|
import globals from '../globals';
|
||||||
|
import RootValidate from './validate/root';
|
||||||
|
import res400 from './validate/res400';
|
||||||
|
import ChangelogModel from '../models/changelog';
|
||||||
|
import mongoose from 'mongoose';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
@ -12,4 +17,18 @@ router.get('/authorized', (req, res) => {
|
|||||||
res.json({status: 'Authorization successful', method: req.authDetails.method});
|
res.json({status: 'Authorization successful', method: req.authDetails.method});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/changelog/:timestamp/:page?/:pagesize?', (req, res, next) => {
|
||||||
|
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
|
const {error, value: options} = RootValidate.changelogParams({timestamp: req.params.timestamp, page: req.params.page, pagesize: req.params.pagesize});
|
||||||
|
if (error) return res400(error, res);
|
||||||
|
|
||||||
|
const id = new mongoose.Types.ObjectId(Math.floor(new Date(options.timestamp).getTime() / 1000).toString(16) + '0000000000000000');
|
||||||
|
ChangelogModel.find({_id: {$lte: id}}).sort({_id: -1}).skip(options.page * options.pagesize).limit(options.pagesize).lean().exec((err, data) => {
|
||||||
|
if (err) return next(err);
|
||||||
|
|
||||||
|
res.json(_.compact(data.map(e => RootValidate.changelogOutput(e)))); // validate all and filter null values from validation errors
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -13,7 +13,6 @@ import mongoose from 'mongoose';
|
|||||||
// TODO: write script for data import
|
// TODO: write script for data import
|
||||||
// TODO: allow adding sample numbers for existing samples
|
// TODO: allow adding sample numbers for existing samples
|
||||||
|
|
||||||
|
|
||||||
describe('/sample', () => {
|
describe('/sample', () => {
|
||||||
let server;
|
let server;
|
||||||
before(done => TestHelper.before(done));
|
before(done => TestHelper.before(done));
|
||||||
@ -374,6 +373,22 @@ describe('/sample', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {type: 'part', color: 'signalviolet', batch: '114531', condition: {condition_template: '200000000000000000000003'}, material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
log: {
|
||||||
|
collection: 'samples',
|
||||||
|
dataAdd: {
|
||||||
|
status: 0
|
||||||
|
},
|
||||||
|
dataIgn: ['notes', 'note_id']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('adjusts the note_fields correctly', done => {
|
it('adjusts the note_fields correctly', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -707,6 +722,19 @@ describe('/sample', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'delete',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
log: {
|
||||||
|
collection: 'samples',
|
||||||
|
skip: 1,
|
||||||
|
dataAdd: {status: -1}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('keeps the notes of the sample', done => {
|
it('keeps the notes of the sample', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
@ -867,6 +895,24 @@ describe('/sample', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/restore/400000000000000000000005',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {},
|
||||||
|
log: {
|
||||||
|
collection: 'samples',
|
||||||
|
dataAdd: {
|
||||||
|
group_id: '900000000000000000000002',
|
||||||
|
supplier_id: '110000000000000000000002',
|
||||||
|
status: 0
|
||||||
|
},
|
||||||
|
dataIgn: ['group_id', 'supplier_id']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -922,6 +968,24 @@ describe('/sample', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/validate/400000000000000000000003',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {},
|
||||||
|
log: {
|
||||||
|
collection: 'samples',
|
||||||
|
dataAdd: {
|
||||||
|
group_id: '900000000000000000000002',
|
||||||
|
supplier_id: '110000000000000000000002',
|
||||||
|
status: 10
|
||||||
|
},
|
||||||
|
dataIgn: ['group_id', 'supplier_id']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects validating a sample without condition', done => {
|
it('rejects validating a sample without condition', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -1038,6 +1102,24 @@ describe('/sample', () => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
log: {
|
||||||
|
collection: 'samples',
|
||||||
|
dataAdd: {
|
||||||
|
number: 'Rng37',
|
||||||
|
user_id: '000000000000000000000002',
|
||||||
|
status: 0
|
||||||
|
},
|
||||||
|
dataIgn: ['notes', 'note_id']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('stores the custom fields', done => {
|
it('stores the custom fields', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
@ -14,6 +14,7 @@ import mongoose from 'mongoose';
|
|||||||
import ConditionTemplateModel from '../models/condition_template';
|
import ConditionTemplateModel from '../models/condition_template';
|
||||||
import ParametersValidate from './validate/parameters';
|
import ParametersValidate from './validate/parameters';
|
||||||
import globals from '../globals';
|
import globals from '../globals';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -101,9 +102,9 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
newNotes = !_.isEqual(_.pick(IdValidate.stringify(data), _.keys(sample.notes)), sample.notes); // check if notes were changed
|
newNotes = !_.isEqual(_.pick(IdValidate.stringify(data), _.keys(sample.notes)), sample.notes); // check if notes were changed
|
||||||
if (newNotes) {
|
if (newNotes) {
|
||||||
if (data.hasOwnProperty('custom_fields')) { // update note_fields
|
if (data.hasOwnProperty('custom_fields')) { // update note_fields
|
||||||
customFieldsChange(Object.keys(data.custom_fields), -1);
|
customFieldsChange(Object.keys(data.custom_fields), -1, req);
|
||||||
}
|
}
|
||||||
await NoteModel.findByIdAndDelete(sampleData.note_id).lean().exec(err => { // delete old notes
|
await NoteModel.findByIdAndDelete(sampleData.note_id).log(req).lean().exec(err => { // delete old notes
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -112,9 +113,10 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
if (_.keys(sample.notes).length > 0 && newNotes) { // save new notes
|
if (_.keys(sample.notes).length > 0 && newNotes) { // save new notes
|
||||||
if (!await sampleRefCheck(sample, res, next)) return;
|
if (!await sampleRefCheck(sample, res, next)) return;
|
||||||
if (sample.notes.hasOwnProperty('custom_fields') && Object.keys(sample.notes.custom_fields).length > 0) { // new custom_fields
|
if (sample.notes.hasOwnProperty('custom_fields') && Object.keys(sample.notes.custom_fields).length > 0) { // new custom_fields
|
||||||
customFieldsChange(Object.keys(sample.notes.custom_fields), 1);
|
customFieldsChange(Object.keys(sample.notes.custom_fields), 1, req);
|
||||||
}
|
}
|
||||||
let data = await new NoteModel(sample.notes).save().catch(err => { return next(err)}); // save new notes
|
let data = await new NoteModel(sample.notes).save().catch(err => { return next(err)}); // save new notes
|
||||||
|
db.log(req, 'notes', {_id: data._id}, data.toObject());
|
||||||
delete sample.notes;
|
delete sample.notes;
|
||||||
sample.note_id = data._id;
|
sample.note_id = data._id;
|
||||||
}
|
}
|
||||||
@ -125,7 +127,7 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
sample.status = globals.status.new;
|
sample.status = globals.status.new;
|
||||||
}
|
}
|
||||||
|
|
||||||
await SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).lean().exec((err, data: any) => {
|
await SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).log(req).lean().exec((err, data: any) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(SampleValidate.output(data));
|
res.json(SampleValidate.output(data));
|
||||||
});
|
});
|
||||||
@ -145,18 +147,18 @@ router.delete('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
// only maintain and admin are allowed to edit other user's data
|
// only maintain and admin are allowed to edit other user's data
|
||||||
if (sampleData.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
if (sampleData.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
await SampleModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).lean().exec(err => { // set sample status
|
await SampleModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).log(req).lean().exec(err => { // set sample status
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
// set status of associated measurements also to deleted
|
// set status of associated measurements also to deleted
|
||||||
MeasurementModel.updateMany({sample_id: mongoose.Types.ObjectId(req.params.id)}, {status: -1}).lean().exec(err => {
|
MeasurementModel.updateMany({sample_id: mongoose.Types.ObjectId(req.params.id)}, {status: -1}).log(req).lean().exec(err => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
if (sampleData.note_id !== null) { // handle notes
|
if (sampleData.note_id !== null) { // handle notes
|
||||||
NoteModel.findById(sampleData.note_id).lean().exec((err, data: any) => { // find notes to update note_fields
|
NoteModel.findById(sampleData.note_id).lean().exec((err, data: any) => { // find notes to update note_fields
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
if (data.hasOwnProperty('custom_fields')) { // update note_fields
|
if (data.hasOwnProperty('custom_fields')) { // update note_fields
|
||||||
customFieldsChange(Object.keys(data.custom_fields), -1);
|
customFieldsChange(Object.keys(data.custom_fields), -1, req);
|
||||||
}
|
}
|
||||||
res.json({status: 'OK'});
|
res.json({status: 'OK'});
|
||||||
});
|
});
|
||||||
@ -172,7 +174,7 @@ router.delete('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
router.put('/sample/restore/' + IdValidate.parameter(), (req, res, next) => {
|
router.put('/sample/restore/' + IdValidate.parameter(), (req, res, next) => {
|
||||||
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
SampleModel.findByIdAndUpdate(req.params.id, {status: globals.status.new}).lean().exec((err, data) => {
|
SampleModel.findByIdAndUpdate(req.params.id, {status: globals.status.new}).log(req).lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@ -202,7 +204,7 @@ router.put('/sample/validate/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
return res.status(400).json({status: 'Sample without measurements cannot be valid'});
|
return res.status(400).json({status: 'Sample without measurements cannot be valid'});
|
||||||
}
|
}
|
||||||
|
|
||||||
SampleModel.findByIdAndUpdate(req.params.id, {status: globals.status.validated}).lean().exec(err => {
|
SampleModel.findByIdAndUpdate(req.params.id, {status: globals.status.validated}).log(req).lean().exec(err => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json({status: 'OK'});
|
res.json({status: 'OK'});
|
||||||
});
|
});
|
||||||
@ -224,7 +226,7 @@ router.post('/sample/new', async (req, res, next) => {
|
|||||||
if (!await sampleRefCheck(sample, res, next)) return;
|
if (!await sampleRefCheck(sample, res, next)) return;
|
||||||
|
|
||||||
if (sample.notes.hasOwnProperty('custom_fields') && Object.keys(sample.notes.custom_fields).length > 0) { // new custom_fields
|
if (sample.notes.hasOwnProperty('custom_fields') && Object.keys(sample.notes.custom_fields).length > 0) { // new custom_fields
|
||||||
customFieldsChange(Object.keys(sample.notes.custom_fields), 1);
|
customFieldsChange(Object.keys(sample.notes.custom_fields), 1, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isEmpty(sample.condition)) { // do not execute check if condition is empty
|
if (!_.isEmpty(sample.condition)) { // do not execute check if condition is empty
|
||||||
@ -242,12 +244,14 @@ router.post('/sample/new', async (req, res, next) => {
|
|||||||
|
|
||||||
await new NoteModel(sample.notes).save((err, data) => { // save notes
|
await new NoteModel(sample.notes).save((err, data) => { // save notes
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
db.log(req, 'notes', {_id: data._id}, data.toObject());
|
||||||
delete sample.notes;
|
delete sample.notes;
|
||||||
sample.note_id = data._id;
|
sample.note_id = data._id;
|
||||||
sample.user_id = req.authDetails.id;
|
sample.user_id = req.authDetails.id;
|
||||||
|
|
||||||
new SampleModel(sample).save((err, data) => {
|
new SampleModel(sample).save((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
db.log(req, 'samples', {_id: data._id}, data.toObject());
|
||||||
res.json(SampleValidate.output(data.toObject()));
|
res.json(SampleValidate.output(data.toObject()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -330,7 +334,7 @@ async function conditionCheck (condition, param, res, next, checkVersion = true)
|
|||||||
|
|
||||||
function sampleRefCheck (sample, res, next) { // validate sample_references, resolves false for invalid reference
|
function sampleRefCheck (sample, res, next) { // validate sample_references, resolves false for invalid reference
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
if (sample.notes.sample_references.length > 0) { // there are sample_references
|
if (sample.notes.hasOwnProperty('sample_references') && sample.notes.sample_references.length > 0) { // there are sample_references
|
||||||
let referencesCount = sample.notes.sample_references.length; // count to keep track of running async operations
|
let referencesCount = sample.notes.sample_references.length; // count to keep track of running async operations
|
||||||
|
|
||||||
sample.notes.sample_references.forEach(reference => {
|
sample.notes.sample_references.forEach(reference => {
|
||||||
@ -353,17 +357,18 @@ function sampleRefCheck (sample, res, next) { // validate sample_references, re
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function customFieldsChange (fields, amount) { // update custom_fields and respective quantities
|
function customFieldsChange (fields, amount, req) { // update custom_fields and respective quantities
|
||||||
fields.forEach(field => {
|
fields.forEach(field => {
|
||||||
NoteFieldModel.findOneAndUpdate({name: field}, {$inc: {qty: amount}}, {new: true}).lean().exec((err, data: any) => { // check if field exists
|
NoteFieldModel.findOneAndUpdate({name: field}, {$inc: {qty: amount}} as any, {new: true}).log(req).lean().exec((err, data: any) => { // check if field exists
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
if (!data) { // new field
|
if (!data) { // new field
|
||||||
new NoteFieldModel({name: field, qty: 1}).save(err => {
|
new NoteFieldModel({name: field, qty: 1}).save((err, data) => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
|
db.log(req, 'note_fields', {_id: data._id}, data.toObject());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else if (data.qty <= 0) { // delete document if field is not used anymore
|
else if (data.qty <= 0) { // delete document if field is not used anymore
|
||||||
NoteFieldModel.findOneAndDelete({name: field}).lean().exec(err => {
|
NoteFieldModel.findOneAndDelete({name: field}).log(req).lean().exec(err => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,22 @@ describe('/template', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/template/condition/200000000000000000000001',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]},
|
||||||
|
log: {
|
||||||
|
collection: 'condition_templates',
|
||||||
|
dataAdd: {
|
||||||
|
first_id: '200000000000000000000001',
|
||||||
|
version: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('allows changing only one property', done => {
|
it('allows changing only one property', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -328,6 +344,20 @@ describe('/template', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/template/condition/new',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]},
|
||||||
|
log: {
|
||||||
|
collection: 'condition_templates',
|
||||||
|
dataAdd: {version: 1},
|
||||||
|
dataIgn: ['first_id']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects a missing name', done => {
|
it('rejects a missing name', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
@ -552,7 +582,7 @@ describe('/template', () => {
|
|||||||
url: '/template/measurement/300000000000000000000001',
|
url: '/template/measurement/300000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {name: 'IR spectrum', parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]},
|
req: {name: 'IR spectrum', parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(_.omit(res.body, '_id')).be.eql({name: 'IR spectrum', version: 2, parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]});
|
should(_.omit(res.body, '_id')).be.eql({name: 'IR spectrum', version: 2, parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]});
|
||||||
@ -571,6 +601,22 @@ describe('/template', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/template/measurement/300000000000000000000001',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {name: 'IR spectrum', parameters: [{name: 'data point table', range: {min: 0, max: 1000}}]},
|
||||||
|
log: {
|
||||||
|
collection: 'measurement_templates',
|
||||||
|
dataAdd: {
|
||||||
|
first_id: '300000000000000000000001',
|
||||||
|
version: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('allows changing only one property', done => {
|
it('allows changing only one property', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -747,6 +793,20 @@ describe('/template', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/template/measurement/new',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {name: 'vz', parameters: [{name: 'vz', range: {min: 1}}]},
|
||||||
|
log: {
|
||||||
|
collection: 'measurement_templates',
|
||||||
|
dataAdd: {version: 1},
|
||||||
|
dataIgn: ['first_id']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects a missing name', done => {
|
it('rejects a missing name', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
@ -7,6 +7,7 @@ import MeasurementTemplateModel from '../models/measurement_template';
|
|||||||
import res400 from './validate/res400';
|
import res400 from './validate/res400';
|
||||||
import IdValidate from './validate/id';
|
import IdValidate from './validate/id';
|
||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ router.put('/template/:collection(measurement|condition)/' + IdValidate.paramete
|
|||||||
template.version = templateData.version + 1; // increase version
|
template.version = templateData.version + 1; // increase version
|
||||||
await new (model(req))(_.assign({}, _.omit(templateData, ['_id', '__v']), template)).save((err, data) => { // save new template, fill with old properties
|
await new (model(req))(_.assign({}, _.omit(templateData, ['_id', '__v']), template)).save((err, data) => { // save new template, fill with old properties
|
||||||
if (err) next (err);
|
if (err) next (err);
|
||||||
|
db.log(req, req.params.collection + '_templates', {_id: data._id}, data.toObject());
|
||||||
res.json(TemplateValidate.output(data.toObject()));
|
res.json(TemplateValidate.output(data.toObject()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -71,6 +73,7 @@ router.post('/template/:collection(measurement|condition)/new', async (req, res,
|
|||||||
template.version = 1; // set template version
|
template.version = 1; // set template version
|
||||||
await new (model(req))(template).save((err, data) => {
|
await new (model(req))(template).save((err, data) => {
|
||||||
if (err) next (err);
|
if (err) next (err);
|
||||||
|
db.log(req, req.params.collection + '_templates', {_id: data._id}, data.toObject());
|
||||||
res.json(TemplateValidate.output(data.toObject()));
|
res.json(TemplateValidate.output(data.toObject()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ import UserModel from '../models/user';
|
|||||||
import TestHelper from "../test/helper";
|
import TestHelper from "../test/helper";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe('/user', () => {
|
describe('/user', () => {
|
||||||
let server;
|
let server;
|
||||||
before(done => TestHelper.before(done));
|
before(done => TestHelper.before(done));
|
||||||
@ -199,6 +200,19 @@ describe('/user', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/user',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {name: 'adminnew', email: 'adminnew@bosch.com', pass: 'Abc123##', location: 'Abt', device_name: 'test'},
|
||||||
|
log: {
|
||||||
|
collection: 'users',
|
||||||
|
dataIgn: ['pass']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('lets the admin change a user level', done => {
|
it('lets the admin change a user level', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -370,6 +384,17 @@ describe('/user', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'delete',
|
||||||
|
url: '/user',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
log: {
|
||||||
|
collection: 'users'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects requests from non-admins for another user', done => {
|
it('rejects requests from non-admins for another user', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
@ -482,6 +507,19 @@ describe('/user', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/user/new',
|
||||||
|
auth: {basic: 'admin'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {email: 'john.doe@bosch.com', name: 'johndoe', pass: 'Abc123!#', level: 'read', location: 'Rng', device_name: 'Alpha II'},
|
||||||
|
log: {
|
||||||
|
collection: 'users',
|
||||||
|
dataIgn: ['pass', 'key']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects a username already in use', done => {
|
it('rejects a username already in use', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
@ -587,6 +625,18 @@ describe('/user', () => {
|
|||||||
res: {status: 'OK'}
|
res: {status: 'OK'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('creates a changelog', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/user/passreset',
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {email: 'jane.doe@bosch.com', name: 'janedoe'},
|
||||||
|
log: {
|
||||||
|
collection: 'users',
|
||||||
|
dataIgn: ['email', 'name', 'pass']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('returns 404 for wrong username/email combo', done => {
|
it('returns 404 for wrong username/email combo', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
@ -7,6 +7,7 @@ import UserValidate from './validate/user';
|
|||||||
import UserModel from '../models/user';
|
import UserModel from '../models/user';
|
||||||
import mail from '../helpers/mail';
|
import mail from '../helpers/mail';
|
||||||
import res400 from './validate/res400';
|
import res400 from './validate/res400';
|
||||||
|
import db from '../db';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ router.put('/user:username([/](?!key|new).?*|/?)', async (req, res, next) => {
|
|||||||
if (!await usernameCheck(user.name, res, next)) return;
|
if (!await usernameCheck(user.name, res, next)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await UserModel.findOneAndUpdate({name: username}, user, {new: true}).lean().exec( (err, data:any) => {
|
await UserModel.findOneAndUpdate({name: username}, user, {new: true}).log(req).lean().exec( (err, data:any) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
if (data) {
|
if (data) {
|
||||||
res.json(UserValidate.output(data));
|
res.json(UserValidate.output(data));
|
||||||
@ -70,7 +71,7 @@ router.delete('/user:username([/](?!key|new).?*|/?)', (req, res, next) => { //
|
|||||||
const username = getUsername(req, res);
|
const username = getUsername(req, res);
|
||||||
if (!username) return;
|
if (!username) return;
|
||||||
|
|
||||||
UserModel.findOneAndDelete({name: username}).lean().exec( (err, data:any) => {
|
UserModel.findOneAndDelete({name: username}).log(req).lean().exec( (err, data:any) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
if (data) {
|
if (data) {
|
||||||
res.json({status: 'OK'})
|
res.json({status: 'OK'})
|
||||||
@ -105,6 +106,7 @@ router.post('/user/new', async (req, res, next) => {
|
|||||||
user.pass = hash;
|
user.pass = hash;
|
||||||
new UserModel(user).save((err, data) => { // store user
|
new UserModel(user).save((err, data) => { // store user
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
db.log(req, 'users', {_id: data._id}, data.toObject());
|
||||||
res.json(UserValidate.output(data.toObject()));
|
res.json(UserValidate.output(data.toObject()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -119,7 +121,7 @@ router.post('/user/passreset', (req, res, next) => {
|
|||||||
bcrypt.hash(newPass, 10, (err, hash) => { // password hashing
|
bcrypt.hash(newPass, 10, (err, hash) => { // password hashing
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
UserModel.findByIdAndUpdate(data[0]._id, {pass: hash}, err => { // write new password
|
UserModel.findByIdAndUpdate(data[0]._id, {pass: hash}).log(req).exec(err => { // write new password
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
// send email
|
// send email
|
||||||
|
50
src/routes/validate/root.ts
Normal file
50
src/routes/validate/root.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import Joi from '@hapi/joi';
|
||||||
|
import IdValidate from './id';
|
||||||
|
|
||||||
|
export default class RootValidate { // validate input for root methods
|
||||||
|
private static changelog = {
|
||||||
|
timestamp: Joi.date()
|
||||||
|
.iso()
|
||||||
|
.min('1970-01-01T00:00:00.000Z'),
|
||||||
|
|
||||||
|
page: Joi.number()
|
||||||
|
.integer()
|
||||||
|
.min(0)
|
||||||
|
.default(0),
|
||||||
|
|
||||||
|
pagesize: Joi.number()
|
||||||
|
.integer()
|
||||||
|
.min(0)
|
||||||
|
.default(25),
|
||||||
|
|
||||||
|
action: Joi.string(),
|
||||||
|
|
||||||
|
collection: Joi.string(),
|
||||||
|
|
||||||
|
conditions: Joi.object(),
|
||||||
|
|
||||||
|
data: Joi.object()
|
||||||
|
};
|
||||||
|
|
||||||
|
static changelogParams (data) {
|
||||||
|
return Joi.object({
|
||||||
|
timestamp: this.changelog.timestamp.required(),
|
||||||
|
page: this.changelog.page,
|
||||||
|
pagesize: this.changelog.pagesize
|
||||||
|
}).validate(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static changelogOutput (data) {
|
||||||
|
data.date = data._id.getTimestamp();
|
||||||
|
data.collection = data.collectionName;
|
||||||
|
data = IdValidate.stringify(data);
|
||||||
|
const {value, error} = Joi.object({
|
||||||
|
date: this.changelog.timestamp,
|
||||||
|
action: this.changelog.action,
|
||||||
|
collection: this.changelog.collection,
|
||||||
|
conditions: this.changelog.conditions,
|
||||||
|
data: this.changelog.data,
|
||||||
|
}).validate(data, {stripUnknown: true});
|
||||||
|
return error !== undefined? null : value;
|
||||||
|
}
|
||||||
|
}
|
@ -69,7 +69,7 @@ export default class SampleValidate {
|
|||||||
}
|
}
|
||||||
else if (param === 'new-admin') {
|
else if (param === 'new-admin') {
|
||||||
return Joi.object({
|
return Joi.object({
|
||||||
number: this.sample.number.required(),
|
number: this.sample.number,
|
||||||
color: this.sample.color.required(),
|
color: this.sample.color.required(),
|
||||||
type: this.sample.type.required(),
|
type: this.sample.type.required(),
|
||||||
batch: this.sample.batch.required(),
|
batch: this.sample.batch.required(),
|
||||||
|
@ -596,6 +596,64 @@
|
|||||||
"key": "000000000000000000001004",
|
"key": "000000000000000000001004",
|
||||||
"__v": 0
|
"__v": 0
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"changelogs": [
|
||||||
|
{
|
||||||
|
"_id" : {"$oid": "120000010000000000000000"},
|
||||||
|
"action" : "PUT /sample/400000000000000000000001",
|
||||||
|
"collectionName" : "samples",
|
||||||
|
"conditions" : {
|
||||||
|
"_id" : {"$oid": "400000000000000000000001"}
|
||||||
|
},
|
||||||
|
"data" : {
|
||||||
|
"type" : "part",
|
||||||
|
"status" : 0
|
||||||
|
},
|
||||||
|
"user_id" : {"$oid": "000000000000000000000003"},
|
||||||
|
"__v" : 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id" : {"$oid": "120000020000000000000000"},
|
||||||
|
"action" : "PUT /sample/400000000000000000000001",
|
||||||
|
"collectionName" : "samples",
|
||||||
|
"conditions" : {
|
||||||
|
"_id" : {"$oid": "400000000000000000000001"}
|
||||||
|
},
|
||||||
|
"data" : {
|
||||||
|
"type" : "part",
|
||||||
|
"status" : 0
|
||||||
|
},
|
||||||
|
"user_id" : {"$oid": "000000000000000000000003"},
|
||||||
|
"__v" : 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id" : {"$oid": "120000030000000000000000"},
|
||||||
|
"action" : "PUT /sample/400000000000000000000001",
|
||||||
|
"collectionName" : "samples",
|
||||||
|
"conditions" : {
|
||||||
|
"_id" : {"$oid": "400000000000000000000001"}
|
||||||
|
},
|
||||||
|
"data" : {
|
||||||
|
"type" : "part",
|
||||||
|
"status" : 0
|
||||||
|
},
|
||||||
|
"user_id" : {"$oid": "000000000000000000000003"},
|
||||||
|
"__v" : 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id" : {"$oid": "120000040000000000000000"},
|
||||||
|
"action" : "PUT /sample/400000000000000000000001",
|
||||||
|
"collectionName" : "samples",
|
||||||
|
"conditions" : {
|
||||||
|
"_id" : {"$oid": "400000000000000000000001"}
|
||||||
|
},
|
||||||
|
"data" : {
|
||||||
|
"type" : "part",
|
||||||
|
"status" : 0
|
||||||
|
},
|
||||||
|
"user_id" : {"$oid": "000000000000000000000003"},
|
||||||
|
"__v" : 0
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,17 @@
|
|||||||
import supertest from 'supertest';
|
import supertest from 'supertest';
|
||||||
import should from 'should/as-function';
|
import should from 'should/as-function';
|
||||||
import db from "../db";
|
import _ from 'lodash';
|
||||||
|
import db from '../db';
|
||||||
|
import ChangelogModel from '../models/changelog';
|
||||||
|
import IdValidate from '../routes/validate/id';
|
||||||
|
|
||||||
|
|
||||||
export default class TestHelper {
|
export default class TestHelper {
|
||||||
public static auth = { // test user credentials
|
public static auth = { // test user credentials
|
||||||
admin: {pass: 'Abc123!#', key: '000000000000000000001003'},
|
admin: {pass: 'Abc123!#', key: '000000000000000000001003', id: '000000000000000000000003'},
|
||||||
janedoe: {pass: 'Xyz890*)', key: '000000000000000000001002'},
|
janedoe: {pass: 'Xyz890*)', key: '000000000000000000001002', id: '000000000000000000000002'},
|
||||||
user: {pass: 'Xyz890*)', key: '000000000000000000001001'},
|
user: {pass: 'Xyz890*)', key: '000000000000000000001001', id: '000000000000000000000001'},
|
||||||
johnnydoe: {pass: 'Xyz890*)', key: '000000000000000000001004'}
|
johnnydoe: {pass: 'Xyz890*)', key: '000000000000000000001004', id: '000000000000000000000004'}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static res = { // default responses
|
public static res = { // default responses
|
||||||
@ -92,6 +95,35 @@ export default class TestHelper {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (options.hasOwnProperty('log')) { // check changelog, takes log: {collection, skip, data/(dataAdd, dataIgn)}
|
||||||
|
return st.end(err => {
|
||||||
|
if (err) return done (err);
|
||||||
|
ChangelogModel.findOne({}).sort({_id: -1}).skip(options.log.skip? options.log.skip : 0).lean().exec((err, data) => { // latest entry
|
||||||
|
if (err) return done(err);
|
||||||
|
should(data).have.only.keys('_id', 'action', 'collectionName', 'conditions', 'data', 'user_id', '__v');
|
||||||
|
should(data).have.property('action', options.method.toUpperCase() + ' ' + options.url);
|
||||||
|
should(data).have.property('collectionName', options.log.collection);
|
||||||
|
if (options.log.hasOwnProperty('data')) {
|
||||||
|
should(data).have.property('data', options.log.data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const ignore = ['_id', '__v'];
|
||||||
|
if (options.log.hasOwnProperty('dataIgn')) {
|
||||||
|
ignore.push(...options.log.dataIgn);
|
||||||
|
}
|
||||||
|
let tmp = options.req ? options.req : {};
|
||||||
|
if (options.log.hasOwnProperty('dataAdd')) {
|
||||||
|
_.assign(tmp, options.log.dataAdd)
|
||||||
|
}
|
||||||
|
should(IdValidate.stringify(_.omit(data.data, ignore))).be.eql(_.omit(tmp, ignore));
|
||||||
|
}
|
||||||
|
if (data.user_id) {
|
||||||
|
should(data.user_id.toString()).be.eql(this.auth[options.auth.basic].id);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
else { // return object to do .end() manually
|
else { // return object to do .end() manually
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user