diff --git a/client/components/import/import.controller.js b/client/components/import/import.controller.js index 9f61d73..5995a96 100644 --- a/client/components/import/import.controller.js +++ b/client/components/import/import.controller.js @@ -1,28 +1,28 @@ 'use strict'; angular.module('manticoreApp') .controller('ImportCtrl', function ($scope, FileUploader, Auth) { var uploader = new FileUploader({ - url: '/upload', + url: '/api/documents/upload', removeAfterUpload: true, autoUpload: true, headers: { 'Authorization': 'Bearer ' + Auth.getToken() } }); uploader.filters.push({ name: 'sizeFilter', fn: function (item) { return item.size <= 10485760; // 10 Megabytes } }); uploader.filters.push({ name: 'typeFilter', fn: function (item) { return item.type === 'application/vnd.oasis.opendocument.text'; } }); $scope.uploader = uploader; }); diff --git a/server/api/document/document.controller.js b/server/api/document/document.controller.js index ddc16d7..cc4c1ba 100644 --- a/server/api/document/document.controller.js +++ b/server/api/document/document.controller.js @@ -1,68 +1,126 @@ /** * Using Rails-like standard naming convention for endpoints. * GET /documents -> index * POST /documents -> create * GET /documents/:id -> show * PUT /documents/:id -> update * DELETE /documents/:id -> destroy */ 'use strict'; var _ = require('lodash'); +var mongoose = require('mongoose'); +var Grid = require('gridfs-stream'); +var multer = require('multer'); + +var DocumentChunk = require('./document.model').DocumentChunk; var Document = require('./document.model').Document; +var gfs = Grid(mongoose.connection.db, mongoose.mongo); + // Get list of documents exports.index = function(req, res) { Document.find(function (err, documents) { if(err) { return handleError(res, err); } return res.json(200, documents); }); }; // Get a single document exports.show = function(req, res) { Document.findById(req.params.id, function (err, document) { if(err) { return handleError(res, err); } if(!document) { return res.send(404); } return res.json(document); }); }; +exports.upload = function (req, res, next) { + multer({ + upload: null, + limits: { + fileSize: 1024 * 1024 * 20, // 20 Megabytes + files: 5 + }, + onFileUploadStart: function (file) { + var firstChunk = new DocumentChunk(); + var newDocument = new Document({ + title: file.originalname, + creator: req.user._id, + chunks: [firstChunk._id] + }); + this.upload = gfs.createWriteStream({ + _id: mongoose.Types.ObjectId(firstChunk._id), + filename: file.originalname, + mode: 'w', + chunkSize: 1024 * 4, + content_type: file.mimetype, + root: 'fs' + }); + this.upload.on('finish', function () { + firstChunk.save(function (err) { + if (!err) { + newDocument.save(); + } + }); + }); + }, + onFileUploadData: function (file, data) { + this.upload.write(data); + }, + onFileUploadComplete: function (file) { + this.upload.end(); + } + })(req, res, next); +}; + +exports.acknowledgeUpload = function (req, res) { + return res.send(200); +}; + +exports.showFile = function(req, res) { + Document.findById(req.params.id, function (err, document) { + if (err) { return handleError(res, err); } + if (!document) { return res.send(404); } + DocumentChunks.findById(document.chunks[document.chunks.length - 1]); + }); +}; + // Creates a new document in the DB. exports.create = function(req, res) { Document.create(req.body, function(err, document) { if(err) { return handleError(res, err); } return res.json(201, document); }); }; // Updates an existing document in the DB. exports.update = function(req, res) { if(req.body._id) { delete req.body._id; } Document.findById(req.params.id, function (err, document) { if (err) { return handleError(res, err); } if(!document) { return res.send(404); } var updated = _.merge(document, req.body); updated.save(function (err) { if (err) { return handleError(res, err); } return res.json(200, document); }); }); }; // Deletes a document from the DB. exports.destroy = function(req, res) { Document.findById(req.params.id, function (err, document) { if(err) { return handleError(res, err); } if(!document) { return res.send(404); } document.remove(function(err) { if(err) { return handleError(res, err); } return res.send(204); }); }); }; function handleError(res, err) { return res.send(500, err); } diff --git a/server/api/document/document.spec.js b/server/api/document/document.spec.js index ee73d2c..aa7e5c6 100644 --- a/server/api/document/document.spec.js +++ b/server/api/document/document.spec.js @@ -1,20 +1,61 @@ 'use strict'; var should = require('should'); var app = require('../../app'); var request = require('supertest'); +var User = require('../user/user.model'); -describe('GET /api/documents', function() { +describe('/api/documents tests', function () { + var user = new User({ + provider: 'local', + name: 'Fake User', + email: 'test@test.com', + password: 'password' + }), + authorization, + agent; - it('should respond with JSON array', function(done) { - request(app) - .get('/api/documents') - .expect(200) - .expect('Content-Type', /json/) - .end(function(err, res) { - if (err) return done(err); - res.body.should.be.instanceof(Array); - done(); + function loginUser() { + return function(done) { + agent + .post('/auth/local') + .send({ email: 'test@test.com', password: 'password' }) + .expect(200) + .end(onResponse); + + function onResponse(err, res) { + if (err) return done(err); + authorization = 'Bearer ' + res.body.token; + return done(); + } + }; + } + + beforeEach(function (done) { + user.save(function () { + agent = request.agent(app); + loginUser()(done); + }); + }); + + afterEach(function (done) { + User.remove().exec().then(function () { + done(); + }); + }); + + describe('GET /api/documents', function() { + it('should respond with JSON array', function(done) { + agent + .get('/api/documents') + .set('Authorization', authorization) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + res.body.should.be.instanceof(Array); + done(); + }); }); - }); -}); + }); +}) diff --git a/server/api/document/index.js b/server/api/document/index.js index 50357f7..75ad489 100644 --- a/server/api/document/index.js +++ b/server/api/document/index.js @@ -1,15 +1,19 @@ 'use strict'; var express = require('express'); var controller = require('./document.controller'); +var auth = require('../../auth/auth.service'); var router = express.Router(); -router.get('/', controller.index); -router.get('/:id', controller.show); -router.post('/', controller.create); -router.put('/:id', controller.update); -router.patch('/:id', controller.update); -router.delete('/:id', controller.destroy); +router.get('/', auth.isAuthenticated(), controller.index); +router.get('/:id', auth.isAuthenticated(), controller.show); +router.post('/', auth.isAuthenticated(), controller.create); +router.put('/:id', auth.isAuthenticated(), controller.update); +router.patch('/:id', auth.isAuthenticated(), controller.update); +router.delete('/:id', auth.isAuthenticated(), controller.destroy); + +router.post('/upload', auth.isAuthenticated(), controller.upload, + controller.acknowledgeUpload); module.exports = router; diff --git a/server/api/upload/index.js b/server/api/upload/index.js deleted file mode 100644 index cfbbf50..0000000 --- a/server/api/upload/index.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; - -var express = require('express'); -var multer = require('multer'); -var _ = require('lodash'); -var Grid = require('gridfs-stream'); -var mongoose = require('mongoose'); - -var auth = require('../../auth/auth.service'); -var DocumentChunk = require('../document/document.model').DocumentChunk; -var Document = require('../document/document.model').Document; - -var gfs = Grid(mongoose.connection.db, mongoose.mongo); -var router = express.Router(); - -router.post('/', auth.isAuthenticated(), function (req, res, next) { - multer({ - upload: null, - limits: { - fileSize: 1024 * 1024 * 20, // 20 Megabytes - files: 5 - }, - onFileUploadStart: function (file) { - var firstChunk = new DocumentChunk(); - var newDocument = new Document({ - title: file.originalname, - creator: req.user._id, - chunks: [firstChunk._id] - }); - this.upload = gfs.createWriteStream({ - _id: mongoose.Types.ObjectId(firstChunk._id), - filename: file.originalname, - mode: 'w', - chunkSize: 1024 * 4, - content_type: file.mimetype, - root: 'fs' - }); - this.upload.on('finish', function () { - firstChunk.save(function (err) { - if (!err) { - newDocument.save(); - } - }); - }); - }, - onFileUploadData: function (file, data) { - this.upload.write(data); - }, - onFileUploadComplete: function (file) { - this.upload.end(); - } - })(req, res, next); -}, function (req, res) { - res.status(200).send("OK"); -}); - -module.exports = router; diff --git a/server/config/environment/test.js b/server/config/environment/test.js index 21969ea..14e4245 100644 --- a/server/config/environment/test.js +++ b/server/config/environment/test.js @@ -1,10 +1,10 @@ 'use strict'; // Test specific configuration // =========================== module.exports = { // MongoDB connection options mongo: { uri: 'mongodb://localhost/manticore-test' } -}; \ No newline at end of file +}; diff --git a/server/routes.js b/server/routes.js index 13db8a5..fd38254 100644 --- a/server/routes.js +++ b/server/routes.js @@ -1,27 +1,26 @@ /** * Main application routes */ 'use strict'; var errors = require('./components/errors'); module.exports = function(app) { // Insert routes below app.use('/api/documents', require('./api/document')); app.use('/api/users', require('./api/user')); - app.use('/upload', require('./api/upload')); app.use('/auth', require('./auth')); // All undefined asset or api routes should return a 404 app.route('/:url(api|auth|components|app|bower_components|assets)/*') .get(errors[404]); // All other routes should redirect to the index.html app.route('/*') .get(function(req, res) { res.sendfile(app.get('appPath') + '/index.html'); }); };