diff --git a/app/models/Upload.js b/app/models/Upload.js index 4b77826..3b43c6a 100644 --- a/app/models/Upload.js +++ b/app/models/Upload.js @@ -11,6 +11,7 @@ var UploadSchema = mongoose.Schema({ default: 0 }, uploader: String, + uploadKey: String, date: Date, file: Object }); diff --git a/app/routes/routes.js b/app/routes/routes.js index 5ff6175..fe75047 100644 --- a/app/routes/routes.js +++ b/app/routes/routes.js @@ -8,17 +8,40 @@ var login = require('./login.js'); var panel = require('./panel.js'); var keys = require('./keys.js'); -var fs = require('fs'); -var path = require('path'); +var Key = require('../models/Key.js'); -var requireLogin = function(req, res, next) { +var checkApiKey = function (key, cb) { + Key.find({key: key}, function (err, res) { + if (err) throw err; + cb(res.length === 1); + }); +}; + +var requireLogin = function (req, res, next) { if (!req.session || !req.session.passport) return res.redirect('/login'); else return next(); }; -module.exports = function(app) { +var requireLoginApi = function(req, res, next) { + if (!req.session || !req.session.passport) { + if (!req.body.apikey) { + return res.redirect('/login'); + } else { + checkApiKey(res.body.apikey, function(valid) { + if (!valid) + return res.sendStatus(401); + else + return next(); + }); + } + } else { + return next(); + } +}; + +module.exports = function (app) { app.use('/', index); app.use('/home', requireLogin, home); app.use('/v', view); @@ -30,7 +53,7 @@ module.exports = function(app) { app.use('/panel', requireLogin, panel); app.use('/panel*', requireLogin, panel); - app.use(function(err, req, res, next) { + app.use(function (err, req, res, next) { if (err.name === 'UnauthorizedError') { res.status(401); res.json({"message": err.name + ": " + err.message}); diff --git a/app/routes/upload.js b/app/routes/upload.js index b5138ff..7f6b8c3 100644 --- a/app/routes/upload.js +++ b/app/routes/upload.js @@ -4,6 +4,7 @@ var router = express.Router(); var mongoose = require('mongoose'); var User = require('../models/User.js'); var Upload = require('../models/Upload.js'); +var Key = require('../models/Key.js'); var multer = require('multer'); var dest = multer({dest: 'uploads/'}); @@ -14,12 +15,6 @@ function fileNameExists(name) { }); } -function updateUserStats(user, size) { - User.updateOne({username: user}, {$inc: {uploadCount: 1, uploadSize: size}}, function (err, res) { - if (err) throw err; - }); -} - function genFileName() { var charset = "abcdefghijklmnopqrstuvwxyz"; do { @@ -30,32 +25,90 @@ function genFileName() { return chars.join(''); } -router.post('/', dest.single('file'), function (req, res) { - // Size must be below 128 Megabytes (1024*1024*128 Bytes) - if (req.file.size >= 134217728) { - res.status(413).json({'message': 'File too large.'}); - return; +function updateStats(type, id, size) { + if (type === 'session') { + User.updateOne({username: id}, {$inc: {uploadCount: 1, uploadSize: size}}, function (err) { + if (err) throw err; + }); + } else if (type === 'apikey') { + Key.updateOne({key: id}, {$inc: {uploadCount: 1, uploadSize: size}}, function (err) { + if (err) throw err; + }); } +} - updateUserStats(req.session.passport.user, req.file.size); +var checkApiKey = function (key, cb) { + Key.find({key: key}, function (err, res) { + if (err) throw err; + cb(res.length === 1, res); + }); +}; - var entry = { - name: genFileName(), - uploader: req.session.passport.user, - created: Date.now(), - file: req.file - }; +var checkScope = function (type, id, perm, cb) { + if (type === 'session') { + User.findOne({username: id}, function (err, user) { + if (err) throw err; + cb(user.scope.indexOf(perm) !== -1); + }); + } else { + Key.findOne({key: id}, function (err, key) { + if (err) throw err; + cb(key.scope.indexOf(perm) !== -1); + }); + } +}; - Upload.create(entry, function (err, next) { - if (err) { - next(err); - } else { - res.send({ +function uploadFile(req, res, type, key) { + if (!req.file) + return res.status(400).json({'message': 'No file specified.'}); + + // Size must be below 128 Megabytes (1024*1024*128 Bytes) + if (req.file.size >= 134217728) + return res.status(413).json({'message': 'File too large.'}); + + var uploader = type === 'session' ? req.session.passport.user : key[0].username; + var uploadKey = type === 'apikey' ? key[0].key : null; + var id = type === 'session' ? req.session.passport.user : key[0].key; + + checkScope(type, id, 'file.upload', function (valid) { + if (!valid) + return res.status(403).json({'message': 'No permission.'}); + + var entry = { + name: genFileName(), + uploader: uploader, + uploadKey: uploadKey, + date: Date.now(), + file: req.file + }; + + updateStats(type, id, req.file.size); + + Upload.create(entry, function (err) { + if (err) throw err; + res.status(200).json({ name: entry.name, url: 'https://shimapan.rocks/v/' + entry.name }); - } + }); }); +} + +router.post('/', dest.single('file'), function (req, res) { + if (!req.session || !req.session.passport) { + if (!req.body.apikey) { + return res.sendStatus(401); + } else { + checkApiKey(req.body.apikey, function (valid, key) { + if (!valid) + return res.sendStatus(401); + else + uploadFile(req, res, 'apikey', key); + }); + } + } else { + uploadFile(req, res, 'session'); + } }); module.exports = router;