Archived
2

Merge pull request #29 in ~VLE2FE/definma-api from develop to master

* commit 'd363064dbae564136a092c149b0768a59884c936':
  test fix
  changed type names
  small fixes
  improved globals and added status and spectrum
This commit is contained in:
Veit Lukas (PEA4-Fe) 2020-08-12 12:48:02 +02:00
commit d244b6e39b
38 changed files with 290 additions and 227 deletions

View File

@ -1,7 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4"> <module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.nyc_output" />
<excludeFolder url="file://$MODULE_DIR$/data_import" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
</content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>

View File

@ -1,37 +1,53 @@
<component name="ProjectDictionaryState"> <component name="ProjectDictionaryState">
<dictionary name="VLE2FE"> <dictionary name="VLE2FE">
<words> <words>
<w>adminnew</w>
<w>adminxx</w>
<w>akro</w> <w>akro</w>
<w>amodel</w> <w>amodel</w>
<w>anwendungsbeschränkt</w> <w>anwendungsbeschränkt</w>
<w>apidoc</w>
<w>arora</w>
<w>batchgranulate</w> <w>batchgranulate</w>
<w>bcrypt</w> <w>bcrypt</w>
<w>bnpd</w> <w>bnpd</w>
<w>bsontype</w>
<w>cfenv</w> <w>cfenv</w>
<w>changeadmin</w>
<w>colordesignatiomsuppl</w> <w>colordesignatiomsuppl</w>
<w>colordesignationsuppl</w> <w>colordesignationsuppl</w>
<w>contentin</w> <w>contentin</w>
<w>crastin</w>
<w>definma</w> <w>definma</w>
<w>dfopdb</w> <w>dfopdb</w>
<w>dosiergeschw</w> <w>dosiergeschw</w>
<w>dpts</w> <w>dpts</w>
<w>einspritzgeschw</w> <w>einspritzgeschw</w>
<w>errback</w>
<w>frameguard</w> <w>frameguard</w>
<w>frankland</w>
<w>functionlink</w> <w>functionlink</w>
<w>glassfibrecontent</w> <w>glassfibrecontent</w>
<w>isin</w> <w>isin</w>
<w>janedoe</w> <w>janedoe</w>
<w>johndoe</w>
<w>johnnydoe</w> <w>johnnydoe</w>
<w>kfingew</w> <w>kfingew</w>
<w>latamid</w> <w>latamid</w>
<w>lati</w> <w>lati</w>
<w>lyucy</w> <w>lyucy</w>
<w>materialnumber</w> <w>materialnumber</w>
<w>nvmrc</w>
<w>oldpass</w>
<w>opblock</w>
<w>pagesize</w> <w>pagesize</w>
<w>pagesizes</w>
<w>pnach</w> <w>pnach</w>
<w>preaged</w> <w>preaged</w>
<w>puneet</w>
<w>reinforcementmaterial</w> <w>reinforcementmaterial</w>
<w>reinforcingmaterial</w> <w>reinforcingmaterial</w>
<w>rewatch</w>
<w>samplenumber</w> <w>samplenumber</w>
<w>sdpt</w> <w>sdpt</w>
<w>signalviolet</w> <w>signalviolet</w>
@ -42,7 +58,10 @@
<w>stringin</w> <w>stringin</w>
<w>testcomment</w> <w>testcomment</w>
<w>ultramid</w> <w>ultramid</w>
<w>unknownroute</w>
<w>vorgealtert</w> <w>vorgealtert</w>
<w>xcopy</w>
<w>yankov</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

View File

@ -1,8 +1,25 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<profile version="1.0"> <profile version="1.0">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="CheckDtdRefs" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CheckTagEmptyBody" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckXmlFileWithXercesValidator" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<scope name="Tests" level="WEAK WARNING" enabled="false" />
</inspection_tool>
<inspection_tool class="JSUnfilteredForInLoop" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="JSUnfilteredForInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true">
<scope name="Tests" level="WARNING" enabled="false" />
</inspection_tool>
<inspection_tool class="ReservedWordUsedAsNameJS" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="ReservedWordUsedAsNameJS" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlDefaultAttributeValue" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlDeprecatedElement" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlDuplicatedId" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="XmlHighlighting" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="XmlInvalidId" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="XmlPathReference" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="XmlUnboundNsPrefix" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlUnusedNamespaceDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlWrongRootElement" enabled="false" level="ERROR" enabled_by_default="false" />
</profile> </profile>
</component> </component>

View File

@ -1,4 +1,4 @@
# Digital fingerprint of plastics - API # DeFinMa - API
This is the API to access the database of the digital fingerprint of plastics project. This is the API to access the database of the digital fingerprint of plastics project.

View File

@ -1,6 +1,5 @@
openapi: 3.0.2 openapi: 3.0.2
info: info:
title: Digital fingerprint of plastics - API title: Digital fingerprint of plastics - API
version: 1.0.0 version: 1.0.0

View File

@ -97,7 +97,7 @@
data: data:
type: object type: object
example: example:
type: part type: processed
status: 0 status: 0
401: 401:
$ref: 'api.yaml#/components/responses/401' $ref: 'api.yaml#/components/responses/401'

View File

@ -20,7 +20,7 @@ SampleProperties:
example: Rng172 example: Rng172
type: type:
type: string type: string
example: granulate example: as-delivered/raw
batch: batch:
type: string type: string
example: 1560237365 example: 1560237365

View File

