Explorar el Código

Merged dev into master

Pitu hace 8 años
padre
commit
6b7fd3bcf4

+ 2 - 1
.gitignore

@@ -3,4 +3,5 @@ uploads/
 logs/
 database/db
 config.js
-start.json
+start.json
+npm-debug.log

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Pitu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 21 - 9
README.md


+ 3 - 0
config.sample.js

@@ -9,6 +9,9 @@ module.exports = {
 	*/
 	private: true,
 	
+	// If true, users will be able to create accounts and access their uploaded files
+	enableUserAccounts: true,
+	
 	// The registered domain where you will be serving the app. Use IP if none.
 	domains: [
 

+ 78 - 55
controllers/albumsController.js

@@ -5,93 +5,116 @@ let albumsController = {}
 
 albumsController.list = function(req, res, next){
 	
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-	let fields = ['id', 'name']
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'})
 
-	if(req.params.sidebar === undefined)
-		fields.push('timestamp')
-	
-	db.table('albums').select(fields).where('enabled', 1).then((albums) => {
+		let fields = ['id', 'name']
+
+		if(req.params.sidebar === undefined)
+			fields.push('timestamp')
 		
-		if(req.params.sidebar !== undefined)
-			return res.json({ success: true, albums })
+		db.table('albums').select(fields).where({enabled: 1, userid: user[0].id}).then((albums) => {
+			
+			if(req.params.sidebar !== undefined)
+				return res.json({ success: true, albums })
 
-		let ids = []
-		for(let album of albums){
-			album.date = new Date(album.timestamp * 1000)
-			album.date = album.date.getFullYear() + '-' + (album.date.getMonth() + 1) + '-' + album.date.getDate() + ' ' + (album.date.getHours() < 10 ? '0' : '') + album.date.getHours() + ':' + (album.date.getMinutes() < 10 ? '0' : '') + album.date.getMinutes() + ':' + (album.date.getSeconds() < 10 ? '0' : '') + album.date.getSeconds()
+			let ids = []
+			for(let album of albums){
+				album.date = new Date(album.timestamp * 1000)
+				album.date = album.date.getFullYear() + '-' + (album.date.getMonth() + 1) + '-' + album.date.getDate() + ' ' + (album.date.getHours() < 10 ? '0' : '') + album.date.getHours() + ':' + (album.date.getMinutes() < 10 ? '0' : '') + album.date.getMinutes() + ':' + (album.date.getSeconds() < 10 ? '0' : '') + album.date.getSeconds()
 
-			ids.push(album.id)
-		}
+				ids.push(album.id)
+			}
 
-		db.table('files').whereIn('albumid', ids).select('albumid').then((files) => {
+			db.table('files').whereIn('albumid', ids).select('albumid').then((files) => {
 
-			let albumsCount = {}
-			
-			for(let id of ids)  albumsCount[id] = 0
-			for(let file of files) albumsCount[file.albumid] += 1
-			for(let album of albums) album.files = albumsCount[album.id]
+				let albumsCount = {}
+				
+				for(let id of ids)  albumsCount[id] = 0
+				for(let file of files) albumsCount[file.albumid] += 1
+				for(let album of albums) album.files = albumsCount[album.id]
 
-			return res.json({ success: true, albums })
+				return res.json({ success: true, albums })
+			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 		}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+
 }
 
 albumsController.create = function(req, res, next){
 	
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-	let name = req.body.name
-	if(name === undefined || name === '')
-		return res.json({ success: false, description: 'No album name specified' })	
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'})
 
-	db.table('albums').where('name', name).where('enabled', 1).then((album) => {
-		if(album.length !== 0) return res.json({ success: false, description: 'There\'s already an album with that name' })	
+		let name = req.body.name
+		if(name === undefined || name === '')
+			return res.json({ success: false, description: 'No album name specified' })	
 
-		db.table('albums').insert({ 
-			name: name, 
+		db.table('albums').where({
+			name: name,
 			enabled: 1,
-			timestamp: Math.floor(Date.now() / 1000) 
-		}).then(() => {
-			return res.json({ success: true })	
-		})
+			userid: user[0].id
+		}).then((album) => {
+			if(album.length !== 0) return res.json({ success: false, description: 'There\'s already an album with that name' })	
+
+			db.table('albums').insert({ 
+				name: name, 
+				enabled: 1,
+				userid: user[0].id,
+				timestamp: Math.floor(Date.now() / 1000) 
+			}).then(() => {
+				return res.json({ success: true })	
+			})
+		}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+
+	
 }
 
 albumsController.delete = function(req, res, next){
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-	let id = req.body.id
-	if(id === undefined || id === '')
-		return res.json({ success: false, description: 'No album specified' })
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'})
 
-	db.table('albums').where('id', id).update({ enabled: 0 }).then(() => {
-		return res.json({ success: true })	
+		let id = req.body.id
+		if(id === undefined || id === '')
+			return res.json({ success: false, description: 'No album specified' })
+
+		db.table('albums').where({id: id, userid: user[0].id}).update({ enabled: 0 }).then(() => {
+			return res.json({ success: true })	
+		}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 }
 
 albumsController.rename = function(req, res, next){
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-	let id = req.body.id
-	if(id === undefined || id === '')
-		return res.json({ success: false, description: 'No album specified' })
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'})
 
-	let name = req.body.name
-	if(name === undefined || name === '')
-		return res.json({ success: false, description: 'No name specified' })
+		let id = req.body.id
+		if(id === undefined || id === '')
+			return res.json({ success: false, description: 'No album specified' })
 
-	db.table('albums').where('name', name).then((results) => {
-		if(results.length !== 0)
-			return res.json({ success: false, description: 'Name already in use' })
+		let name = req.body.name
+		if(name === undefined || name === '')
+			return res.json({ success: false, description: 'No name specified' })
 
-		db.table('albums').where('id', id).update({ name: name }).then(() => {
-			return res.json({ success: true })	
+		db.table('albums').where({name: name, userid: user[0].id}).then((results) => {
+			if(results.length !== 0) return res.json({ success: false, description: 'Name already in use' })
+
+			db.table('albums').where({id: id, userid: user[0].id}).update({ name: name }).then(() => {
+				return res.json({ success: true })	
+			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 		}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 

+ 89 - 0
controllers/authController.js

@@ -0,0 +1,89 @@
+const config = require('../config.js')
+const db = require('knex')(config.database)
+const bcrypt = require('bcrypt')
+const saltRounds = 10
+const randomstring = require('randomstring')
+
+let authController = {}
+
+authController.verify = function(req, res, next){
+	
+	let username = req.body.username
+	let password = req.body.password
+
+	if(username === undefined) return res.json({ success: false, description: 'No username provided' })
+	if(password === undefined) return res.json({ success: false, description: 'No password provided' })
+
+	db.table('users').where('username', username).then((user) => {
+		if(user.length === 0) return res.json({ success: false, description: 'Username doesn\'t exist' })
+
+		bcrypt.compare(password, user[0].password, function(err, result) {
+			if(result === false) return res.json({ success: false, description: 'Wrong password' })
+			return res.json({ success: true, token: user[0].token })
+		})
+	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+
+}
+
+authController.register = function(req, res, next){
+
+	if(config.enableUserAccounts === false) 
+		return res.json({ success: false, description: 'Register is disabled at the moment' })
+
+	let username = req.body.username
+	let password = req.body.password
+
+	if(username === undefined) return res.json({ success: false, description: 'No username provided' })
+	if(password === undefined) return res.json({ success: false, description: 'No password provided' })
+
+	if(username.length < 4 || username.length > 32)
+		return res.json({ success: false, description: 'Username must have 6-32 characters' })
+	if(password.length < 6 || password.length > 64)
+		return res.json({ success: false, description: 'Password must have 6-64 characters' })
+
+	db.table('users').where('username', username).then((user) => {
+		if(user.length !== 0) return res.json({ success: false, description: 'Username already exists' })
+
+		bcrypt.hash(password, saltRounds, function(err, hash) {
+			if(err) return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' })
+
+			let token = randomstring.generate(64)
+
+			db.table('users').insert({
+				username: username,
+				password: hash,
+				token: token
+			}).then(() => {
+				return res.json({ success: true, token: token})
+			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+		})
+
+	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+
+}
+
+authController.changePassword = function(req, res, next){
+
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
+
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'})
+		
+		let password = req.body.password
+		if(password === undefined) return res.json({ success: false, description: 'No password provided' })
+		if(password.length < 6 || password.length > 64)
+			return res.json({ success: false, description: 'Password must have 6-64 characters' })
+
+		bcrypt.hash(password, saltRounds, function(err, hash) {
+			if(err) return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' })
+
+			db.table('users').where('id', user[0].id).update({password: hash}).then(() => {
+				return res.json({ success: true})
+			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+		})
+	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+
+}
+
+module.exports = authController

+ 25 - 38
controllers/tokenController.js

@@ -1,60 +1,47 @@
 const config = require('../config.js')
 const db = require('knex')(config.database)
+const randomstring = require('randomstring')
 
 let tokenController = {}
 
 tokenController.verify = function(req, res, next){
-	let type = req.body.type
-	let token = req.body.token
-
-	if(type === undefined) return res.json({ success: false, description: 'No type provided.' })
-	if(token === undefined) return res.json({ success: false, description: 'No token provided.' })
-	if(type !== 'client' && type !== 'admin') return res.json({ success: false, description: 'Wrong type provided.' })
 
-	if(type === 'client'){
-		if(token !== config.clientToken) return res.json({ success: false, description: 'Token mismatch.' })
-		return res.json({ success: true })
-	}
+	if(req.body.token === undefined) return res.json({ success: false, description: 'No token provided' })
+	let token = req.body.token
 
-	if(type === 'admin'){
-		if(token !== config.adminToken) return res.json({ success: false, description: 'Token mismatch.' })
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.json({ success: false, description: 'Token mismatch' })
 		return res.json({ success: true })
-	}
-
-	return res.json({ success: false, description: '(╯°□°)╯︵ ┻━┻' })
+	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+	
 }
 
 tokenController.list = function(req, res, next){
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
 
-	return res.json({
-		clientToken: config.clientToken,
-		adminToken: config.adminToken
-	})
-}
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-tokenController.change = function(req, res, next){
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.json({ success: false, description: 'Token mismatch' })
+		return res.json({ success: true, token: token })
+	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 
-	let type = req.body.type
-	let token = req.body.token
+}
 
-	if(type === undefined) return res.json({ success: false, description: 'No type provided.' })
-	if(token === undefined) return res.json({ success: false, description: 'No token provided.' })
-	if(type !== 'client' && type !== 'admin') return res.json({ success: false, description: 'Wrong type provided.' })
+tokenController.change = function(req, res, next){
 
-	db.table('tokens').where('name', type).update({ value: token, timestamp: Math.floor(Date.now() / 1000) })
-	.then(() => {
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-		if(type === 'client')
-			config.clientToken = token
-		else if(type === 'admin')
-			config.adminToken = token
-		
-		res.json({ success: true }) 
+	let newtoken = randomstring.generate(64)
+	
+	db.table('users').where('token', token).update({
+		token: newtoken,
+		timestamp:  Math.floor(Date.now() / 1000)
+	}).then(() => {
+		res.json({ success: true, token: newtoken })
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+	
 }
 
 module.exports = tokenController

+ 168 - 141
controllers/uploadController.js

@@ -25,81 +25,92 @@ const upload = multer({
 
 uploadsController.upload = function(req, res, next){
 
+	// Get the token
+	let token = req.headers.token
+
+	// If we're running in private and there's no token, error
 	if(config.private === true)
-		if(req.headers.auth !== config.clientToken)
-			return res.status(401).json({ success: false, description: 'not-authorized'})
+		if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-	let album = req.params.albumid
-	
-	if(album !== undefined)
-		if(req.headers.adminauth !== config.adminToken)
-			return res.status(401).json({ success: false, description: 'not-authorized'})
+	// If there is no token then just leave it blank so the query fails
+	if(token === undefined) token = ''
 	
-	upload(req, res, function (err) {
-		if (err) {
-			console.error(err)
-			return res.json({ 
-				success: false,
-				description: err
-			})
+	db.table('users').where('token', token).then((user) => {
+		let userid
+		if(user.length > 0)
+			userid = user[0].id
+
+		// Check if user is trying to upload to an album
+		let album = undefined
+		if(userid !== undefined){
+			album = req.headers.albumid
+			if(album === undefined)
+				album = req.params.albumid
 		}
 
-		if(req.files.length === 0) return res.json({ success: false, description: 'no-files' })
-
-		let files = []
-		let existingFiles = []
-		let iteration = 1
+		upload(req, res, function (err) {
+			if (err) {
+				console.error(err)
+				return res.json({ 
+					success: false,
+					description: err
+				})
+			}
 
-		req.files.forEach(function(file) {
+			if(req.files.length === 0) return res.json({ success: false, description: 'no-files' })
 
-			// Check if the file exists by checking hash and size
-			let hash = crypto.createHash('md5')
-			let stream = fs.createReadStream('./' + config.uploads.folder + '/' + file.filename)
+			let files = []
+			let existingFiles = []
+			let iteration = 1
 
-			stream.on('data', function (data) {
-				hash.update(data, 'utf8')
-			})
+			req.files.forEach(function(file) {
 
-			stream.on('end', function () {
-				let fileHash = hash.digest('hex') // 34f7a3113803f8ed3b8fd7ce5656ebec
-
-				db.table('files').where({
-					hash: fileHash,
-					size: file.size
-				}).then((dbfile) => {
-
-					if(dbfile.length !== 0){
-						uploadsController.deleteFile(file.filename).then(() => {}).catch((e) => console.error(e))
-						existingFiles.push(dbfile[0])
-					}else{
-						files.push({
-							name: file.filename, 
-							original: file.originalname,
-							type: file.mimetype,
-							size: file.size, 
-							hash: fileHash,
-							ip: req.ip,
-							albumid: album,
-							timestamp: Math.floor(Date.now() / 1000)
-						})
-					}
+				// Check if the file exists by checking hash and size
+				let hash = crypto.createHash('md5')
+				let stream = fs.createReadStream('./' + config.uploads.folder + '/' + file.filename)
 
-					if(iteration === req.files.length)
-						return uploadsController.processFilesForDisplay(req, res, files, existingFiles)
-					iteration++
+				stream.on('data', function (data) {
+					hash.update(data, 'utf8')
 				})
 
-			})
-
-		})
+				stream.on('end', function () {
+					let fileHash = hash.digest('hex') // 34f7a3113803f8ed3b8fd7ce5656ebec
+
+					db.table('files').where({
+						hash: fileHash,
+						size: file.size
+					}).then((dbfile) => {
+
+						if(dbfile.length !== 0){
+							uploadsController.deleteFile(file.filename).then(() => {}).catch((e) => console.error(e))
+							existingFiles.push(dbfile[0])
+						}else{
+							files.push({
+								name: file.filename, 
+								original: file.originalname,
+								type: file.mimetype,
+								size: file.size, 
+								hash: fileHash,
+								ip: req.ip,
+								albumid: album,
+								userid: userid,
+								timestamp: Math.floor(Date.now() / 1000)
+							})
+						}
 
-	})
+						if(iteration === req.files.length)
+							return uploadsController.processFilesForDisplay(req, res, files, existingFiles)
+						iteration++
 
+					}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+				})
+			})
+		})
+	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 }
 
 uploadsController.processFilesForDisplay = function(req, res, files, existingFiles){
 
-
 	let basedomain = req.get('host')
 	for(let domain of config.domains)
 		if(domain.host === req.get('host'))
@@ -139,28 +150,38 @@ uploadsController.processFilesForDisplay = function(req, res, files, existingFil
 
 uploadsController.delete = function(req, res){
 
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
 	let id = req.body.id
 	if(id === undefined || id === '')
 		return res.json({ success: false, description: 'No file specified' })
 
-	db.table('files').where('id', id).then((file) => {
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'})
 
-		uploadsController.deleteFile(file[0].name).then(() => {
-			db.table('files').where('id', id).del().then(() =>{
-				return res.json({ success: true })
-			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
-		}).catch((e) => {
-			console.log(e.toString())
-			db.table('files').where('id', id).del().then(() =>{
-				return res.json({ success: true })
-			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+		db.table('files')
+		.where('id', id)
+		.where(function(){
+			if(user[0].username !== 'root')
+				this.where('userid', user[0].id)
 		})
+		.then((file) => {
+
+			uploadsController.deleteFile(file[0].name).then(() => {
+				db.table('files').where('id', id).del().then(() =>{
+					return res.json({ success: true })
+				}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+			}).catch((e) => {
+				console.log(e.toString())
+				db.table('files').where('id', id).del().then(() =>{
+					return res.json({ success: true })
+				}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+			})
 
+		}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
-	
+
 }
 
 uploadsController.deleteFile = function(file){
@@ -179,86 +200,92 @@ uploadsController.deleteFile = function(file){
 
 uploadsController.list = function(req, res){
 
-	if(req.headers.auth !== config.adminToken)
-		return res.status(401).json({ success: false, description: 'not-authorized'})
+	let token = req.headers.token
+	if(token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
 
-	let offset = req.params.page
-	if(offset === undefined) offset = 0
+	db.table('users').where('token', token).then((user) => {
+		if(user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'})
 
-	db.table('files')
-	.where(function(){
-		if(req.params.id === undefined)
-			this.where('id', '<>', '')
-		else
-			this.where('albumid', req.params.id)
-	})
-	.orderBy('id', 'DESC')
-	.limit(25)
-	.offset(25 * offset)
-	.then((files) => {
-		db.table('albums').then((albums) => {
-
-			let basedomain = req.get('host')
-			for(let domain of config.domains)
-				if(domain.host === req.get('host'))
-					if(domain.hasOwnProperty('resolve'))
-						basedomain = domain.resolve
-
-			for(let file of files){
-				file.file = basedomain + '/' + file.name
-				file.date = new Date(file.timestamp * 1000)
-				file.date = file.date.getFullYear() + '-' + (file.date.getMonth() + 1) + '-' + file.date.getDate() + ' ' + (file.date.getHours() < 10 ? '0' : '') + file.date.getHours() + ':' + (file.date.getMinutes() < 10 ? '0' : '') + file.date.getMinutes() + ':' + (file.date.getSeconds() < 10 ? '0' : '') + file.date.getSeconds()
-
-				file.album = ''
-				
-				if(file.albumid !== undefined)
-					for(let album of albums)
-						if(file.albumid === album.id)
-							file.album = album.name
-
-				if(config.uploads.generateThumbnails === true){
-
-					let extensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png']
-					for(let ext of extensions){
-						if(path.extname(file.name) === ext){
-
-							file.thumb = basedomain + '/thumbs/' + file.name.slice(0, -4) + '.png'
-
-							let thumbname = path.join(__dirname, '..', 'uploads', 'thumbs') + '/' + file.name.slice(0, -4) + '.png'
-							fs.access(thumbname, function(err) {
-								if (err && err.code === 'ENOENT') {
-									// File doesnt exist
-
-									let size = {
-										width: 200, 
-										height: 200
-									}
+		let offset = req.params.page
+		if(offset === undefined) offset = 0
 
-									gm('./' + config.uploads.folder + '/' + file.name)
-										.resize(size.width, size.height + '>')
-										.gravity('Center')
-										.extent(size.width, size.height)
-										.background('transparent')
-										.write(thumbname, function (error) {
-											if (error) console.log('Error - ', error)
-										})
-								}
-							})
+		db.table('files')
+		.where(function(){
+			if(req.params.id === undefined)
+				this.where('id', '<>', '')
+			else
+				this.where('albumid', req.params.id)
+		})
+		.where(function(){
+			if(user[0].username !== 'root')
+				this.where('userid', user[0].id)
+		})
+		.orderBy('id', 'DESC')
+		.limit(25)
+		.offset(25 * offset)
+		.then((files) => {
+			db.table('albums').then((albums) => {
+
+				let basedomain = req.get('host')
+				for(let domain of config.domains)
+					if(domain.host === req.get('host'))
+						if(domain.hasOwnProperty('resolve'))
+							basedomain = domain.resolve
+
+				for(let file of files){
+					file.file = basedomain + '/' + file.name
+					file.date = new Date(file.timestamp * 1000)
+					file.date = file.date.getFullYear() + '-' + (file.date.getMonth() + 1) + '-' + file.date.getDate() + ' ' + (file.date.getHours() < 10 ? '0' : '') + file.date.getHours() + ':' + (file.date.getMinutes() < 10 ? '0' : '') + file.date.getMinutes() + ':' + (file.date.getSeconds() < 10 ? '0' : '') + file.date.getSeconds()
+
+					file.album = ''
+					
+					if(file.albumid !== undefined)
+						for(let album of albums)
+							if(file.albumid === album.id)
+								file.album = album.name
+
+					if(config.uploads.generateThumbnails === true){
+
+						let extensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png']
+						for(let ext of extensions){
+							if(path.extname(file.name) === ext){
+
+								file.thumb = basedomain + '/thumbs/' + file.name.slice(0, -4) + '.png'
+
+								let thumbname = path.join(__dirname, '..', 'uploads', 'thumbs') + '/' + file.name.slice(0, -4) + '.png'
+								fs.access(thumbname, function(err) {
+									if (err && err.code === 'ENOENT') {
+										// File doesnt exist
+
+										let size = {
+											width: 200, 
+											height: 200
+										}
+
+										gm('./' + config.uploads.folder + '/' + file.name)
+											.resize(size.width, size.height + '>')
+											.gravity('Center')
+											.extent(size.width, size.height)
+											.background('transparent')
+											.write(thumbname, function (error) {
+												if (error) console.log('Error - ', error)
+											})
+									}
+								})
+							}
 						}
 					}
-
 				}
-				
 
-			}
-
-			return res.json({
-				success: true,
-				files
-			})
+				return res.json({
+					success: true,
+					files
+				})
 
+			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 		}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
-	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
+
+	})	
 }
 
 module.exports = uploadsController

+ 22 - 41
database/db.js

@@ -1,9 +1,9 @@
-
-let init = function(db, config){
+let init = function(db){
 
 	// Create the tables we need to store galleries and files
 	db.schema.createTableIfNotExists('albums', function (table) {
 		table.increments()
+		table.integer('userid')
 		table.string('name')
 		table.integer('enabled')
 		table.integer('timestamp')
@@ -11,6 +11,7 @@ let init = function(db, config){
 
 	db.schema.createTableIfNotExists('files', function (table) {
 		table.increments()
+		table.integer('userid')
 		table.string('name')
 		table.string('original')
 		table.string('type')
@@ -21,48 +22,28 @@ let init = function(db, config){
 		table.integer('timestamp')
 	}).then(() => {})
 
-	db.schema.createTableIfNotExists('tokens', function (table) {
-		table.string('name')
-		table.string('value')
+	db.schema.createTableIfNotExists('users', function (table) {
+		table.increments()
+		table.string('username')
+		table.string('password')
+		table.string('token')
 		table.integer('timestamp')
 	}).then(() => {
-
-		// == Generate a 1 time token == //
-		db.table('tokens').then((tokens) => {
-			if(tokens.length !== 0) return printAndSave(config, tokens[0].value, tokens[1].value)
-
-			// This is the first launch of the app
-			let clientToken = require('randomstring').generate()
-			let adminToken = require('randomstring').generate()
-			let now = Math.floor(Date.now() / 1000)
-
-			db.table('tokens').insert(
-				[
-					{ 
-						name: 'client', 
-						value: clientToken,
-						timestamp: now
-					},
-					{ 
-						name: 'admin', 
-						value: adminToken,
-						timestamp: now
-					}
-				]
-			).then(() => {
-				printAndSave(config, clientToken, adminToken)
-			}).catch(function(error) { console.log(error) })
-		}).catch(function(error) { console.log(error) })
-
+		db.table('users').where({username: 'root'}).then((user) => {
+			if(user.length > 0) return
+
+			require('bcrypt').hash('root', 10, function(err, hash) {
+				if(err) console.error('Error generating password hash for root')
+
+				db.table('users').insert({
+					username: 'root',
+					password: hash,
+					token: require('randomstring').generate(64),
+					timestamp: Math.floor(Date.now() / 1000)
+				}).then(() => {})
+			})
+		})
 	})
-
-}
-
-function printAndSave(config, clientToken, adminToken){
-	console.log('Your client token is: ' + clientToken)
-	console.log('Your admin token is: ' + adminToken)
-	config.clientToken = clientToken
-	config.adminToken = adminToken
 }
 
 module.exports = init

+ 2 - 1
lolisafe.js

@@ -6,7 +6,7 @@ const db = require('knex')(config.database)
 const fs = require('fs')
 const safe = express()
 
-require('./database/db.js')(db, config)
+require('./database/db.js')(db)
 
 fs.existsSync('./' + config.logsFolder) || fs.mkdirSync('./' + config.logsFolder)
 fs.existsSync('./' + config.uploads.folder) || fs.mkdirSync('./' + config.uploads.folder)
@@ -22,6 +22,7 @@ safe.use('/', express.static('./public'))
 safe.use('/api', api)
 
 safe.get('/', (req, res, next) => res.sendFile('home.html', { root: './pages/' }))
+safe.get('/auth', (req, res, next) => res.sendFile('auth.html', { root: './pages/' }))
 safe.get('/panel', (req, res, next) => res.sendFile('panel.html', { root: './pages/' }))
 safe.use((req, res, next) => res.status(404).sendFile('404.html', { root: './pages/error/' }))
 safe.use((req, res, next) => res.status(500).sendFile('500.html', { root: './pages/error/' }))

+ 2 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "loli-safe",
-  "version": "1.0.0",
+  "version": "2.0.0",
   "description": "Pomf-like uploading service, written in node",
   "author": "kanadeko",
   "repository": {
@@ -15,6 +15,7 @@
   },
   "license": "MIT",
   "dependencies": {
+    "bcrypt": "^1.0.2",
     "body-parser": "^1.16.0",
     "express": "^4.14.0",
     "gm": "^1.23.0",

+ 57 - 0
pages/auth.html

@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>loli-safe - A self hosted upload service</title>
+        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.3.0/css/bulma.min.css">
+        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
+        <link rel="stylesheet" type="text/css" href="/css/style.css">
+        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
+        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
+        <script type="text/javascript" src="https://use.fontawesome.com/cd26baa9bd.js"></script>
+        <script type="text/javascript" src="/js/auth.js"></script>
+    </head>
+    <body>
+
+        <style type="text/css">
+            section#login {
+                background-color: #f5f6f8;
+            }
+        </style>
+
+        <section id='login' class="hero is-fullheight">
+            <div class="hero-body">
+                <div class="container">
+                    <h1 class="title">
+                        Dashboard Access
+                    </h1>
+                    <h2 class="subtitle">
+                        Login or register
+                    </h2>
+                    <div class="columns">
+                        <div class="column">
+                            <p class="control">
+                                <input id='user' class="input" type="text" placeholder="Your username">
+                            </p>
+                            <p class="control">
+                                <input id='pass' class="input" type="password" placeholder="Your password">
+                            </p>
+                            
+                            <p class="control has-addons is-pulled-right">
+                                <a class="button" id='registerBtn' onclick="page.do('register')">
+                                    <span>Register</span>
+                                </a>
+                                <a class="button" id='loginBtn' onclick="page.do('login')">
+                                    <span>Log in</span>
+                                </a>
+                            </p>
+
+                        </div>
+                        <div class="column is-hidden-mobile"></div>
+                        <div class="column is-hidden-mobile"></div>
+                    </div>
+                </div>
+            </div>
+        </section>
+
+    </body>
+</html>

+ 3 - 3
pages/home.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
     <head>
-        <title>loli-safe - A self hosted upload service</title>
+        <title>loli-safe - A small safe worth protecting.</title>
         <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.3.0/css/bulma.min.css">
         <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
         <link rel="stylesheet" type="text/css" href="/css/style.css">
@@ -27,7 +27,7 @@
                         <div class="column" id='uploadContainer'>
 
                             <p id='tokenContainer' class="control has-addons has-addons-centered">
-                                <input id='token' class="input is-danger" type="text" placeholder="Your upload token">
+                                <input id='token' class="input is-danger" type="text" placeholder="Your token">
                                 <a id='tokenSubmit' class="button is-danger">Check</a>
                             </p>
 
@@ -48,7 +48,7 @@
                     </div>
                     
                     <h3 id="links">
-                        <a href="https://github.com/kanadeko/loli-safe" target="_blank" class="is-danger">View on Github</a><span>|</span><a href="https://chrome.google.com/webstore/detail/loli-safe-uploader/enkkmplljfjppcdaancckgilmgoiofnj" target="_blank" class="is-danger">Chrome extension</a><span>|</span><a href="/panel" target="_blank" class="is-danger">Dashboard</a>
+                        <a href="https://github.com/kanadeko/loli-safe" target="_blank" class="is-danger">View on Github</a><span>|</span><a href="https://chrome.google.com/webstore/detail/loli-safe-uploader/enkkmplljfjppcdaancckgilmgoiofnj" target="_blank" class="is-danger">Chrome extension</a><span>|</span><a href="/auth" target="_blank" class="is-danger">Manage your uploads</a>
                     </h3>
 
                 </div>

+ 1 - 1
pages/panel.html

@@ -53,7 +53,7 @@
                             </ul>
                             <p class="menu-label">Administration</p>
                             <ul class="menu-list">
-                                <li><a id="itemTokens" onclick="panel.changeTokens()">Change your tokens</a></li>
+                                <li><a id="itemTokens" onclick="panel.changeTokens()">Change your token</a></li>
                                 <li><a onclick="panel.logout()">Logout</a></li>
                             </ul>
                         </aside>

+ 13 - 0
public/css/style.css

@@ -78,6 +78,19 @@ section#home div#uploads { margin-bottom: 25px; }
 		PANEL
 ------------------ */
 
+section#login input, section#login p.control a.button {
+	border-left: 0px;
+    border-top: 0px;
+    border-right: 0px;
+    border-radius: 0px;
+    box-shadow: 0 0 0;
+}
+
+section#login p.control a.button { margin-left: 10px; }
+section#login p.control a#loginBtn { border-right: 0px; }
+section#login p.control a#registerBtn { border-left: 0px; }
+
+
 section#auth, section#dashboard { display: none }
 section#auth input { background: rgba(0, 0, 0, 0); }
 section#auth input, section#auth a {

+ 56 - 0
public/js/auth.js

@@ -0,0 +1,56 @@
+var page = {};
+
+page.do = function(dest){
+
+	var user = document.getElementById('user').value;
+	var pass = document.getElementById('pass').value;
+
+	if(user === undefined || user === null || user === '')
+		return swal('Error', 'You need to specify a username', 'error');
+	if(pass === undefined || pass === null || pass === '')
+		return swal('Error', 'You need to specify a username', 'error');
+
+	axios.post('/api/' + dest, {
+		username: user,
+		password: pass
+	})
+	.then(function (response) {
+
+		if(response.data.success === false)
+			return swal('Error', response.data.description, 'error');
+		
+		localStorage.token = response.data.token;
+		window.location = '/panel';
+
+	})
+	.catch(function (error) {
+		return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
+		console.log(error);
+	});
+}
+
+page.verify = function(){
+	page.token = localStorage.token;
+	if(page.token === undefined) return;
+
+	axios.post('/api/tokens/verify', {
+		token: page.token
+	})
+	.then(function (response) {
+
+		if(response.data.success === false)
+			return swal('Error', response.data.description, 'error');
+		
+		window.location = '/panel';
+
+	})
+	.catch(function (error) {
+		return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
+		console.log(error);
+	});
+
+}
+
+window.onload = function () {
+	page.verify();
+}

+ 27 - 71
public/js/panel.js

@@ -1,17 +1,11 @@
 let panel = {}
 
 panel.page;
-panel.token = localStorage.admintoken;
+panel.token = localStorage.token;
 panel.filesView = localStorage.filesView;
 
 panel.preparePage = function(){
-	if(!panel.token){
-		document.getElementById('auth').style.display = 'flex';
-		document.getElementById('tokenSubmit').addEventListener('click', function(){
-			panel.verifyToken(document.getElementById('token').value);
-		});
-		return;
-	}
+	if(!panel.token) return window.location = '/auth';
 	panel.verifyToken(panel.token, true);
 }
 
@@ -20,7 +14,6 @@ panel.verifyToken = function(token, reloadOnError){
 		reloadOnError = false;
 
 	axios.post('/api/tokens/verify', {
-		type: 'admin',
 		token: token
 	})
 	.then(function (response) {
@@ -32,15 +25,15 @@ panel.verifyToken = function(token, reloadOnError){
 				type: "error"
 			}, function(){
 				if(reloadOnError){
-					localStorage.removeItem("admintoken");
-					location.reload();
+					localStorage.removeItem("token");
+					location.location = '/auth';
 				}
 			})
 			return;
 		}
 
-		axios.defaults.headers.common['auth'] = token;
-		localStorage.admintoken = token;
+		axios.defaults.headers.common['token'] = token;
+		localStorage.token = token;
 		panel.token = token;
 		return panel.prepareDashboard();
 
@@ -73,7 +66,7 @@ panel.prepareDashboard = function(){
 }
 
 panel.logout = function(){
-	localStorage.removeItem("admintoken");
+	localStorage.removeItem("token");
 	location.reload('/');
 }
 
@@ -85,14 +78,12 @@ panel.getUploads = function(album = undefined, page = undefined){
 	if(album !== undefined)
 		url = '/api/album/' + album + '/' + page
 
-	axios.get(url)
-	.then(function (response) {
+	axios.get(url).then(function (response) {
 		if(response.data.success === false){
-			if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+			if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 			else return swal("An error ocurred", response.data.description, "error");		
 		}
 		
-
 		var prevPage = 0;
 		var nextPage = page + 1;
 
@@ -125,9 +116,7 @@ panel.getUploads = function(album = undefined, page = undefined){
 
 		if(panel.filesView === 'thumbs'){
 
-
 			container.innerHTML = `
-				
 				${pagination}
 				<hr>
 				${listType}
@@ -135,10 +124,8 @@ panel.getUploads = function(album = undefined, page = undefined){
 
 				</div>
 				${pagination}
-
 			`;
 
-
 			panel.page.appendChild(container);
 			var table = document.getElementById('table');
 
@@ -157,7 +144,6 @@ panel.getUploads = function(album = undefined, page = undefined){
 		}else{
 
 			container.innerHTML = `
-				
 				${pagination}
 				<hr>
 				${listType}
@@ -175,7 +161,6 @@ panel.getUploads = function(album = undefined, page = undefined){
 				</table>
 				<hr>
 				${pagination}
-
 			`;
 
 			panel.page.appendChild(container);
@@ -201,11 +186,7 @@ panel.getUploads = function(album = undefined, page = undefined){
 
 				table.appendChild(tr);
 			}
-
 		}
-
-
-
 	})
 	.catch(function (error) {
 		return swal("An error ocurred", 'There was an error with the request, please check the console for more information.', "error");
@@ -238,7 +219,7 @@ panel.deleteFile = function(id){
 			.then(function (response) {
 
 				if(response.data.success === false){
-					if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+					if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 					else return swal("An error ocurred", response.data.description, "error");		
 				}
 
@@ -258,10 +239,9 @@ panel.deleteFile = function(id){
 
 panel.getAlbums = function(){
 
-	axios.get('/api/albums')
-	.then(function (response) {
+	axios.get('/api/albums').then(function (response) {
 		if(response.data.success === false){
-			if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+			if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 			else return swal("An error ocurred", response.data.description, "error");		
 		}
 
@@ -324,7 +304,6 @@ panel.getAlbums = function(){
 			panel.submitAlbum();
 		});
 
-
 	})
 	.catch(function (error) {
 		return swal("An error ocurred", 'There was an error with the request, please check the console for more information.', "error");
@@ -357,7 +336,7 @@ panel.renameAlbum = function(id){
 		.then(function (response) {
 
 			if(response.data.success === false){
-				if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+				if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 				else if(response.data.description === 'Name already in use') swal.showInputError("That name is already in use!");
 				else swal("An error ocurred", response.data.description, "error");
 				return;
@@ -396,7 +375,7 @@ panel.deleteAlbum = function(id){
 			.then(function (response) {
 
 				if(response.data.success === false){
-					if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+					if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 					else return swal("An error ocurred", response.data.description, "error");		
 				}
 
@@ -424,7 +403,7 @@ panel.submitAlbum = function(){
 	.then(function (response) {
 
 		if(response.data.success === false){
-			if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+			if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 			else return swal("An error ocurred", response.data.description, "error");		
 		}
 
@@ -446,7 +425,7 @@ panel.getAlbumsSidebar = function(){
 	axios.get('/api/albums/sidebar')
 	.then(function (response) {
 		if(response.data.success === false){
-			if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+			if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 			else return swal("An error ocurred", response.data.description, "error");		
 		}
 
@@ -489,7 +468,7 @@ panel.changeTokens = function(){
 	axios.get('/api/tokens')
 	.then(function (response) {
 		if(response.data.success === false){
-			if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+			if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 			else return swal("An error ocurred", response.data.description, "error");		
 		}
 
@@ -497,35 +476,21 @@ panel.changeTokens = function(){
 		var container = document.createElement('div');
 		container.className = "container";
 		container.innerHTML = `
-			<h2 class="subtitle">Manage your tokens</h2>
-
-			<label class="label">Client token:</label>
-			<p class="control has-addons">
-				<input id="clientToken" class="input is-expanded" type="text" placeholder="Your client token">
-				<a id="submitClientToken" class="button is-primary">Save</a>
-			</p>
+			<h2 class="subtitle">Manage your token</h2>
 
-			<label class="label">Admin token:</label>
+			<label class="label">Your current token:</label>
 			<p class="control has-addons">
-				<input id="adminToken" class="input is-expanded" type="text" placeholder="Your admin token">
-				<a id="submitAdminToken" class="button is-primary">Save</a>
+				<input id="token" readonly class="input is-expanded" type="text" placeholder="Your token" value="${response.data.token}">
+				<a id="getNewToken" class="button is-primary">Request new token</a>
 			</p>
 		`;
 
 		panel.page.appendChild(container);
 
-		document.getElementById('clientToken').value = response.data.clientToken;
-		document.getElementById('adminToken').value = response.data.adminToken;
-
-		document.getElementById('submitClientToken').addEventListener('click', function(){
-			panel.submitToken('client', document.getElementById('clientToken').value);
+		document.getElementById('getNewToken').addEventListener('click', function(){
+			panel.getNewToken();
 		});
 
-		document.getElementById('submitAdminToken').addEventListener('click', function(){
-			panel.submitToken('admin', document.getElementById('adminToken').value);
-		});
-
-
 	})
 	.catch(function (error) {
 		return swal("An error ocurred", 'There was an error with the request, please check the console for more information.', "error");
@@ -534,16 +499,13 @@ panel.changeTokens = function(){
 
 }
 
-panel.submitToken = function(type, token){
+panel.getNewToken = function(){
 
-	axios.post('/api/tokens/change', {
-		type: type,
-		token: token
-	})
+	axios.post('/api/tokens/change')
 	.then(function (response) {
 
 		if(response.data.success === false){
-			if(response.data.description === 'not-authorized') return panel.verifyToken(panel.token);
+			if(response.data.description === 'No token provided') return panel.verifyToken(panel.token);
 			else return swal("An error ocurred", response.data.description, "error");		
 		}
 
@@ -552,14 +514,8 @@ panel.submitToken = function(type, token){
 			text: 'Your token was changed successfully.', 
 			type: "success"
 		}, function(){
-			
-			if(type === 'client')
-				localStorage.token = token;
-			else if(type === 'admin')
-				localStorage.admintoken = token
-
+			localStorage.token = response.data.token;
 			location.reload();
-				
 		})
 
 	})

+ 18 - 2
public/js/upload.js

@@ -36,7 +36,6 @@ upload.verifyToken = function(token, reloadOnError){
 		reloadOnError = false;
 	
 	axios.post('/api/tokens/verify', {
-		type: 'client',
 		token: token
 	})
   	.then(function (response) {
@@ -101,10 +100,11 @@ upload.prepareDropzone = function(){
 		maxFiles: 1000,
 		autoProcessQueue: true,
 		headers: {
-    		'auth': upload.token
+    		'token': upload.token
 		},
 		init: function() {
 			this.on('addedfile', function(file) { 
+				myDropzone = this;
 				document.getElementById('uploads').style.display = 'block';
 			});
 		}
@@ -139,6 +139,22 @@ upload.prepareDropzone = function(){
 
 }
 
+//Handle image paste event
+window.addEventListener('paste', function(event) {
+	var items = (event.clipboardData || event.originalEvent.clipboardData).items;
+	for (index in items) {
+		var item = items[index];
+		if (item.kind === 'file') {
+			var blob = item.getAsFile();
+			console.log(blob.type);
+			var file = new File([blob], "pasted-image."+blob.type.match(/(?:[^\/]*\/)([^;]*)/)[1]);
+			file.type = blob.type;
+			console.log(file);
+			myDropzone.addFile(file);
+		}
+	}
+});
+
 window.onload = function () {
 	upload.checkIfPublic();
 };

+ 4 - 0
routes/api.js

@@ -3,6 +3,7 @@ const routes = require('express').Router()
 const uploadController = require('../controllers/uploadController')
 const albumsController = require('../controllers/albumsController')
 const tokenController = require('../controllers/tokenController')
+const authController = require('../controllers/authController')
 
 routes.get ('/check', (req, res, next) => {
 	return res.json({ 
@@ -11,6 +12,9 @@ routes.get ('/check', (req, res, next) => {
 	})
 })
 
+routes.post ('/login', (req, res, next) => authController.verify(req, res, next))
+routes.post ('/register', (req, res, next) => authController.register(req, res, next))
+
 routes.get  ('/uploads', (req, res, next) => uploadController.list(req, res))
 routes.get  ('/uploads/:page', (req, res, next) => uploadController.list(req, res))
 routes.post ('/upload', (req, res, next) => uploadController.upload(req, res, next))