adapted existing /sample methods to condition, removed /condition route
This commit is contained in:
parent
2829752d0c
commit
0acb9dd6fc
@ -4,6 +4,8 @@
|
|||||||
<w>bcrypt</w>
|
<w>bcrypt</w>
|
||||||
<w>cfenv</w>
|
<w>cfenv</w>
|
||||||
<w>dfopdb</w>
|
<w>dfopdb</w>
|
||||||
|
<w>janedoe</w>
|
||||||
|
<w>testcomment</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</component>
|
</component>
|
@ -1,13 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="dist" type="javaScript">
|
|
||||||
<properties>
|
|
||||||
<sourceFilesUrls>
|
|
||||||
<item url="file://$PROJECT_DIR$/dist" />
|
|
||||||
</sourceFilesUrls>
|
|
||||||
</properties>
|
|
||||||
<CLASSES>
|
|
||||||
<root url="file://$PROJECT_DIR$/dist" />
|
|
||||||
</CLASSES>
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
@ -66,7 +66,6 @@ paths:
|
|||||||
- $ref: 'others.yaml'
|
- $ref: 'others.yaml'
|
||||||
- $ref: 'sample.yaml'
|
- $ref: 'sample.yaml'
|
||||||
- $ref: 'material.yaml'
|
- $ref: 'material.yaml'
|
||||||
- $ref: 'condition.yaml'
|
|
||||||
- $ref: 'measurement.yaml'
|
- $ref: 'measurement.yaml'
|
||||||
- $ref: 'template.yaml'
|
- $ref: 'template.yaml'
|
||||||
- $ref: 'model.yaml'
|
- $ref: 'model.yaml'
|
||||||
|
@ -1,111 +0,0 @@
|
|||||||
/condition/{id}:
|
|
||||||
parameters:
|
|
||||||
- $ref: 'api.yaml#/components/parameters/Id'
|
|
||||||
get:
|
|
||||||
summary: condition by id
|
|
||||||
description: 'Auth: all, levels: read, write, maintain, dev, admin'
|
|
||||||
x-doc: status handling (accessible (only for maintain/admin))? # TODO after decision
|
|
||||||
tags:
|
|
||||||
- /condition
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: condition details
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: 'api.yaml#/components/schemas/Condition'
|
|
||||||
400:
|
|
||||||
$ref: 'api.yaml#/components/responses/400'
|
|
||||||
401:
|
|
||||||
$ref: 'api.yaml#/components/responses/401'
|
|
||||||
404:
|
|
||||||
$ref: 'api.yaml#/components/responses/404'
|
|
||||||
500:
|
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
|
||||||
put:
|
|
||||||
summary: change condition
|
|
||||||
description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to reference samples created by another user'
|
|
||||||
x-doc: status is reset to 0 on any changes
|
|
||||||
tags:
|
|
||||||
- /condition
|
|
||||||
security:
|
|
||||||
- BasicAuth: []
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
allOf:
|
|
||||||
- $ref: 'api.yaml#/components/schemas/_Id'
|
|
||||||
properties:
|
|
||||||
parameters:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: condition details
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: 'api.yaml#/components/schemas/Condition'
|
|
||||||
400:
|
|
||||||
$ref: 'api.yaml#/components/responses/400'
|
|
||||||
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'
|
|
||||||
delete:
|
|
||||||
summary: delete condition
|
|
||||||
description: 'Auth: basic, levels: write, maintain, dev, admin'
|
|
||||||
x-doc: sets status to -1
|
|
||||||
tags:
|
|
||||||
- /condition
|
|
||||||
security:
|
|
||||||
- BasicAuth: []
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
$ref: 'api.yaml#/components/responses/Ok'
|
|
||||||
400:
|
|
||||||
$ref: 'api.yaml#/components/responses/400'
|
|
||||||
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'
|
|
||||||
|
|
||||||
/condition/new:
|
|
||||||
post:
|
|
||||||
summary: add condition
|
|
||||||
description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to reference samples created by another user'
|
|
||||||
x-doc: 'Adds status: 0 automatically'
|
|
||||||
tags:
|
|
||||||
- /condition
|
|
||||||
security:
|
|
||||||
- BasicAuth: []
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: 'api.yaml#/components/schemas/Condition'
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: condition details
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: 'api.yaml#/components/schemas/Condition'
|
|
||||||
400:
|
|
||||||
$ref: 'api.yaml#/components/responses/400'
|
|
||||||
401:
|
|
||||||
$ref: 'api.yaml#/components/responses/401'
|
|
||||||
403:
|
|
||||||
$ref: 'api.yaml#/components/responses/403'
|
|
||||||
500:
|
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
|
@ -19,7 +19,7 @@
|
|||||||
500:
|
500:
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
$ref: 'api.yaml#/components/responses/500'
|
||||||
|
|
||||||
/samples{group}:
|
/samples/{group}:
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: 'api.yaml#/components/parameters/Group'
|
- $ref: 'api.yaml#/components/parameters/Group'
|
||||||
get:
|
get:
|
||||||
@ -48,7 +48,7 @@
|
|||||||
get:
|
get:
|
||||||
summary: TODO sample details
|
summary: TODO sample details
|
||||||
description: 'Auth: all, levels: read, write, maintain, dev, admin'
|
description: 'Auth: all, levels: read, write, maintain, dev, admin'
|
||||||
x-doc: status handling (accessible (only for maintain/admin))? # TODO after decision
|
x-doc: deleted samples are available only for maintain/admin
|
||||||
tags:
|
tags:
|
||||||
- /sample
|
- /sample
|
||||||
responses:
|
responses:
|
||||||
|
@ -24,6 +24,15 @@ SampleProperties:
|
|||||||
batch:
|
batch:
|
||||||
type: string
|
type: string
|
||||||
example: 1560237365
|
example: 1560237365
|
||||||
|
condition:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
condition_template:
|
||||||
|
$ref: 'api.yaml#/components/schemas/Id'
|
||||||
|
example:
|
||||||
|
condition_template: 5ea0450ed851c30a90e70894
|
||||||
|
material: hot air
|
||||||
|
weeks: 5
|
||||||
|
|
||||||
SampleRefs:
|
SampleRefs:
|
||||||
allOf:
|
allOf:
|
||||||
@ -55,7 +64,7 @@ Sample:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
properties:
|
properties:
|
||||||
id:
|
sample_id:
|
||||||
$ref: 'api.yaml#/components/schemas/Id'
|
$ref: 'api.yaml#/components/schemas/Id'
|
||||||
relation:
|
relation:
|
||||||
type: string
|
type: string
|
||||||
@ -67,7 +76,8 @@ SampleDetail:
|
|||||||
- $ref: 'api.yaml#/components/schemas/SampleProperties'
|
- $ref: 'api.yaml#/components/schemas/SampleProperties'
|
||||||
properties:
|
properties:
|
||||||
material:
|
material:
|
||||||
$ref: 'api.yaml#/components/schemas/Material'
|
allOf:
|
||||||
|
- $ref: 'api.yaml#/components/schemas/Material'
|
||||||
notes:
|
notes:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -77,10 +87,14 @@ SampleDetail:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: 'api.yaml#/components/schemas/Id'
|
$ref: 'api.yaml#/components/schemas/Id'
|
||||||
conditions:
|
measurements:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: 'api.yaml#/components/schemas/Condition'
|
allOf:
|
||||||
|
- $ref: 'api.yaml#/components/schemas/Measurement'
|
||||||
|
user:
|
||||||
|
type: string
|
||||||
|
example: admin
|
||||||
|
|
||||||
Material:
|
Material:
|
||||||
allOf:
|
allOf:
|
||||||
@ -115,21 +129,6 @@ Material:
|
|||||||
type: string
|
type: string
|
||||||
example: 5514263423
|
example: 5514263423
|
||||||
|
|
||||||
Condition:
|
|
||||||
allOf:
|
|
||||||
- $ref: 'api.yaml#/components/schemas/_Id'
|
|
||||||
properties:
|
|
||||||
sample_id:
|
|
||||||
$ref: 'api.yaml#/components/schemas/Id'
|
|
||||||
number:
|
|
||||||
type: string
|
|
||||||
readOnly: true
|
|
||||||
example: B1
|
|
||||||
parameters:
|
|
||||||
type: object
|
|
||||||
treatment_template:
|
|
||||||
$ref: 'api.yaml#/components/schemas/Id'
|
|
||||||
|
|
||||||
Measurement:
|
Measurement:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: 'api.yaml#/components/schemas/_Id'
|
- $ref: 'api.yaml#/components/schemas/_Id'
|
||||||
@ -166,7 +165,7 @@ Template:
|
|||||||
min: 0
|
min: 0
|
||||||
max: 2
|
max: 2
|
||||||
|
|
||||||
TreatmentTemplate:
|
ConditionTemplate:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: 'api.yaml#/components/schemas/Template'
|
- $ref: 'api.yaml#/components/schemas/Template'
|
||||||
properties:
|
properties:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/template/treatments:
|
/template/conditions:
|
||||||
get:
|
get:
|
||||||
summary: all available treatment methods
|
summary: all available condition methods
|
||||||
description: 'Auth: basic, levels: read, write, maintain, dev, admin'
|
description: 'Auth: basic, levels: read, write, maintain, dev, admin'
|
||||||
tags:
|
tags:
|
||||||
- /template
|
- /template
|
||||||
@ -8,23 +8,23 @@
|
|||||||
- BasicAuth: []
|
- BasicAuth: []
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: list of treatments
|
description: list of conditions
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: 'api.yaml#/components/schemas/TreatmentTemplate'
|
$ref: 'api.yaml#/components/schemas/ConditionTemplate'
|
||||||
401:
|
401:
|
||||||
$ref: 'api.yaml#/components/responses/401'
|
$ref: 'api.yaml#/components/responses/401'
|
||||||
500:
|
500:
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
$ref: 'api.yaml#/components/responses/500'
|
||||||
|
|
||||||
/template/treatment/{id}:
|
/template/condition/{id}:
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: 'api.yaml#/components/parameters/Id'
|
- $ref: 'api.yaml#/components/parameters/Id'
|
||||||
get:
|
get:
|
||||||
summary: treatment method details
|
summary: condition method details
|
||||||
description: 'Auth: basic, levels: read, write, maintain, admin'
|
description: 'Auth: basic, levels: read, write, maintain, admin'
|
||||||
tags:
|
tags:
|
||||||
- /template
|
- /template
|
||||||
@ -32,11 +32,11 @@
|
|||||||
- BasicAuth: []
|
- BasicAuth: []
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: treatment details
|
description: condition details
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: 'api.yaml#/components/schemas/TreatmentTemplate'
|
$ref: 'api.yaml#/components/schemas/ConditionTemplate'
|
||||||
401:
|
401:
|
||||||
$ref: 'api.yaml#/components/responses/401'
|
$ref: 'api.yaml#/components/responses/401'
|
||||||
404:
|
404:
|
||||||
@ -44,7 +44,7 @@
|
|||||||
500:
|
500:
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
$ref: 'api.yaml#/components/responses/500'
|
||||||
put:
|
put:
|
||||||
summary: change treatment method
|
summary: change condition method
|
||||||
description: 'Auth: basic, levels: maintain, admin'
|
description: 'Auth: basic, levels: maintain, admin'
|
||||||
x-doc: With a change a new version is set, resulting in a new template with a new id
|
x-doc: With a change a new version is set, resulting in a new template with a new id
|
||||||
tags:
|
tags:
|
||||||
@ -56,14 +56,14 @@
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: 'api.yaml#/components/schemas/TreatmentTemplate'
|
$ref: 'api.yaml#/components/schemas/ConditionTemplate'
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: treatment details
|
description: condition details
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: 'api.yaml#/components/schemas/TreatmentTemplate'
|
$ref: 'api.yaml#/components/schemas/ConditionTemplate'
|
||||||
400:
|
400:
|
||||||
$ref: 'api.yaml#/components/responses/400'
|
$ref: 'api.yaml#/components/responses/400'
|
||||||
401:
|
401:
|
||||||
@ -75,9 +75,9 @@
|
|||||||
500:
|
500:
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
$ref: 'api.yaml#/components/responses/500'
|
||||||
|
|
||||||
/template/treatment/new:
|
/template/condition/new:
|
||||||
post:
|
post:
|
||||||
summary: add treatment method
|
summary: add condition method
|
||||||
description: 'Auth: basic, levels: maintain, admin'
|
description: 'Auth: basic, levels: maintain, admin'
|
||||||
tags:
|
tags:
|
||||||
- /template
|
- /template
|
||||||
@ -88,14 +88,14 @@
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: 'api.yaml#/components/schemas/TreatmentTemplate'
|
$ref: 'api.yaml#/components/schemas/ConditionTemplate'
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: treatment details
|
description: condition details
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: 'api.yaml#/components/schemas/TreatmentTemplate'
|
$ref: 'api.yaml#/components/schemas/ConditionTemplate'
|
||||||
400:
|
400:
|
||||||
$ref: 'api.yaml#/components/responses/400'
|
$ref: 'api.yaml#/components/responses/400'
|
||||||
401:
|
401:
|
||||||
|
976
package-lock.json
generated
976
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -5,10 +5,12 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
|
"tsc-full": "del /q dist\\* & (for /d %x in (dist\\*) do @rd /s /q \"%x\") & tsc",
|
||||||
"test": "mocha dist/**/**.spec.js",
|
"test": "mocha dist/**/**.spec.js",
|
||||||
"start": "tsc && node dist/index.js || exit 1",
|
"start": "tsc && node dist/index.js || exit 1",
|
||||||
"dev": "nodemon -e ts,yaml --exec \"npm run start\"",
|
"dev": "nodemon -e ts,yaml --exec \"npm run start\"",
|
||||||
"loadDev": "node dist/test/loadDev.js"
|
"loadDev": "node dist/test/loadDev.js",
|
||||||
|
"coverage": "nyc --reporter=html --reporter=tex mocha dist/**/**.spec.js"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@ -44,6 +46,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/lodash": "^4.14.150",
|
"@types/lodash": "^4.14.150",
|
||||||
"mocha": "^7.1.2",
|
"mocha": "^7.1.2",
|
||||||
|
"nyc": "^15.0.1",
|
||||||
"should": "^13.2.3",
|
"should": "^13.2.3",
|
||||||
"supertest": "^4.0.2"
|
"supertest": "^4.0.2"
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,13 @@ const globals = {
|
|||||||
'maintain',
|
'maintain',
|
||||||
'dev',
|
'dev',
|
||||||
'admin'
|
'admin'
|
||||||
]
|
],
|
||||||
|
|
||||||
|
status: { // document statuses
|
||||||
|
deleted: -1,
|
||||||
|
new: 0,
|
||||||
|
validated: 10,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default globals;
|
export default globals;
|
21
src/index.ts
21
src/index.ts
@ -11,6 +11,7 @@ import db from './db';
|
|||||||
// TODO: validation: VZ, Humidity: min/max value, DPT: filename
|
// TODO: validation: VZ, Humidity: min/max value, DPT: filename
|
||||||
// TODO: condition values not needed on initial add
|
// TODO: condition values not needed on initial add
|
||||||
// TODO: add multiple samples at once
|
// TODO: add multiple samples at once
|
||||||
|
// TODO: coverage
|
||||||
|
|
||||||
// tell if server is running in debug or production environment
|
// tell if server is running in debug or production environment
|
||||||
console.info(process.env.NODE_ENV === 'production' ? '===== PRODUCTION =====' : process.env.NODE_ENV === 'test' ? '' :'===== DEVELOPMENT =====');
|
console.info(process.env.NODE_ENV === 'production' ? '===== PRODUCTION =====' : process.env.NODE_ENV === 'test' ? '' :'===== DEVELOPMENT =====');
|
||||||
@ -48,14 +49,20 @@ app.use((req, res, next) => { // no database connection error
|
|||||||
});
|
});
|
||||||
app.use(require('./helpers/authorize')); // handle authentication
|
app.use(require('./helpers/authorize')); // handle authentication
|
||||||
|
|
||||||
|
// redirect /api routes for Angular proxy in development
|
||||||
|
app.use('/api/:url', (req, res) => {
|
||||||
|
req.url = '/' + req.params.url;
|
||||||
|
app.handle(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// require routes
|
// require routes
|
||||||
app.use('/api', require('./routes/root'));
|
app.use('/', require('./routes/root'));
|
||||||
app.use('/api', require('./routes/sample'));
|
app.use('/', require('./routes/sample'));
|
||||||
app.use('/api', require('./routes/material'));
|
app.use('/', require('./routes/material'));
|
||||||
app.use('/api', require('./routes/template'));
|
app.use('/', require('./routes/template'));
|
||||||
app.use('/api', require('./routes/user'));
|
app.use('/', require('./routes/user'));
|
||||||
app.use('/api', require('./routes/condition'));
|
app.use('/', require('./routes/measurement'));
|
||||||
app.use('/api', require('./routes/measurement'));
|
|
||||||
|
|
||||||
// static files
|
// static files
|
||||||
app.use('/static', express.static('static'));
|
app.use('/static', express.static('static'));
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import mongoose from 'mongoose';
|
|
||||||
import SampleModel from './sample';
|
|
||||||
import TreatmentTemplateModel from './treatment_template';
|
|
||||||
|
|
||||||
const ConditionSchema = new mongoose.Schema({
|
|
||||||
sample_id: {type: mongoose.Schema.Types.ObjectId, ref: SampleModel},
|
|
||||||
number: String,
|
|
||||||
parameters: mongoose.Schema.Types.Mixed,
|
|
||||||
treatment_template: {type: mongoose.Schema.Types.ObjectId, ref: TreatmentTemplateModel},
|
|
||||||
status: Number
|
|
||||||
});
|
|
||||||
|
|
||||||
export default mongoose.model('condition', ConditionSchema);
|
|
@ -1,13 +1,12 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
|
||||||
const TreatmentTemplateSchema = new mongoose.Schema({
|
const ConditionTemplateSchema = new mongoose.Schema({
|
||||||
name: String,
|
name: String,
|
||||||
version: Number,
|
version: Number,
|
||||||
number_prefix: String,
|
|
||||||
parameters: [{
|
parameters: [{
|
||||||
name: String,
|
name: String,
|
||||||
range: mongoose.Schema.Types.Mixed
|
range: mongoose.Schema.Types.Mixed
|
||||||
}]
|
}]
|
||||||
}, {minimize: false}); // to allow empty objects
|
}, {minimize: false}); // to allow empty objects
|
||||||
|
|
||||||
export default mongoose.model('treatment_template', TreatmentTemplateSchema);
|
export default mongoose.model('condition_template', ConditionTemplateSchema);
|
@ -1,9 +1,11 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import ConditionModel from './condition';
|
import SampleModel from './sample';
|
||||||
import MeasurementTemplateModel from './measurement_template';
|
import MeasurementTemplateModel from './measurement_template';
|
||||||
|
|
||||||
|
// TODO: change to sample_id
|
||||||
|
|
||||||
const MeasurementSchema = new mongoose.Schema({
|
const MeasurementSchema = new mongoose.Schema({
|
||||||
condition_id: {type: mongoose.Schema.Types.ObjectId, ref: ConditionModel},
|
sample_id: {type: mongoose.Schema.Types.ObjectId, ref: SampleModel},
|
||||||
values: mongoose.Schema.Types.Mixed,
|
values: mongoose.Schema.Types.Mixed,
|
||||||
measurement_template: {type: mongoose.Schema.Types.ObjectId, ref: MeasurementTemplateModel},
|
measurement_template: {type: mongoose.Schema.Types.ObjectId, ref: MeasurementTemplateModel},
|
||||||
status: Number
|
status: Number
|
||||||
|
@ -3,7 +3,7 @@ import mongoose from 'mongoose';
|
|||||||
const NoteSchema = new mongoose.Schema({
|
const NoteSchema = new mongoose.Schema({
|
||||||
comment: String,
|
comment: String,
|
||||||
sample_references: [{
|
sample_references: [{
|
||||||
id: mongoose.Schema.Types.ObjectId,
|
sample_id: mongoose.Schema.Types.ObjectId,
|
||||||
relation: String
|
relation: String
|
||||||
}],
|
}],
|
||||||
custom_fields: mongoose.Schema.Types.Mixed
|
custom_fields: mongoose.Schema.Types.Mixed
|
||||||
|
@ -9,10 +9,11 @@ const SampleSchema = new mongoose.Schema({
|
|||||||
type: String,
|
type: String,
|
||||||
color: String,
|
color: String,
|
||||||
batch: String,
|
batch: String,
|
||||||
|
condition: mongoose.Schema.Types.Mixed,
|
||||||
material_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialModel},
|
material_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialModel},
|
||||||
note_id: {type: mongoose.Schema.Types.ObjectId, ref: NoteModel},
|
note_id: {type: mongoose.Schema.Types.ObjectId, ref: NoteModel},
|
||||||
user_id: {type: mongoose.Schema.Types.ObjectId, ref: UserModel},
|
user_id: {type: mongoose.Schema.Types.ObjectId, ref: UserModel},
|
||||||
status: Number
|
status: Number
|
||||||
});
|
}, {minimize: false});
|
||||||
|
|
||||||
export default mongoose.model('sample', SampleSchema);
|
export default mongoose.model('sample', SampleSchema);
|
@ -1,583 +0,0 @@
|
|||||||
import should from 'should/as-function';
|
|
||||||
import ConditionModel from '../models/condition';
|
|
||||||
import TestHelper from "../test/helper";
|
|
||||||
|
|
||||||
// TODO: adding conditions allowed only for m/a
|
|
||||||
// TODO: deleted data only visible for m/a
|
|
||||||
// TODO: restore deleted
|
|
||||||
// TODO: remove number_prefix
|
|
||||||
|
|
||||||
describe('/condition', () => {
|
|
||||||
let server;
|
|
||||||
before(done => TestHelper.before(done));
|
|
||||||
beforeEach(done => server = TestHelper.beforeEach(server, done));
|
|
||||||
afterEach(done => TestHelper.afterEach(server, done));
|
|
||||||
|
|
||||||
describe('GET /condition/{id}', () => {
|
|
||||||
it('returns the right condition', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'get',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', parameters: {material: 'copper', weeks: 3}, treatment_template: '200000000000000000000001'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('returns the right condition for an API key', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'get',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {key: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', parameters: {material: 'copper', weeks: 3}, treatment_template: '200000000000000000000001'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an invalid id', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'get',
|
|
||||||
url: '/condition/70000000000t000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 404
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an unknown id', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'get',
|
|
||||||
url: '/condition/000000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 404
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects unauthorized requests', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'get',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
httpStatus: 401
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('PUT /condition{id}', () => {
|
|
||||||
it('returns the right condition', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {},
|
|
||||||
res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('keeps unchanged properties', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {parameters: {material: 'copper', weeks: 3}}
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}});
|
|
||||||
ConditionModel.findById('700000000000000000000001').lean().exec((err, data) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(data).have.property('status', 10);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('keeps only one unchanged parameter', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {parameters: {material: 'copper'}}
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}});
|
|
||||||
ConditionModel.findById('700000000000000000000001').lean().exec((err, data) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(data).have.property('status', 10);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('changes the given properties', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {parameters: {material: 'hot air', weeks: 10}}
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', treatment_template: '200000000000000000000001', parameters: {material: 'hot air', weeks: 10}});
|
|
||||||
ConditionModel.findById('700000000000000000000001').lean().exec((err, data: any) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v');
|
|
||||||
should(data.sample_id.toString()).be.eql('400000000000000000000001');
|
|
||||||
should(data).have.property('number', 'A1');
|
|
||||||
should(data.treatment_template.toString()).be.eql('200000000000000000000001');
|
|
||||||
should(data).have.property('status', 0);
|
|
||||||
should(data).have.property('parameters');
|
|
||||||
should(data.parameters).have.property('material', 'hot air');
|
|
||||||
should(data.parameters).have.property('weeks', 10);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('allows changing only one parameter', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {parameters: {weeks: 8}},
|
|
||||||
res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 8}}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects changing the condition number', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {number: 'C2'},
|
|
||||||
res: {status: 'Invalid body format', details: '"number" is not allowed'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects not specified parameters', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {parameters: {xx: 13}},
|
|
||||||
res: {status: 'Invalid body format', details: '"xx" is not allowed'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a parameter not in the value range', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {parameters: {material: 'xxx'}},
|
|
||||||
res: {status: 'Invalid body format', details: '"material" must be one of [copper, hot air]'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a parameter below minimum range', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {parameters: {weeks: -10}},
|
|
||||||
res: {status: 'Invalid body format', details: '"weeks" must be larger than or equal to 1'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a parameter above maximum range', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {parameters: {weeks: 11}},
|
|
||||||
res: {status: 'Invalid body format', details: '"weeks" must be less than or equal to 10'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a new treatment_template', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {treatment_template: '200000000000000000000002'},
|
|
||||||
res: {status: 'Invalid body format', details: '"treatment_template" is not allowed'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects editing a condition for a write user who did not create this condition', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000003',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 403,
|
|
||||||
req: {parameters: {weeks: 8}}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('accepts editing a condition of another user for a maintain/admin user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'admin'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {parameters: {material: 'hot air', weeks: 10}},
|
|
||||||
res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'A1', treatment_template: '200000000000000000000001', parameters: {material: 'hot air', weeks: 10}}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an API key', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {key: 'janedoe'},
|
|
||||||
httpStatus: 401,
|
|
||||||
req: {parameters: {material: 'hot air', weeks: 10}}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects requests from a read user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
auth: {basic: 'user'},
|
|
||||||
httpStatus: 403,
|
|
||||||
req: {parameters: {material: 'hot air', weeks: 10}}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects unauthorized requests', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/condition/700000000000000000000001',
|
|
||||||
httpStatus: 401,
|
|
||||||
req: {parameters: {material: 'hot air', weeks: 10}}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('DELETE /condition/{id}', () => {
|
|
||||||
it('sets the status to deleted', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/700000000000000000000004',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(res.body).be.eql({status: 'OK'});
|
|
||||||
ConditionModel.findById('700000000000000000000004').lean().exec((err, data: any) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v');
|
|
||||||
should(data.sample_id.toString()).be.eql('400000000000000000000001');
|
|
||||||
should(data).have.property('number', 'A2');
|
|
||||||
should(data.treatment_template.toString()).be.eql('200000000000000000000001');
|
|
||||||
should(data).have.property('status', -1);
|
|
||||||
should(data).have.property('parameters');
|
|
||||||
should(data.parameters).have.property('material', 'hot air');
|
|
||||||
should(data.parameters).have.property('weeks', 5);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects deleting a condition referenced by measurements'/*, done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/700000000000000000000002',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
res: {status: 'Condition still in use'}
|
|
||||||
});
|
|
||||||
}*/); // TODO after decision
|
|
||||||
it('rejects an invalid id', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/70000000000w000000000002',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 404
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an API key', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/700000000000000000000004',
|
|
||||||
auth: {key: 'janedoe'},
|
|
||||||
httpStatus: 401
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects requests from a read user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/700000000000000000000004',
|
|
||||||
auth: {basic: 'user'},
|
|
||||||
httpStatus: 403
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a write user deleting a condition belonging to a sample of another user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/700000000000000000000003',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 403
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('accepts an maintain/admin user deleting a condition belonging to a sample of another user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/700000000000000000000004',
|
|
||||||
auth: {basic: 'admin'},
|
|
||||||
httpStatus: 200
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(res.body).be.eql({status: 'OK'});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('returns 404 for an unknown id', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/000000000000000000000002',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 404
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects unauthorized requests', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'delete',
|
|
||||||
url: '/condition/700000000000000000000004',
|
|
||||||
httpStatus: 401
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('POST /condition/new', () => {
|
|
||||||
it('returns the right condition', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(res.body).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template');
|
|
||||||
should(res.body).have.property('_id').be.type('string');
|
|
||||||
should(res.body).have.property('sample_id', '400000000000000000000002');
|
|
||||||
should(res.body).have.property('number', 'A2');
|
|
||||||
should(res.body).have.property('treatment_template', '200000000000000000000001');
|
|
||||||
should(res.body).have.property('parameters');
|
|
||||||
should(res.body.parameters).have.property('material', 'hot air');
|
|
||||||
should(res.body.parameters).have.property('weeks', 10);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('stores the condition', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
ConditionModel.findById(res.body._id).lean().exec((err, data: any) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v');
|
|
||||||
should(data.sample_id.toString()).be.eql('400000000000000000000002');
|
|
||||||
should(data).have.property('number', 'A2');
|
|
||||||
should(data.treatment_template.toString()).be.eql('200000000000000000000001');
|
|
||||||
should(data).have.property('status', 0);
|
|
||||||
should(data).have.property('parameters');
|
|
||||||
should(data.parameters).have.property('material', 'hot air');
|
|
||||||
should(data.parameters).have.property('weeks', 10);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('stores the first condition as 1', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'admin'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {sample_id: '400000000000000000000003', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
ConditionModel.findById(res.body._id).lean().exec((err, data: any) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v');
|
|
||||||
should(data.sample_id.toString()).be.eql('400000000000000000000003');
|
|
||||||
should(data).have.property('number', 'A1');
|
|
||||||
should(data.treatment_template.toString()).be.eql('200000000000000000000001');
|
|
||||||
should(data).have.property('status', 0);
|
|
||||||
should(data).have.property('parameters');
|
|
||||||
should(data.parameters).have.property('material', 'hot air');
|
|
||||||
should(data.parameters).have.property('weeks', 10);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an invalid sample id', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '4000000000h0000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"sample_id" with value "4000000000h0000000000002" fails to match the required pattern: /[0-9a-f]{24}/'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a sample id not available', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '000000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Sample id not available'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an invalid treatment_template id', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000h00000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"treatment_template" with value "200000000000h00000000001" fails to match the required pattern: /[0-9a-f]{24}/'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a treatment_template which does not exist', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '000000000000000000000001'},
|
|
||||||
res: {status: 'Treatment template not available'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects setting a condition number', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000001', number: 'A7', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"number" is not allowed'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects not specified parameters', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10, xx: 12}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"xx" is not allowed'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects missing parameters', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air'}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"weeks" is required'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a parameter not in the value range', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'xxx', weeks: 10}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"material" must be one of [copper, hot air]'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a parameter below minimum range', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: -10}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"weeks" must be larger than or equal to 1'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a parameter above maximum range', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 11}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"weeks" must be less than or equal to 10'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a missing sample id', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'},
|
|
||||||
res: {status: 'Invalid body format', details: '"sample_id" is required'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a missing treatment_template', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}},
|
|
||||||
res: {status: 'Invalid body format', details: '"treatment_template" is required'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects adding a condition to the sample of an other user for a write user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'janedoe'},
|
|
||||||
httpStatus: 403,
|
|
||||||
req: {sample_id: '400000000000000000000003', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('accepts adding a condition to the sample of an other user for a maintain/admin user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'admin'},
|
|
||||||
httpStatus: 200,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
}).end((err, res) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
should(res.body).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template');
|
|
||||||
should(res.body).have.property('_id').be.type('string');
|
|
||||||
should(res.body).have.property('sample_id', '400000000000000000000002');
|
|
||||||
should(res.body).have.property('number', 'A2');
|
|
||||||
should(res.body).have.property('treatment_template', '200000000000000000000001');
|
|
||||||
should(res.body).have.property('parameters');
|
|
||||||
should(res.body.parameters).have.property('material', 'hot air');
|
|
||||||
should(res.body.parameters).have.property('weeks', 10);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an API key', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {key: 'janedoe'},
|
|
||||||
httpStatus: 401,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects requests from a read user', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
auth: {basic: 'user'},
|
|
||||||
httpStatus: 403,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects unauthorized requests', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/condition/new',
|
|
||||||
httpStatus: 401,
|
|
||||||
req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,133 +0,0 @@
|
|||||||
import express from 'express';
|
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
import ConditionValidate from './validate/condition';
|
|
||||||
import ParametersValidate from './validate/parameters';
|
|
||||||
import res400 from './validate/res400';
|
|
||||||
import SampleModel from '../models/sample';
|
|
||||||
import ConditionModel from '../models/condition';
|
|
||||||
import TreatmentTemplateModel from '../models/treatment_template';
|
|
||||||
import IdValidate from './validate/id';
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.get('/condition/' + IdValidate.parameter(), (req, res, next) => {
|
|
||||||
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
|
|
||||||
|
|
||||||
ConditionModel.findById(req.params.id).lean().exec((err, data) => {
|
|
||||||
if (err) return next(err);
|
|
||||||
if (data) {
|
|
||||||
res.json(ConditionValidate.output(data));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res.status(404).json({status: 'Not found'});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
router.put('/condition/' + IdValidate.parameter(), async (req, res, next) => {
|
|
||||||
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
|
||||||
|
|
||||||
const {error, value: condition} = ConditionValidate.input(req.body, 'change');
|
|
||||||
if (error) return res400(error, res);
|
|
||||||
|
|
||||||
const data = await ConditionModel.findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
|
|
||||||
if (data instanceof Error) return;
|
|
||||||
if (!data) {
|
|
||||||
res.status(404).json({status: 'Not found'});
|
|
||||||
}
|
|
||||||
|
|
||||||
// add properties needed for sampleIdCheck
|
|
||||||
condition.treatment_template = data.treatment_template;
|
|
||||||
condition.sample_id = data.sample_id;
|
|
||||||
if (!await sampleIdCheck(condition, req, res, next)) return;
|
|
||||||
if (condition.parameters) {
|
|
||||||
condition.parameters = _.assign({}, data.parameters, condition.parameters);
|
|
||||||
if (!_.isEqual(condition.parameters, data.parameters)) { // parameters did not change
|
|
||||||
condition.status = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!await treatmentCheck(condition, 'change', res, next)) return;
|
|
||||||
|
|
||||||
await ConditionModel.findByIdAndUpdate(req.params.id, condition, {new: true}).lean().exec((err, data) => {
|
|
||||||
if (err) return next(err);
|
|
||||||
res.json(ConditionValidate.output(data));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
router.delete('/condition/' + IdValidate.parameter(), (req, res, next) => {
|
|
||||||
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
|
||||||
|
|
||||||
ConditionModel.findById(req.params.id).lean().exec(async (err, data: any) => {
|
|
||||||
if (err) return next(err);
|
|
||||||
if (!data) {
|
|
||||||
res.status(404).json({status: 'Not found'});
|
|
||||||
}
|
|
||||||
if (!await sampleIdCheck(data, req, res, next)) return;
|
|
||||||
await ConditionModel.findByIdAndUpdate(req.params.id, {status: -1}).lean().exec(err => {
|
|
||||||
if (err) return next(err);
|
|
||||||
res.json({status: 'OK'});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
router.post('/condition/new', async (req, res, next) => {
|
|
||||||
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
|
||||||
|
|
||||||
const {error, value: condition} = ConditionValidate.input(req.body, 'new');
|
|
||||||
if (error) return res400(error, res);
|
|
||||||
|
|
||||||
if (!await sampleIdCheck(condition, req, res, next)) return;
|
|
||||||
const treatmentData = await treatmentCheck(condition, 'new', res, next)
|
|
||||||
if (!treatmentData) return;
|
|
||||||
|
|
||||||
condition.number = await numberGenerate(condition, treatmentData, next);
|
|
||||||
if (!condition.number) return;
|
|
||||||
condition.status = 0; // set status to new
|
|
||||||
await new ConditionModel(condition).save((err, data) => {
|
|
||||||
if (err) return next(err);
|
|
||||||
res.json(ConditionValidate.output(data.toObject()));
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|
||||||
|
|
||||||
async function sampleIdCheck (condition, req, res, next) { // validate sample_id, returns false if invalid
|
|
||||||
const sampleData = await SampleModel.findById(condition.sample_id).lean().exec().catch(err => {next(err); return false;}) as any;
|
|
||||||
if (!sampleData) { // sample_id not found
|
|
||||||
res.status(400).json({status: 'Sample id not available'});
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sampleData.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return false; // sample does not belong to user
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function numberGenerate (condition, treatmentData, next) { // generate number, returns false on error
|
|
||||||
const conditionData = await ConditionModel // find condition with highest number belonging to the same sample
|
|
||||||
.find({sample_id: condition.sample_id, number: new RegExp('^' + treatmentData.number_prefix + '[0-9]+$', 'm')})
|
|
||||||
.sort({number: -1})
|
|
||||||
.limit(1)
|
|
||||||
.lean()
|
|
||||||
.exec()
|
|
||||||
.catch(err => next(err)) as any;
|
|
||||||
if (conditionData instanceof Error) return false;
|
|
||||||
return treatmentData.number_prefix + (conditionData.length > 0 ? Number(conditionData[0].number.replace(/[^0-9]+/g, '')) + 1 : 1); // return new number
|
|
||||||
}
|
|
||||||
|
|
||||||
async function treatmentCheck (condition, param, res, next) { // validate treatment template, returns false if invalid, otherwise template data
|
|
||||||
const treatmentData = await TreatmentTemplateModel.findById(condition.treatment_template).lean().exec().catch(err => next(err)) as any;
|
|
||||||
if (treatmentData instanceof Error) return false;
|
|
||||||
if (!treatmentData) { // template not found
|
|
||||||
res.status(400).json({status: 'Treatment template not available'});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate parameters
|
|
||||||
const {error, value: ignore} = ParametersValidate.input(condition.parameters, treatmentData.parameters, param);
|
|
||||||
if (error) {res400(error, res); return false;}
|
|
||||||
return treatmentData;
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ import should from 'should/as-function';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import MaterialModel from '../models/material';
|
import MaterialModel from '../models/material';
|
||||||
import TestHelper from "../test/helper";
|
import TestHelper from "../test/helper";
|
||||||
|
import globals from '../globals';
|
||||||
|
|
||||||
// TODO: color name must be unique to get color number
|
// TODO: color name must be unique to get color number
|
||||||
// TODO: separate supplier/ material name into own collections
|
// TODO: separate supplier/ material name into own collections
|
||||||
@ -22,7 +23,7 @@ describe('/material', () => {
|
|||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 10).length);
|
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === globals.status.validated).length);
|
||||||
should(res.body).matchEach(material => {
|
should(res.body).matchEach(material => {
|
||||||
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
||||||
should(material).have.property('_id').be.type('string');
|
should(material).have.property('_id').be.type('string');
|
||||||
@ -50,7 +51,7 @@ describe('/material', () => {
|
|||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 10).length);
|
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === globals.status.validated).length);
|
||||||
should(res.body).matchEach(material => {
|
should(res.body).matchEach(material => {
|
||||||
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
||||||
should(material).have.property('_id').be.type('string');
|
should(material).have.property('_id').be.type('string');
|
||||||
@ -89,7 +90,7 @@ describe('/material', () => {
|
|||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
let asyncCounter = res.body.length;
|
let asyncCounter = res.body.length;
|
||||||
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 0).length);
|
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status ===globals.status.new).length);
|
||||||
should(res.body).matchEach(material => {
|
should(res.body).matchEach(material => {
|
||||||
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
||||||
should(material).have.property('_id').be.type('string');
|
should(material).have.property('_id').be.type('string');
|
||||||
@ -105,7 +106,7 @@ describe('/material', () => {
|
|||||||
should(number).have.property('number').be.type('string');
|
should(number).have.property('number').be.type('string');
|
||||||
});
|
});
|
||||||
MaterialModel.findById(material._id).lean().exec((err, data) => {
|
MaterialModel.findById(material._id).lean().exec((err, data) => {
|
||||||
should(data).have.property('status', 0);
|
should(data).have.property('status',globals.status.new);
|
||||||
if (--asyncCounter === 0) {
|
if (--asyncCounter === 0) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
@ -123,7 +124,7 @@ describe('/material', () => {
|
|||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
let asyncCounter = res.body.length;
|
let asyncCounter = res.body.length;
|
||||||
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === -1).length);
|
should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status ===globals.status.deleted).length);
|
||||||
should(res.body).matchEach(material => {
|
should(res.body).matchEach(material => {
|
||||||
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
|
||||||
should(material).have.property('_id').be.type('string');
|
should(material).have.property('_id').be.type('string');
|
||||||
@ -139,7 +140,7 @@ describe('/material', () => {
|
|||||||
should(number).have.property('number').be.type('string');
|
should(number).have.property('number').be.type('string');
|
||||||
});
|
});
|
||||||
MaterialModel.findById(material._id).lean().exec((err, data) => {
|
MaterialModel.findById(material._id).lean().exec((err, data) => {
|
||||||
should(data).have.property('status', -1);
|
should(data).have.property('status',globals.status.deleted);
|
||||||
if (--asyncCounter === 0) {
|
if (--asyncCounter === 0) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
@ -249,7 +250,7 @@ describe('/material', () => {
|
|||||||
should(res.body).be.eql({_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: '5514263423'}, {color: 'natural', number: '5514263422'}]});
|
should(res.body).be.eql({_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: '5514263423'}, {color: 'natural', number: '5514263422'}]});
|
||||||
MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => {
|
MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.property('status', 10);
|
should(data).have.property('status',globals.status.validated);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -266,7 +267,7 @@ describe('/material', () => {
|
|||||||
should(res.body).be.eql({_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: '5514263423'}, {color: 'natural', number: '5514263422'}]});
|
should(res.body).be.eql({_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: '5514263423'}, {color: 'natural', number: '5514263422'}]});
|
||||||
MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => {
|
MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.property('status', 10);
|
should(data).have.property('status',globals.status.validated);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -513,7 +514,7 @@ describe('/material', () => {
|
|||||||
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', 0);
|
should(data[0]).have.property('status',globals.status.new);
|
||||||
should(data[0].numbers).have.lengthOf(0);
|
should(data[0].numbers).have.lengthOf(0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -552,7 +553,7 @@ describe('/material', () => {
|
|||||||
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', 0);
|
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();
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,7 @@ import SampleModel from '../models/sample';
|
|||||||
import IdValidate from './validate/id';
|
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';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ const router = express.Router();
|
|||||||
router.get('/materials', (req, res, next) => {
|
router.get('/materials', (req, res, next) => {
|
||||||
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
|
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
|
||||||
|
|
||||||
MaterialModel.find({status: 10}).lean().exec((err, data) => {
|
MaterialModel.find({status:globals.status.validated}).lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(_.compact(data.map(e => MaterialValidate.output(e)))); // validate all and filter null values from validation errors
|
res.json(_.compact(data.map(e => MaterialValidate.output(e)))); // validate all and filter null values from validation errors
|
||||||
});
|
});
|
||||||
@ -24,14 +25,7 @@ router.get('/materials', (req, res, next) => {
|
|||||||
router.get('/materials/:group(new|deleted)', (req, res, next) => {
|
router.get('/materials/:group(new|deleted)', (req, res, next) => {
|
||||||
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
let status;
|
MaterialModel.find({status: globals.status[req.params.group]}).lean().exec((err, data) => {
|
||||||
switch (req.params.group) {
|
|
||||||
case 'new': status = 0;
|
|
||||||
break;
|
|
||||||
case 'deleted': status = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MaterialModel.find({status: status}).lean().exec((err, data) => {
|
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(_.compact(data.map(e => MaterialValidate.output(e)))); // validate all and filter null values from validation errors
|
res.json(_.compact(data.map(e => MaterialValidate.output(e)))); // validate all and filter null values from validation errors
|
||||||
});
|
});
|
||||||
@ -67,7 +61,7 @@ router.put('/material/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
|
|
||||||
// check for changes
|
// check for changes
|
||||||
if (!_.isEqual(_.pick(IdValidate.stringify(materialData), _.keys(material)), material)) {
|
if (!_.isEqual(_.pick(IdValidate.stringify(materialData), _.keys(material)), material)) {
|
||||||
material.status = 0; // set status to new
|
material.status = globals.status.new; // set status to new
|
||||||
}
|
}
|
||||||
|
|
||||||
await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).lean().exec((err, data) => {
|
await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).lean().exec((err, data) => {
|
||||||
@ -86,7 +80,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: -1}).lean().exec((err, data) => {
|
MaterialModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).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'});
|
||||||
@ -106,7 +100,7 @@ router.post('/material/new', async (req, res, next) => {
|
|||||||
|
|
||||||
if (!await nameCheck(material, res, next)) return;
|
if (!await nameCheck(material, res, next)) return;
|
||||||
|
|
||||||
material.status = 0; // set status to new
|
material.status = globals.status.new; // set status to new
|
||||||
await new MaterialModel(material).save((err, data) => {
|
await new MaterialModel(material).save((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(MaterialValidate.output(data.toObject()));
|
res.json(MaterialValidate.output(data.toObject()));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import should from 'should/as-function';
|
import should from 'should/as-function';
|
||||||
import MeasurementModel from '../models/measurement';
|
import MeasurementModel from '../models/measurement';
|
||||||
import TestHelper from "../test/helper";
|
import TestHelper from "../test/helper";
|
||||||
|
import globals from '../globals';
|
||||||
|
|
||||||
// TODO: allow empty values
|
// TODO: allow empty values
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ describe('/measurement', () => {
|
|||||||
should(res.body).be.eql({_id: '800000000000000000000001', condition_id: '700000000000000000000001', values: {dpt: [[3997.12558,98.00555],[3995.08519,98.03253],[3993.04480,98.02657]]}, measurement_template: '300000000000000000000001'});
|
should(res.body).be.eql({_id: '800000000000000000000001', condition_id: '700000000000000000000001', values: {dpt: [[3997.12558,98.00555],[3995.08519,98.03253],[3993.04480,98.02657]]}, measurement_template: '300000000000000000000001'});
|
||||||
MeasurementModel.findById('800000000000000000000001').lean().exec((err, data: any) => {
|
MeasurementModel.findById('800000000000000000000001').lean().exec((err, data: any) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.property('status', 10);
|
should(data).have.property('status',globals.status.validated);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -95,7 +96,7 @@ describe('/measurement', () => {
|
|||||||
should(res.body).be.eql({_id: '800000000000000000000002', condition_id: '700000000000000000000002', values: {'weight %': 0.5, 'standard deviation': 0.2}, measurement_template: '300000000000000000000002'});
|
should(res.body).be.eql({_id: '800000000000000000000002', condition_id: '700000000000000000000002', values: {'weight %': 0.5, 'standard deviation': 0.2}, measurement_template: '300000000000000000000002'});
|
||||||
MeasurementModel.findById('800000000000000000000002').lean().exec((err, data: any) => {
|
MeasurementModel.findById('800000000000000000000002').lean().exec((err, data: any) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.property('status', 10);
|
should(data).have.property('status',globals.status.validated);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -114,7 +115,7 @@ describe('/measurement', () => {
|
|||||||
should(data).have.only.keys('_id', 'condition_id', 'values', 'measurement_template', 'status', '__v');
|
should(data).have.only.keys('_id', 'condition_id', 'values', 'measurement_template', 'status', '__v');
|
||||||
should(data.condition_id.toString()).be.eql('700000000000000000000001');
|
should(data.condition_id.toString()).be.eql('700000000000000000000001');
|
||||||
should(data.measurement_template.toString()).be.eql('300000000000000000000001');
|
should(data.measurement_template.toString()).be.eql('300000000000000000000001');
|
||||||
should(data).have.property('status', 0);
|
should(data).have.property('status',globals.status.new);
|
||||||
should(data).have.property('values');
|
should(data).have.property('values');
|
||||||
should(data.values).have.property('dpt', [[1,2],[3,4],[5,6]]);
|
should(data.values).have.property('dpt', [[1,2],[3,4],[5,6]]);
|
||||||
done();
|
done();
|
||||||
@ -256,7 +257,7 @@ describe('/measurement', () => {
|
|||||||
should(res.body).be.eql({status: 'OK'});
|
should(res.body).be.eql({status: 'OK'});
|
||||||
MeasurementModel.findById('800000000000000000000001').lean().exec((err, data) => {
|
MeasurementModel.findById('800000000000000000000001').lean().exec((err, data) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.property('status', -1);
|
should(data).have.property('status',globals.status.deleted);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,12 +2,12 @@ import express from 'express';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import MeasurementModel from '../models/measurement';
|
import MeasurementModel from '../models/measurement';
|
||||||
import ConditionModel from '../models/condition';
|
|
||||||
import MeasurementTemplateModel from '../models/measurement_template';
|
import MeasurementTemplateModel from '../models/measurement_template';
|
||||||
import MeasurementValidate from './validate/measurement';
|
import MeasurementValidate from './validate/measurement';
|
||||||
import IdValidate from './validate/id';
|
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';
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -46,7 +46,7 @@ router.put('/measurement/' + IdValidate.parameter(), async (req, res, next) => {
|
|||||||
if (measurement.values) {
|
if (measurement.values) {
|
||||||
measurement.values = _.assign({}, data.values, measurement.values);
|
measurement.values = _.assign({}, data.values, measurement.values);
|
||||||
if (!_.isEqual(measurement.values, data.values)) {
|
if (!_.isEqual(measurement.values, data.values)) {
|
||||||
measurement.status = 0; // set status to new
|
measurement.status = globals.status.new; // set status to new
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ router.delete('/measurement/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
res.status(404).json({status: 'Not found'});
|
res.status(404).json({status: 'Not found'});
|
||||||
}
|
}
|
||||||
if (!await conditionIdCheck(data, req, res, next)) return;
|
if (!await conditionIdCheck(data, req, res, next)) return;
|
||||||
await MeasurementModel.findByIdAndUpdate(req.params.id, {status: -1}).lean().exec(err => {
|
await MeasurementModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).lean().exec(err => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json({status: 'OK'});
|
res.json({status: 'OK'});
|
||||||
});
|
});
|
||||||
@ -93,14 +93,14 @@ router.post('/measurement/new', async (req, res, next) => {
|
|||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|
||||||
async function conditionIdCheck (measurement, req, res, next) { // validate condition_id, returns false if invalid
|
async function conditionIdCheck (measurement, req, res, next) { // validate condition_id, returns false if invalid // TODO
|
||||||
const sampleData = await ConditionModel.findById(measurement.condition_id).populate('sample_id').lean().exec().catch(err => {next(err); return false;}) as any;
|
// const sampleData = await ConditionModel.findById(measurement.condition_id).populate('sample_id').lean().exec().catch(err => {next(err); return false;}) as any;
|
||||||
if (!sampleData) { // sample_id not found
|
// if (!sampleData) { // sample_id not found
|
||||||
res.status(400).json({status: 'Condition id not available'});
|
// res.status(400).json({status: 'Condition id not available'});
|
||||||
return false
|
return false
|
||||||
}
|
// }
|
||||||
if (sampleData.sample_id.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return false; // sample does not belong to user
|
// if (sampleData.sample_id.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return false; // sample does not belong to user
|
||||||
return true;
|
// return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function templateCheck (measurement, param, res, next) { // validate measurement_template and values, param for new/change
|
async function templateCheck (measurement, param, res, next) { // validate measurement_template and values, param for new/change
|
||||||
|
@ -3,10 +3,16 @@ import SampleModel from '../models/sample';
|
|||||||
import NoteModel from '../models/note';
|
import NoteModel from '../models/note';
|
||||||
import NoteFieldModel from '../models/note_field';
|
import NoteFieldModel from '../models/note_field';
|
||||||
import TestHelper from "../test/helper";
|
import TestHelper from "../test/helper";
|
||||||
|
import globals from '../globals';
|
||||||
|
|
||||||
// TODO: generate output for ML in format DPT -> data, implement filtering, field selection
|
// TODO: generate output for ML in format DPT -> data, implement filtering, field selection
|
||||||
|
// TODO: filter by not completely filled/no measurements
|
||||||
// TODO: write script for data import
|
// TODO: write script for data import
|
||||||
// TODO: delete everything (measurements, condition) with sample
|
// TODO: delete everything (measurements, condition) with sample
|
||||||
|
// TODO: allow adding sample numbers for existing samples
|
||||||
|
|
||||||
|
// TODO: Do not allow validation or measurement entry without condition
|
||||||
|
|
||||||
|
|
||||||
describe('/sample', () => {
|
describe('/sample', () => {
|
||||||
let server;
|
let server;
|
||||||
@ -24,14 +30,16 @@ describe('/sample', () => {
|
|||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === 10).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.validated).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
should(sample).have.property('color').be.type('string');
|
should(sample).have.property('color').be.type('string');
|
||||||
should(sample).have.property('batch').be.type('string');
|
should(sample).have.property('batch').be.type('string');
|
||||||
|
should(sample).have.property('condition').be.type('object');
|
||||||
|
should(sample.condition).have.property('condition_template').be.type('string');
|
||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
@ -48,17 +56,19 @@ describe('/sample', () => {
|
|||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === 10).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.validated).length);
|
||||||
should(res.body).matchEach(material => {
|
should(res.body).matchEach(sample => {
|
||||||
should(material).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
||||||
should(material).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(material).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(material).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
should(material).have.property('color').be.type('string');
|
should(sample).have.property('color').be.type('string');
|
||||||
should(material).have.property('batch').be.type('string');
|
should(sample).have.property('batch').be.type('string');
|
||||||
should(material).have.property('material_id').be.type('string');
|
should(sample).have.property('condition').be.type('object');
|
||||||
should(material).have.property('note_id');
|
should(sample.condition).have.property('condition_template').be.type('string');
|
||||||
should(material).have.property('user_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
|
should(sample).have.property('note_id');
|
||||||
|
should(sample).have.property('user_id').be.type('string');
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -83,25 +93,28 @@ describe('/sample', () => {
|
|||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
let asyncCounter = res.body.length;
|
let asyncCounter = res.body.length;
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === 0).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.new).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
should(sample).have.property('color').be.type('string');
|
should(sample).have.property('color').be.type('string');
|
||||||
should(sample).have.property('batch').be.type('string');
|
should(sample).have.property('batch').be.type('string');
|
||||||
|
should(sample).have.property('condition').be.type('object');
|
||||||
|
if (Object.keys(sample.condition).length > 0) {
|
||||||
|
should(sample.condition).have.property('condition_template').be.type('string');
|
||||||
|
}
|
||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
||||||
should(data).have.property('status', 0);
|
should(data).have.property('status',globals.status.new);
|
||||||
if (--asyncCounter === 0) {
|
if (--asyncCounter === 0) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('returns all deleted samples', done => {
|
it('returns all deleted samples', done => {
|
||||||
@ -116,23 +129,26 @@ describe('/sample', () => {
|
|||||||
let asyncCounter = res.body.length;
|
let asyncCounter = res.body.length;
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === -1).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === -1).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
should(sample).have.property('color').be.type('string');
|
should(sample).have.property('color').be.type('string');
|
||||||
should(sample).have.property('batch').be.type('string');
|
should(sample).have.property('batch').be.type('string');
|
||||||
|
should(sample).have.property('condition').be.type('object');
|
||||||
|
should(sample.condition).have.property('condition_template').be.type('string');
|
||||||
|
should(sample.condition).have.property('condition_template').be.type('string');
|
||||||
|
should(sample.condition).have.property('condition_template').be.type('string');
|
||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
||||||
should(data).have.property('status', -1);
|
should(data).have.property('status',globals.status.deleted);
|
||||||
if (--asyncCounter === 0) {
|
if (--asyncCounter === 0) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects requests from a write user', done => {
|
it('rejects requests from a write user', done => {
|
||||||
@ -160,6 +176,73 @@ describe('/sample', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('GET /sample/{id}', () => {
|
||||||
|
it('returns the right sample', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/sample/400000000000000000000003',
|
||||||
|
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', mineral: 0, glass_fiber: 33, carbon_fiber: 0, numbers: [{color: 'black', number: '5514262406'}]}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, user: 'admin'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with an API key', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/sample/400000000000000000000003',
|
||||||
|
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', mineral: 0, glass_fiber: 33, carbon_fiber: 0, numbers: [{color: 'black', number: '5514262406'}]}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, user: 'admin'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a deleted sample for a maintain/admin user', done => { // TODO: make tests work
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/sample/400000000000000000000005',
|
||||||
|
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', mineral: 0, glass_fiber: 33, carbon_fiber: 0, numbers: [{color: 'black', number: '5514262406'}]}, notes: {}, user: 'admin'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 403 for a write user when requesting a deleted sample', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/sample/400000000000000000000005',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 403
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 404 for an unknown sample', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/sample/000000000000000000000005',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 404
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects an invalid id', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/sample/400000000h00000000000005',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 404
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects unauthorized requests', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/sample/400000000000000000000005',
|
||||||
|
httpStatus: 401
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('PUT /sample/{id}', () => {
|
describe('PUT /sample/{id}', () => {
|
||||||
it('returns the right sample', done => {
|
it('returns the right sample', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
@ -168,7 +251,7 @@ describe('/sample', () => {
|
|||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {},
|
req: {},
|
||||||
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('keeps unchanged properties', done => {
|
it('keeps unchanged properties', done => {
|
||||||
@ -177,21 +260,22 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', notes: {}}
|
req: {type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', notes: {}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
||||||
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
||||||
should(data).have.property('_id');
|
should(data).have.property('_id');
|
||||||
should(data).have.property('number', '1');
|
should(data).have.property('number', '1');
|
||||||
should(data).have.property('color', 'black');
|
should(data).have.property('color', 'black');
|
||||||
should(data).have.property('type', 'granulate');
|
should(data).have.property('type', 'granulate');
|
||||||
should(data).have.property('batch', '');
|
should(data).have.property('batch', '');
|
||||||
|
should(data).have.property('condition', {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'});
|
||||||
should(data.material_id.toString()).be.eql('100000000000000000000004');
|
should(data.material_id.toString()).be.eql('100000000000000000000004');
|
||||||
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
||||||
should(data).have.property('status', 10);
|
should(data).have.property('status',globals.status.validated);
|
||||||
should(data).have.property('note_id', null);
|
should(data).have.property('note_id', null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -206,10 +290,27 @@ describe('/sample', () => {
|
|||||||
req: {type: 'granulate'}
|
req: {type: 'granulate'}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
||||||
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(data).have.property('status', 10);
|
should(data).have.property('status',globals.status.validated);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('keeps an unchanged condition', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}}
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
||||||
|
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
||||||
|
if (err) return done (err);
|
||||||
|
should(data).have.property('status',globals.status.validated);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -223,18 +324,21 @@ describe('/sample', () => {
|
|||||||
req: {notes: {comment: 'Stoff gesperrt', sample_references: []}}
|
req: {notes: {comment: 'Stoff gesperrt', sample_references: []}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({_id: '400000000000000000000002', number: '21', type: 'granulate', color: 'natural', batch: '1560237365', material_id: '100000000000000000000001', note_id: '500000000000000000000001', user_id: '000000000000000000000002'});
|
should(res.body).be.eql({_id: '400000000000000000000002', number: '21', type: 'granulate', color: 'natural', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', note_id: '500000000000000000000001', user_id: '000000000000000000000002'});
|
||||||
SampleModel.findById('400000000000000000000002').lean().exec((err, data: any) => {
|
SampleModel.findById('400000000000000000000002').lean().exec((err, data: any) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
||||||
should(data).have.property('_id');
|
should(data).have.property('_id');
|
||||||
should(data).have.property('number', '21');
|
should(data).have.property('number', '21');
|
||||||
should(data).have.property('color', 'natural');
|
should(data).have.property('color', 'natural');
|
||||||
should(data).have.property('type', 'granulate');
|
should(data).have.property('type', 'granulate');
|
||||||
should(data).have.property('batch', '1560237365');
|
should(data).have.property('batch', '1560237365');
|
||||||
|
should(data.condition).have.property('material', 'copper');
|
||||||
|
should(data.condition).have.property('weeks', 3);
|
||||||
|
should(data.condition.condition_template.toString()).be.eql('200000000000000000000001');
|
||||||
should(data.material_id.toString()).be.eql('100000000000000000000001');
|
should(data.material_id.toString()).be.eql('100000000000000000000001');
|
||||||
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
||||||
should(data).have.property('status', 10);
|
should(data).have.property('status',globals.status.validated);
|
||||||
should(data.note_id.toString()).be.eql('500000000000000000000001');
|
should(data.note_id.toString()).be.eql('500000000000000000000001');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -246,20 +350,21 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
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'}]}}
|
||||||
}).end(err => {
|
}).end(err => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
||||||
should(data).have.property('_id');
|
should(data).have.property('_id');
|
||||||
should(data).have.property('number', '1');
|
should(data).have.property('number', '1');
|
||||||
should(data).have.property('color', 'signalviolet');
|
should(data).have.property('color', 'signalviolet');
|
||||||
should(data).have.property('type', 'part');
|
should(data).have.property('type', 'part');
|
||||||
should(data).have.property('batch', '114531');
|
should(data).have.property('batch', '114531');
|
||||||
|
should(data).have.property('condition', {condition_template: '200000000000000000000003'});
|
||||||
should(data.material_id.toString()).be.eql('100000000000000000000002');
|
should(data.material_id.toString()).be.eql('100000000000000000000002');
|
||||||
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
||||||
should(data).have.property('status', 0);
|
should(data).have.property('status',globals.status.new);
|
||||||
should(data).have.property('note_id');
|
should(data).have.property('note_id');
|
||||||
NoteModel.findById(data.note_id).lean().exec((err, data: any) => {
|
NoteModel.findById(data.note_id).lean().exec((err, data: any) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
@ -267,7 +372,7 @@ describe('/sample', () => {
|
|||||||
should(data).have.property('comment', 'Testcomment');
|
should(data).have.property('comment', 'Testcomment');
|
||||||
should(data).have.property('sample_references');
|
should(data).have.property('sample_references');
|
||||||
should(data.sample_references).have.lengthOf(1);
|
should(data.sample_references).have.lengthOf(1);
|
||||||
should(data.sample_references[0].id.toString()).be.eql('400000000000000000000003');
|
should(data.sample_references[0].sample_id.toString()).be.eql('400000000000000000000003');
|
||||||
should(data.sample_references[0]).have.property('relation', 'part to this sample');
|
should(data.sample_references[0]).have.property('relation', 'part to this sample');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -350,7 +455,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Color not available for material'}
|
res: {status: 'Color not available for material'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -360,7 +465,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '000000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '000000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Material not available'}
|
res: {status: 'Material not available'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -370,7 +475,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {number: 25, type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {number: 25, type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"number" is not allowed'}
|
res: {status: 'Invalid body format', details: '"number" is not allowed'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -380,7 +485,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '000000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '000000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Sample reference not available'}
|
res: {status: 'Sample reference not available'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -390,7 +495,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '10000000000h000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '10000000000h000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"material_id" with value "10000000000h000000000001" fails to match the required pattern: /[0-9a-f]{24}/'}
|
res: {status: 'Invalid body format', details: '"material_id" with value "10000000000h000000000001" fails to match the required pattern: /[0-9a-f]{24}/'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -400,7 +505,87 @@ describe('/sample', () => {
|
|||||||
url: '/sample/10000000000h000000000001',
|
url: '/sample/10000000000h000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 404,
|
httpStatus: 404,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects not specified condition parameters', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {condition: {material: 'copper', weeks: 3, xxx: 44, condition_template: '200000000000000000000001'}},
|
||||||
|
res: {status: 'Invalid body format', details: '"xxx" is not allowed'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a condition parameter not in the value range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {condition: {material: 'xx', weeks: 3, condition_template: '200000000000000000000001'}},
|
||||||
|
res: {status: 'Invalid body format', details: '"material" must be one of [copper, hot air]'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a condition parameter below minimum range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {condition: {material: 'copper', weeks: 0, condition_template: '200000000000000000000001'}},
|
||||||
|
res: {status: 'Invalid body format', details: '"weeks" must be larger than or equal to 1'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a condition parameter above maximum range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {condition: {material: 'copper', weeks: 10.5, condition_template: '200000000000000000000001'}},
|
||||||
|
res: {status: 'Invalid body format', details: '"weeks" must be less than or equal to 10'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects an invalid condition template', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {condition: {material: 'copper', weeks: 3, condition_template: '200000000000h00000000001'}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects an unknown condition template', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {condition: {material: 'copper', weeks: 3, condition_template: '000000000000000000000001'}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('allows keeping an empty condition empty', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000006',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {condition: {}},
|
||||||
|
res: {_id: '400000000000000000000006', number: 'Rng36', type: 'granulate', color: 'black', batch: '', condition: {}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects an changing back to an empty condition', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'put',
|
||||||
|
url: '/sample/400000000000000000000001',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {condition: {}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
@ -409,7 +594,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {key: 'janedoe'},
|
auth: {key: 'janedoe'},
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects changes for samples from another user for a write user', done => {
|
it('rejects changes for samples from another user for a write user', done => {
|
||||||
@ -428,7 +613,7 @@ describe('/sample', () => {
|
|||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {},
|
req: {},
|
||||||
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {condition_template: '200000000000000000000001', material: 'copper', weeks: 3}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects requests from a read user', done => {
|
it('rejects requests from a read user', done => {
|
||||||
@ -437,7 +622,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
auth: {basic: 'user'},
|
auth: {basic: 'user'},
|
||||||
httpStatus: 403,
|
httpStatus: 403,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('returns 404 for an unknown sample', done => {
|
it('returns 404 for an unknown sample', done => {
|
||||||
@ -446,7 +631,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/000000000000000000000001',
|
url: '/sample/000000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 404,
|
httpStatus: 404,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
it('rejects unauthorized requests', done => {
|
it('rejects unauthorized requests', done => {
|
||||||
@ -454,7 +639,7 @@ describe('/sample', () => {
|
|||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/sample/400000000000000000000001',
|
url: '/sample/400000000000000000000001',
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'part', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -471,15 +656,18 @@ describe('/sample', () => {
|
|||||||
should(res.body).be.eql({status: 'OK'});
|
should(res.body).be.eql({status: 'OK'});
|
||||||
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
||||||
should(data).have.property('_id');
|
should(data).have.property('_id');
|
||||||
should(data).have.property('number', '1');
|
should(data).have.property('number', '1');
|
||||||
should(data).have.property('color', 'black');
|
should(data).have.property('color', 'black');
|
||||||
should(data).have.property('type', 'granulate');
|
should(data).have.property('type', 'granulate');
|
||||||
should(data).have.property('batch', '');
|
should(data).have.property('batch', '');
|
||||||
|
should(data.condition).have.property('material', 'copper');
|
||||||
|
should(data.condition).have.property('weeks', 3);
|
||||||
|
should(data.condition.condition_template.toString()).be.eql('200000000000000000000001');
|
||||||
should(data.material_id.toString()).be.eql('100000000000000000000004');
|
should(data.material_id.toString()).be.eql('100000000000000000000004');
|
||||||
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
should(data.user_id.toString()).be.eql('000000000000000000000002');
|
||||||
should(data).have.property('status', -1);
|
should(data).have.property('status',globals.status.deleted);
|
||||||
should(data).have.property('note_id', null);
|
should(data).have.property('note_id', null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -536,7 +724,7 @@ describe('/sample', () => {
|
|||||||
NoteModel.findById('500000000000000000000003').lean().exec((err, data: any) => {
|
NoteModel.findById('500000000000000000000003').lean().exec((err, data: any) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.property('sample_references').with.lengthOf(1);
|
should(data).have.property('sample_references').with.lengthOf(1);
|
||||||
should(data.sample_references[0].id.toString()).be.eql('400000000000000000000003');
|
should(data.sample_references[0].sample_id.toString()).be.eql('400000000000000000000003');
|
||||||
should(data.sample_references[0]).have.property('relation', 'part to sample');
|
should(data.sample_references[0]).have.property('relation', 'part to sample');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -555,7 +743,7 @@ describe('/sample', () => {
|
|||||||
should(res.body).be.eql({status: 'OK'});
|
should(res.body).be.eql({status: 'OK'});
|
||||||
SampleModel.findById('400000000000000000000001').lean().exec((err, data) => {
|
SampleModel.findById('400000000000000000000001').lean().exec((err, data) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.property('status', -1);
|
should(data).have.property('status',globals.status.deleted);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -617,15 +805,16 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
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'}]}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id');
|
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
||||||
should(res.body).have.property('_id').be.type('string');
|
should(res.body).have.property('_id').be.type('string');
|
||||||
should(res.body).have.property('number', 'Rng34');
|
should(res.body).have.property('number', 'Rng37');
|
||||||
should(res.body).have.property('color', 'black');
|
should(res.body).have.property('color', 'black');
|
||||||
should(res.body).have.property('type', 'granulate');
|
should(res.body).have.property('type', 'granulate');
|
||||||
should(res.body).have.property('batch', '1560237365');
|
should(res.body).have.property('batch', '1560237365');
|
||||||
|
should(res.body).have.property('condition', {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'});
|
||||||
should(res.body).have.property('material_id', '100000000000000000000001');
|
should(res.body).have.property('material_id', '100000000000000000000001');
|
||||||
should(res.body).have.property('note_id').be.type('string');
|
should(res.body).have.property('note_id').be.type('string');
|
||||||
should(res.body).have.property('user_id', '000000000000000000000002');
|
should(res.body).have.property('user_id', '000000000000000000000002');
|
||||||
@ -638,21 +827,22 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
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'}]}}
|
||||||
}).end(err => {
|
}).end(err => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
SampleModel.find({number: 'Rng34'}).lean().exec((err, data: any) => {
|
SampleModel.find({number: 'Rng37'}).lean().exec((err, data: any) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(data).have.lengthOf(1);
|
should(data).have.lengthOf(1);
|
||||||
should(data[0]).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
should(data[0]).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
||||||
should(data[0]).have.property('_id');
|
should(data[0]).have.property('_id');
|
||||||
should(data[0]).have.property('number', 'Rng34');
|
should(data[0]).have.property('number', 'Rng37');
|
||||||
should(data[0]).have.property('color', 'black');
|
should(data[0]).have.property('color', 'black');
|
||||||
should(data[0]).have.property('type', 'granulate');
|
should(data[0]).have.property('type', 'granulate');
|
||||||
should(data[0]).have.property('batch', '1560237365');
|
should(data[0]).have.property('batch', '1560237365');
|
||||||
|
should(data[0]).have.property('condition', {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'});
|
||||||
should(data[0].material_id.toString()).be.eql('100000000000000000000001');
|
should(data[0].material_id.toString()).be.eql('100000000000000000000001');
|
||||||
should(data[0].user_id.toString()).be.eql('000000000000000000000002');
|
should(data[0].user_id.toString()).be.eql('000000000000000000000002');
|
||||||
should(data[0]).have.property('status', 0);
|
should(data[0]).have.property('status',globals.status.new);
|
||||||
should(data[0]).have.property('note_id');
|
should(data[0]).have.property('note_id');
|
||||||
NoteModel.findById(data[0].note_id).lean().exec((err, data: any) => {
|
NoteModel.findById(data[0].note_id).lean().exec((err, data: any) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
@ -660,7 +850,7 @@ describe('/sample', () => {
|
|||||||
should(data).have.property('comment', 'Testcomment');
|
should(data).have.property('comment', 'Testcomment');
|
||||||
should(data).have.property('sample_references');
|
should(data).have.property('sample_references');
|
||||||
should(data.sample_references).have.lengthOf(1);
|
should(data.sample_references).have.lengthOf(1);
|
||||||
should(data.sample_references[0].id.toString()).be.eql('400000000000000000000003');
|
should(data.sample_references[0].sample_id.toString()).be.eql('400000000000000000000003');
|
||||||
should(data.sample_references[0]).have.property('relation', 'part to this sample');
|
should(data.sample_references[0]).have.property('relation', 'part to this sample');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -710,10 +900,10 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'johnnydoe'},
|
auth: {basic: 'johnnydoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id');
|
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
||||||
should(res.body).have.property('_id').be.type('string');
|
should(res.body).have.property('_id').be.type('string');
|
||||||
should(res.body).have.property('number', 'Fe1');
|
should(res.body).have.property('number', 'Fe1');
|
||||||
should(res.body).have.property('color', 'black');
|
should(res.body).have.property('color', 'black');
|
||||||
@ -725,13 +915,35 @@ describe('/sample', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('accepts a sample without condition', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done (err);
|
||||||
|
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
||||||
|
should(res.body).have.property('_id').be.type('string');
|
||||||
|
should(res.body).have.property('number', 'Rng37');
|
||||||
|
should(res.body).have.property('color', 'black');
|
||||||
|
should(res.body).have.property('type', 'granulate');
|
||||||
|
should(res.body).have.property('batch', '1560237365');
|
||||||
|
should(res.body).have.property('condition', {});
|
||||||
|
should(res.body).have.property('material_id', '100000000000000000000001');
|
||||||
|
should(res.body).have.property('note_id').be.type('string');
|
||||||
|
should(res.body).have.property('user_id', '000000000000000000000002');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects a color not defined for the material', done => {
|
it('rejects a color not defined for the material', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {color: 'green', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {color: 'green', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Color not available for material'}
|
res: {status: 'Color not available for material'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -741,7 +953,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '000000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '000000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Material not available'}
|
res: {status: 'Material not available'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -751,7 +963,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {number: 'Rng34', color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {number: 'Rng34', color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"number" is not allowed'}
|
res: {status: 'Invalid body format', details: '"number" is not allowed'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -761,17 +973,97 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '000000000000000000000003', relation: 'part to this sample'}]}},
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '000000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Sample reference not available'}
|
res: {status: 'Sample reference not available'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('rejects an invalid condition_template id', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '20000h000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a not existing condition_template id', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '000000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects not specified condition parameters', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 3, xxx: 23, condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects missing condition parameters', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects condition parameters not in the value range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'xxx', weeks: 3, condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a condition parameter below minimum range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 0, condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a condition parameter above maximum range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 11, condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a condition without condition template', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'post',
|
||||||
|
url: '/sample/new',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 3}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
|
res: {status: 'Condition template not available'}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects a missing color', done => {
|
it('rejects a missing color', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"color" is required'}
|
res: {status: 'Invalid body format', details: '"color" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -781,7 +1073,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {color: 'black', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {color: 'black', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"type" is required'}
|
res: {status: 'Invalid body format', details: '"type" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -791,7 +1083,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {color: 'black', type: 'granulate', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {color: 'black', type: 'granulate', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"batch" is required'}
|
res: {status: 'Invalid body format', details: '"batch" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -801,7 +1093,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {color: 'black', type: 'granulate', batch: '1560237365', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"material_id" is required'}
|
res: {status: 'Invalid body format', details: '"material_id" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -811,7 +1103,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '10000000000h000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '10000000000h000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
res: {status: 'Invalid body format', details: '"material_id" with value "10000000000h000000000001" fails to match the required pattern: /[0-9a-f]{24}/'}
|
res: {status: 'Invalid body format', details: '"material_id" with value "10000000000h000000000001" fails to match the required pattern: /[0-9a-f]{24}/'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -821,7 +1113,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {key: 'janedoe'},
|
auth: {key: 'janedoe'},
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects requests from a read user', done => {
|
it('rejects requests from a read user', done => {
|
||||||
@ -830,7 +1122,7 @@ describe('/sample', () => {
|
|||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
auth: {basic: 'user'},
|
auth: {basic: 'user'},
|
||||||
httpStatus: 403,
|
httpStatus: 403,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects unauthorized requests', done => {
|
it('rejects unauthorized requests', done => {
|
||||||
@ -838,7 +1130,7 @@ describe('/sample', () => {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/sample/new',
|
url: '/sample/new',
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,10 +5,15 @@ import SampleValidate from './validate/sample';
|
|||||||
import NoteFieldValidate from './validate/note_field';
|
import NoteFieldValidate from './validate/note_field';
|
||||||
import res400 from './validate/res400';
|
import res400 from './validate/res400';
|
||||||
import SampleModel from '../models/sample'
|
import SampleModel from '../models/sample'
|
||||||
|
import MeasurementModel from '../models/measurement';
|
||||||
import MaterialModel from '../models/material';
|
import MaterialModel from '../models/material';
|
||||||
import NoteModel from '../models/note';
|
import NoteModel from '../models/note';
|
||||||
import NoteFieldModel from '../models/note_field';
|
import NoteFieldModel from '../models/note_field';
|
||||||
import IdValidate from './validate/id';
|
import IdValidate from './validate/id';
|
||||||
|
import mongoose from "mongoose";
|
||||||
|
import ConditionTemplateModel from '../models/condition_template';
|
||||||
|
import ParametersValidate from './validate/parameters';
|
||||||
|
import globals from '../globals';
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -16,7 +21,7 @@ const router = express.Router();
|
|||||||
router.get('/samples', (req, res, next) => {
|
router.get('/samples', (req, res, next) => {
|
||||||
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
|
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
|
||||||
|
|
||||||
SampleModel.find({status: 10}).lean().exec((err, data) => {
|
SampleModel.find({status: globals.status.validated}).lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(_.compact(data.map(e => SampleValidate.output(e)))); // validate all and filter null values from validation errors
|
res.json(_.compact(data.map(e => SampleValidate.output(e)))); // validate all and filter null values from validation errors
|
||||||
})
|
})
|
||||||
@ -25,17 +30,32 @@ router.get('/samples', (req, res, next) => {
|
|||||||
router.get('/samples/:group(new|deleted)', (req, res, next) => {
|
router.get('/samples/:group(new|deleted)', (req, res, next) => {
|
||||||
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
let status;
|
SampleModel.find({status: globals.status[req.params.group]}).lean().exec((err, data) => {
|
||||||
switch (req.params.group) {
|
|
||||||
case 'new': status = 0;
|
|
||||||
break;
|
|
||||||
case 'deleted': status = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SampleModel.find({status: status}).lean().exec((err, data) => {
|
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
res.json(_.compact(data.map(e => SampleValidate.output(e)))); // validate all and filter null values from validation errors
|
res.json(_.compact(data.map(e => SampleValidate.output(e)))); // validate all and filter null values from validation errors
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
||||||
|
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
|
||||||
|
|
||||||
|
SampleModel.findById(req.params.id).populate('material_id').populate('user_id', 'name').populate('note_id').lean().exec((err, sampleData: any) => {
|
||||||
|
if (err) return next(err);
|
||||||
|
|
||||||
|
if (sampleData) {
|
||||||
|
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.user = sampleData.user_id.name;
|
||||||
|
sampleData.notes = sampleData.note_id ? sampleData.note_id : {};
|
||||||
|
MeasurementModel.find({sample_id: mongoose.Types.ObjectId(req.params.id)}).lean().exec((err, data) => {
|
||||||
|
sampleData.measurements = data;
|
||||||
|
res.json(SampleValidate.output(sampleData, 'details'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.status(404).json({status: 'Not found'});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
||||||
@ -60,6 +80,10 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
if (!await materialCheck(sample, res, next, sampleData.material_id)) return;
|
if (!await materialCheck(sample, res, next, sampleData.material_id)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sample.hasOwnProperty('condition') && !(_.isEmpty(sample.condition) && _.isEmpty(sampleData.condition))) { // do not execute check if condition is and was empty
|
||||||
|
if (!await conditionCheck(sample.condition, 'change', res, next)) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sample.hasOwnProperty('notes')) {
|
if (sample.hasOwnProperty('notes')) {
|
||||||
let newNotes = true;
|
let newNotes = true;
|
||||||
if (sampleData.note_id !== null) { // old notes data exists
|
if (sampleData.note_id !== null) { // old notes data exists
|
||||||
@ -89,10 +113,10 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
|
|
||||||
// check for changes
|
// check for changes
|
||||||
if (!_.isEqual(_.pick(IdValidate.stringify(sampleData), _.keys(sample)), _.omit(sample, ['notes']))) {
|
if (!_.isEqual(_.pick(IdValidate.stringify(sampleData), _.keys(sample)), _.omit(sample, ['notes']))) {
|
||||||
sample.status = 0;
|
sample.status = globals.status.new;
|
||||||
}
|
}
|
||||||
|
|
||||||
await SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).lean().exec((err, data) => {
|
await SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).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));
|
||||||
});
|
});
|
||||||
@ -112,7 +136,7 @@ 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: -1}).lean().exec(err => { // set sample status
|
await SampleModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).lean().exec(err => { // set sample status
|
||||||
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
|
||||||
@ -133,6 +157,10 @@ router.delete('/sample/' + IdValidate.parameter(), (req, res, next) => {
|
|||||||
router.post('/sample/new', async (req, res, next) => {
|
router.post('/sample/new', async (req, res, next) => {
|
||||||
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
|
if (!req.body.hasOwnProperty('condition')) { // add empty condition if not specified
|
||||||
|
req.body.condition = {};
|
||||||
|
}
|
||||||
|
|
||||||
const {error, value: sample} = SampleValidate.input(req.body, 'new');
|
const {error, value: sample} = SampleValidate.input(req.body, 'new');
|
||||||
if (error) return res400(error, res);
|
if (error) return res400(error, res);
|
||||||
|
|
||||||
@ -143,7 +171,11 @@ router.post('/sample/new', async (req, res, next) => {
|
|||||||
customFieldsChange(Object.keys(sample.notes.custom_fields), 1);
|
customFieldsChange(Object.keys(sample.notes.custom_fields), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sample.status = 0; // set status to new
|
if (!_.isEmpty(sample.condition)) { // do not execute check if condition is empty
|
||||||
|
if (!await conditionCheck(sample.condition, 'change', res, next)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sample.status = globals.status.new; // set status to new
|
||||||
sample.number = await numberGenerate(sample, req, res, next);
|
sample.number = await numberGenerate(sample, req, res, next);
|
||||||
if (!sample.number) return;
|
if (!sample.number) return;
|
||||||
|
|
||||||
@ -152,6 +184,7 @@ router.post('/sample/new', async (req, res, next) => {
|
|||||||
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);
|
||||||
res.json(SampleValidate.output(data.toObject()));
|
res.json(SampleValidate.output(data.toObject()));
|
||||||
@ -172,14 +205,15 @@ router.get('/sample/notes/fields', (req, res, next) => {
|
|||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|
||||||
async function numberGenerate (sample, req, res, next) { // generate number, returns false on error
|
async function numberGenerate (sample, req, res, next) { // generate number in format Location32, returns false on error
|
||||||
const sampleData = await SampleModel
|
const sampleData = await SampleModel
|
||||||
.find({number: new RegExp('^' + req.authDetails.location + '[0-9]+$', 'm')})
|
.findOne({number: new RegExp('^' + req.authDetails.location + '[0-9]+$', 'm')})
|
||||||
|
.sort({number: -1})
|
||||||
.lean()
|
.lean()
|
||||||
.exec()
|
.exec()
|
||||||
.catch(err => next(err));
|
.catch(err => next(err));
|
||||||
if (sampleData instanceof Error) return false;
|
if (sampleData instanceof Error) return false;
|
||||||
return req.authDetails.location + (sampleData.length > 0 ? Number(sampleData[0].number.replace(/[^0-9]+/g, '')) + 1 : 1);
|
return req.authDetails.location + (sampleData ? Number(sampleData.number.replace(/[^0-9]+/g, '')) + 1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function materialCheck (sample, res, next, id = sample.material_id) { // validate material_id and color, returns false if invalid
|
async function materialCheck (sample, res, next, id = sample.material_id) { // validate material_id and color, returns false if invalid
|
||||||
@ -196,13 +230,31 @@ async function materialCheck (sample, res, next, id = sample.material_id) { //
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function conditionCheck (condition, param, res, next) { // validate treatment template, returns false if invalid, otherwise template data
|
||||||
|
if (!condition.condition_template || !IdValidate.valid(condition.condition_template)) { // template id not found
|
||||||
|
res.status(400).json({status: 'Condition template not available'});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const conditionData = await ConditionTemplateModel.findById(condition.condition_template).lean().exec().catch(err => next(err)) as any;
|
||||||
|
if (conditionData instanceof Error) return false;
|
||||||
|
if (!conditionData) { // template not found
|
||||||
|
res.status(400).json({status: 'Condition template not available'});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate parameters
|
||||||
|
const {error, value: ignore} = ParametersValidate.input(_.omit(condition, 'condition_template'), conditionData.parameters, param);
|
||||||
|
if (error) {res400(error, res); return false;}
|
||||||
|
return conditionData;
|
||||||
|
}
|
||||||
|
|
||||||
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.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 => {
|
||||||
SampleModel.findById(reference.id).lean().exec((err, data) => {
|
SampleModel.findById(reference.sample_id).lean().exec((err, data) => {
|
||||||
if (err) {next(err); resolve(false)}
|
if (err) {next(err); resolve(false)}
|
||||||
if (!data) {
|
if (!data) {
|
||||||
res.status(400).json({status: 'Sample reference not available'});
|
res.status(400).json({status: 'Sample reference not available'});
|
||||||
@ -230,7 +282,7 @@ function customFieldsChange (fields, amount) { // update custom_fields and resp
|
|||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else if (data.qty <= 0) {
|
else if (data.qty <= 0) { // delete document if field is not used anymore
|
||||||
NoteFieldModel.findOneAndDelete({name: field}).lean().exec(err => {
|
NoteFieldModel.findOneAndDelete({name: field}).lean().exec(err => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import should from 'should/as-function';
|
import should from 'should/as-function';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import TemplateTreatmentModel from '../models/treatment_template';
|
import TemplateConditionModel from '../models/condition_template';
|
||||||
import TemplateMeasurementModel from '../models/measurement_template';
|
import TemplateMeasurementModel from '../models/measurement_template';
|
||||||
import TestHelper from "../test/helper";
|
import TestHelper from "../test/helper";
|
||||||
|
|
||||||
// TODO: do not allow usage of old templates for new samples
|
// TODO: do not allow usage of old templates for new samples
|
||||||
|
// TODO: remove number_prefix
|
||||||
|
// TODO: template parameters are not allowed to be condition_template
|
||||||
|
|
||||||
describe('/template', () => {
|
describe('/template', () => {
|
||||||
let server;
|
let server;
|
||||||
@ -12,25 +14,24 @@ describe('/template', () => {
|
|||||||
beforeEach(done => server = TestHelper.beforeEach(server, done));
|
beforeEach(done => server = TestHelper.beforeEach(server, done));
|
||||||
afterEach(done => TestHelper.afterEach(server, done));
|
afterEach(done => TestHelper.afterEach(server, done));
|
||||||
|
|
||||||
describe('/template/treatment', () => {
|
describe('/template/condition', () => {
|
||||||
describe('GET /template/treatments', () => {
|
describe('GET /template/conditions', () => {
|
||||||
it('returns all treatment templates', done => {
|
it('returns all condition templates', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/template/treatments',
|
url: '/template/conditions',
|
||||||
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);
|
||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.treatment_templates.length);
|
should(res.body).have.lengthOf(json.collections.condition_templates.length);
|
||||||
should(res.body).matchEach(treatment => {
|
should(res.body).matchEach(condition => {
|
||||||
should(treatment).have.only.keys('_id', 'name', 'version', 'parameters', 'number_prefix');
|
should(condition).have.only.keys('_id', 'name', 'version', 'parameters');
|
||||||
should(treatment).have.property('_id').be.type('string');
|
should(condition).have.property('_id').be.type('string');
|
||||||
should(treatment).have.property('name').be.type('string');
|
should(condition).have.property('name').be.type('string');
|
||||||
should(treatment).have.property('version').be.type('number');
|
should(condition).have.property('version').be.type('number');
|
||||||
should(treatment).have.property('number_prefix').be.type('string');
|
should(condition.parameters).matchEach(number => {
|
||||||
should(treatment.parameters).matchEach(number => {
|
|
||||||
should(number).have.only.keys('name', 'range');
|
should(number).have.only.keys('name', 'range');
|
||||||
should(number).have.property('name').be.type('string');
|
should(number).have.property('name').be.type('string');
|
||||||
should(number).have.property('range').be.type('object');
|
should(number).have.property('range').be.type('object');
|
||||||
@ -42,7 +43,7 @@ describe('/template', () => {
|
|||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/template/treatments',
|
url: '/template/conditions',
|
||||||
auth: {key: 'janedoe'},
|
auth: {key: 'janedoe'},
|
||||||
httpStatus: 401
|
httpStatus: 401
|
||||||
});
|
});
|
||||||
@ -50,26 +51,26 @@ describe('/template', () => {
|
|||||||
it('rejects unauthorized requests', done => {
|
it('rejects unauthorized requests', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/template/treatments',
|
url: '/template/conditions',
|
||||||
httpStatus: 401
|
httpStatus: 401
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GET /template/treatment/{id}', () => {
|
describe('GET /template/condition/{id}', () => {
|
||||||
it('returns the right treatment template', done => {
|
it('returns the right condition template', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, number_prefix: 'A', parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {key: 'janedoe'},
|
auth: {key: 'janedoe'},
|
||||||
httpStatus: 401
|
httpStatus: 401
|
||||||
});
|
});
|
||||||
@ -77,7 +78,7 @@ describe('/template', () => {
|
|||||||
it('rejects an unknown id', done => {
|
it('rejects an unknown id', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/template/treatment/000000000000000000000001',
|
url: '/template/condition/000000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 404
|
httpStatus: 404
|
||||||
});
|
});
|
||||||
@ -85,58 +86,57 @@ describe('/template', () => {
|
|||||||
it('rejects unauthorized requests', done => {
|
it('rejects unauthorized requests', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
httpStatus: 401
|
httpStatus: 401
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('PUT /template/treatment/{name}', () => {
|
describe('PUT /template/condition/{name}', () => {
|
||||||
it('returns the right treatment template', done => {
|
it('returns the right condition template', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {},
|
req: {},
|
||||||
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, number_prefix: 'A', parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('keeps unchanged properties', done => {
|
it('keeps unchanged properties', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {name: 'heat treatment', parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]},
|
req: {name: 'heat treatment', parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]},
|
||||||
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, number_prefix: 'A', parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('keeps only one unchanged property', done => {
|
it('keeps only one unchanged property', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {name: 'heat treatment'},
|
req: {name: 'heat treatment'},
|
||||||
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, number_prefix: 'A', parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
res: {_id: '200000000000000000000001', name: 'heat treatment', version: 1, parameters: [{name: 'material', range: {values: ['copper', 'hot air']}}, {name: 'weeks', range: {min: 1, max: 10}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('changes the given properties', done => {
|
it('changes the given properties', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
TemplateTreatmentModel.findById(res.body._id).lean().exec((err, data:any) => {
|
TemplateConditionModel.findById(res.body._id).lean().exec((err, data:any) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.only.keys('_id', 'name', 'version', 'number_prefix', 'parameters', '__v');
|
should(data).have.only.keys('_id', 'name', 'version', 'parameters', '__v');
|
||||||
should(data).have.property('name', 'heat aging');
|
should(data).have.property('name', 'heat aging');
|
||||||
should(data).have.property('version', 2);
|
should(data).have.property('version', 2);
|
||||||
should(data).have.property('number_prefix', 'A');
|
|
||||||
should(data).have.property('parameters').have.lengthOf(1);
|
should(data).have.property('parameters').have.lengthOf(1);
|
||||||
should(data.parameters[0]).have.property('name', 'time');
|
should(data.parameters[0]).have.property('name', 'time');
|
||||||
should(data.parameters[0]).have.property('range');
|
should(data.parameters[0]).have.property('range');
|
||||||
@ -148,18 +148,17 @@ describe('/template', () => {
|
|||||||
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',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {name: 'heat aging'}
|
req: {name: 'heat aging'}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
TemplateTreatmentModel.findById(res.body._id).lean().exec((err, data:any) => {
|
TemplateConditionModel.findById(res.body._id).lean().exec((err, data:any) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.only.keys('_id', 'name', 'version', 'number_prefix', 'parameters', '__v');
|
should(data).have.only.keys('_id', 'name', 'version', 'parameters', '__v');
|
||||||
should(data).have.property('name', 'heat aging');
|
should(data).have.property('name', 'heat aging');
|
||||||
should(data).have.property('version', 2);
|
should(data).have.property('version', 2);
|
||||||
should(data).have.property('number_prefix', 'A');
|
|
||||||
should(data).have.property('parameters').have.lengthOf(2);
|
should(data).have.property('parameters').have.lengthOf(2);
|
||||||
should(data.parameters[0]).have.property('name', 'material');
|
should(data.parameters[0]).have.property('name', 'material');
|
||||||
should(data.parameters[1]).have.property('name', 'weeks');
|
should(data.parameters[1]).have.property('name', 'weeks');
|
||||||
@ -170,59 +169,59 @@ describe('/template', () => {
|
|||||||
it('supports values ranges', done => {
|
it('supports values ranges', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {parameters: [{name: 'time', range: {values: [1, 2, 5]}}]}
|
req: {parameters: [{name: 'time', range: {values: [1, 2, 5]}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {values: [1, 2, 5]}}]});
|
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, parameters: [{name: 'time', range: {values: [1, 2, 5]}}]});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('supports min max ranges', done => {
|
it('supports min max ranges', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {parameters: [{name: 'time', range: {min: 1, max: 11}}]}
|
req: {parameters: [{name: 'time', range: {min: 1, max: 11}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {min: 1, max: 11}}]});
|
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, parameters: [{name: 'time', range: {min: 1, max: 11}}]});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('supports array type ranges', done => {
|
it('supports array type ranges', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {parameters: [{name: 'time', range: {type: 'array'}}]}
|
req: {parameters: [{name: 'time', range: {type: 'array'}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {type: 'array'}}]});
|
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, parameters: [{name: 'time', range: {type: 'array'}}]});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('supports empty ranges', done => {
|
it('supports empty ranges', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {parameters: [{name: 'time', range: {}}]}
|
req: {parameters: [{name: 'time', range: {}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, number_prefix: 'A', parameters: [{name: 'time', range: {}}]});
|
should(_.omit(res.body, '_id')).be.eql({name: 'heat treatment', version: 2, parameters: [{name: 'time', range: {}}]});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects not specified parameters', done => {
|
it('rejects not specified parameters', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {name: 'heat treatment', parameters: [{name: 'material', range: {xx: 5}}]},
|
req: {name: 'heat treatment', parameters: [{name: 'material', range: {xx: 5}}]},
|
||||||
@ -232,7 +231,7 @@ describe('/template', () => {
|
|||||||
it('rejects an invalid id', done => {
|
it('rejects an invalid id', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/2000000000h0000000000001',
|
url: '/template/condition/2000000000h0000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 404,
|
httpStatus: 404,
|
||||||
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
||||||
@ -241,26 +240,16 @@ describe('/template', () => {
|
|||||||
it('rejects an unknown id', done => {
|
it('rejects an unknown id', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/000000000000000000000001',
|
url: '/template/condition/000000000000000000000001',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 404,
|
httpStatus: 404,
|
||||||
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects already existing number prefixes', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'put',
|
|
||||||
url: '/template/treatment/200000000000000000000001',
|
|
||||||
auth: {basic: 'admin'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {number_prefix: 'B', parameters: [{name: 'time', range: {min: 1}}]},
|
|
||||||
res: {status: 'Number prefix already taken'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {key: 'admin'},
|
auth: {key: 'admin'},
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {}
|
req: {}
|
||||||
@ -269,7 +258,7 @@ describe('/template', () => {
|
|||||||
it('rejects requests from a write user', done => {
|
it('rejects requests from a write user', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 403,
|
httpStatus: 403,
|
||||||
req: {}
|
req: {}
|
||||||
@ -278,27 +267,26 @@ describe('/template', () => {
|
|||||||
it('rejects unauthorized requests', done => {
|
it('rejects unauthorized requests', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
url: '/template/treatment/200000000000000000000001',
|
url: '/template/condition/200000000000000000000001',
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {}
|
req: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('POST /template/treatment/new', () => {
|
describe('POST /template/condition/new', () => {
|
||||||
it('returns the right treatment template', done => {
|
it('returns the right condition template', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {name: 'heat treatment3', number_prefix: 'C', parameters: [{name: 'material', range: {values: ['copper']}}]}
|
req: {name: 'heat treatment3', parameters: [{name: 'material', range: {values: ['copper']}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).have.only.keys('_id', 'name', 'version', 'number_prefix', 'parameters');
|
should(res.body).have.only.keys('_id', 'name', 'version', 'parameters');
|
||||||
should(res.body).have.property('name', 'heat treatment3');
|
should(res.body).have.property('name', 'heat treatment3');
|
||||||
should(res.body).have.property('version', 1);
|
should(res.body).have.property('version', 1);
|
||||||
should(res.body).have.property('number_prefix', 'C');
|
|
||||||
should(res.body).have.property('parameters').have.lengthOf(1);
|
should(res.body).have.property('parameters').have.lengthOf(1);
|
||||||
should(res.body.parameters[0]).have.property('name', 'material');
|
should(res.body.parameters[0]).have.property('name', 'material');
|
||||||
should(res.body.parameters[0]).have.property('range');
|
should(res.body.parameters[0]).have.property('range');
|
||||||
@ -310,18 +298,17 @@ describe('/template', () => {
|
|||||||
it('stores the template', done => {
|
it('stores the template', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time', range: {min: 1}}]}
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
TemplateTreatmentModel.findById(res.body._id).lean().exec((err, data:any) => {
|
TemplateConditionModel.findById(res.body._id).lean().exec((err, data:any) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(data).have.only.keys('_id', 'name', 'version', 'number_prefix', 'parameters', '__v');
|
should(data).have.only.keys('_id', 'name', 'version', 'parameters', '__v');
|
||||||
should(data).have.property('name', 'heat aging');
|
should(data).have.property('name', 'heat aging');
|
||||||
should(data).have.property('version', 1);
|
should(data).have.property('version', 1);
|
||||||
should(data).have.property('number_prefix', 'C');
|
|
||||||
should(data).have.property('parameters').have.lengthOf(1);
|
should(data).have.property('parameters').have.lengthOf(1);
|
||||||
should(data.parameters[0]).have.property('name', 'time');
|
should(data.parameters[0]).have.property('name', 'time');
|
||||||
should(data.parameters[0]).have.property('range');
|
should(data.parameters[0]).have.property('range');
|
||||||
@ -333,117 +320,97 @@ describe('/template', () => {
|
|||||||
it('rejects a missing name', done => {
|
it('rejects a missing name', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {number_prefix: 'C', parameters: [{name: 'time', range: {min: 1}}]},
|
req: {parameters: [{name: 'time', range: {min: 1}}]},
|
||||||
res: {status: 'Invalid body format', details: '"name" is required'}
|
res: {status: 'Invalid body format', details: '"name" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects a missing number prefix', done => {
|
it('rejects a number prefix', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]},
|
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time', range: {min: 1}}]},
|
||||||
res: {status: 'Invalid body format', details: '"number_prefix" is required'}
|
res: {status: 'Invalid body format', details: '"number_prefix" is not allowed'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects missing parameters', done => {
|
it('rejects missing parameters', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {name: 'heat aging', number_prefix: 'C'},
|
req: {name: 'heat aging'},
|
||||||
res: {status: 'Invalid body format', details: '"parameters" is required'}
|
res: {status: 'Invalid body format', details: '"parameters" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects a missing parameter name', done => {
|
it('rejects a missing parameter name', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{range: {min: 1}}]},
|
req: {name: 'heat aging', parameters: [{range: {min: 1}}]},
|
||||||
res: {status: 'Invalid body format', details: '"parameters[0].name" is required'}
|
res: {status: 'Invalid body format', details: '"parameters[0].name" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects a number prefix containing numbers', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/template/treatment/new',
|
|
||||||
auth: {basic: 'admin'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {name: 'heat aging', number_prefix: 'AB5', parameters: [{name: 'time', range: {min: 1}}]},
|
|
||||||
res: {status: 'Invalid body format', details: '"number_prefix" with value "AB5" fails to match the required pattern: /^[a-zA-Z]+$/'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects a missing parameter range', done => {
|
it('rejects a missing parameter range', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time'}]},
|
req: {name: 'heat aging', parameters: [{name: 'time'}]},
|
||||||
res: {status: 'Invalid body format', details: '"parameters[0].range" is required'}
|
res: {status: 'Invalid body format', details: '"parameters[0].range" is required'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects an invalid parameter range property', done => {
|
it('rejects an invalid parameter range property', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time', range: {xx: 1}}]},
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {xx: 1}}]},
|
||||||
res: {status: 'Invalid body format', details: '"parameters[0].range.xx" is not allowed'}
|
res: {status: 'Invalid body format', details: '"parameters[0].range.xx" is not allowed'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects wrong properties', done => {
|
it('rejects wrong properties', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 400,
|
httpStatus: 400,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time', range: {}}], xx: 33},
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {}}], xx: 33},
|
||||||
res: {status: 'Invalid body format', details: '"xx" is not allowed'}
|
res: {status: 'Invalid body format', details: '"xx" is not allowed'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects already existing number prefixes', done => {
|
|
||||||
TestHelper.request(server, done, {
|
|
||||||
method: 'post',
|
|
||||||
url: '/template/treatment/new',
|
|
||||||
auth: {basic: 'admin'},
|
|
||||||
httpStatus: 400,
|
|
||||||
req: {name: 'heat aging', number_prefix: 'B', parameters: [{name: 'time', range: {min: 1}}]},
|
|
||||||
res: {status: 'Number prefix already taken'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('rejects an API key', done => {
|
it('rejects an API key', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {key: 'admin'},
|
auth: {key: 'admin'},
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time', range: {min: 1}}]}
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects requests from a write user', done => {
|
it('rejects requests from a write user', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 403,
|
httpStatus: 403,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time', range: {min: 1}}]}
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects unauthorized requests', done => {
|
it('rejects unauthorized requests', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/template/treatment/new',
|
url: '/template/condition/new',
|
||||||
httpStatus: 401,
|
httpStatus: 401,
|
||||||
req: {name: 'heat aging', number_prefix: 'C', parameters: [{name: 'time', range: {min: 1}}]}
|
req: {name: 'heat aging', parameters: [{name: 'time', range: {min: 1}}]}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,8 +2,8 @@ import express from 'express';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import TemplateValidate from './validate/template';
|
import TemplateValidate from './validate/template';
|
||||||
import TemplateTreatmentModel from '../models/treatment_template';
|
import ConditionTemplateModel from '../models/condition_template';
|
||||||
import TemplateMeasurementModel from '../models/measurement_template';
|
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';
|
||||||
|
|
||||||
@ -11,23 +11,23 @@ import IdValidate from './validate/id';
|
|||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.get('/template/:collection(measurements|treatments)', (req, res, next) => {
|
router.get('/template/:collection(measurements|conditions)', (req, res, next) => {
|
||||||
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
req.params.collection = req.params.collection.replace(/s$/g, ''); // remove trailing s
|
req.params.collection = req.params.collection.replace(/s$/g, ''); // remove trailing s
|
||||||
model(req).find({}).lean().exec((err, data) => {
|
model(req).find({}).lean().exec((err, data) => {
|
||||||
if (err) next (err);
|
if (err) next (err);
|
||||||
res.json(_.compact(data.map(e => TemplateValidate.output(e, req.params.collection)))); // validate all and filter null values from validation errors
|
res.json(_.compact(data.map(e => TemplateValidate.output(e)))); // validate all and filter null values from validation errors
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/template/:collection(measurement|treatment)/' + IdValidate.parameter(), (req, res, next) => {
|
router.get('/template/:collection(measurement|condition)/' + IdValidate.parameter(), (req, res, next) => {
|
||||||
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
model(req).findById(req.params.id).lean().exec((err, data) => {
|
model(req).findById(req.params.id).lean().exec((err, data) => {
|
||||||
if (err) next (err);
|
if (err) next (err);
|
||||||
if (data) {
|
if (data) {
|
||||||
res.json(TemplateValidate.output(data, req.params.collection));
|
res.json(TemplateValidate.output(data));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.status(404).json({status: 'Not found'});
|
res.status(404).json({status: 'Not found'});
|
||||||
@ -35,10 +35,10 @@ router.get('/template/:collection(measurement|treatment)/' + IdValidate.paramete
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put('/template/:collection(measurement|treatment)/' + IdValidate.parameter(), async (req, res, next) => {
|
router.put('/template/:collection(measurement|condition)/' + IdValidate.parameter(), async (req, res, next) => {
|
||||||
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
const {error, value: template} = TemplateValidate.input(req.body, 'change', req.params.collection);
|
const {error, value: template} = TemplateValidate.input(req.body, 'change');
|
||||||
if (error) return res400(error, res);
|
if (error) return res400(error, res);
|
||||||
|
|
||||||
const templateData = await model(req).findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
|
const templateData = await model(req).findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
|
||||||
@ -47,52 +47,34 @@ router.put('/template/:collection(measurement|treatment)/' + IdValidate.paramete
|
|||||||
res.status(404).json({status: 'Not found'});
|
res.status(404).json({status: 'Not found'});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_.has(template, 'number_prefix') && template.number_prefix !== templateData.number_prefix) { // got new number_prefix
|
|
||||||
if (!await numberPrefixCheck(template, req, res, next)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_.isEqual(_.pick(templateData, _.keys(template)), template)) { // data was changed
|
if (!_.isEqual(_.pick(templateData, _.keys(template)), template)) { // data was changed
|
||||||
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);
|
||||||
res.json(TemplateValidate.output(data.toObject(), req.params.collection));
|
res.json(TemplateValidate.output(data.toObject()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.json(TemplateValidate.output(templateData, req.params.collection));
|
res.json(TemplateValidate.output(templateData));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post('/template/:collection(measurement|treatment)/new', async (req, res, next) => {
|
router.post('/template/:collection(measurement|condition)/new', async (req, res, next) => {
|
||||||
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
|
||||||
|
|
||||||
const {error, value: template} = TemplateValidate.input(req.body, 'new', req.params.collection);
|
const {error, value: template} = TemplateValidate.input(req.body, 'new');
|
||||||
if (error) return res400(error, res);
|
if (error) return res400(error, res);
|
||||||
|
|
||||||
if (_.has(template, 'number_prefix')) { // got number_prefix
|
|
||||||
if (!await numberPrefixCheck(template, req, res, next)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
res.json(TemplateValidate.output(data.toObject(), req.params.collection));
|
res.json(TemplateValidate.output(data.toObject()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|
||||||
async function numberPrefixCheck (template, req, res, next) { // check if number_prefix is available
|
|
||||||
const data = await model(req).findOne({number_prefix: template.number_prefix}).lean().exec().catch(err => {next(err); return false;}) as any;
|
|
||||||
if (data) {
|
|
||||||
res.status(400).json({status: 'Number prefix already taken'});
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function model (req) { // return right template model
|
function model (req) { // return right template model
|
||||||
return req.params.collection === 'treatment' ? TemplateTreatmentModel : TemplateMeasurementModel;
|
return req.params.collection === 'condition' ? ConditionTemplateModel : MeasurementTemplateModel;
|
||||||
}
|
}
|
@ -40,7 +40,6 @@ router.put('/user:username([/](?!key|new).?*|/?)', async (req, res, next) => {
|
|||||||
|
|
||||||
const username = getUsername(req, res);
|
const username = getUsername(req, res);
|
||||||
if (!username) return;
|
if (!username) return;
|
||||||
console.log(username);
|
|
||||||
|
|
||||||
const {error, value: user} = UserValidate.input(req.body, 'change' + (req.authDetails.level === 'admin'? 'admin' : ''));
|
const {error, value: user} = UserValidate.input(req.body, 'change' + (req.authDetails.level === 'admin'? 'admin' : ''));
|
||||||
if (error) return res400(error, res);
|
if (error) return res400(error, res);
|
||||||
@ -154,8 +153,6 @@ function getUsername (req, res) { // returns username or false if action is not
|
|||||||
async function usernameCheck (name, res, next) { // check if username is already taken
|
async function usernameCheck (name, res, next) { // check if username is already taken
|
||||||
const userData = await UserModel.findOne({name: name}).lean().exec().catch(err => next(err)) as any;
|
const userData = await UserModel.findOne({name: name}).lean().exec().catch(err => next(err)) as any;
|
||||||
if (userData instanceof Error) return false;
|
if (userData instanceof Error) return false;
|
||||||
console.log(userData);
|
|
||||||
console.log(UserValidate.isSpecialName(name));
|
|
||||||
if (userData || UserValidate.isSpecialName(name)) {
|
if (userData || UserValidate.isSpecialName(name)) {
|
||||||
res.status(400).json({status: 'Username already taken'});
|
res.status(400).json({status: 'Username already taken'});
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
import Joi from '@hapi/joi';
|
|
||||||
|
|
||||||
import IdValidate from './id';
|
|
||||||
|
|
||||||
export default class ConditionValidate {
|
|
||||||
private static condition = {
|
|
||||||
number: Joi.string()
|
|
||||||
.max(128),
|
|
||||||
|
|
||||||
parameters: Joi.object()
|
|
||||||
.pattern(/.*/, Joi.alternatives()
|
|
||||||
.try(
|
|
||||||
Joi.string().max(128),
|
|
||||||
Joi.number(),
|
|
||||||
Joi.boolean(),
|
|
||||||
Joi.array()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
static input (data, param) { // validate input, set param to 'new' to make all attributes required
|
|
||||||
if (param === 'new') {
|
|
||||||
return Joi.object({
|
|
||||||
sample_id: IdValidate.get().required(),
|
|
||||||
parameters: this.condition.parameters.required(),
|
|
||||||
treatment_template: IdValidate.get().required()
|
|
||||||
}).validate(data);
|
|
||||||
}
|
|
||||||
else if (param === 'change') {
|
|
||||||
return Joi.object({
|
|
||||||
parameters: this.condition.parameters
|
|
||||||
}).validate(data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return{error: 'No parameter specified!', value: {}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static output (data) { // validate output and strip unwanted properties, returns null if not valid
|
|
||||||
data = IdValidate.stringify(data);
|
|
||||||
const {value, error} = Joi.object({
|
|
||||||
_id: IdValidate.get(),
|
|
||||||
sample_id: IdValidate.get(),
|
|
||||||
number: this.condition.number,
|
|
||||||
parameters: this.condition.parameters,
|
|
||||||
treatment_template: IdValidate.get()
|
|
||||||
}).validate(data, {stripUnknown: true});
|
|
||||||
return error !== undefined? null : value;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +1,39 @@
|
|||||||
import joi from '@hapi/joi';
|
import Joi from '@hapi/joi';
|
||||||
|
|
||||||
import IdValidate from './id';
|
import IdValidate from './id';
|
||||||
|
|
||||||
export default class MaterialValidate { // validate input for material
|
export default class MaterialValidate { // validate input for material
|
||||||
private static material = {
|
private static material = {
|
||||||
name: joi.string()
|
name: Joi.string()
|
||||||
.max(128),
|
.max(128),
|
||||||
|
|
||||||
supplier: joi.string()
|
supplier: Joi.string()
|
||||||
.max(128),
|
.max(128),
|
||||||
|
|
||||||
group: joi.string()
|
group: Joi.string()
|
||||||
.max(128),
|
.max(128),
|
||||||
|
|
||||||
mineral: joi.number()
|
mineral: Joi.number()
|
||||||
.integer()
|
.integer()
|
||||||
.min(0)
|
.min(0)
|
||||||
.max(100),
|
.max(100),
|
||||||
|
|
||||||
glass_fiber: joi.number()
|
glass_fiber: Joi.number()
|
||||||
.integer()
|
.integer()
|
||||||
.min(0)
|
.min(0)
|
||||||
.max(100),
|
.max(100),
|
||||||
|
|
||||||
carbon_fiber: joi.number()
|
carbon_fiber: Joi.number()
|
||||||
.integer()
|
.integer()
|
||||||
.min(0)
|
.min(0)
|
||||||
.max(100),
|
.max(100),
|
||||||
|
|
||||||
numbers: joi.array()
|
numbers: Joi.array()
|
||||||
.items(joi.object({
|
.items(Joi.object({
|
||||||
color: joi.string()
|
color: Joi.string()
|
||||||
.max(128)
|
.max(128)
|
||||||
.required(),
|
.required(),
|
||||||
number: joi.string()
|
number: Joi.string()
|
||||||
.max(128)
|
.max(128)
|
||||||
.allow('')
|
.allow('')
|
||||||
.required()
|
.required()
|
||||||
@ -42,7 +42,7 @@ export default class MaterialValidate { // validate input for material
|
|||||||
|
|
||||||
static input (data, param) { // validate input, set param to 'new' to make all attributes required
|
static input (data, param) { // validate input, set param to 'new' to make all attributes required
|
||||||
if (param === 'new') {
|
if (param === 'new') {
|
||||||
return joi.object({
|
return Joi.object({
|
||||||
name: this.material.name.required(),
|
name: this.material.name.required(),
|
||||||
supplier: this.material.supplier.required(),
|
supplier: this.material.supplier.required(),
|
||||||
group: this.material.group.required(),
|
group: this.material.group.required(),
|
||||||
@ -53,7 +53,7 @@ export default class MaterialValidate { // validate input for material
|
|||||||
}).validate(data);
|
}).validate(data);
|
||||||
}
|
}
|
||||||
else if (param === 'change') {
|
else if (param === 'change') {
|
||||||
return joi.object({
|
return Joi.object({
|
||||||
name: this.material.name,
|
name: this.material.name,
|
||||||
supplier: this.material.supplier,
|
supplier: this.material.supplier,
|
||||||
group: this.material.group,
|
group: this.material.group,
|
||||||
@ -70,7 +70,7 @@ export default class MaterialValidate { // validate input for material
|
|||||||
|
|
||||||
static output (data) { // validate output and strip unwanted properties, returns null if not valid
|
static output (data) { // validate output and strip unwanted properties, returns null if not valid
|
||||||
data = IdValidate.stringify(data);
|
data = IdValidate.stringify(data);
|
||||||
const {value, error} = joi.object({
|
const {value, error} = Joi.object({
|
||||||
_id: IdValidate.get(),
|
_id: IdValidate.get(),
|
||||||
name: this.material.name,
|
name: this.material.name,
|
||||||
supplier: this.material.supplier,
|
supplier: this.material.supplier,
|
||||||
@ -82,4 +82,17 @@ export default class MaterialValidate { // validate input for material
|
|||||||
}).validate(data, {stripUnknown: true});
|
}).validate(data, {stripUnknown: true});
|
||||||
return error !== undefined? null : value;
|
return error !== undefined? null : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static outputV() { // return output validator
|
||||||
|
return Joi.object({
|
||||||
|
_id: IdValidate.get(),
|
||||||
|
name: this.material.name,
|
||||||
|
supplier: this.material.supplier,
|
||||||
|
group: this.material.group,
|
||||||
|
mineral: this.material.mineral,
|
||||||
|
glass_fiber: this.material.glass_fiber,
|
||||||
|
carbon_fiber: this.material.carbon_fiber,
|
||||||
|
numbers: this.material.numbers
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import Joi from '@hapi/joi';
|
import Joi from '@hapi/joi';
|
||||||
|
|
||||||
import IdValidate from './id';
|
import IdValidate from './id';
|
||||||
|
import UserValidate from './user';
|
||||||
|
import MaterialValidate from './material';
|
||||||
|
|
||||||
export default class SampleValidate {
|
export default class SampleValidate {
|
||||||
private static sample = {
|
private static sample = {
|
||||||
@ -17,13 +19,16 @@ export default class SampleValidate {
|
|||||||
.max(128)
|
.max(128)
|
||||||
.allow(''),
|
.allow(''),
|
||||||
|
|
||||||
|
condition: Joi.object(),
|
||||||
|
|
||||||
notes: Joi.object({
|
notes: Joi.object({
|
||||||
comment: Joi.string()
|
comment: Joi.string()
|
||||||
.max(512),
|
.max(512)
|
||||||
|
.allow(''),
|
||||||
|
|
||||||
sample_references: Joi.array()
|
sample_references: Joi.array()
|
||||||
.items(Joi.object({
|
.items(Joi.object({
|
||||||
id: IdValidate.get(),
|
sample_id: IdValidate.get(),
|
||||||
|
|
||||||
relation: Joi.string()
|
relation: Joi.string()
|
||||||
.max(128)
|
.max(128)
|
||||||
@ -47,6 +52,7 @@ export default class SampleValidate {
|
|||||||
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(),
|
||||||
|
condition: this.sample.condition.required(),
|
||||||
material_id: IdValidate.get().required(),
|
material_id: IdValidate.get().required(),
|
||||||
notes: this.sample.notes.required()
|
notes: this.sample.notes.required()
|
||||||
}).validate(data);
|
}).validate(data);
|
||||||
@ -56,6 +62,7 @@ export default class SampleValidate {
|
|||||||
color: this.sample.color,
|
color: this.sample.color,
|
||||||
type: this.sample.type,
|
type: this.sample.type,
|
||||||
batch: this.sample.batch,
|
batch: this.sample.batch,
|
||||||
|
condition: this.sample.condition,
|
||||||
material_id: IdValidate.get(),
|
material_id: IdValidate.get(),
|
||||||
notes: this.sample.notes,
|
notes: this.sample.notes,
|
||||||
}).validate(data);
|
}).validate(data);
|
||||||
@ -65,18 +72,39 @@ export default class SampleValidate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static output (data) { // validate output and strip unwanted properties, returns null if not valid
|
static output (data, param = 'refs') { // validate output and strip unwanted properties, returns null if not valid
|
||||||
data = IdValidate.stringify(data);
|
data = IdValidate.stringify(data);
|
||||||
const {value, error} = Joi.object({
|
let joiObject;
|
||||||
_id: IdValidate.get(),
|
if (param === 'refs') {
|
||||||
number: this.sample.number,
|
joiObject = {
|
||||||
color: this.sample.color,
|
_id: IdValidate.get(),
|
||||||
type: this.sample.type,
|
number: this.sample.number,
|
||||||
batch: this.sample.batch,
|
color: this.sample.color,
|
||||||
material_id: IdValidate.get(),
|
type: this.sample.type,
|
||||||
note_id: IdValidate.get().allow(null),
|
batch: this.sample.batch,
|
||||||
user_id: IdValidate.get()
|
condition: this.sample.condition,
|
||||||
}).validate(data, {stripUnknown: true});
|
material_id: IdValidate.get(),
|
||||||
|
note_id: IdValidate.get().allow(null),
|
||||||
|
user_id: IdValidate.get()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if(param === 'details') {
|
||||||
|
joiObject = {
|
||||||
|
_id: IdValidate.get(),
|
||||||
|
number: this.sample.number,
|
||||||
|
color: this.sample.color,
|
||||||
|
type: this.sample.type,
|
||||||
|
batch: this.sample.batch,
|
||||||
|
condition: this.sample.condition,
|
||||||
|
material: MaterialValidate.outputV(),
|
||||||
|
notes: this.sample.notes,
|
||||||
|
user: UserValidate.username()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const {value, error} = Joi.object(joiObject).validate(data, {stripUnknown: true});
|
||||||
return error !== undefined? null : value;
|
return error !== undefined? null : value;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,11 +9,6 @@ export default class TemplateValidate {
|
|||||||
version: Joi.number()
|
version: Joi.number()
|
||||||
.min(1),
|
.min(1),
|
||||||
|
|
||||||
number_prefix: Joi.string()
|
|
||||||
.pattern(/^[a-zA-Z]+$/)
|
|
||||||
.min(1)
|
|
||||||
.max(16),
|
|
||||||
|
|
||||||
parameters: Joi.array()
|
parameters: Joi.array()
|
||||||
.min(1)
|
.min(1)
|
||||||
.items(
|
.items(
|
||||||
@ -43,63 +38,32 @@ export default class TemplateValidate {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
static input (data, param, template) { // validate input, set param to 'new' to make all attributes required
|
static input (data, param) { // validate input, set param to 'new' to make all attributes required
|
||||||
if (param === 'new') {
|
if (param === 'new') {
|
||||||
if (template === 'treatment') {
|
return Joi.object({
|
||||||
return Joi.object({
|
name: this.template.name.required(),
|
||||||
name: this.template.name.required(),
|
parameters: this.template.parameters.required()
|
||||||
number_prefix: this.template.number_prefix.required(),
|
}).validate(data);
|
||||||
parameters: this.template.parameters.required()
|
|
||||||
}).validate(data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Joi.object({
|
|
||||||
name: this.template.name.required(),
|
|
||||||
parameters: this.template.parameters.required()
|
|
||||||
}).validate(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (param === 'change') {
|
else if (param === 'change') {
|
||||||
if (template === 'treatment') {
|
return Joi.object({
|
||||||
return Joi.object({
|
name: this.template.name,
|
||||||
name: this.template.name,
|
parameters: this.template.parameters
|
||||||
number_prefix: this.template.number_prefix,
|
}).validate(data);
|
||||||
parameters: this.template.parameters
|
|
||||||
}).validate(data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Joi.object({
|
|
||||||
name: this.template.name,
|
|
||||||
parameters: this.template.parameters
|
|
||||||
}).validate(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return{error: 'No parameter specified!', value: {}};
|
return{error: 'No parameter specified!', value: {}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static output (data, template) { // validate output and strip unwanted properties, returns null if not valid
|
static output (data) { // validate output and strip unwanted properties, returns null if not valid
|
||||||
data = IdValidate.stringify(data);
|
data = IdValidate.stringify(data);
|
||||||
let joiObject;
|
const {value, error} = Joi.object({
|
||||||
if (template === 'treatment') { // differentiate between measurement and treatment (has number_prefix) template
|
_id: IdValidate.get(),
|
||||||
joiObject = {
|
name: this.template.name,
|
||||||
_id: IdValidate.get(),
|
version: this.template.version,
|
||||||
name: this.template.name,
|
parameters: this.template.parameters
|
||||||
version: this.template.version,
|
}).validate(data, {stripUnknown: true});
|
||||||
number_prefix: this.template.number_prefix,
|
|
||||||
parameters: this.template.parameters
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
joiObject = {
|
|
||||||
_id: IdValidate.get(),
|
|
||||||
name: this.template.name,
|
|
||||||
version: this.template.version,
|
|
||||||
parameters: this.template.parameters
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const {value, error} = Joi.object(joiObject).validate(data, {stripUnknown: true});
|
|
||||||
return error !== undefined? null : value;
|
return error !== undefined? null : value;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -84,4 +84,8 @@ export default class UserValidate { // validate input for user
|
|||||||
static isSpecialName (name) { // true if name belongs to special names
|
static isSpecialName (name) { // true if name belongs to special names
|
||||||
return this.specialUsernames.indexOf(name) > -1;
|
return this.specialUsernames.indexOf(name) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static username() {
|
||||||
|
return this.user.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
110
src/test/db.json
110
src/test/db.json
@ -7,6 +7,11 @@
|
|||||||
"type": "granulate",
|
"type": "granulate",
|
||||||
"color": "black",
|
"color": "black",
|
||||||
"batch": "",
|
"batch": "",
|
||||||
|
"condition": {
|
||||||
|
"material": "copper",
|
||||||
|
"weeks": 3,
|
||||||
|
"condition_template": {"$oid":"200000000000000000000001"}
|
||||||
|
},
|
||||||
"material_id": {"$oid":"100000000000000000000004"},
|
"material_id": {"$oid":"100000000000000000000004"},
|
||||||
"note_id": null,
|
"note_id": null,
|
||||||
"user_id": {"$oid":"000000000000000000000002"},
|
"user_id": {"$oid":"000000000000000000000002"},
|
||||||
@ -19,6 +24,11 @@
|
|||||||
"type": "granulate",
|
"type": "granulate",
|
||||||
"color": "natural",
|
"color": "natural",
|
||||||
"batch": "1560237365",
|
"batch": "1560237365",
|
||||||
|
"condition": {
|
||||||
|
"material": "copper",
|
||||||
|
"weeks": 3,
|
||||||
|
"condition_template": {"$oid":"200000000000000000000001"}
|
||||||
|
},
|
||||||
"material_id": {"$oid":"100000000000000000000001"},
|
"material_id": {"$oid":"100000000000000000000001"},
|
||||||
"note_id": {"$oid":"500000000000000000000001"},
|
"note_id": {"$oid":"500000000000000000000001"},
|
||||||
"user_id": {"$oid":"000000000000000000000002"},
|
"user_id": {"$oid":"000000000000000000000002"},
|
||||||
@ -31,6 +41,11 @@
|
|||||||
"type": "part",
|
"type": "part",
|
||||||
"color": "black",
|
"color": "black",
|
||||||
"batch": "1704-005",
|
"batch": "1704-005",
|
||||||
|
"condition": {
|
||||||
|
"material": "copper",
|
||||||
|
"weeks": 3,
|
||||||
|
"condition_template": {"$oid":"200000000000000000000001"}
|
||||||
|
},
|
||||||
"material_id": {"$oid":"100000000000000000000005"},
|
"material_id": {"$oid":"100000000000000000000005"},
|
||||||
"note_id": {"$oid":"500000000000000000000002"},
|
"note_id": {"$oid":"500000000000000000000002"},
|
||||||
"user_id": {"$oid":"000000000000000000000003"},
|
"user_id": {"$oid":"000000000000000000000003"},
|
||||||
@ -43,6 +58,11 @@
|
|||||||
"type": "granulate",
|
"type": "granulate",
|
||||||
"color": "black",
|
"color": "black",
|
||||||
"batch": "1653000308",
|
"batch": "1653000308",
|
||||||
|
"condition": {
|
||||||
|
"material": "hot air",
|
||||||
|
"weeks": 5,
|
||||||
|
"condition_template": {"$oid":"200000000000000000000001"}
|
||||||
|
},
|
||||||
"material_id": {"$oid":"100000000000000000000005"},
|
"material_id": {"$oid":"100000000000000000000005"},
|
||||||
"note_id": {"$oid":"500000000000000000000003"},
|
"note_id": {"$oid":"500000000000000000000003"},
|
||||||
"user_id": {"$oid":"000000000000000000000003"},
|
"user_id": {"$oid":"000000000000000000000003"},
|
||||||
@ -55,11 +75,27 @@
|
|||||||
"type": "granulate",
|
"type": "granulate",
|
||||||
"color": "black",
|
"color": "black",
|
||||||
"batch": "1653000308",
|
"batch": "1653000308",
|
||||||
|
"condition": {
|
||||||
|
"condition_template": {"$oid":"200000000000000000000003"}
|
||||||
|
},
|
||||||
"material_id": {"$oid":"100000000000000000000005"},
|
"material_id": {"$oid":"100000000000000000000005"},
|
||||||
"note_id": {"$oid":"500000000000000000000003"},
|
"note_id": null,
|
||||||
"user_id": {"$oid":"000000000000000000000003"},
|
"user_id": {"$oid":"000000000000000000000003"},
|
||||||
"status": -1,
|
"status": -1,
|
||||||
"__v": 0
|
"__v": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": {"$oid":"400000000000000000000006"},
|
||||||
|
"number": "Rng36",
|
||||||
|
"type": "granulate",
|
||||||
|
"color": "black",
|
||||||
|
"batch": "",
|
||||||
|
"condition": {},
|
||||||
|
"material_id": {"$oid":"100000000000000000000004"},
|
||||||
|
"note_id": null,
|
||||||
|
"user_id": {"$oid":"000000000000000000000002"},
|
||||||
|
"status": 0,
|
||||||
|
"__v": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"notes": [
|
"notes": [
|
||||||
@ -73,7 +109,7 @@
|
|||||||
"_id": {"$oid":"500000000000000000000002"},
|
"_id": {"$oid":"500000000000000000000002"},
|
||||||
"comment": "",
|
"comment": "",
|
||||||
"sample_references": [{
|
"sample_references": [{
|
||||||
"id": {"$oid":"400000000000000000000004"},
|
"sample_id": {"$oid":"400000000000000000000004"},
|
||||||
"relation": "granulate to sample"
|
"relation": "granulate to sample"
|
||||||
}],
|
}],
|
||||||
"custom_fields": {
|
"custom_fields": {
|
||||||
@ -85,7 +121,7 @@
|
|||||||
"_id": {"$oid":"500000000000000000000003"},
|
"_id": {"$oid":"500000000000000000000003"},
|
||||||
"comment": "",
|
"comment": "",
|
||||||
"sample_references": [{
|
"sample_references": [{
|
||||||
"id": {"$oid":"400000000000000000000003"},
|
"sample_id": {"$oid":"400000000000000000000003"},
|
||||||
"relation": "part to sample"
|
"relation": "part to sample"
|
||||||
}],
|
}],
|
||||||
"custom_fields": {
|
"custom_fields": {
|
||||||
@ -234,60 +270,10 @@
|
|||||||
"__v": 0
|
"__v": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"conditions": [
|
|
||||||
{
|
|
||||||
"_id": {"$oid":"700000000000000000000001"},
|
|
||||||
"sample_id": {"$oid":"400000000000000000000001"},
|
|
||||||
"number": "A1",
|
|
||||||
"parameters": {
|
|
||||||
"material": "copper",
|
|
||||||
"weeks": 3
|
|
||||||
},
|
|
||||||
"treatment_template": {"$oid":"200000000000000000000001"},
|
|
||||||
"status": 10,
|
|
||||||
"__v": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": {"$oid":"700000000000000000000002"},
|
|
||||||
"sample_id": {"$oid":"400000000000000000000002"},
|
|
||||||
"number": "A1",
|
|
||||||
"parameters": {
|
|
||||||
"material": "copper",
|
|
||||||
"weeks": 3
|
|
||||||
},
|
|
||||||
"treatment_template": {"$oid":"200000000000000000000001"},
|
|
||||||
"status": 10,
|
|
||||||
"__v": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": {"$oid":"700000000000000000000003"},
|
|
||||||
"sample_id": {"$oid":"400000000000000000000004"},
|
|
||||||
"number": "A1",
|
|
||||||
"parameters": {
|
|
||||||
"material": "copper",
|
|
||||||
"weeks": 3
|
|
||||||
},
|
|
||||||
"treatment_template": {"$oid":"200000000000000000000001"},
|
|
||||||
"status": 10,
|
|
||||||
"__v": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": {"$oid":"700000000000000000000004"},
|
|
||||||
"sample_id": {"$oid":"400000000000000000000001"},
|
|
||||||
"number": "A2",
|
|
||||||
"parameters": {
|
|
||||||
"material": "hot air",
|
|
||||||
"weeks": 5
|
|
||||||
},
|
|
||||||
"treatment_template": {"$oid":"200000000000000000000001"},
|
|
||||||
"status": 10,
|
|
||||||
"__v": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"measurements": [
|
"measurements": [
|
||||||
{
|
{
|
||||||
"_id": {"$oid":"800000000000000000000001"},
|
"_id": {"$oid":"800000000000000000000001"},
|
||||||
"condition_id": {"$oid":"700000000000000000000001"},
|
"sample_id": {"$oid":"400000000000000000000001"},
|
||||||
"values": {
|
"values": {
|
||||||
"dpt": [
|
"dpt": [
|
||||||
[3997.12558,98.00555],
|
[3997.12558,98.00555],
|
||||||
@ -301,7 +287,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": {"$oid":"800000000000000000000002"},
|
"_id": {"$oid":"800000000000000000000002"},
|
||||||
"condition_id": {"$oid":"700000000000000000000002"},
|
"sample_id": {"$oid":"400000000000000000000002"},
|
||||||
"values": {
|
"values": {
|
||||||
"weight %": 0.5,
|
"weight %": 0.5,
|
||||||
"standard deviation": 0.2
|
"standard deviation": 0.2
|
||||||
@ -312,7 +298,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": {"$oid":"800000000000000000000003"},
|
"_id": {"$oid":"800000000000000000000003"},
|
||||||
"condition_id": {"$oid":"700000000000000000000003"},
|
"sample_id": {"$oid":"400000000000000000000003"},
|
||||||
"values": {
|
"values": {
|
||||||
"val1": 1
|
"val1": 1
|
||||||
},
|
},
|
||||||
@ -321,12 +307,11 @@
|
|||||||
"__v": 0
|
"__v": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"treatment_templates": [
|
"condition_templates": [
|
||||||
{
|
{
|
||||||
"_id": {"$oid":"200000000000000000000001"},
|
"_id": {"$oid":"200000000000000000000001"},
|
||||||
"name": "heat treatment",
|
"name": "heat treatment",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"number_prefix": "A",
|
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "material",
|
"name": "material",
|
||||||
@ -351,7 +336,6 @@
|
|||||||
"_id": {"$oid":"200000000000000000000002"},
|
"_id": {"$oid":"200000000000000000000002"},
|
||||||
"name": "heat treatment 2",
|
"name": "heat treatment 2",
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"number_prefix": "B",
|
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "material",
|
"name": "material",
|
||||||
@ -359,6 +343,14 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"__v": 0
|
"__v": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": {"$oid":"200000000000000000000003"},
|
||||||
|
"name": "raw material",
|
||||||
|
"version": 1,
|
||||||
|
"parameters": [
|
||||||
|
],
|
||||||
|
"__v": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"measurement_templates": [
|
"measurement_templates": [
|
||||||
|
@ -10,6 +10,7 @@ export default class TestHelper {
|
|||||||
user: {pass: 'Xyz890*)', key: '000000000000000000001001'},
|
user: {pass: 'Xyz890*)', key: '000000000000000000001001'},
|
||||||
johnnydoe: {pass: 'Xyz890*)', key: '000000000000000000001004'}
|
johnnydoe: {pass: 'Xyz890*)', key: '000000000000000000001004'}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static res = { // default responses
|
public static res = { // default responses
|
||||||
400: {status: 'Bad request'},
|
400: {status: 'Bad request'},
|
||||||
401: {status: 'Unauthorized'},
|
401: {status: 'Unauthorized'},
|
||||||
|
Reference in New Issue
Block a user