@ -996,11 +996,11 @@ function customFields (comment, sampleNumber) {
function sampleType (type) { function sampleType (type) {
type = stripSpaces(type).toLowerCase(); type = stripSpaces(type).toLowerCase();
const allowedTypes = {'tension rod': 'tension rod', 'Zugstab': 'tension rod', 'part': 'part', 'granulate': 'granulate'}; const allowedTypes = {'tension rod': 'processed', 'Zugstab': 'processed', 'part': 'processed', 'granulate': 'as-delivered/raw'};
if (!allowedTypes[type]) { if (!allowedTypes[type]) {
typeLog.push(type); typeLog.push(type);
} }
return allowedTypes[type] ? allowedTypes[type] : 'part'; return allowedTypes[type] ? allowedTypes[type] : 'processed';
} }
function stripSpaces(s) { function stripSpaces(s) {

View File

@ -67,6 +67,7 @@ function resolveXDoc (doc) { // resolve x-doc properties recursively
// templates // templates
// noinspection LongLine
const htmlTplString = ` const htmlTplString = `
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">

View File

@ -10,7 +10,7 @@
/* =================== USAGE =================== /* =================== USAGE ===================
import * as express from "express"; import * as express from "express";
var app = express(); let app = express();
=============================================== */ =============================================== */
@ -29,40 +29,44 @@ declare function e(): core.Express;
declare namespace e { declare namespace e {
/** /**
* This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on body-parser. * This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on
* body-parser.
* @since 4.16.0 * @since 4.16.0
*/ */
var json: typeof bodyParser.json; let json: typeof bodyParser.json;
/** /**
* This is a built-in middleware function in Express. It parses incoming requests with Buffer payloads and is based on body-parser. * This is a built-in middleware function in Express. It parses incoming requests with Buffer payloads and is based
* on body-parser.
* @since 4.17.0 * @since 4.17.0
*/ */
var raw: typeof bodyParser.raw; let raw: typeof bodyParser.raw;
/** /**
* This is a built-in middleware function in Express. It parses incoming requests with text payloads and is based on body-parser. * This is a built-in middleware function in Express. It parses incoming requests with text payloads and is based on
* body-parser.
* @since 4.17.0 * @since 4.17.0
*/ */
var text: typeof bodyParser.text; let text: typeof bodyParser.text;
/** /**
* These are the exposed prototypes. * These are the exposed prototypes.
*/ */
var application: Application; let application: Application;
var request: Request; let request: Request;
var response: Response; let response: Response;
/** /**
* This is a built-in middleware function in Express. It serves static files and is based on serve-static. * This is a built-in middleware function in Express. It serves static files and is based on serve-static.
*/ */
var static: typeof serveStatic; let static: typeof serveStatic;
/** /**
* This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads and is based on body-parser. * This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads and is
* based on body-parser.
* @since 4.16.0 * @since 4.16.0
*/ */
var urlencoded: typeof bodyParser.urlencoded; let urlencoded: typeof bodyParser.urlencoded;
/** /**
* This is a built-in middleware function in Express. It parses incoming request query parameters. * This is a built-in middleware function in Express. It parses incoming request query parameters.
@ -95,7 +99,8 @@ declare namespace e {
interface Application extends core.Application { } interface Application extends core.Application { }
interface CookieOptions extends core.CookieOptions { } interface CookieOptions extends core.CookieOptions { }
interface Errback extends core.Errback { } interface Errback extends core.Errback { }
interface ErrorRequestHandler<P extends core.Params = core.ParamsDictionary, ResBody = any, ReqBody = any, ReqQuery = core.Query> interface ErrorRequestHandler<P extends core.Params = core.ParamsDictionary, ResBody = any, ReqBody = any,
ReqQuery = core.Query>
extends core.ErrorRequestHandler<P, ResBody, ReqBody, ReqQuery> { } extends core.ErrorRequestHandler<P, ResBody, ReqBody, ReqQuery> { }
interface Express extends core.Express { } interface Express extends core.Express { }
interface Handler extends core.Handler { } interface Handler extends core.Handler { }
@ -105,8 +110,10 @@ declare namespace e {
interface IRouterMatcher<T> extends core.IRouterMatcher<T> { } interface IRouterMatcher<T> extends core.IRouterMatcher<T> { }
interface MediaType extends core.MediaType { } interface MediaType extends core.MediaType { }
interface NextFunction extends core.NextFunction { } interface NextFunction extends core.NextFunction { }
interface Request<P extends core.Params = core.ParamsDictionary, ResBody = any, ReqBody = any, ReqQuery = core.Query> extends core.Request<P, ResBody, ReqBody, ReqQuery> { } interface Request<P extends core.Params = core.ParamsDictionary, ResBody = any, ReqBody = any,
interface RequestHandler<P extends core.Params = core.ParamsDictionary, ResBody = any, ReqBody = any, ReqQuery = core.Query> extends core.RequestHandler<P, ResBody, ReqBody, ReqQuery> { } ReqQuery = core.Query> extends core.Request<P, ResBody, ReqBody, ReqQuery> { }
interface RequestHandler<P extends core.Params = core.ParamsDictionary, ResBody = any, ReqBody = any,
ReqQuery = core.Query> extends core.RequestHandler<P, ResBody, ReqBody, ReqQuery> { }
interface RequestParamHandler extends core.RequestParamHandler { } interface RequestParamHandler extends core.RequestParamHandler { }
export interface Response<ResBody = any> extends core.Response<ResBody> { } export interface Response<ResBody = any> extends core.Response<ResBody> { }
interface Router extends core.Router { } interface Router extends core.Router { }

View File

@ -146,7 +146,7 @@ export default class db {
}); });
new ChangelogModel({ new ChangelogModel({
action: req.method + ' ' + req.url, action: req.method + ' ' + req.url,
collectionName: thisOrCollection._collection.collectionName, collection_name: thisOrCollection._collection.collectionName,
conditions: thisOrCollection._conditions, conditions: thisOrCollection._conditions,
data: data, data: data,
user_id: req.authDetails.id ? req.authDetails.id : null user_id: req.authDetails.id ? req.authDetails.id : null
@ -157,7 +157,7 @@ export default class db {
else { // (req, collection, conditions, data) else { // (req, collection, conditions, data)
new ChangelogModel({ new ChangelogModel({
action: req.method + ' ' + req.url, action: req.method + ' ' + req.url,
collectionName: thisOrCollection, collection_name: thisOrCollection,
conditions: conditions, conditions: conditions,
data: data, data: data,
user_id: req.authDetails.id ? req.authDetails.id : null user_id: req.authDetails.id ? req.authDetails.id : null

View File

@ -1,16 +1,24 @@
const globals = { // globals for required names in the database. change values here to rename these properties
levels: [ // access levels, sorted asc by rights // the keys are the terms used internally, the values can be changed to other terms used in database and output
'read',
'write',
'dev',
'admin'
],
status: [ // document statuses const globals = {
'deleted', levels: { // access levels, sorted asc by rights
'new', read: 'read',
'validated', write: 'write',
] dev: 'dev',
admin: 'admin'
},
status: { // names of the document statuses
del: 'deleted',
new: 'new',
val: 'validated',
},
spectrum: { // names of required spectrum fields
spectrum: 'spectrum',
dpt: 'dpt'
}
}; };
export default globals; export default globals;

View File

@ -1,6 +1,7 @@
import basicAuth from 'basic-auth'; import basicAuth from 'basic-auth';
import bcrypt from 'bcryptjs'; import bcrypt from 'bcryptjs';
import UserModel from '../models/user'; import UserModel from '../models/user';
import globals from '../globals';
// appends req.auth(res, ['levels'], method = 'all') // appends req.auth(res, ['levels'], method = 'all')
@ -64,7 +65,12 @@ function basic (req, next): any { // checks basic auth and returns changed user
bcrypt.compare(auth.pass, data[0].pass, (err, res) => { // check password bcrypt.compare(auth.pass, data[0].pass, (err, res) => { // check password
if (err) return next(err); if (err) return next(err);
if (res === true) { // password correct if (res === true) { // password correct
resolve({level: data[0].level, name: data[0].name, id: data[0]._id.toString(), location: data[0].location}); resolve({
level: Object.entries(globals.levels).find(e => e[1] === data[0].level)[0],
name: data[0].name,
id: data[0]._id.toString(),
location: data[0].location
});
} }
else { else {
resolve(null); resolve(null);
@ -88,7 +94,12 @@ function key (req, next): any { // checks API key and returns changed user obje
UserModel.find({key: req.query.key}).lean().exec( (err, data: any) => { // find user UserModel.find({key: req.query.key}).lean().exec( (err, data: any) => { // find user
if (err) return next(err); if (err) return next(err);
if (data.length === 1) { // one user found if (data.length === 1) { // one user found
resolve({level: data[0].level, name: data[0].name, id: data[0]._id.toString(), location: data[0].location}); resolve({
level: Object.entries(globals.levels).find(e => e[1] === data[0].level)[0],
name: data[0].name,
id: data[0]._id.toString(),
location: data[0].location
});
if (!/^\/api/m.test(req.url)){ if (!/^\/api/m.test(req.url)){
delete req.query.key; // delete query parameter to avoid interference with later validation delete req.query.key; // delete query parameter to avoid interference with later validation
} }

View File

@ -1,11 +1,12 @@
import globals from '../globals';
export default function flatten (data, keepArray = false) { // flatten object: {a: {b: true}} -> {a.b: true} export default function flatten (data, keepArray = false) { // flatten object: {a: {b: true}} -> {a.b: true}
const result = {}; const result = {};
function recurse (cur, prop) { function recurse (cur, prop) {
if (Object(cur) !== cur || Object.keys(cur).length === 0) { if (Object(cur) !== cur || Object.keys(cur).length === 0) {
result[prop] = cur; result[prop] = cur;
} }
else if (prop === 'spectrum.dpt') { else if (prop === `${globals.spectrum.spectrum}.${globals.spectrum.dpt}`) {
console.log('dpt');
result[prop + '.labels'] = cur.map(e => e[0]); result[prop + '.labels'] = cur.map(e => e[0]);
result[prop + '.values'] = cur.map(e => e[1]); result[prop + '.values'] = cur.map(e => e[1]);
} }

View File

@ -78,10 +78,10 @@ app.use(compression()); // compress responses
app.use(express.json({ limit: '5mb'})); app.use(express.json({ limit: '5mb'}));
app.use(express.urlencoded({ extended: false, limit: '5mb' })); app.use(express.urlencoded({ extended: false, limit: '5mb' }));
app.use(bodyParser.json()); app.use(bodyParser.json());
const injectionBlackList = ['$', '{', '&&', '||'];
app.use(contentFilter({ app.use(contentFilter({
urlBlackList: injectionBlackList, urlBlackList: ['$', '&&', '||'],
bodyBlackList: injectionBlackList bodyBlackList: ['$', '{', '&&', '||'],
appendFound: true
})); // filter URL query attacks })); // filter URL query attacks
app.use((err, req, res, ignore) => { // bodyParser error handling app.use((err, req, res, ignore) => { // bodyParser error handling
res.status(400).send({status: 'Invalid JSON body'}); res.status(400).send({status: 'Invalid JSON body'});

View File

@ -2,7 +2,7 @@ import mongoose from 'mongoose';
const ChangelogSchema = new mongoose.Schema({ const ChangelogSchema = new mongoose.Schema({
action: String, action: String,
collectionName: String, collection_name: String,
conditions: Object, conditions: Object,
data: Object, data: Object,
user_id: mongoose.Schema.Types.ObjectId user_id: mongoose.Schema.Types.ObjectId

View File

@ -3,7 +3,6 @@ import MaterialModel from '../models/material';
import MaterialGroupModel from '../models/material_groups'; import MaterialGroupModel from '../models/material_groups';
import MaterialSupplierModel from '../models/material_suppliers'; import MaterialSupplierModel from '../models/material_suppliers';
import TestHelper from "../test/helper"; import TestHelper from "../test/helper";
import globals from '../globals';
describe('/material', () => { describe('/material', () => {

View File

@ -9,10 +9,10 @@ import MaterialSupplierModel from '../models/material_suppliers';
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';
import db from '../db'; import db from '../db';
import MaterialTemplateModel from '../models/material_template'; import MaterialTemplateModel from '../models/material_template';
import ParametersValidate from './validate/parameters'; import ParametersValidate from './validate/parameters';
import globals from '../globals';
@ -28,14 +28,14 @@ router.get('/materials', (req, res, next) => {
if (filters.hasOwnProperty('status')) { if (filters.hasOwnProperty('status')) {
if(filters.status === 'all') { if(filters.status === 'all') {
conditions = {$or: [{status: 'validated'}, {status: 'new'}]} conditions = {$or: [{status: globals.status.val}, {status: globals.status.new}]}
} }
else { else {
conditions = {status: filters.status}; conditions = {status: filters.status};
} }
} }
else { // default else { // default
conditions = {status: 'validated'}; conditions = {status: globals.status.val};
} }
MaterialModel.find(conditions).populate('group_id').populate('supplier_id').lean().exec((err, data) => { MaterialModel.find(conditions).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
@ -46,7 +46,7 @@ router.get('/materials', (req, res, next) => {
}); });
}); });
router.get('/materials/:state(new|deleted)', (req, res, next) => { router.get(`/materials/:state(${globals.status.new}|${globals.status.del})`, (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
MaterialModel.find({status: req.params.state}).populate('group_id').populate('supplier_id') MaterialModel.find({status: req.params.state}).populate('group_id').populate('supplier_id')
@ -69,7 +69,7 @@ router.get('/material/' + IdValidate.parameter(), (req, res, next) => {
} }
// deleted materials only available for dev/admin // deleted materials only available for dev/admin
if (data.status === 'deleted' && !req.auth(res, ['dev', 'admin'], 'all')) return; if (data.status === globals.status.del && !req.auth(res, ['dev', 'admin'], 'all')) return;
res.json(MaterialValidate.output(data)); res.json(MaterialValidate.output(data));
}); });
}); });
@ -105,7 +105,7 @@ router.put('/material/' + IdValidate.parameter(), (req, res, next) => {
// check for changes // check for changes
if (!_.isEqual(_.pick(IdValidate.stringify(materialData), _.keys(material)), IdValidate.stringify(material))) { if (!_.isEqual(_.pick(IdValidate.stringify(materialData), _.keys(material)), IdValidate.stringify(material))) {
material.status = 'new'; // set status to new material.status = globals.status.new; // set status to new
} }
await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}) await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true})
@ -125,7 +125,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:'deleted'}) MaterialModel.findByIdAndUpdate(req.params.id, {status: globals.status.del})
.log(req).populate('group_id').populate('supplier_id').lean().exec((err, data) => { .log(req).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
if (err) return next(err); if (err) return next(err);
if (data) { if (data) {
@ -141,13 +141,13 @@ router.delete('/material/' + IdValidate.parameter(), (req, res, next) => {
router.put('/material/restore/' + IdValidate.parameter(), (req, res, next) => { router.put('/material/restore/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
setStatus('new', req, res, next); setStatus(globals.status.new, req, res, next);
}); });
router.put('/material/validate/' + IdValidate.parameter(), (req, res, next) => { router.put('/material/validate/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
setStatus('validated', req, res, next); setStatus(globals.status.val, req, res, next);
}); });
router.post('/material/new', async (req, res, next) => { router.post('/material/new', async (req, res, next) => {
@ -163,7 +163,7 @@ router.post('/material/new', async (req, res, next) => {
if (!material) return; if (!material) return;
if (!await propertiesCheck(material.properties, 'new', res, next)) return; if (!await propertiesCheck(material.properties, 'new', res, next)) return;
material.status = 'new'; // set status to new material.status = globals.status.new; // set status to new
await new MaterialModel(material).save(async (err, data) => { await new MaterialModel(material).save(async (err, data) => {
if (err) return next(err); if (err) return next(err);
db.log(req, 'materials', {_id: data._id}, data.toObject()); db.log(req, 'materials', {_id: data._id}, data.toObject());

View File

@ -1,7 +1,6 @@
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';
describe('/measurement', () => { describe('/measurement', () => {

View File

@ -8,8 +8,8 @@ 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';
import db from '../db'; import db from '../db';
import globals from '../globals';
const router = express.Router(); const router = express.Router();
@ -23,7 +23,7 @@ router.get('/measurement/' + IdValidate.parameter(), (req, res, next) => {
return res.status(404).json({status: 'Not found'}); return res.status(404).json({status: 'Not found'});
} }
// deleted measurements only available for dev/admin // deleted measurements only available for dev/admin
if (data.status === 'deleted' && !req.auth(res, ['dev', 'admin'], 'all')) return; if (data.status === globals.status.del && !req.auth(res, ['dev', 'admin'], 'all')) return;
res.json(MeasurementValidate.output(data, req)); res.json(MeasurementValidate.output(data, req));
}); });
@ -53,7 +53,7 @@ router.put('/measurement/' + IdValidate.parameter(), async (req, res, next) => {
if (measurement.values) { // fill not changed values from database if (measurement.values) { // fill not changed values from database
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 = 'new'; // set status to new measurement.status = globals.status.new; // set status to new
} }
} }
@ -74,7 +74,7 @@ router.delete('/measurement/' + IdValidate.parameter(), (req, res, next) => {
return res.status(404).json({status: 'Not found'}); return res.status(404).json({status: 'Not found'});
} }
if (!await sampleIdCheck(data, req, res, next)) return; if (!await sampleIdCheck(data, req, res, next)) return;
await MeasurementModel.findByIdAndUpdate(req.params.id, {status:'deleted'}) await MeasurementModel.findByIdAndUpdate(req.params.id, {status: globals.status.del})
.log(req).lean().exec(err => { .log(req).lean().exec(err => {
if (err) return next(err); if (err) return next(err);
return res.json({status: 'OK'}); return res.json({status: 'OK'});
@ -85,13 +85,13 @@ router.delete('/measurement/' + IdValidate.parameter(), (req, res, next) => {
router.put('/measurement/restore/' + IdValidate.parameter(), (req, res, next) => { router.put('/measurement/restore/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
setStatus('new', req, res, next); setStatus(globals.status.new, req, res, next);
}); });
router.put('/measurement/validate/' + IdValidate.parameter(), (req, res, next) => { router.put('/measurement/validate/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
setStatus('validated', req, res, next); setStatus(globals.status.val, req, res, next);
}); });
router.post('/measurement/new', async (req, res, next) => { router.post('/measurement/new', async (req, res, next) => {
@ -104,7 +104,7 @@ router.post('/measurement/new', async (req, res, next) => {
measurement.values = await templateCheck(measurement, 'new', res, next); measurement.values = await templateCheck(measurement, 'new', res, next);
if (!measurement.values) return; if (!measurement.values) return;
measurement.status = 'new'; measurement.status = globals.status.new;
await new MeasurementModel(measurement).save((err, data) => { await new MeasurementModel(measurement).save((err, data) => {
if (err) return next(err); if (err) return next(err);
db.log(req, 'measurements', {_id: data._id}, data.toObject()); db.log(req, 'measurements', {_id: data._id}, data.toObject());

View File

@ -38,7 +38,7 @@ describe('/', () => {
should(log).have.property('action', 'PUT /sample/400000000000000000000001'); should(log).have.property('action', 'PUT /sample/400000000000000000000001');
should(log).have.property('collection', 'samples'); should(log).have.property('collection', 'samples');
should(log).have.property('conditions', {_id: '400000000000000000000001'}); should(log).have.property('conditions', {_id: '400000000000000000000001'});
should(log).have.property('data', {type: 'part', status: 0}); should(log).have.property('data', {type: 'processed', status: 0});
}); });
done(); done();
}); });
@ -58,7 +58,7 @@ describe('/', () => {
should(log).have.property('action', 'PUT /sample/400000000000000000000001'); should(log).have.property('action', 'PUT /sample/400000000000000000000001');
should(log).have.property('collection', 'samples'); should(log).have.property('collection', 'samples');
should(log).have.property('conditions', {_id: '400000000000000000000001'}); should(log).have.property('conditions', {_id: '400000000000000000000001'});
should(log).have.property('data', {type: 'part', status: 0}); should(log).have.property('data', {type: 'processed', status: 0});
done(); done();
}); });
}); });

View File

@ -13,7 +13,7 @@ router.get('/', (req, res) => {
}); });
router.get('/authorized', (req, res) => { router.get('/authorized', (req, res) => {
if (!req.auth(res, globals.levels)) return; if (!req.auth(res, Object.values(globals.levels))) return;
res.json({ res.json({
status: 'Authorization successful', status: 'Authorization successful',
method: req.authDetails.method, method: req.authDetails.method,

View File

@ -301,15 +301,15 @@ describe('/sample', () => {
it('filters a sample property', done => { // TODO: implement filters it('filters a sample property', done => { // TODO: implement filters
TestHelper.request(server, done, { TestHelper.request(server, done, {
method: 'get', method: 'get',
url: '/samples?status[]=new&status[]=validated&fields[]=number&fields[]=type&filters[]=%7B%22mode%22%3A%22eq%22%2C%22field%22%3A%22type%22%2C%22values%22%3A%5B%22part%22%5D%7D', url: '/samples?status[]=new&status[]=validated&fields[]=number&fields[]=type&filters[]=%7B%22mode%22%3A%22eq%22%2C%22field%22%3A%22type%22%2C%22values%22%3A%5B%22processed%22%5D%7D',
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.samples.filter(e => e.type === 'part').length); should(res.body).have.lengthOf(json.collections.samples.filter(e => e.type === 'processed').length);
should(res.body).matchEach(sample => { should(res.body).matchEach(sample => {
should(sample).have.property('type', 'part'); should(sample).have.property('type', 'processed');
}); });
done(); done();
}); });
@ -459,8 +459,8 @@ describe('/sample', () => {
}).end((err, res) => { }).end((err, res) => {
if (err) return done(err); if (err) return done(err);
should(res.text).be.eql('"_id","number","type","color","batch","condition.material","condition.weeks","condition.condition_template","material_id","note_id","user_id","added"\r\n' + should(res.text).be.eql('"_id","number","type","color","batch","condition.material","condition.weeks","condition.condition_template","material_id","note_id","user_id","added"\r\n' +
'"400000000000000000000001","1","granulate","black","","copper",3,"200000000000000000000001","100000000000000000000004",,"000000000000000000000002","2004-01-10T13:37:04.000Z"\r\n' + '"400000000000000000000001","1","as-delivered/raw","black","","copper",3,"200000000000000000000001","100000000000000000000004",,"000000000000000000000002","2004-01-10T13:37:04.000Z"\r\n' +
'"400000000000000000000002","21","granulate","natural","1560237365","copper",3,"200000000000000000000001","100000000000000000000001","500000000000000000000001","000000000000000000000002","2004-01-10T13:37:04.000Z"'); '"400000000000000000000002","21","as-delivered/raw","natural","1560237365","copper",3,"200000000000000000000001","100000000000000000000001","500000000000000000000001","000000000000000000000002","2004-01-10T13:37:04.000Z"');
done(); done();
}); });
}); });
@ -729,7 +729,7 @@ describe('/sample', () => {
url: '/sample/400000000000000000000003', url: '/sample/400000000000000000000003',
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000003', number: '33', type: 'part', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'} res: {_id: '400000000000000000000003', number: '33', type: 'processed', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'as-delivered/raw to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'}
}); });
}); });
it('works with an API key', done => { it('works with an API key', done => {
@ -738,7 +738,7 @@ describe('/sample', () => {
url: '/sample/400000000000000000000003', url: '/sample/400000000000000000000003',
auth: {key: 'janedoe'}, auth: {key: 'janedoe'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000003', number: '33', type: 'part', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'} res: {_id: '400000000000000000000003', number: '33', type: 'processed', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'as-delivered/raw to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'}
}); });
}); });
it ('filters out spectral data for a write user', done => { it ('filters out spectral data for a write user', done => {
@ -747,7 +747,7 @@ describe('/sample', () => {
url: '/sample/400000000000000000000001', url: '/sample/400000000000000000000001',
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'} res: {_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'}
}); });
}); });
it ('returns spectral data for an admin user', done => { it ('returns spectral data for an admin user', done => {
@ -756,7 +756,7 @@ describe('/sample', () => {
url: '/sample/400000000000000000000001', url: '/sample/400000000000000000000001',
auth: {basic: 'admin'}, auth: {basic: 'admin'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {dpt: [[ 3997.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]],device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {dpt: [[ 3996.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]], device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'} res: {_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {dpt: [[ 3997.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]],device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {dpt: [[ 3996.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]], device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'}
}); });
}); });
it('returns a deleted sample for a dev/admin user', done => { it('returns a deleted sample for a dev/admin user', done => {
@ -765,7 +765,7 @@ describe('/sample', () => {
url: '/sample/400000000000000000000005', url: '/sample/400000000000000000000005',
auth: {basic: 'admin'}, auth: {basic: 'admin'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000005', number: 'Rng33', type: 'granulate', color: 'black', batch: '1653000308', condition: {condition_template: '200000000000000000000003'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {}, measurements: [], status: 'deleted', user: 'admin'} res: {_id: '400000000000000000000005', number: 'Rng33', type: 'as-delivered/raw', color: 'black', batch: '1653000308', condition: {condition_template: '200000000000000000000003'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {}, measurements: [], status: 'deleted', user: 'admin'}
}); });
}); });
it('returns 403 for a write user when requesting a deleted sample', done => { it('returns 403 for a write user when requesting a deleted sample', done => {
@ -809,7 +809,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: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'} res: {_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'}
}); });
}); });
it('keeps unchanged properties', done => { it('keeps unchanged properties', done => {
@ -818,17 +818,17 @@ describe('/sample', () => {
url: '/sample/400000000000000000000001', url: '/sample/400000000000000000000001',
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
req: {type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', notes: {}} req: {type: 'as-delivered/raw', 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: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'}); should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'});
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', 'condition', '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', 'as-delivered/raw');
should(data).have.property('batch', ''); should(data).have.property('batch', '');
should(data).have.property('condition', {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}); 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');
@ -845,10 +845,10 @@ describe('/sample', () => {
url: '/sample/400000000000000000000001', url: '/sample/400000000000000000000001',
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
req: {type: 'granulate'} req: {type: 'as-delivered/raw'}
}).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: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'}); should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'});
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','validated'); should(data).have.property('status','validated');
@ -865,7 +865,7 @@ describe('/sample', () => {
req: {condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}} req: {condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}}
}).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: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'}); should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'});
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','validated'); should(data).have.property('status','validated');
@ -882,14 +882,14 @@ 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', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', note_id: '500000000000000000000001', user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'}); should(res.body).be.eql({_id: '400000000000000000000002', number: '21', type: 'as-delivered/raw', color: 'natural', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', note_id: '500000000000000000000001', user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'});
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', 'condition', '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', 'as-delivered/raw');
should(data).have.property('batch', '1560237365'); should(data).have.property('batch', '1560237365');
should(data.condition).have.property('material', 'copper'); should(data.condition).have.property('material', 'copper');
should(data.condition).have.property('weeks', 3); should(data.condition).have.property('weeks', 3);
@ -908,7 +908,7 @@ 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', condition: {condition_template: '200000000000000000000003'}, material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {type: 'processed', 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) => {
@ -917,7 +917,7 @@ describe('/sample', () => {
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', 'processed');
should(data).have.property('batch', '114531'); should(data).have.property('batch', '114531');
should(data).have.property('condition', {condition_template: '200000000000000000000003'}); should(data).have.property('condition', {condition_template: '200000000000000000000003'});
should(data.material_id.toString()).be.eql('100000000000000000000002'); should(data.material_id.toString()).be.eql('100000000000000000000002');
@ -943,7 +943,7 @@ 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', condition: {condition_template: '200000000000000000000003'}, material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', color: 'signalviolet', batch: '114531', condition: {condition_template: '200000000000000000000003'}, material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
log: { log: {
collection: 'samples', collection: 'samples',
dataAdd: { dataAdd: {
@ -995,7 +995,7 @@ describe('/sample', () => {
url: '/sample/400000000000000000000002', url: '/sample/400000000000000000000002',
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
req: {type: 'part'} req: {type: 'processed'}
}).end((err, res) => { }).end((err, res) => {
if (err) return done (err); if (err) return done (err);
NoteModel.findById(res.body.note_id).lean().exec((err, data) => { NoteModel.findById(res.body.note_id).lean().exec((err, data) => {
@ -1029,7 +1029,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', 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'}
}); });
}); });
@ -1039,7 +1039,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {number: 25, type: 'processed', 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'}
}); });
}); });
@ -1049,7 +1049,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: [{sample_id: '000000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', 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'}
}); });
}); });
@ -1059,7 +1059,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', 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: 'Invalid object id'} res: {status: 'Invalid body format', details: 'Invalid object id'}
}); });
}); });
@ -1069,7 +1069,7 @@ 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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', 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 => { it('rejects not specified condition parameters', done => {
@ -1139,7 +1139,7 @@ describe('/sample', () => {
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 400, httpStatus: 400,
req: {type: 'xx'}, req: {type: 'xx'},
res: {status: 'Invalid body format', details: '"type" must be one of [granulate, part, tension rod]'} res: {status: 'Invalid body format', details: '"type" must be one of [as-delivered/raw, processed]'}
}); });
}); });
it('allows keeping an empty condition empty', done => { it('allows keeping an empty condition empty', done => {
@ -1149,7 +1149,7 @@ describe('/sample', () => {
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
req: {condition: {}}, req: {condition: {}},
res: {_id: '400000000000000000000006', number: 'Rng36', type: 'granulate', color: 'black', batch: '', condition: {}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'new', added: '2004-01-10T13:37:04.000Z'} res: {_id: '400000000000000000000006', number: 'Rng36', type: 'as-delivered/raw', color: 'black', batch: '', condition: {}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'new', added: '2004-01-10T13:37:04.000Z'}
}); });
}); });
it('rejects an old version of a condition template', done => { it('rejects an old version of a condition template', done => {
@ -1169,7 +1169,7 @@ describe('/sample', () => {
auth: {basic: 'admin'}, auth: {basic: 'admin'},
httpStatus: 200, httpStatus: 200,
req: {condition: {p1: 36, condition_template: '200000000000000000000004'}}, req: {condition: {p1: 36, condition_template: '200000000000000000000004'}},
res: {_id: '400000000000000000000004', number: '32', type: 'granulate', color: 'black', batch: '1653000308', condition: {p1: 36, condition_template: '200000000000000000000004'}, material_id: '100000000000000000000005', note_id: '500000000000000000000003', user_id: '000000000000000000000003', status: 'new', added: '2004-01-10T13:37:04.000Z'} res: {_id: '400000000000000000000004', number: '32', type: 'as-delivered/raw', color: 'black', batch: '1653000308', condition: {p1: 36, condition_template: '200000000000000000000004'}, material_id: '100000000000000000000005', note_id: '500000000000000000000003', user_id: '000000000000000000000003', status: 'new', added: '2004-01-10T13:37:04.000Z'}
}); });
}); });
it('rejects changing back to an empty condition', done => { it('rejects changing back to an empty condition', done => {
@ -1197,7 +1197,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', 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 => {
@ -1216,7 +1216,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: '', condition: {condition_template: '200000000000000000000001', material: 'copper', weeks: 3}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'} res: {_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {condition_template: '200000000000000000000001', material: 'copper', weeks: 3}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', status: 'validated', added: '2004-01-10T13:37:04.000Z'}
}); });
}); });
it('rejects requests from a read user', done => { it('rejects requests from a read user', done => {
@ -1225,7 +1225,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', 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 => {
@ -1234,7 +1234,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {type: 'processed', 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 => {
@ -1242,7 +1242,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'processed', color: 'signalviolet', batch: '114531', material_id: '100000000000000000000002', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
}); });
}); });
}); });
@ -1263,7 +1263,7 @@ describe('/sample', () => {
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', 'as-delivered/raw');
should(data).have.property('batch', ''); should(data).have.property('batch', '');
should(data.condition).have.property('material', 'copper'); should(data.condition).have.property('material', 'copper');
should(data.condition).have.property('weeks', 3); should(data.condition).have.property('weeks', 3);
@ -1438,7 +1438,7 @@ describe('/sample', () => {
url: '/sample/number/33', url: '/sample/number/33',
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000003', number: '33', type: 'part', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'} res: {_id: '400000000000000000000003', number: '33', type: 'processed', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'as-delivered/raw to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'}
}); });
}); });
it('works with an API key', done => { it('works with an API key', done => {
@ -1447,7 +1447,7 @@ describe('/sample', () => {
url: '/sample/number/33', url: '/sample/number/33',
auth: {key: 'janedoe'}, auth: {key: 'janedoe'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000003', number: '33', type: 'part', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'granulate to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'} res: {_id: '400000000000000000000003', number: '33', type: 'processed', color: 'black', batch: '1704-005', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {comment: '', sample_references: [{sample_id: '400000000000000000000004', relation: 'as-delivered/raw to sample'}], custom_fields: {'not allowed for new applications': true}}, measurements: [{_id: '800000000000000000000003', sample_id: '400000000000000000000003', values: {val1: 1}, measurement_template: '300000000000000000000003'}], status: 'new', user: 'admin'}
}); });
}); });
it('returns a deleted sample for a dev/admin user', done => { it('returns a deleted sample for a dev/admin user', done => {
@ -1456,7 +1456,7 @@ describe('/sample', () => {
url: '/sample/number/Rng33', url: '/sample/number/Rng33',
auth: {basic: 'admin'}, auth: {basic: 'admin'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000005', number: 'Rng33', type: 'granulate', color: 'black', batch: '1653000308', condition: {condition_template: '200000000000000000000003'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {}, measurements: [], status: 'deleted', user: 'admin'} res: {_id: '400000000000000000000005', number: 'Rng33', type: 'as-delivered/raw', color: 'black', batch: '1653000308', condition: {condition_template: '200000000000000000000003'}, material: {_id: '100000000000000000000005', name: 'Amodel A 1133 HS', supplier: 'Solvay', group: 'PPA', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 33, carbon_fiber: 0}, numbers: ['5514262406']}, notes: {}, measurements: [], status: 'deleted', user: 'admin'}
}); });
}); });
it ('filters out spectral data for a write user', done => { it ('filters out spectral data for a write user', done => {
@ -1465,7 +1465,7 @@ describe('/sample', () => {
url: '/sample/number/1', url: '/sample/number/1',
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'} res: {_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'}
}); });
}); });
it ('returns spectral data for an admin user', done => { it ('returns spectral data for an admin user', done => {
@ -1474,7 +1474,7 @@ describe('/sample', () => {
url: '/sample/number/1', url: '/sample/number/1',
auth: {basic: 'admin'}, auth: {basic: 'admin'},
httpStatus: 200, httpStatus: 200,
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {dpt: [[ 3997.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]],device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {dpt: [[ 3996.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]], device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'} res: {_id: '400000000000000000000001', number: '1', type: 'as-delivered/raw', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material: {numbers: ['5513933405'], _id: '100000000000000000000004', name: 'Schulamid 66 GF 25 H', properties: {material_template: '130000000000000000000003', mineral: 0, glass_fiber: 25, carbon_fiber: 0}, group: 'PA66', supplier: 'Schulmann'}, user: 'janedoe', notes: {}, measurements: [{_id: '800000000000000000000001', sample_id: '400000000000000000000001', values: {dpt: [[ 3997.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]],device: 'Alpha I'}, measurement_template: '300000000000000000000001'}, {_id: '800000000000000000000007', sample_id: '400000000000000000000001', values: {dpt: [[ 3996.12558, 98.00555 ], [ 3995.08519, 98.03253 ], [ 3993.0448, 98.02657 ]], device: 'Alpha II'}, measurement_template: '300000000000000000000001'}], status: 'validated'}
}); });
}); });
it('returns 403 for a write user when requesting a deleted sample', done => { it('returns 403 for a write user when requesting a deleted sample', done => {
@ -1697,14 +1697,14 @@ 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', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {color: 'black', type: 'as-delivered/raw', 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', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added'); should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added');
should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('_id').be.type('string');
should(res.body).have.property('number', 'Rng37'); 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', 'as-delivered/raw');
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('condition', {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'});
should(res.body).have.property('material_id', '100000000000000000000001'); should(res.body).have.property('material_id', '100000000000000000000001');
@ -1722,7 +1722,7 @@ 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', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {color: 'black', type: 'as-delivered/raw', 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: 'Rng37'}).lean().exec((err, data: any) => { SampleModel.find({number: 'Rng37'}).lean().exec((err, data: any) => {
@ -1732,7 +1732,7 @@ describe('/sample', () => {
should(data[0]).have.property('_id'); should(data[0]).have.property('_id');
should(data[0]).have.property('number', 'Rng37'); 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', 'as-delivered/raw');
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]).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');
@ -1758,7 +1758,7 @@ 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', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
log: { log: {
collection: 'samples', collection: 'samples',
dataAdd: { dataAdd: {
@ -1776,7 +1776,7 @@ 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: [], custom_fields: {field1: 'a', field2: 'b', 'not allowed for new applications': true}}} req: {color: 'black', type: 'as-delivered/raw', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [], custom_fields: {field1: 'a', field2: 'b', 'not allowed for new applications': true}}}
}).end((err, res) => { }).end((err, res) => {
if (err) return done (err); if (err) return done (err);
NoteModel.findById(res.body.note_id).lean().exec((err, data: any) => { NoteModel.findById(res.body.note_id).lean().exec((err, data: any) => {
@ -1813,14 +1813,14 @@ 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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {color: 'black', type: 'as-delivered/raw', 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', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added'); should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added');
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');
should(res.body).have.property('type', 'granulate'); should(res.body).have.property('type', 'as-delivered/raw');
should(res.body).have.property('batch', '1560237365'); should(res.body).have.property('batch', '1560237365');
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');
@ -1837,14 +1837,14 @@ 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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {color: 'black', type: 'as-delivered/raw', 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', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added'); should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added');
should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('_id').be.type('string');
should(res.body).have.property('number', 'Rng37'); 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', 'as-delivered/raw');
should(res.body).have.property('batch', '1560237365'); should(res.body).have.property('batch', '1560237365');
should(res.body).have.property('condition', {}); should(res.body).have.property('condition', {});
should(res.body).have.property('material_id', '100000000000000000000001'); should(res.body).have.property('material_id', '100000000000000000000001');
@ -1862,7 +1862,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'}
}); });
}); });
@ -1872,7 +1872,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {number: 'Rng34', color: 'black', type: 'as-delivered/raw', 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'}
}); });
}); });
@ -1882,14 +1882,14 @@ describe('/sample', () => {
url: '/sample/new', url: '/sample/new',
auth: {basic: 'admin'}, auth: {basic: 'admin'},
httpStatus: 200, httpStatus: 200,
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'}]}}, req: {number: 'Rng34', color: 'black', type: 'as-delivered/raw', 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', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added'); should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', 'added');
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', 'Rng34');
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', 'as-delivered/raw');
should(res.body).have.property('batch', '1560237365'); should(res.body).have.property('batch', '1560237365');
should(res.body).have.property('condition', {}); should(res.body).have.property('condition', {});
should(res.body).have.property('material_id', '100000000000000000000001'); should(res.body).have.property('material_id', '100000000000000000000001');
@ -1907,7 +1907,7 @@ describe('/sample', () => {
url: '/sample/new', url: '/sample/new',
auth: {basic: 'admin'}, auth: {basic: 'admin'},
httpStatus: 400, httpStatus: 400,
req: {number: 'Rng33', color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {number: 'Rng33', color: 'black', type: 'as-delivered/raw', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
res: {status: 'Sample number already taken'} res: {status: 'Sample number already taken'}
}); });
}); });
@ -1917,7 +1917,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: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '000000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'}
}); });
}); });
@ -1927,7 +1927,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', condition: {material: 'copper', weeks: 3, condition_template: '20000h000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -1937,7 +1937,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', condition: {material: 'copper', weeks: 3, condition_template: '000000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -1947,7 +1947,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', 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'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -1957,7 +1957,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', condition: {material: 'copper', condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -1967,7 +1967,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', condition: {material: 'xxx', weeks: 3, condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -1977,7 +1977,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', condition: {material: 'copper', weeks: 0, condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -1987,7 +1987,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', condition: {material: 'copper', weeks: 11, condition_template: '20000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -1997,7 +1997,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', condition: {material: 'copper', weeks: 3}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'} res: {status: 'Condition template not available'}
}); });
}); });
@ -2007,7 +2007,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', condition: {p1: 36, condition_template: '200000000000000000000004'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', batch: '1560237365', condition: {p1: 36, condition_template: '200000000000000000000004'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
res: {status: 'Old template version not allowed'} res: {status: 'Old template version not allowed'}
}); });
}); });
@ -2017,7 +2017,7 @@ describe('/sample', () => {
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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {type: 'as-delivered/raw', 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'}
}); });
}); });
@ -2037,7 +2037,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'}
}); });
}); });
@ -2047,7 +2047,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', 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'}
}); });
}); });
@ -2057,7 +2057,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}, req: {color: 'black', type: 'as-delivered/raw', batch: '1560237365', material_id: '10000000000h000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
res: {status: 'Invalid body format', details: 'Invalid object id'} res: {status: 'Invalid body format', details: 'Invalid object id'}
}); });
}); });
@ -2068,7 +2068,7 @@ describe('/sample', () => {
auth: {basic: 'janedoe'}, auth: {basic: 'janedoe'},
httpStatus: 400, httpStatus: 400,
req: {color: 'black', type: 'xx', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment'}}, req: {color: 'black', type: 'xx', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment'}},
res: {status: 'Invalid body format', details: '"type" must be one of [granulate, part, tension rod]'} res: {status: 'Invalid body format', details: '"type" must be one of [as-delivered/raw, processed]'}
}); });
}); });
it('rejects an API key', done => { it('rejects an API key', done => {
@ -2077,7 +2077,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {color: 'black', type: 'as-delivered/raw', 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 => {
@ -2086,7 +2086,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {color: 'black', type: 'as-delivered/raw', 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 => {
@ -2094,7 +2094,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: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}} req: {color: 'black', type: 'as-delivered/raw', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
}); });
}); });
}); });

View File

@ -17,6 +17,7 @@ import ParametersValidate from './validate/parameters';
import db from '../db'; import db from '../db';
import csv from '../helpers/csv'; import csv from '../helpers/csv';
import flatten from '../helpers/flatten'; import flatten from '../helpers/flatten';
import globals from '../globals';
const router = express.Router(); const router = express.Router();
@ -36,7 +37,7 @@ router.get('/samples', async (req, res, next) => {
if (error) return res400(error, res); if (error) return res400(error, res);
// spectral data and csv not allowed for read/write users // spectral data and csv not allowed for read/write users
if ((filters.fields.find(e => /\.dpt$/.test(e)) || filters.output !== 'json') && if ((filters.fields.find(e => e.indexOf('.' + globals.spectrum.dpt) >= 0) || filters.output !== 'json') &&
!req.auth(res, ['dev', 'admin'], 'all')) return; !req.auth(res, ['dev', 'admin'], 'all')) return;
// TODO: find a better place for these // TODO: find a better place for these
@ -260,7 +261,7 @@ router.get('/samples', async (req, res, next) => {
// count total number of items before $skip and $limit, only works when from-id is not specified and spectra are not // count total number of items before $skip and $limit, only works when from-id is not specified and spectra are not
// included // included
if (!filters.fields.find(e => /spectrum\./.test(e)) && !filters['from-id']) { if (!filters.fields.find(e => e.indexOf(globals.spectrum.spectrum + '.') >= 0) && !filters['from-id']) {
queryPtr.push({$facet: {count: [{$count: 'count'}], samples: []}}); queryPtr.push({$facet: {count: [{$count: 'count'}], samples: []}});
queryPtr = queryPtr[queryPtr.length - 1].$facet.samples; // add rest of aggregation pipeline into $facet queryPtr = queryPtr[queryPtr.length - 1].$facet.samples; // add rest of aggregation pipeline into $facet
} }
@ -328,7 +329,7 @@ router.get('/samples', async (req, res, next) => {
return res.status(400).json({status: 'Invalid body format', details: 'Measurement key not found'}); return res.status(400).json({status: 'Invalid body format', details: 'Measurement key not found'});
} }
// use different lookup methods with and without spectrum for the best performance // use different lookup methods with and without spectrum for the best performance
if (fieldsToAdd.find(e => /spectrum\./.test(e))) { if (fieldsToAdd.find(e => e.indexOf(globals.spectrum.spectrum + '.') >= 0)) {
queryPtr.push( queryPtr.push(
{$lookup: {from: 'measurements', localField: '_id', foreignField: 'sample_id', as: 'measurements'}} {$lookup: {from: 'measurements', localField: '_id', foreignField: 'sample_id', as: 'measurements'}}
); );
@ -343,22 +344,12 @@ router.get('/samples', async (req, res, next) => {
as: 'measurements' as: 'measurements'
}}); }});
} }
measurementTemplates.forEach(template => { // TODO: hard coded dpt for special treatment, change later measurementTemplates.forEach(template => {
addMeasurements(queryPtr, template); addMeasurements(queryPtr, template);
if (measurementFieldsFields.find(e => e === 'spectrum')) { if (measurementFieldsFields.find(e => e === globals.spectrum.spectrum)) {
queryPtr.push({$unwind: '$spectrum'}); queryPtr.push({$unwind: '$' + globals.spectrum.spectrum});
} }
}); });
// if (measurementFieldsFields.find(e => e === 'spectrum')) { // TODO: remove hardcoded as well
// queryPtr.push(
// {$addFields: {spectrum: {$filter: {input: '$measurements', cond: {
// $eq: ['$$this.measurement_template', measurementTemplates.filter(e => e.name === 'spectrum')[0]._id]
// }}}}},
// {$addFields: {spectrum: '$spectrum.values'}},
// {$unwind: '$spectrum'}
// );
// }
// queryPtr.push({$unset: 'measurements'});
queryPtr.push({$project: {measurements: 0}}); queryPtr.push({$project: {measurements: 0}});
} }
@ -372,7 +363,8 @@ router.get('/samples', async (req, res, next) => {
projection._id = false; projection._id = false;
} }
queryPtr.push({$project: projection}); queryPtr.push({$project: projection});
if (!fieldsToAdd.find(e => /spectrum\./.test(e))) { // use streaming when including spectrum files // use streaming when including spectrum files
if (!fieldsToAdd.find(e => e.indexOf(globals.spectrum.spectrum + '.') >= 0)) {
collection.aggregate(query).allowDiskUse(true).exec((err, data) => { collection.aggregate(query).allowDiskUse(true).exec((err, data) => {
if (err) return next(err); if (err) return next(err);
if (data[0] && data[0].count) { if (data[0] && data[0].count) {
@ -439,7 +431,7 @@ router.get('/samples', async (req, res, next) => {
} }
}); });
router.get('/samples/:state(new|deleted)', (req, res, next) => { router.get(`/samples/:state(${globals.status.new}|${globals.status.del})`, (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
SampleModel.find({status: req.params.state}).lean().exec((err, data) => { SampleModel.find({status: req.params.state}).lean().exec((err, data) => {
@ -479,7 +471,7 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
if (!sampleData) { if (!sampleData) {
return res.status(404).json({status: 'Not found'}); return res.status(404).json({status: 'Not found'});
} }
if (sampleData.status === 'deleted') { if (sampleData.status === globals.status.del) {
return res.status(403).json({status: 'Forbidden'}); return res.status(403).json({status: 'Forbidden'});
} }
@ -527,7 +519,7 @@ 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 = 'new'; sample.status = globals.status.new;
} }
await SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).log(req).lean().exec((err, data: any) => { await SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).log(req).lean().exec((err, data: any) => {
@ -555,7 +547,7 @@ router.delete('/sample/' + IdValidate.parameter(), (req, res, next) => {
if (err) return next(err); if (err) return next(err);
// set status of associated measurements also to deleted // set status of associated measurements also to deleted
MeasurementModel.updateMany({sample_id: mongoose.Types.ObjectId(req.params.id)}, {status: 'deleted'}) MeasurementModel.updateMany({sample_id: mongoose.Types.ObjectId(req.params.id)}, {status: globals.status.del})
.log(req).lean().exec(err => { .log(req).lean().exec(err => {
if (err) return next(err); if (err) return next(err);
@ -589,27 +581,13 @@ router.get('/sample/number/:number', (req, res, next) => {
router.put('/sample/restore/' + IdValidate.parameter(), (req, res, next) => { router.put('/sample/restore/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
SampleModel.findByIdAndUpdate(req.params.id, {status: 'new'}).log(req).lean().exec((err, data) => { setStatus(globals.status.new, req, res, next);
if (err) return next(err);
if (!data) {
return res.status(404).json({status: 'Not found'});
}
res.json({status: 'OK'});
});
}); });
router.put('/sample/validate/' + IdValidate.parameter(), (req, res, next) => { router.put('/sample/validate/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['dev', 'admin'], 'basic')) return; if (!req.auth(res, ['dev', 'admin'], 'basic')) return;
SampleModel.findByIdAndUpdate(req.params.id, {status: 'validated'}).log(req).lean().exec((err, data) => { setStatus(globals.status.val, req, res, next);
if (err) return next(err);
if (!data) {
return res.status(404).json({status: 'Not found'});
}
res.json({status: 'OK'});
});
}); });
router.post('/sample/new', async (req, res, next) => { router.post('/sample/new', async (req, res, next) => {
@ -635,7 +613,7 @@ router.post('/sample/new', async (req, res, next) => {
if (!await conditionCheck(sample.condition, 'change', res, next)) return; if (!await conditionCheck(sample.condition, 'change', res, next)) return;
} }
sample.status = 'new'; // set status to new sample.status = globals.status.new; // set status to new
if (sample.hasOwnProperty('number')) { if (sample.hasOwnProperty('number')) {
if (!await numberCheck(sample, res, next)) return; if (!await numberCheck(sample, res, next)) return;
} }
@ -885,7 +863,7 @@ async function sampleReturn (sampleData, req, res, next) {
sampleData = sampleData.toObject(); sampleData = sampleData.toObject();
// deleted samples only available for dev/admin // deleted samples only available for dev/admin
if (sampleData.status === 'deleted' && !req.auth(res, ['dev', 'admin'], 'all')) return; if (sampleData.status === globals.status.del && !req.auth(res, ['dev', 'admin'], 'all')) return;
sampleData.material = sampleData.material_id; // map data to right keys sampleData.material = sampleData.material_id; // map data to right keys
sampleData.material.group = sampleData.material.group_id.name; sampleData.material.group = sampleData.material.group_id.name;
sampleData.material.supplier = sampleData.material.supplier_id.name; sampleData.material.supplier = sampleData.material.supplier_id.name;
@ -896,8 +874,8 @@ async function sampleReturn (sampleData, req, res, next) {
sampleData.measurements = data; sampleData.measurements = data;
if (['dev', 'admin'].indexOf(req.authDetails.level) < 0) { // strip dpt values if not dev or admin if (['dev', 'admin'].indexOf(req.authDetails.level) < 0) { // strip dpt values if not dev or admin
sampleData.measurements.forEach(measurement => { sampleData.measurements.forEach(measurement => {
if (measurement.values.dpt) { if (measurement.values[globals.spectrum.dpt]) {
delete measurement.values.dpt; delete measurement.values[globals.spectrum.dpt];
} }
}); });
} }
@ -908,3 +886,14 @@ async function sampleReturn (sampleData, req, res, next) {
res.status(404).json({status: 'Not found'}); res.status(404).json({status: 'Not found'});
} }
} }
function setStatus (status, req, res, next) {
SampleModel.findByIdAndUpdate(req.params.id, {status}).log(req).lean().exec((err, data) => {
if (err) return next(err);
if (!data) {
return res.status(404).json({status: 'Not found'});
}
res.json({status: 'OK'});
});
}

View File

@ -60,13 +60,13 @@ router.put('/user:username([/](?!key|new).?*|/?)', async (req, res, next) => {
} }
// get current mail address to compare to given address // get current mail address to compare to given address
const {email: oldMail} = await UserModel.findOne({name: username}).lean().exec().catch(err => next(err)); const oldUserData = await UserModel.findOne({name: username}).lean().exec().catch(err => next(err));
await UserModel.findOneAndUpdate({name: username}, user, {new: true}).log(req).lean().exec( (err, data:any) => { await UserModel.findOneAndUpdate({name: username}, user, {new: true}).log(req).lean().exec( (err, data:any) => {
if (err) return next(err); if (err) return next(err);
if (data) { if (data) {
if (data.mail !== oldMail) { // mail address was changed, send notice to old address if (data.mail !== oldUserData.email) { // mail address was changed, send notice to old address
Mail.send(oldMail, 'Email change in your DeFinMa database account', Mail.send(oldUserData.email, 'Email change in your DeFinMa database account',
'Hi, <br><br> Your email address of your DeFinMa account was changed to ' + data.mail + 'Hi, <br><br> Your email address of your DeFinMa account was changed to ' + data.mail +
'<br><br>If you actually did this, just delete this email.' + '<br><br>If you actually did this, just delete this email.' +
'<br><br>If you did not change your email, someone might be messing around with your account, ' + '<br><br>If you did not change your email, someone might be messing around with your account, ' +

View File

@ -1,7 +1,10 @@
import Joi from 'joi'; import Joi from 'joi';
export default class IdValidate { export default class IdValidate {
private static id = Joi.string().pattern(new RegExp('[0-9a-f]{24}')).length(24).messages({'string.pattern.base': 'Invalid object id'}); private static id = Joi.string()
.pattern(new RegExp('[0-9a-f]{24}'))
.length(24)
.messages({'string.pattern.base': 'Invalid object id'});
static get () { // return joi validation static get () { // return joi validation
return this.id; return this.id;
@ -17,7 +20,8 @@ export default class IdValidate {
static stringify (data) { // convert all ObjectID objects to plain strings static stringify (data) { // convert all ObjectID objects to plain strings
Object.keys(data).forEach(key => { Object.keys(data).forEach(key => {
if (data[key] !== null && data[key].hasOwnProperty('_bsontype') && data[key]._bsontype === 'ObjectID') { // stringify id // stringify id
if (data[key] !== null && data[key].hasOwnProperty('_bsontype') && data[key]._bsontype === 'ObjectID') {
data[key] = data[key].toString(); data[key] = data[key].toString();
} }
else if (typeof data[key] === 'object' && data[key] !== null) { // deeper into recursion else if (typeof data[key] === 'object' && data[key] !== null) { // deeper into recursion

View File

@ -1,6 +1,7 @@
import Joi from 'joi'; import Joi from 'joi';
import IdValidate from './id'; import IdValidate from './id';
import globals from '../../globals';
export default class MaterialValidate { // validate input for material export default class MaterialValidate { // validate input for material
private static material = { private static material = {
@ -84,7 +85,7 @@ export default class MaterialValidate { // validate input for material
static query (data) { static query (data) {
return Joi.object({ return Joi.object({
status: Joi.string().valid('validated', 'new', 'all') status: Joi.string().valid(globals.status.val, globals.status.new, 'all')
}).validate(data); }).validate(data);
} }
} }

View File

@ -1,6 +1,7 @@
import Joi from 'joi'; import Joi from 'joi';
import IdValidate from './id'; import IdValidate from './id';
import globals from '../../globals';
export default class MeasurementValidate { export default class MeasurementValidate {
private static measurement = { private static measurement = {
@ -37,8 +38,8 @@ export default class MeasurementValidate {
static output (data, req) { // validate output and strip unwanted properties, returns null if not valid static output (data, req) { // validate output and strip unwanted properties, returns null if not valid
data = IdValidate.stringify(data); data = IdValidate.stringify(data);
// spectral data not allowed for read/write users // spectral data not allowed for read/write users
if (['dev', 'admin'].indexOf(req.authDetails.level) < 0 && data.values.dpt) { if (['dev', 'admin'].indexOf(req.authDetails.level) < 0 && data.values[globals.spectrum.dpt]) {
delete data.values.dpt; delete data.values[globals.spectrum.dpt];
} }
const {value, error} = Joi.object({ const {value, error} = Joi.object({
_id: IdValidate.get(), _id: IdValidate.get(),

View File

@ -1,7 +1,8 @@
import Joi from 'joi'; import Joi from 'joi';
export default class ParametersValidate { export default class ParametersValidate {
static input (data, parameters, param) { // data to validate, parameters from template, param: 'new', 'change', 'null'(null values are allowed) // data to validate, parameters from template, param: 'new', 'change', 'null'(null values are allowed)
static input (data, parameters, param) {
let joiObject = {}; let joiObject = {};
parameters.forEach(parameter => { parameters.forEach(parameter => {
if (parameter.range.hasOwnProperty('values')) { // append right validation method according to parameter if (parameter.range.hasOwnProperty('values')) { // append right validation method according to parameter

View File

@ -36,7 +36,7 @@ export default class RootValidate { // validate input for root methods
static changelogOutput (data) { static changelogOutput (data) {
data.date = data._id.getTimestamp(); data.date = data._id.getTimestamp();
data.collection = data.collectionName; data.collection = data.collection_name;
data = IdValidate.stringify(data); data = IdValidate.stringify(data);
const {value, error} = Joi.object({ const {value, error} = Joi.object({
date: this.changelog.timestamp, date: this.changelog.timestamp,

View File

@ -16,7 +16,7 @@ export default class SampleValidate {
.allow(''), .allow(''),
type: Joi.string() type: Joi.string()
.valid('granulate', 'part', 'tension rod'), .valid('as-delivered/raw', 'processed'),
batch: Joi.string() batch: Joi.string()
.max(128) .max(128)
@ -53,7 +53,7 @@ export default class SampleValidate {
.min('1970-01-01T00:00:00.000Z'), .min('1970-01-01T00:00:00.000Z'),
status: Joi.string() status: Joi.string()
.valid(...globals.status) .valid(...Object.values(globals.status))
}; };
private static sortKeys = [ private static sortKeys = [
@ -68,7 +68,7 @@ export default class SampleValidate {
'material.supplier', 'material.supplier',
'material.group', 'material.group',
'material.properties.*', 'material.properties.*',
'measurements.(?!spectrum\.dpt)*' `measurements.(?!${globals.spectrum.spectrum}.${globals.spectrum.dpt})*`
]; ];
private static fieldKeys = [ private static fieldKeys = [
@ -81,7 +81,7 @@ export default class SampleValidate {
'user_id', 'user_id',
'material._id', 'material._id',
'material.numbers', 'material.numbers',
'measurements.spectrum.dpt', `measurements.${globals.spectrum.spectrum}.${globals.spectrum.dpt}`,
]; ];
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
@ -215,12 +215,12 @@ export default class SampleValidate {
return {error: {details: [{message: 'Invalid JSON string for filter parameter'}]}, value: null} return {error: {details: [{message: 'Invalid JSON string for filter parameter'}]}, value: null}
} }
} }
const acceptedStatuses = ['validated', 'new']; const acceptedStatuses = [globals.status.val, globals.status.new];
if (dev) { // dev and admin can also access deleted samples if (dev) { // dev and admin can also access deleted samples
acceptedStatuses.push('deleted') acceptedStatuses.push(globals.status.del)
} }
return Joi.object({ return Joi.object({
status: Joi.array().items(Joi.string().valid(...acceptedStatuses)).default(['validated']), status: Joi.array().items(Joi.string().valid(...acceptedStatuses)).default([globals.status.val]),
'from-id': IdValidate.get(), 'from-id': IdValidate.get(),
'to-page': Joi.number().integer(), 'to-page': Joi.number().integer(),
'page-size': Joi.number().integer().min(1), 'page-size': Joi.number().integer().min(1),

View File

@ -21,7 +21,7 @@ export default class UserValidate { // validate input for user
.max(128), .max(128),
level: Joi.string() level: Joi.string()
.valid(...globals.levels), .valid(...Object.values(globals.levels)),
location: Joi.string() location: Joi.string()
.alphanum() .alphanum()

View File

@ -4,7 +4,7 @@
{ {
"_id": {"$oid":"400000000000000000000001"}, "_id": {"$oid":"400000000000000000000001"},
"number": "1", "number": "1",
"type": "granulate", "type": "as-delivered/raw",
"color": "black", "color": "black",
"batch": "", "batch": "",
"condition": { "condition": {
@ -21,7 +21,7 @@
{ {
"_id": {"$oid":"400000000000000000000002"}, "_id": {"$oid":"400000000000000000000002"},
"number": "21", "number": "21",
"type": "granulate", "type": "as-delivered/raw",
"color": "natural", "color": "natural",
"batch": "1560237365", "batch": "1560237365",
"condition": { "condition": {
@ -38,7 +38,7 @@
{ {
"_id": {"$oid":"400000000000000000000003"}, "_id": {"$oid":"400000000000000000000003"},
"number": "33", "number": "33",
"type": "part", "type": "processed",
"color": "black", "color": "black",
"batch": "1704-005", "batch": "1704-005",
"condition": { "condition": {
@ -55,7 +55,7 @@
{ {
"_id": {"$oid":"400000000000000000000004"}, "_id": {"$oid":"400000000000000000000004"},
"number": "32", "number": "32",
"type": "granulate", "type": "as-delivered/raw",
"color": "black", "color": "black",
"batch": "1653000308", "batch": "1653000308",
"condition": { "condition": {
@ -71,7 +71,7 @@
{ {
"_id": {"$oid":"400000000000000000000005"}, "_id": {"$oid":"400000000000000000000005"},
"number": "Rng33", "number": "Rng33",
"type": "granulate", "type": "as-delivered/raw",
"color": "black", "color": "black",
"batch": "1653000308", "batch": "1653000308",
"condition": { "condition": {
@ -86,7 +86,7 @@
{ {
"_id": {"$oid":"400000000000000000000006"}, "_id": {"$oid":"400000000000000000000006"},
"number": "Rng36", "number": "Rng36",
"type": "granulate", "type": "as-delivered/raw",
"color": "black", "color": "black",
"batch": "", "batch": "",
"condition": {}, "condition": {},
@ -99,7 +99,7 @@
{ {
"_id": {"$oid":"400000000000000000000007"}, "_id": {"$oid":"400000000000000000000007"},
"number": "34", "number": "34",
"type": "part", "type": "processed",
"color": "black", "color": "black",
"batch": "", "batch": "",
"condition": {}, "condition": {},
@ -122,7 +122,7 @@
"comment": "", "comment": "",
"sample_references": [{ "sample_references": [{
"sample_id": {"$oid":"400000000000000000000004"}, "sample_id": {"$oid":"400000000000000000000004"},
"relation": "granulate to sample" "relation": "as-delivered/raw to sample"
}], }],
"custom_fields": { "custom_fields": {
"not allowed for new applications": true "not allowed for new applications": true
@ -728,12 +728,12 @@
{ {
"_id" : {"$oid": "120000010000000000000000"}, "_id" : {"$oid": "120000010000000000000000"},
"action" : "PUT /sample/400000000000000000000001", "action" : "PUT /sample/400000000000000000000001",
"collectionName" : "samples", "collection_name" : "samples",
"conditions" : { "conditions" : {
"_id" : {"$oid": "400000000000000000000001"} "_id" : {"$oid": "400000000000000000000001"}
}, },
"data" : { "data" : {
"type" : "part", "type" : "processed",
"status" : 0 "status" : 0
}, },
"user_id" : {"$oid": "000000000000000000000003"}, "user_id" : {"$oid": "000000000000000000000003"},
@ -742,12 +742,12 @@
{ {
"_id" : {"$oid": "120000020000000000000000"}, "_id" : {"$oid": "120000020000000000000000"},
"action" : "PUT /sample/400000000000000000000001", "action" : "PUT /sample/400000000000000000000001",
"collectionName" : "samples", "collection_name" : "samples",
"conditions" : { "conditions" : {
"_id" : {"$oid": "400000000000000000000001"} "_id" : {"$oid": "400000000000000000000001"}
}, },
"data" : { "data" : {
"type" : "part", "type" : "processed",
"status" : 0 "status" : 0
}, },
"user_id" : {"$oid": "000000000000000000000003"}, "user_id" : {"$oid": "000000000000000000000003"},
@ -756,12 +756,12 @@
{ {
"_id" : {"$oid": "120000030000000000000000"}, "_id" : {"$oid": "120000030000000000000000"},
"action" : "PUT /sample/400000000000000000000001", "action" : "PUT /sample/400000000000000000000001",
"collectionName" : "samples", "collection_name" : "samples",
"conditions" : { "conditions" : {
"_id" : {"$oid": "400000000000000000000001"} "_id" : {"$oid": "400000000000000000000001"}
}, },
"data" : { "data" : {
"type" : "part", "type" : "processed",
"status" : 0 "status" : 0
}, },
"user_id" : {"$oid": "000000000000000000000003"}, "user_id" : {"$oid": "000000000000000000000003"},
@ -770,12 +770,12 @@
{ {
"_id" : {"$oid": "120000040000000000000000"}, "_id" : {"$oid": "120000040000000000000000"},
"action" : "PUT /sample/400000000000000000000001", "action" : "PUT /sample/400000000000000000000001",
"collectionName" : "samples", "collection_name" : "samples",
"conditions" : { "conditions" : {
"_id" : {"$oid": "400000000000000000000001"} "_id" : {"$oid": "400000000000000000000001"}
}, },
"data" : { "data" : {
"type" : "part", "type" : "processed",
"status" : 0 "status" : 0
}, },
"user_id" : {"$oid": "000000000000000000000003"}, "user_id" : {"$oid": "000000000000000000000003"},

View File

@ -104,9 +104,9 @@ export default class TestHelper {
ChangelogModel.findOne({}).sort({_id: -1}).skip(options.log.skip? options.log.skip : 0) ChangelogModel.findOne({}).sort({_id: -1}).skip(options.log.skip? options.log.skip : 0)
.lean().exec((err, data) => { // latest entry .lean().exec((err, data) => { // latest entry
if (err) return done(err); if (err) return done(err);
should(data).have.only.keys('_id', 'action', 'collectionName', 'conditions', 'data', 'user_id', '__v'); should(data).have.only.keys('_id', 'action', 'collection_name', 'conditions', 'data', 'user_id', '__v');
should(data).have.property('action', options.method.toUpperCase() + ' ' + options.url); should(data).have.property('action', options.method.toUpperCase() + ' ' + options.url);
should(data).have.property('collectionName', options.log.collection); should(data).have.property('collection_name', options.log.collection);
if (options.log.hasOwnProperty('data')) { if (options.log.hasOwnProperty('data')) {
should(data).have.property('data', options.log.data); should(data).have.property('data', options.log.data);
} }

View File

@ -23,7 +23,6 @@
.go-btn button { .go-btn button {
color: #ffffff; color: #ffffff;
border-color: #008ecf; border-color: #008ecf;
background: linear-gradient(to bottom, #005691 0%, #005691 50%, #008ecf 50%, #008ecf 100%);
border-width: 1px; border-width: 1px;
line-height: 40px; line-height: 40px;
padding: 30px 60px; padding: 30px 60px;
@ -33,7 +32,7 @@
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
transition: border, background cubic-bezier(0.38, 0.04, 0.35, 0.96) 600ms; transition: border, background cubic-bezier(0.38, 0.04, 0.35, 0.96) 600ms;
background-position: 0 0; background: linear-gradient(to bottom, #005691 0%, #005691 50%, #008ecf 50%, #008ecf 100%) 0 0;
background-size: 100% 200%; background-size: 100% 200%;
} }

View File

@ -31,7 +31,7 @@
color: #000; color: #000;
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
font-size: 8.5px; font-size: 9px;
left: 39px; left: 39px;
} }

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="en">
<head> <head>
<title>DeFinMaDB - Introduction</title> <title>DeFinMaDB - Introduction</title>
<meta charset="utf-8"> <meta charset="utf-8">
@ -248,7 +248,7 @@ layout: true
class: content, theme-dark-green class: content, theme-dark-green
layout: true layout: true
# Thats all # That's all
--- ---
@ -264,7 +264,7 @@ layout: true
<script src="assets/remark-latest.min.js"> <script src="assets/remark-latest.min.js">
</script> </script>
<script> <script>
var slideshow = remark.create({ let slideshow = remark.create({
ratio: '16:9', ratio: '16:9',
slideNumberFormat: '%current% <div class="footer"><span class="intern">Intern</span>| CR/APS1 | 2020/08/07</div>', slideNumberFormat: '%current% <div class="footer"><span class="intern">Intern</span>| CR/APS1 | 2020/08/07</div>',
countIncrementalSlides: false countIncrementalSlides: false

View File

@ -229,7 +229,10 @@ body:after {
color: var(--red); color: var(--red);
} }
/*Remove colored parameters bar*/ /*Remove colored parameters bar*/
.swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span::after { .swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span::after,
.swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span::after,
.swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span::after,
.swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span::after {
background: none; background: none;
} }