import express from 'express'; import bodyParser from 'body-parser'; import ModelFileModel from '../models/model_file'; import ModelModel from '../models/model'; import UserModel from '../models/user'; import _ from 'lodash'; import ModelValidate from './validate/model'; import res400 from './validate/res400'; import db from '../db'; import mongoose from "mongoose"; const router = express.Router(); router.get('/model/groups', (req, res, next) => { if (!req.auth(res, ['predict', 'read', 'write', 'dev', 'admin'], 'basic')) return; let conditions: any = [{}, {}]; if (['dev', 'admin'].indexOf(req.authDetails.level) < 0) { // if not dev or admin, user has to possess model rights conditions = [ {'models._id': {$in: req.authDetails.models.map(e => mongoose.Types.ObjectId(e))}}, {group: true, 'models.$': true} ] } ModelModel.find(...conditions).lean().exec((err, data) => { if (err) return next(err); // validate all and filter null values from validation errors res.json(_.compact(data.map(e => ModelValidate.output(e)))); }); }); router.post('/model/:group', (req, res, next) => { if (!req.auth(res, ['dev', 'admin'], 'basic')) return; const {error, value: model} = ModelValidate.input(req.body); if (error) return res400(error, res); ModelModel.findOne({group: req.params.group}).lean().exec((err, data) => { if (err) return next(err); if (data) { // group exists if (data.models.find(e => e.name === model.name)) { // name exists, overwrite ModelModel.findOneAndUpdate( {$and: [{group: req.params.group}, {'models.name': model.name}]}, {'models.$': model}, {upsert: true}).log(req).lean().exec(err => { if (err) return next(err); res.json({status: 'OK'}) }); } else { // create new ModelModel.findOneAndUpdate( {group: req.params.group}, {$push: {models: model as never}} ).log(req).lean().exec(err => { if (err) return next(err); res.json({status: 'OK'}); }); } } else { // create new group new ModelModel({group: req.params.group, models: [model]}).save((err, data) => { if (err) return next(err); db.log(req, 'models', {_id: data._id}, data.toObject()); res.json({status: 'OK'}); }); } }); }); router.delete('/model/:group(((?!file)[^\\/]+?))/:name', (req, res, next) => { if (!req.auth(res, ['dev', 'admin'], 'basic')) return; ModelModel.findOne({group: req.params.group}).lean().exec((err, data) => { if (err) return next(err); if (!data || !data.models.find(e => e.name === req.params.name)) { return res.status(404).json({status: 'Not found'}); } // delete all references in user.models UserModel.updateMany({}, {$pull: {models: data.models.find(e => e.name === req.params.name)._id as never}}, { multi: true }).log(req).lean().exec(err => { if (err) return next(err); if (data.models.length > 1) { // only remove model ModelModel.findOneAndUpdate( {group: req.params.group}, {$pull: {models: data.models.find(e => e.name === req.params.name) as never}} ).log(req).lean().exec(err => { if (err) return next(err); res.json({status: 'OK'}) }); } else { // remove document ModelModel.findOneAndDelete({group: req.params.group}).log(req).lean().exec(err => { if (err) return next(err); res.json({status: 'OK'}) }); } }); }); }); router.get('/model/files', (req, res, next) => { if (!req.auth(res, ['dev', 'admin'], 'basic')) return; ModelFileModel.find().exec((err, data) => { if (err) return next(err); res.json(data.map(e => ModelValidate.fileOutput(e))); }); }); router.get('/model/file/:name', (req, res, next) => { if (!req.auth(res, ['dev', 'admin'], 'all')) return; ModelFileModel.findOne({name: req.params.name}).lean().exec((err, data) => { if (err) return next(err); if (data) { res.set('Content-Type', 'application/octet-stream'); res.send(data.data.buffer); } else { res.status(404).json({status: 'Not found'}); } }); }); router.post('/model/file/:name', bodyParser.raw({limit: '50mb'}), (req, res, next) => { if (!req.auth(res, ['dev', 'admin'], 'all')) return; ModelFileModel.replaceOne({name: req.params.name}, {name: req.params.name, data: req.body}).setOptions({upsert: true}) .lean().exec(err => { if (err) return next(err); res.json({status: 'OK'}); }); }); router.delete('/model/file/:name', (req, res, next) => { if (!req.auth(res, ['dev', 'admin'], 'basic')) return; ModelFileModel.findOneAndDelete({name: req.params.name}).lean().exec((err, data) => { if (err) return next(err); if (data) { res.json({status: 'OK'}); } else { res.status(404).json({status: 'Not found'}); } }); }); router.get('/model/authorized/:url', (req, res, next) => { if (!req.auth(res, ['predict', 'read', 'write', 'dev', 'admin'], 'basic')) return; if (['dev', 'admin'].indexOf(req.authDetails.level) < 0) { // if not dev or admin, user has to possess model rights ModelModel.findOne({models: { $elemMatch: { url: decodeURIComponent(req.params.url), '_id': {$in: req.authDetails.models.map(e => mongoose.Types.ObjectId(e))} }}}).lean().exec((err, data) => { if (err) return next(err); if (data) { res.json({status: 'OK'}); } else { res.status(403).json({status: 'Forbidden'}); } }); } else { res.json({status: 'OK'}); } }); module.exports = router;