From 825190030920bf481cd547003da094e24880599d Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 11 Oct 2017 10:15:19 -0400 Subject: [PATCH] Work on stuff... --- .gitignore | 2 + app/models/User.js | 14 +++-- app/routes.js | 21 ++++++- app/routes/auth.js | 53 +++++++++++++++++ app/routes/register.js | 9 +++ app/routes/upload.js | 10 +++- app/routes/view.js | 3 +- config/passport.js | 29 ++++++++++ package.json | 5 +- public/css/splash.css | 7 +++ public/js/app.js | 2 +- public/js/components/RegisterComp.js | 16 ++++++ .../UploadCtrl.js => components/UploadComp.js} | 23 +++++--- public/js/services/AuthSvc.js | 66 ++++++++++++++++++++++ public/views/index.html | 23 ++------ public/views/register-form.html | 11 ++++ public/views/register.html | 24 ++++++++ public/views/upload-form.html | 21 +++++++ server.js | 10 +++- 19 files changed, 311 insertions(+), 38 deletions(-) create mode 100644 app/routes/auth.js create mode 100644 app/routes/register.js create mode 100644 config/passport.js create mode 100644 public/js/components/RegisterComp.js rename public/js/{controllers/UploadCtrl.js => components/UploadComp.js} (57%) create mode 100644 public/js/services/AuthSvc.js create mode 100644 public/views/register-form.html create mode 100644 public/views/register.html create mode 100644 public/views/upload-form.html diff --git a/.gitignore b/.gitignore index 829e1f4..694eb7d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,7 @@ public/libs/ .idea/ .awcache/ +uploads/ + package-lock.json jwt.pem diff --git a/app/models/User.js b/app/models/User.js index dc791f6..502fad7 100644 --- a/app/models/User.js +++ b/app/models/User.js @@ -23,16 +23,20 @@ var UserSchema = mongoose.Schema({ UserSchema.methods.setPassword = function(password) { this.salt = crypto.randomBytes(16).toString('hex'); - this.hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64).toString('hex'); + this.hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64, 'sha256').toString('hex'); }; UserSchema.methods.validatePassword = function(password) { - var hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64).toString('hex'); + var hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64, 'sha256').toString('hex'); return this.hash === hash; }; -UserSchema.methods.generateJwt = function() { - var expiry = Date.now(); +UserSchema.methods.genApiKey = function() { + this.apikey = crypto.randomBytes(16).toString('hex'); +}; + +UserSchema.methods.genJwt = function() { + var expiry = new Date(); expiry.setDate(expiry.getDate() + 7); var payload = { @@ -41,7 +45,7 @@ UserSchema.methods.generateJwt = function() { level: this.level }; - var key = fs.readFileSync(path.join(__dirname, '/jwt.pem'), 'utf8'); + var key = fs.readFileSync(path.join(__dirname, '../../jwt.pem'), 'utf8'); return jwt.sign(payload, key); }; diff --git a/app/routes.js b/app/routes.js index 8761469..9bc30f2 100644 --- a/app/routes.js +++ b/app/routes.js @@ -1,9 +1,28 @@ var index = require('./routes/index.js'); var upload = require('./routes/upload.js'); var view = require('./routes/view.js'); +var auth = require('./routes/auth.js'); +var register = require('./routes/register.js'); + +var fs = require('fs'); +var path = require('path'); +var jwt = require('express-jwt'); +var jwtauth = jwt({ + secret: fs.readFileSync(path.join(__dirname, '../jwt.pem'), 'utf8'), + userProperty: 'payload' +}); module.exports = function(app) { app.use('/', index); app.use('/v', view); app.use('/upload', upload); -}; + app.use('/api/auth', auth); + app.use('/register', register); + + app.use(function(err, req, res, next) { + if (err.name === 'UnauthorizedError') { + res.status(401); + res.json({"message": err.name + ": " + err.message}); + } + }) +}; \ No newline at end of file diff --git a/app/routes/auth.js b/app/routes/auth.js new file mode 100644 index 0000000..7455d03 --- /dev/null +++ b/app/routes/auth.js @@ -0,0 +1,53 @@ +var fs = require('fs'); +var path = require('path'); + +var express = require('express'); +var router = express.Router(); + +var mongoose = require('mongoose'); +var User = mongoose.model('User'); + +var passport = require('passport'); + +router.post('/register', function(req, res) { + console.log(req.body); + + var user = new User(); + user.username = req.body.username; + user.level = 0; + user.genApiKey(); + user.setPassword(req.body.password); + + user.save(function(err) { + var token; + token = user.genJwt(); + res.status(200); + res.json({ + "token": token + }); + }); + +}); + +router.post('/login', function(req, res) { + passport.authenticate('local', function(err, user, info) { + if (err) { + res.status(404).json(err); + return; + } + + var token; + if (user) { + token = user.genJwt(); + res.status(200); + res.json({ + "token": token + }); + } else { + res.status(401).json(info); + } + })(req, res); +}); + + +module.exports = router; \ No newline at end of file diff --git a/app/routes/register.js b/app/routes/register.js new file mode 100644 index 0000000..e04f90a --- /dev/null +++ b/app/routes/register.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); +var path = require('path'); + +router.get('/', function(req, res, next) { + res.sendFile(path.join(__dirname, '../../public/views', 'register.html')); +}); + +module.exports = router; \ No newline at end of file diff --git a/app/routes/upload.js b/app/routes/upload.js index ee0cd08..95cad37 100644 --- a/app/routes/upload.js +++ b/app/routes/upload.js @@ -1,8 +1,10 @@ var express = require('express'); -var multer = require('multer'); var router = express.Router(); +var mongoose = require('mongoose'); var Upload = require('../models/Upload.js'); + +var multer = require('multer'); var dest = multer({dest: 'uploads/'}); function fileNameExists(name) { @@ -22,6 +24,12 @@ function genFileName() { } router.post('/', dest.single('file'), function(req, res) { + //if (!req.payload._id) { + //console.log("Got unauthorized POST attempt"); + //res.status(401); + //return; + //} + var entry = { name: genFileName(), oname: req.file.originalname, diff --git a/app/routes/view.js b/app/routes/view.js index fe61505..f7adf1b 100644 --- a/app/routes/view.js +++ b/app/routes/view.js @@ -1,7 +1,8 @@ var express = require('express'); var router = express.Router(); var fs = require('fs'); -var Upload = require('../models/Upload.js'); +var mongoose = require('mongoose'); +var Upload = mongoose.model('Upload'); router.get('/:name', function(req, res, next) { console.log('GET: ', req.params); diff --git a/config/passport.js b/config/passport.js new file mode 100644 index 0000000..ffea42e --- /dev/null +++ b/config/passport.js @@ -0,0 +1,29 @@ +var passport = require('passport'); +var LocalStrategy = require('passport-local').Strategy; + +var mongoose = require('mongoose'); +var User = require('../app/models/User.js'); + +passport.use(new LocalStrategy({ + usernameField: 'username' + }, + function(username, password, done) { + User.findOne({username: username}, function(err, user) { + if (err) return done(err); + + if (!user) { + return done(null, false, { + message: 'Invalid username.' + }); + } + + if (!user.validatePassword(password)) { + return done(null, false, { + message: 'Invalid password.' + }); + } + + return done(null, user); + }); + } +)); \ No newline at end of file diff --git a/package.json b/package.json index 6afdd6d..6efd675 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,16 @@ "angular-messages": "^1.6.6", "body-parser": "^1.18.2", "express": "latest", + "express-jwt": "^5.3.0", "gulp": "latest", "jsonwebtoken": "^8.1.0", "jwt-sign": "^0.1.0", "method-override": "latest", "mongoose": "latest", "multer": "^1.3.0", - "ng-file-upload": "^12.2.13" + "ng-file-upload": "^12.2.13", + "passport": "^0.4.0", + "passport-local": "^1.0.0" }, "description": "A simple file sharing website.", "main": "index.js", diff --git a/public/css/splash.css b/public/css/splash.css index 521eea1..794211a 100644 --- a/public/css/splash.css +++ b/public/css/splash.css @@ -119,6 +119,13 @@ h1 { outline: none; } +.list-err { + font-family: 'Roboto Mono', monospace; + margin-left: auto; + color: #ff6666; + vertical-align: super; +} + nav > ul, diff --git a/public/js/app.js b/public/js/app.js index 4102a50..41ecedd 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1 +1 @@ -angular.module('shimapan', ['ngFileUpload', 'ngclipboard', 'UploadCtrl']); \ No newline at end of file +angular.module('shimapan', ['ngFileUpload', 'ngclipboard', 'UploadComp', 'RegisterComp']); \ No newline at end of file diff --git a/public/js/components/RegisterComp.js b/public/js/components/RegisterComp.js new file mode 100644 index 0000000..ffcc2eb --- /dev/null +++ b/public/js/components/RegisterComp.js @@ -0,0 +1,16 @@ +function RegisterController($scope, AuthService) { + $scope.register = function() { + AuthService.register({ + username: $scope.username, + password: $scope.password + }).then(function() { + alert('Registered'); + }); + }; +} + +angular.module('RegisterComp', ['AuthSvc']).component('registerComponent', { + templateUrl: '/views/register-form.html', + controller: RegisterController, + controllerAs: 'vm' +}); \ No newline at end of file diff --git a/public/js/controllers/UploadCtrl.js b/public/js/components/UploadComp.js similarity index 57% rename from public/js/controllers/UploadCtrl.js rename to public/js/components/UploadComp.js index 6d61e26..f487c36 100644 --- a/public/js/controllers/UploadCtrl.js +++ b/public/js/components/UploadComp.js @@ -1,11 +1,14 @@ -angular.module('UploadCtrl', ['ngFileUpload']).controller('UploadController', ['$scope', 'Upload', '$timeout', function ($scope, Upload, $timeout) { - $scope.uploadFiles = function (files, errorFiles) { - if (!$scope.files) - $scope.files = files; +function UploadController($scope, Upload, $timeout) { + $scope.errToString = function(err) { + if (err === 'maxSize') + return "File too large."; else - $scope.files = $scope.files.concat(files); + return err; + }; - $scope.errorFiles = errorFiles; + $scope.uploadFiles = function(files, errorFiles) { + $scope.files = $scope.files ? $scope.files.concat(files) : files; + $scope.errorFiles = $scope.errorFiles ? $scope.errorFiles.concat(errorFiles) : errorFiles; angular.forEach(files, function (file) { file.upload = Upload.upload({ @@ -31,4 +34,10 @@ angular.module('UploadCtrl', ['ngFileUpload']).controller('UploadController', [' ); }); }; -}]); \ No newline at end of file +} + +angular.module('UploadComp', ['ngFileUpload']).component('uploadComponent', { + templateUrl: '/views/upload-form.html', + controller: UploadController, + controllerAs: 'vm' +}); diff --git a/public/js/services/AuthSvc.js b/public/js/services/AuthSvc.js new file mode 100644 index 0000000..135f7f5 --- /dev/null +++ b/public/js/services/AuthSvc.js @@ -0,0 +1,66 @@ +angular.module('AuthSvc', []).service('AuthService', ['$http', '$window', function($http, $window) { + function decodeToken(token) { + if (token) { + var payload = token.split('.')[1]; + payload = $window.atob(payload); + payload = JSON.parse(payload); + return payload; + } else { + return {}; + } + } + + function saveToken(token) { + $window.localStorage['shimapan-token'] = token; + } + + function getToken() { + return $window.localStorage['shimapan-token']; + } + + this.login = function(user) { + return $http({ + method: 'POST', + url: '/api/auth/login', + headers: {'Content-Type': 'x-www-form-urlencoded'}, + transformRequest: function(obj) { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + return str.join("&"); + }, + data: user + }).then(function(res) { + saveToken(res.data.token); + }) + }; + this.logout = function() { + $window.localStorage.removeItem('shimapan-token'); + }; + this.isLoggedIn = function() { + var payload = decodeToken(getToken()); + return payload.exp > Date.now() / 1000; + }; + + this.register = function(user) { + return $http({ + method: 'POST', + url: '/api/auth/register', + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + transformRequest: function(obj) { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + return str.join("&"); + }, + data: user + }).then(function(res) { + saveToken(res.data.token); + }); + }; + + this.currentUser = function() { + var payload = decodeToken(getToken()); + return payload.username; + }; +}]); diff --git a/public/views/index.html b/public/views/index.html index a3b5ce8..fc7dda8 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -14,30 +14,15 @@ - + + +

Shimapan~

-
-
- -
- -
+