Various updates

* Switched ESLint + Aqua to Standard. I'm a big fan of Standard. Updated yarn.lock file too.

* Lots of refactors to follow the rules of Standard.

* Fixed issue with uploading as a not logged in user.
This commit is contained in:
Bobby Wibowo 2018-01-24 03:06:30 +07:00
parent da40ea71b1
commit bcdfcd7064
No known key found for this signature in database
GPG Key ID: 51C3A1E1E22D26CF
20 changed files with 2153 additions and 1759 deletions

View File

@ -81,4 +81,4 @@ module.exports = {
connection: { filename: './database/db' },
useNullAsDefault: true
}
};
}

View File

@ -1,58 +1,58 @@
const config = require('../config.js');
const db = require('knex')(config.database);
const randomstring = require('randomstring');
const utils = require('./utilsController.js');
const path = require('path');
const fs = require('fs');
const Zip = require('jszip');
const albumsController = {};
const config = require('../config.js')
const db = require('knex')(config.database)
const randomstring = require('randomstring')
const utils = require('./utilsController.js')
const path = require('path')
const fs = require('fs')
const Zip = require('jszip')
const albumsController = {}
albumsController.list = async (req, res, next) => {
const user = await utils.authorize(req, res);
const user = await utils.authorize(req, res)
const fields = ['id', 'name'];
const fields = ['id', 'name']
if (req.params.sidebar === undefined) {
fields.push('timestamp');
fields.push('identifier');
fields.push('timestamp')
fields.push('identifier')
}
const albums = await db.table('albums').select(fields).where({ enabled: 1, userid: user.id });
const albums = await db.table('albums').select(fields).where({ enabled: 1, userid: user.id })
if (req.params.sidebar !== undefined) {
return res.json({ success: true, albums });
return res.json({ success: true, albums })
}
let ids = [];
let ids = []
for (let album of albums) {
album.date = new Date(album.timestamp * 1000)
album.date = utils.getPrettyDate(album.date)
album.identifier = `${config.domain}/a/${album.identifier}`;
ids.push(album.id);
album.identifier = `${config.domain}/a/${album.identifier}`
ids.push(album.id)
}
const files = await db.table('files').whereIn('albumid', ids).select('albumid');
const albumsCount = {};
const files = await db.table('files').whereIn('albumid', ids).select('albumid')
const 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];
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 })
}
albumsController.create = async (req, res, next) => {
const user = await utils.authorize(req, res);
const user = await utils.authorize(req, res)
const name = req.body.name;
const name = req.body.name
if (name === undefined || name === '') {
return res.json({ success: false, description: 'No album name specified' });
return res.json({ success: false, description: 'No album name specified' })
}
const album = await db.table('albums').where({
name: name,
enabled: 1,
userid: user.id
}).first();
}).first()
if (album) {
return res.json({ success: false, description: 'There\'s already an album with that name' })
@ -64,61 +64,61 @@ albumsController.create = async (req, res, next) => {
userid: user.id,
identifier: randomstring.generate(8),
timestamp: Math.floor(Date.now() / 1000)
});
})
return res.json({ success: true });
};
return res.json({ success: true })
}
albumsController.delete = async (req, res, next) => {
const user = await utils.authorize(req, res);
const user = await utils.authorize(req, res)
const id = req.body.id;
const id = req.body.id
if (id === undefined || id === '') {
return res.json({ success: false, description: 'No album specified' });
return res.json({ success: false, description: 'No album specified' })
}
await db.table('albums').where({ id: id, userid: user.id }).update({ enabled: 0 });
return res.json({ success: true });
};
await db.table('albums').where({ id: id, userid: user.id }).update({ enabled: 0 })
return res.json({ success: true })
}
albumsController.rename = async (req, res, next) => {
const user = await utils.authorize(req, res);
const user = await utils.authorize(req, res)
const id = req.body.id;
const id = req.body.id
if (id === undefined || id === '') {
return res.json({ success: false, description: 'No album specified' });
return res.json({ success: false, description: 'No album specified' })
}
const name = req.body.name;
const name = req.body.name
if (name === undefined || name === '') {
return res.json({ success: false, description: 'No name specified' });
return res.json({ success: false, description: 'No name specified' })
}
const album = await db.table('albums').where({ name: name, userid: user.id }).first();
const album = await db.table('albums').where({ name: name, userid: user.id }).first()
if (album) {
return res.json({ success: false, description: 'Name already in use' })
}
await db.table('albums').where({ id: id, userid: user.id }).update({ name: name })
return res.json({ success: true });
};
return res.json({ success: true })
}
albumsController.get = async (req, res, next) => {
const identifier = req.params.identifier;
if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' });
const identifier = req.params.identifier
if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' })
const album = await db.table('albums').where({ identifier, enabled: 1 }).first();
if (!album) return res.json({ success: false, description: 'Album not found' });
const album = await db.table('albums').where({ identifier, enabled: 1 }).first()
if (!album) return res.json({ success: false, description: 'Album not found' })
const title = album.name;
const files = await db.table('files').select('name').where('albumid', album.id).orderBy('id', 'DESC');
const title = album.name
const files = await db.table('files').select('name').where('albumid', album.id).orderBy('id', 'DESC')
for (let file of files) {
file.file = `${config.domain}/${file.name}`;
file.file = `${config.domain}/${file.name}`
const ext = path.extname(file.name).toLowerCase();
const ext = path.extname(file.name).toLowerCase()
if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) {
file.thumb = `${config.domain}/thumbs/${file.name.slice(0, -ext.length)}.png`;
file.thumb = `${config.domain}/thumbs/${file.name.slice(0, -ext.length)}.png`
}
}
@ -127,36 +127,35 @@ albumsController.get = async (req, res, next) => {
title: title,
count: files.length,
files
});
};
})
}
albumsController.generateZip = async (req, res, next) => {
const identifier = req.params.identifier;
if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' });
if (!config.uploads.generateZips) return res.status(401).json({ success: false, description: 'Zip generation disabled' });
const identifier = req.params.identifier
if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' })
if (!config.uploads.generateZips) return res.status(401).json({ success: false, description: 'Zip generation disabled' })
const album = await db.table('albums').where({ identifier, enabled: 1 }).first();
if (!album) return res.json({ success: false, description: 'Album not found' });
const album = await db.table('albums').where({ identifier, enabled: 1 }).first()
if (!album) return res.json({ success: false, description: 'Album not found' })
if (album.zipGeneratedAt > album.editedAt) {
const filePath = path.join(config.uploads.folder, 'zips', `${identifier}.zip`);
const fileName = `${album.name}.zip`;
return res.download(filePath, fileName);
const filePath = path.join(config.uploads.folder, 'zips', `${identifier}.zip`)
const fileName = `${album.name}.zip`
return res.download(filePath, fileName)
} else {
console.log(`Generating zip for album identifier: ${identifier}`);
const files = await db.table('files').select('name').where('albumid', album.id);
if (files.length === 0) return res.json({ success: false, description: 'There are no files in the album' });
console.log(`Generating zip for album identifier: ${identifier}`)
const files = await db.table('files').select('name').where('albumid', album.id)
if (files.length === 0) return res.json({ success: false, description: 'There are no files in the album' })
const zipPath = path.join(__dirname, '..', config.uploads.folder, 'zips', `${album.identifier}.zip`);
let archive = new Zip();
const zipPath = path.join(__dirname, '..', config.uploads.folder, 'zips', `${album.identifier}.zip`)
let archive = new Zip()
for (let file of files) {
try {
const exists = fs.statSync(path.join(__dirname, '..', config.uploads.folder, file.name));
archive.file(file.name, fs.readFileSync(path.join(__dirname, '..', config.uploads.folder, file.name)));
// const exists = fs.statSync(path.join(__dirname, '..', config.uploads.folder, file.name))
archive.file(file.name, fs.readFileSync(path.join(__dirname, '..', config.uploads.folder, file.name)))
} catch (err) {
console.log(err);
console.log(err)
}
}
@ -164,16 +163,16 @@ albumsController.generateZip = async (req, res, next) => {
.generateNodeStream({ type: 'nodebuffer', streamFiles: true })
.pipe(fs.createWriteStream(zipPath))
.on('finish', async () => {
console.log(`Generated zip for album identifier: ${identifier}`);
console.log(`Generated zip for album identifier: ${identifier}`)
await db.table('albums')
.where('id', album.id)
.update({ zipGeneratedAt: Math.floor(Date.now() / 1000) });
.update({ zipGeneratedAt: Math.floor(Date.now() / 1000) })
const filePath = path.join(config.uploads.folder, 'zips', `${identifier}.zip`);
const fileName = `${album.name}.zip`;
return res.download(filePath, fileName);
});
const filePath = path.join(config.uploads.folder, 'zips', `${identifier}.zip`)
const fileName = `${album.name}.zip`
return res.download(filePath, fileName)
})
}
};
}
module.exports = albumsController;
module.exports = albumsController

View File

@ -1,41 +1,41 @@
const config = require('../config.js');
const db = require('knex')(config.database);
const bcrypt = require('bcrypt');
const randomstring = require('randomstring');
const utils = require('./utilsController.js');
const config = require('../config.js')
const db = require('knex')(config.database)
const bcrypt = require('bcrypt')
const randomstring = require('randomstring')
const utils = require('./utilsController.js')
let authController = {};
let authController = {}
authController.verify = async (req, res, next) => {
const username = req.body.username;
const password = req.body.password;
const username = req.body.username
const 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 === undefined) return res.json({ success: false, description: 'No username provided' })
if (password === undefined) return res.json({ success: false, description: 'No password provided' })
const user = await db.table('users').where('username', username).first();
if (!user) return res.json({ success: false, description: 'Username doesn\'t exist' });
const user = await db.table('users').where('username', username).first()
if (!user) return res.json({ success: false, description: 'Username doesn\'t exist' })
bcrypt.compare(password, user.password, (err, result) => {
if (err) {
console.log(err);
return res.json({ success: false, description: 'There was an error' });
console.log(err)
return res.json({ success: false, description: 'There was an error' })
}
if (result === false) return res.json({ success: false, description: 'Wrong password' });
return res.json({ success: true, token: user.token });
});
};
if (result === false) return res.json({ success: false, description: 'Wrong password' })
return res.json({ success: true, token: user.token })
})
}
authController.register = async (req, res, next) => {
if (config.enableUserAccounts === false) {
return res.json({ success: false, description: 'Register is disabled at the moment' });
return res.json({ success: false, description: 'Register is disabled at the moment' })
}
const username = req.body.username;
const password = req.body.password;
const username = req.body.username
const 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 === 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 4-32 characters' })
@ -44,43 +44,43 @@ authController.register = async (req, res, next) => {
return res.json({ success: false, description: 'Password must have 6-64 characters' })
}
const user = await db.table('users').where('username', username).first();
if (user) return res.json({ success: false, description: 'Username already exists' });
const user = await db.table('users').where('username', username).first()
if (user) return res.json({ success: false, description: 'Username already exists' })
bcrypt.hash(password, 10, async (err, hash) => {
if (err) {
console.log(err);
return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' });
console.log(err)
return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' })
}
const token = randomstring.generate(64);
const token = randomstring.generate(64)
await db.table('users').insert({
username: username,
password: hash,
token: token
});
})
return res.json({ success: true, token: token })
});
};
})
}
authController.changePassword = async (req, res, next) => {
const user = await utils.authorize(req, res);
const user = await utils.authorize(req, res)
let password = req.body.password;
if (password === undefined) return res.json({ success: false, description: 'No password provided' });
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' });
return res.json({ success: false, description: 'Password must have 6-64 characters' })
}
bcrypt.hash(password, 10, async (err, hash) => {
if (err) {
console.log(err);
return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' });
console.log(err)
return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' })
}
await db.table('users').where('id', user.id).update({ password: hash });
return res.json({ success: true });
});
};
await db.table('users').where('id', user.id).update({ password: hash })
return res.json({ success: true })
})
}
module.exports = authController;
module.exports = authController

View File

@ -1,34 +1,34 @@
const config = require('../config.js');
const db = require('knex')(config.database);
const randomstring = require('randomstring');
const utils = require('./utilsController.js');
const config = require('../config.js')
const db = require('knex')(config.database)
const randomstring = require('randomstring')
const utils = require('./utilsController.js')
const tokenController = {};
const tokenController = {}
tokenController.verify = async (req, res, next) => {
const token = req.body.token;
if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' });
const token = req.body.token
if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
const user = await db.table('users').where('token', token).first();
if (!user) return res.status(401).json({ success: false, description: 'Invalid token' });
return res.json({ success: true, username: user.username });
};
const user = await db.table('users').where('token', token).first()
if (!user) return res.status(401).json({ success: false, description: 'Invalid token' })
return res.json({ success: true, username: user.username })
}
tokenController.list = async (req, res, next) => {
const user = await utils.authorize(req, res);
return res.json({ success: true, token: user.token });
};
const user = await utils.authorize(req, res)
return res.json({ success: true, token: user.token })
}
tokenController.change = async (req, res, next) => {
const user = await utils.authorize(req, res);
const newtoken = randomstring.generate(64);
const user = await utils.authorize(req, res)
const newtoken = randomstring.generate(64)
await db.table('users').where('token', user.token).update({
token: newtoken,
timestamp: Math.floor(Date.now() / 1000)
});
})
res.json({ success: true, token: newtoken });
};
res.json({ success: true, token: newtoken })
}
module.exports = tokenController;
module.exports = tokenController

View File

@ -1,93 +1,93 @@
const config = require('../config.js');
const path = require('path');
const multer = require('multer');
const randomstring = require('randomstring');
const db = require('knex')(config.database);
const crypto = require('crypto');
const fs = require('fs');
const utils = require('./utilsController.js');
const config = require('../config.js')
const path = require('path')
const multer = require('multer')
const randomstring = require('randomstring')
const db = require('knex')(config.database)
const crypto = require('crypto')
const fs = require('fs')
const utils = require('./utilsController.js')
const uploadsController = {};
const uploadsController = {}
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, path.join(__dirname, '..', config.uploads.folder));
destination: function (req, file, cb) {
cb(null, path.join(__dirname, '..', config.uploads.folder))
},
filename: function(req, file, cb) {
cb(null, randomstring.generate(config.uploads.fileLength) + path.extname(file.originalname));
filename: function (req, file, cb) {
cb(null, randomstring.generate(config.uploads.fileLength) + path.extname(file.originalname))
}
});
})
const upload = multer({
storage: storage,
limits: { fileSize: config.uploads.maxSize },
fileFilter: function(req, file, cb) {
fileFilter: function (req, file, cb) {
if (config.blockedExtensions !== undefined) {
if (config.blockedExtensions.some(extension => path.extname(file.originalname).toLowerCase() === extension)) {
return cb('This file extension is not allowed');
return cb('This file extension is not allowed') // eslint-disable-line standard/no-callback-literal
}
return cb(null, true);
return cb(null, true)
}
return cb(null, true);
return cb(null, true)
}
}).array('files[]');
}).array('files[]')
uploadsController.upload = async (req, res, next) => {
if (config.private === true) {
await utils.authorize(req, res);
await utils.authorize(req, res)
}
const token = req.headers.token || '';
const user = await db.table('users').where('token', token).first();
const albumid = req.headers.albumid || req.params.albumid;
const token = req.headers.token || ''
const user = await db.table('users').where('token', token).first()
const albumid = req.headers.albumid || req.params.albumid
if (albumid && user) {
const album = await db.table('albums').where({ id: albumid, userid: user.id }).first();
const album = await db.table('albums').where({ id: albumid, userid: user.id }).first()
if (!album) {
return res.json({
success: false,
description: 'Album doesn\'t exist or it doesn\'t belong to the user'
});
})
}
return uploadsController.actuallyUpload(req, res, user, albumid);
return uploadsController.actuallyUpload(req, res, user, albumid)
}
return uploadsController.actuallyUpload(req, res, user, albumid);
};
return uploadsController.actuallyUpload(req, res, user, albumid)
}
uploadsController.actuallyUpload = async (req, res, userid, album) => {
upload(req, res, async err => {
if (err) {
console.error(err);
return res.json({ success: false, description: err });
console.error(err)
return res.json({ success: false, description: err })
}
if (req.files.length === 0) return res.json({ success: false, description: 'no-files' });
if (req.files.length === 0) return res.json({ success: false, description: 'no-files' })
const files = [];
const existingFiles = [];
let iteration = 1;
const files = []
const existingFiles = []
let iteration = 1
req.files.forEach(async file => {
// Check if the file exists by checking hash and size
let hash = crypto.createHash('md5');
let stream = fs.createReadStream(path.join(__dirname, '..', config.uploads.folder, file.filename));
let hash = crypto.createHash('md5')
let stream = fs.createReadStream(path.join(__dirname, '..', config.uploads.folder, file.filename))
stream.on('data', data => {
hash.update(data, 'utf8');
});
hash.update(data, 'utf8')
})
stream.on('end', async () => {
const fileHash = hash.digest('hex');
const fileHash = hash.digest('hex')
const dbFile = await db.table('files')
.where(function() {
if (userid === undefined) this.whereNull('userid');
else this.where('userid', userid.id);
.where(function () {
if (userid === undefined) this.whereNull('userid')
else this.where('userid', userid.id)
})
.where({
hash: fileHash,
size: file.size
})
.first();
.first()
if (!dbFile) {
files.push({
@ -98,25 +98,25 @@ uploadsController.actuallyUpload = async (req, res, userid, album) => {
hash: fileHash,
ip: req.ip,
albumid: album,
userid: userid.id,
userid: userid ? userid.id : null,
timestamp: Math.floor(Date.now() / 1000)
});
})
} else {
uploadsController.deleteFile(file.filename).then(() => {}).catch(err => console.error(err));
existingFiles.push(dbFile);
uploadsController.deleteFile(file.filename).then(() => {}).catch(err => console.error(err))
existingFiles.push(dbFile)
}
if (iteration === req.files.length) {
return uploadsController.processFilesForDisplay(req, res, files, existingFiles);
return uploadsController.processFilesForDisplay(req, res, files, existingFiles)
}
iteration++;
});
});
});
};
iteration++
})
})
})
}
uploadsController.processFilesForDisplay = async (req, res, files, existingFiles) => {
let basedomain = config.domain;
let basedomain = config.domain
if (files.length === 0) {
return res.json({
success: true,
@ -125,13 +125,13 @@ uploadsController.processFilesForDisplay = async (req, res, files, existingFiles
name: file.name,
size: file.size,
url: `${basedomain}/${file.name}`
};
}
})
})
});
}
await db.table('files').insert(files);
for (let efile of existingFiles) files.push(efile);
await db.table('files').insert(files)
for (let efile of existingFiles) files.push(efile)
res.json({
success: true,
@ -140,113 +140,113 @@ uploadsController.processFilesForDisplay = async (req, res, files, existingFiles
name: file.name,
size: file.size,
url: `${basedomain}/${file.name}`
};
}
})
})
});
for (let file of files) {
let ext = path.extname(file.name).toLowerCase();
let ext = path.extname(file.name).toLowerCase()
if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) {
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`;
utils.generateThumbs(file);
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`
utils.generateThumbs(file)
}
if (file.albumid) {
db.table('albums').where('id', file.albumid).update('editedAt', file.timestamp).then(() => {})
.catch(error => { console.log(error); res.json({ success: false, description: 'Error updating album' }); });
.catch(error => { console.log(error); res.json({ success: false, description: 'Error updating album' }) })
}
}
};
}
uploadsController.delete = async (req, res) => {
const user = await utils.authorize(req, res);
const id = req.body.id;
const user = await utils.authorize(req, res)
const id = req.body.id
if (id === undefined || id === '') {
return res.json({ success: false, description: 'No file specified' });
return res.json({ success: false, description: 'No file specified' })
}
const file = await db.table('files')
.where('id', id)
.where(function() {
.where(function () {
if (user.username !== 'root') {
this.where('userid', user.id);
this.where('userid', user.id)
}
})
.first();
.first()
try {
await uploadsController.deleteFile(file.name);
await db.table('files').where('id', id).del();
await uploadsController.deleteFile(file.name)
await db.table('files').where('id', id).del()
if (file.albumid) {
await db.table('albums').where('id', file.albumid).update('editedAt', Math.floor(Date.now() / 1000));
await db.table('albums').where('id', file.albumid).update('editedAt', Math.floor(Date.now() / 1000))
}
} catch (err) {
console.log(err);
console.log(err)
}
return res.json({ success: true });
};
return res.json({ success: true })
}
uploadsController.deleteFile = function(file) {
const ext = path.extname(file).toLowerCase();
uploadsController.deleteFile = function (file) {
const ext = path.extname(file).toLowerCase()
return new Promise((resolve, reject) => {
fs.stat(path.join(__dirname, '..', config.uploads.folder, file), (err, stats) => {
if (err) { return reject(err); }
if (err) { return reject(err) }
fs.unlink(path.join(__dirname, '..', config.uploads.folder, file), err => {
if (err) { return reject(err); }
if (err) { return reject(err) }
if (!utils.imageExtensions.includes(ext) && !utils.videoExtensions.includes(ext)) {
return resolve();
return resolve()
}
file = file.substr(0, file.lastIndexOf('.')) + '.png';
file = file.substr(0, file.lastIndexOf('.')) + '.png'
fs.stat(path.join(__dirname, '..', config.uploads.folder, 'thumbs/', file), (err, stats) => {
if (err) {
console.log(err);
return resolve();
console.log(err)
return resolve()
}
fs.unlink(path.join(__dirname, '..', config.uploads.folder, 'thumbs/', file), err => {
if (err) { return reject(err); }
return resolve();
});
});
});
});
});
};
if (err) { return reject(err) }
return resolve()
})
})
})
})
})
}
uploadsController.list = async (req, res) => {
const user = await utils.authorize(req, res);
const user = await utils.authorize(req, res)
let offset = req.params.page;
if (offset === undefined) offset = 0;
let offset = req.params.page
if (offset === undefined) offset = 0
const files = await db.table('files')
.where(function() {
if (req.params.id === undefined) this.where('id', '<>', '');
else this.where('albumid', req.params.id);
.where(function () {
if (req.params.id === undefined) this.where('id', '<>', '')
else this.where('albumid', req.params.id)
})
.where(function() {
if (user.username !== 'root') this.where('userid', user.id);
.where(function () {
if (user.username !== 'root') this.where('userid', user.id)
})
.orderBy('id', 'DESC')
.limit(25)
.offset(25 * offset)
.select('id', 'albumid', 'timestamp', 'name', 'userid');
.select('id', 'albumid', 'timestamp', 'name', 'userid')
const albums = await db.table('albums');
let basedomain = config.domain;
let userids = [];
const albums = await db.table('albums')
let basedomain = config.domain
let userids = []
for (let file of files) {
file.file = `${basedomain}/${file.name}`;
file.date = new Date(file.timestamp * 1000);
file.date = utils.getPrettyDate(file.date);
file.file = `${basedomain}/${file.name}`
file.date = new Date(file.timestamp * 1000)
file.date = utils.getPrettyDate(file.date)
file.album = '';
file.album = ''
if (file.albumid !== undefined) {
for (let album of albums) {
if (file.albumid === album.id) {
file.album = album.name;
file.album = album.name
}
}
}
@ -254,32 +254,32 @@ uploadsController.list = async (req, res) => {
// Only push usernames if we are root
if (user.username === 'root') {
if (file.userid !== undefined && file.userid !== null && file.userid !== '') {
userids.push(file.userid);
userids.push(file.userid)
}
}
let ext = path.extname(file.name).toLowerCase();
let ext = path.extname(file.name).toLowerCase()
if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) {
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`;
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`
}
}
// If we are a normal user, send response
if (user.username !== 'root') return res.json({ success: true, files });
if (user.username !== 'root') return res.json({ success: true, files })
// If we are root but there are no uploads attached to a user, send response
if (userids.length === 0) return res.json({ success: true, files });
if (userids.length === 0) return res.json({ success: true, files })
const users = await db.table('users').whereIn('id', userids);
const users = await db.table('users').whereIn('id', userids)
for (let dbUser of users) {
for (let file of files) {
if (file.userid === dbUser.id) {
file.username = dbUser.username;
file.username = dbUser.username
}
}
}
return res.json({ success: true, files });
};
return res.json({ success: true, files })
}
module.exports = uploadsController;
module.exports = uploadsController

View File

@ -1,40 +1,40 @@
const path = require('path');
const config = require('../config.js');
const fs = require('fs');
const gm = require('gm');
const ffmpeg = require('fluent-ffmpeg');
const db = require('knex')(config.database);
const path = require('path')
const config = require('../config.js')
const fs = require('fs')
const gm = require('gm')
const ffmpeg = require('fluent-ffmpeg')
const db = require('knex')(config.database)
const utilsController = {};
utilsController.imageExtensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png'];
utilsController.videoExtensions = ['.webm', '.mp4', '.wmv', '.avi', '.mov'];
const utilsController = {}
utilsController.imageExtensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png']
utilsController.videoExtensions = ['.webm', '.mp4', '.wmv', '.avi', '.mov']
utilsController.getPrettyDate = function(date) {
return date.getFullYear() + '-'
+ (date.getMonth() + 1) + '-'
+ date.getDate() + ' '
+ (date.getHours() < 10 ? '0' : '')
+ date.getHours() + ':'
+ (date.getMinutes() < 10 ? '0' : '')
+ date.getMinutes() + ':'
+ (date.getSeconds() < 10 ? '0' : '')
+ date.getSeconds();
utilsController.getPrettyDate = function (date) {
return date.getFullYear() + '-' +
(date.getMonth() + 1) + '-' +
date.getDate() + ' ' +
(date.getHours() < 10 ? '0' : '') +
date.getHours() + ':' +
(date.getMinutes() < 10 ? '0' : '') +
date.getMinutes() + ':' +
(date.getSeconds() < 10 ? '0' : '') +
date.getSeconds()
}
utilsController.authorize = async (req, res) => {
const token = req.headers.token;
if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' });
const token = req.headers.token
if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
const user = await db.table('users').where('token', token).first();
if (!user) return res.status(401).json({ success: false, description: 'Invalid token' });
return user;
};
const user = await db.table('users').where('token', token).first()
if (!user) return res.status(401).json({ success: false, description: 'Invalid token' })
return user
}
utilsController.generateThumbs = function(file, basedomain) {
if (config.uploads.generateThumbnails !== true) return;
const ext = path.extname(file.name).toLowerCase();
utilsController.generateThumbs = function (file, basedomain) {
if (config.uploads.generateThumbnails !== true) return
const ext = path.extname(file.name).toLowerCase()
let thumbname = path.join(__dirname, '..', config.uploads.folder, 'thumbs', file.name.slice(0, -ext.length) + '.png');
let thumbname = path.join(__dirname, '..', config.uploads.folder, 'thumbs', file.name.slice(0, -ext.length) + '.png')
fs.access(thumbname, err => {
if (err && err.code === 'ENOENT') {
if (utilsController.videoExtensions.includes(ext)) {
@ -45,23 +45,23 @@ utilsController.generateThumbs = function(file, basedomain) {
folder: path.join(__dirname, '..', config.uploads.folder, 'thumbs'),
size: '200x?'
})
.on('error', error => console.log('Error - ', error.message));
.on('error', error => console.log('Error - ', error.message))
} else {
let size = {
width: 200,
height: 200
};
}
gm(path.join(__dirname, '..', config.uploads.folder, file.name))
.resize(size.width, size.height + '>')
.gravity('Center')
.extent(size.width, size.height)
.background('transparent')
.write(thumbname, error => {
if (error) console.log('Error - ', error);
});
if (error) console.log('Error - ', error)
})
}
}
});
};
})
}
module.exports = utilsController;
module.exports = utilsController

View File

@ -1,5 +1,4 @@
let init = function(db){
let init = function (db) {
// Create the tables we need to store galleries and files
db.schema.createTableIfNotExists('albums', function (table) {
table.increments()
@ -31,10 +30,10 @@ let init = function(db){
table.integer('timestamp')
}).then(() => {
db.table('users').where({username: 'root'}).then((user) => {
if(user.length > 0) return
if (user.length > 0) return
require('bcrypt').hash('root', 10, function(err, hash) {
if(err) console.error('Error generating password hash for root')
require('bcrypt').hash('root', 10, function (err, hash) {
if (err) console.error('Error generating password hash for root')
db.table('users').insert({
username: 'root',

View File

@ -1,13 +1,13 @@
const config = require('../config.js');
const db = require('knex')(config.database);
const config = require('../config.js')
const db = require('knex')(config.database)
const migration = {};
const migration = {}
migration.start = async () => {
await db.schema.table('albums', table => {
table.dateTime('editedAt');
table.dateTime('zipGeneratedAt');
});
console.log('Migration finished! Now start lolisafe normally');
};
table.dateTime('editedAt')
table.dateTime('zipGeneratedAt')
})
console.log('Migration finished! Now start lolisafe normally')
}
migration.start();
migration.start()

View File

@ -1,58 +1,66 @@
const config = require('./config.js');
const api = require('./routes/api.js');
const album = require('./routes/album.js');
const express = require('express');
const helmet = require('helmet');
const bodyParser = require('body-parser');
const RateLimit = require('express-rate-limit');
const db = require('knex')(config.database);
const fs = require('fs');
const exphbs = require('express-handlebars');
const safe = express();
const config = require('./config.js')
const api = require('./routes/api.js')
const album = require('./routes/album.js')
const express = require('express')
const helmet = require('helmet')
const bodyParser = require('body-parser')
const RateLimit = require('express-rate-limit')
const db = require('knex')(config.database)
const fs = require('fs')
const exphbs = require('express-handlebars')
const safe = express()
require('./database/db.js')(db);
require('./database/db.js')(db)
fs.existsSync('./pages/custom') || fs.mkdirSync('./pages/custom');
fs.existsSync(`./${config.logsFolder}`) || fs.mkdirSync(`./${ config.logsFolder}`);
fs.existsSync(`./${config.uploads.folder}`) || fs.mkdirSync(`./${config.uploads.folder}`);
fs.existsSync(`./${config.uploads.folder}/thumbs`) || fs.mkdirSync(`./${config.uploads.folder }/thumbs`);
fs.existsSync(`./${config.uploads.folder }/zips`) || fs.mkdirSync(`./${config.uploads.folder}/zips`);
fs.existsSync('./pages/custom') || fs.mkdirSync('./pages/custom')
fs.existsSync('./' + config.logsFolder) || fs.mkdirSync('./' + config.logsFolder)
fs.existsSync('./' + config.uploads.folder) || fs.mkdirSync('./' + config.uploads.folder)
fs.existsSync('./' + config.uploads.folder + '/thumbs') || fs.mkdirSync('./' + config.uploads.folder + '/thumbs')
fs.existsSync('./' + config.uploads.folder + '/zips') || fs.mkdirSync('./' + config.uploads.folder + '/zips')
safe.use(helmet());
safe.set('trust proxy', 1);
safe.use(helmet())
safe.set('trust proxy', 1)
safe.engine('handlebars', exphbs({ defaultLayout: 'main' }));
safe.set('view engine', 'handlebars');
safe.enable('view cache');
safe.engine('handlebars', exphbs({ defaultLayout: 'main' }))
safe.set('view engine', 'handlebars')
safe.enable('view cache')
let limiter = new RateLimit({ windowMs: 5000, max: 2 });
safe.use('/api/login/', limiter);
safe.use('/api/register/', limiter);
let limiter = new RateLimit({ windowMs: 5000, max: 2 })
safe.use('/api/login/', limiter)
safe.use('/api/register/', limiter)
safe.use(bodyParser.urlencoded({ extended: true }));
safe.use(bodyParser.json());
safe.use(bodyParser.urlencoded({ extended: true }))
safe.use(bodyParser.json())
if (config.serveFilesWithNode) {
safe.use('/', express.static(config.uploads.folder));
safe.use('/', express.static(config.uploads.folder))
}
safe.use('/', express.static('./public'));
safe.use('/', album);
safe.use('/api', api);
safe.use('/', express.static('./public'))
safe.use('/', album)
safe.use('/api', api)
for (let page of config.pages) {
let root = './pages/';
let root = './pages/'
if (fs.existsSync(`./pages/custom/${page}.html`)) {
root = './pages/custom/';
root = './pages/custom/'
}
if (page === 'home') {
safe.get('/', (req, res, next) => res.sendFile(`${page}.html`, { root: root }));
safe.get('/', (req, res, next) => res.sendFile(`${page}.html`, { root: root }))
} else {
safe.get(`/${page}`, (req, res, next) => res.sendFile(`${page}.html`, { root: root }));
safe.get(`/${page}`, (req, res, next) => res.sendFile(`${page}.html`, { root: root }))
}
}
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/' }));
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/' }))
safe.listen(config.port, () => console.log(`lolisafe started on port ${config.port}`));
safe.listen(config.port, () => console.log(`lolisafe started on port ${config.port}`))
process.on('uncaughtException', err => {
console.error(`Uncaught Exception:\n${err.stack}`)
})
process.on('unhandledRejection', err => {
console.error(`Unhandled Rejection (Promise):\n${err.stack}`)
})

View File

@ -30,19 +30,9 @@
"sqlite3": "^3.1.13"
},
"devDependencies": {
"eslint": "^4.4.1",
"eslint-config-aqua": "^1.5.0"
"standard": "^10.0.3"
},
"eslintConfig": {
"extends": [
"aqua"
],
"env": {
"browser": true,
"node": true
},
"rules": {
"func-names": 0
}
"standard": {
"envs": ["browser", "node"]
}
}

View File

@ -39,6 +39,7 @@
<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>
<style type="text/css">
/** Based on KDE Breeze Dark **/
@ -46,6 +47,7 @@
background-color: #232629;
}
</style>
</head>
<body>

View File

@ -39,6 +39,7 @@
<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/dashboard.js"></script>
<style type="text/css">
/** Based on KDE Breeze Dark **/
@ -122,6 +123,7 @@
border-left-color: #31363b;
}
</style>
</head>
<body>

View File

@ -1,44 +1,56 @@
var page = {};
/* global swal, axios */
page.do = function(dest) {
var user = document.getElementById('user').value;
var pass = document.getElementById('pass').value;
var page = {}
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'); }
page.do = function (dest) {
var user = document.getElementById('user').value
var pass = document.getElementById('pass').value
axios.post(`/api/${dest}`, {
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(response => {
if (response.data.success === false) { return swal('Error', response.data.description, 'error'); }
.then(function (response) {
if (response.data.success === false) {
return swal('Error', response.data.description, 'error')
}
localStorage.token = response.data.token;
window.location = '/dashboard';
localStorage.token = response.data.token
window.location = '/dashboard'
})
.catch(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(response => {
if (response.data.success === false) { return swal('Error', response.data.description, 'error'); }
window.location = '/dashboard';
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
.catch(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();
};
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 = '/dashboard'
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
window.onload = function () {
page.verify()
}

View File

@ -1,102 +1,112 @@
let panel = {};
/* eslint-disable no-unused-expressions */
/* global swal, axios */
panel.page;
panel.username;
panel.token = localStorage.token;
panel.filesView = localStorage.filesView;
let panel = {}
panel.preparePage = function() {
if (!panel.token) return window.location = '/auth';
panel.verifyToken(panel.token, true);
};
panel.page
panel.username
panel.token = localStorage.token
panel.filesView = localStorage.filesView
panel.verifyToken = function(token, reloadOnError) {
if (reloadOnError === undefined) { reloadOnError = false; }
panel.preparePage = function () {
if (!panel.token) {
window.location = '/auth'
return '/auth'
}
panel.verifyToken(panel.token, true)
}
axios.post('/api/tokens/verify', { token: token })
.then(response => {
panel.verifyToken = function (token, reloadOnError) {
if (reloadOnError === undefined) {
reloadOnError = false
}
axios.post('/api/tokens/verify', {
token: token
})
.then(function (response) {
if (response.data.success === false) {
swal({
title: 'An error ocurred',
text: response.data.description,
type: 'error'
}, () => {
}, function () {
if (reloadOnError) {
localStorage.removeItem('token');
location.location = '/auth';
localStorage.removeItem('token')
location.location = '/auth'
}
});
return;
}
axios.defaults.headers.common.token = token;
localStorage.token = token;
panel.token = token;
panel.username = response.data.username;
return panel.prepareDashboard();
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
panel.prepareDashboard = function() {
panel.page = document.getElementById('page');
document.getElementById('auth').style.display = 'none';
document.getElementById('dashboard').style.display = 'block';
document.getElementById('itemUploads').addEventListener('click', function() {
panel.setActiveMenu(this);
});
document.getElementById('itemManageGallery').addEventListener('click', function() {
panel.setActiveMenu(this);
});
document.getElementById('itemTokens').addEventListener('click', function() {
panel.setActiveMenu(this);
});
document.getElementById('itemPassword').addEventListener('click', function() {
panel.setActiveMenu(this);
});
document.getElementById('itemLogout').innerHTML = `Logout ( ${panel.username} )`;
panel.getAlbumsSidebar();
};
panel.logout = function() {
localStorage.removeItem('token');
location.reload('/');
};
panel.getUploads = function(album = undefined, page = undefined) {
if (page === undefined) page = 0;
let url = `/api/uploads/${page}`;
if (album !== undefined) { url = `/api/album/${album}/${page}`; }
axios.get(url).then(response => {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
return
}
var prevPage = 0;
var nextPage = page + 1;
axios.defaults.headers.common.token = token
localStorage.token = token
panel.token = token
panel.username = response.data.username
return panel.prepareDashboard()
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
if (response.data.files.length < 25) { nextPage = page; }
panel.prepareDashboard = function () {
panel.page = document.getElementById('page')
document.getElementById('auth').style.display = 'none'
document.getElementById('dashboard').style.display = 'block'
if (page > 0) prevPage = page - 1;
document.getElementById('itemUploads').addEventListener('click', function () {
panel.setActiveMenu(this)
})
panel.page.innerHTML = '';
var container = document.createElement('div');
document.getElementById('itemManageGallery').addEventListener('click', function () {
panel.setActiveMenu(this)
})
document.getElementById('itemTokens').addEventListener('click', function () {
panel.setActiveMenu(this)
})
document.getElementById('itemPassword').addEventListener('click', function () {
panel.setActiveMenu(this)
})
document.getElementById('itemLogout').innerHTML = `Logout ( ${panel.username} )`
panel.getAlbumsSidebar()
}
panel.logout = function () {
localStorage.removeItem('token')
location.reload('/')
}
panel.getUploads = function (album = undefined, page = undefined) {
if (page === undefined) page = 0
let url = '/api/uploads/' + page
if (album !== undefined) { url = '/api/album/' + album + '/' + page }
axios.get(url).then(function (response) {
if (response.data.success === false) {
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
if (response.data.files.length < 25) { nextPage = page }
if (page > 0) prevPage = page - 1
panel.page.innerHTML = ''
var container = document.createElement('div')
var pagination = `<nav class="pagination is-centered">
<a class="pagination-previous" onclick="panel.getUploads(${album}, ${prevPage} )">Previous</a>
<a class="pagination-next" onclick="panel.getUploads(${album}, ${nextPage} )">Next page</a>
</nav>`;
</nav>`
var listType = `
<div class="columns">
<div class="column">
@ -111,8 +121,9 @@ panel.getUploads = function(album = undefined, page = undefined) {
</span>
</a>
</div>
</div>`;
</div>`
var table, item
if (panel.filesView === 'thumbs') {
container.innerHTML = `
${pagination}
@ -122,20 +133,24 @@ panel.getUploads = function(album = undefined, page = undefined) {
</div>
${pagination}
`;
`
panel.page.appendChild(container);
var table = document.getElementById('table');
panel.page.appendChild(container)
table = document.getElementById('table')
for (var item of response.data.files) {
var div = document.createElement('div');
div.className = 'column is-2';
if (item.thumb !== undefined) { div.innerHTML = `<a href="${item.file}" target="_blank"><img src="${item.thumb}"/></a>`; } else { div.innerHTML = `<a href="${item.file}" target="_blank"><h1 class="title">.${item.file.split('.').pop()}</h1></a>`; }
table.appendChild(div);
for (item of response.data.files) {
var div = document.createElement('div')
div.className = 'column is-2'
if (item.thumb !== undefined) {
div.innerHTML = `<a href="${item.file}" target="_blank"><img src="${item.thumb}"/></a>`
} else {
div.innerHTML = `<a href="${item.file}" target="_blank"><h1 class="title">.${item.file.split('.').pop()}</h1></a>`
}
table.appendChild(div)
}
} else {
var albumOrUser = 'Album';
if (panel.username === 'root') { albumOrUser = 'User'; }
var albumOrUser = 'Album'
if (panel.username === 'root') { albumOrUser = 'User' }
container.innerHTML = `
${pagination}
@ -155,18 +170,19 @@ panel.getUploads = function(album = undefined, page = undefined) {
</table>
<hr>
${pagination}
`;
`
panel.page.appendChild(container);
var table = document.getElementById('table');
panel.page.appendChild(container)
table = document.getElementById('table')
for (var item of response.data.files) {
var tr = document.createElement('tr');
for (item of response.data.files) {
var tr = document.createElement('tr')
var displayAlbumOrUser = item.album;
var displayAlbumOrUser = item.album
console.log(item)
if (panel.username === 'root') {
displayAlbumOrUser = '';
if (item.username !== undefined) { displayAlbumOrUser = item.username; }
displayAlbumOrUser = ''
if (item.username !== undefined) { displayAlbumOrUser = item.username }
}
tr.innerHTML = `
@ -182,25 +198,25 @@ panel.getUploads = function(album = undefined, page = undefined) {
</a>
</td>
</tr>
`;
`
table.appendChild(tr);
table.appendChild(tr)
}
}
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.setFilesView = function(view, album, page) {
localStorage.filesView = view;
panel.filesView = view;
panel.getUploads(album, page);
};
panel.setFilesView = function (view, album, page) {
localStorage.filesView = view
panel.filesView = view
panel.getUploads(album, page)
}
panel.deleteFile = function(id) {
panel.deleteFile = function (id) {
swal({
title: 'Are you sure?',
text: 'You wont be able to recover the file!',
@ -210,35 +226,37 @@ panel.deleteFile = function(id) {
confirmButtonText: 'Yes, delete it!',
closeOnConfirm: false
},
() => {
axios.post('/api/upload/delete', { id: id })
.then(response => {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
}
swal('Deleted!', 'The file has been deleted.', 'success');
panel.getUploads();
function () {
axios.post('/api/upload/delete', {
id: id
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
}
);
};
panel.getAlbums = function() {
axios.get('/api/albums').then(response => {
.then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
panel.page.innerHTML = '';
var container = document.createElement('div');
container.className = 'container';
swal('Deleted!', 'The file has been deleted.', 'success')
panel.getUploads()
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
)
}
panel.getAlbums = function () {
axios.get('/api/albums').then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
panel.page.innerHTML = ''
var container = document.createElement('div')
container.className = 'container'
container.innerHTML = `
<h2 class="subtitle">Create new album</h2>
@ -261,13 +279,13 @@ panel.getAlbums = function() {
</thead>
<tbody id="table">
</tbody>
</table>`;
</table>`
panel.page.appendChild(container);
var table = document.getElementById('table');
panel.page.appendChild(container)
var table = document.getElementById('table')
for (var item of response.data.albums) {
var tr = document.createElement('tr');
var tr = document.createElement('tr')
tr.innerHTML = `
<tr>
<th>${item.name}</th>
@ -287,22 +305,22 @@ panel.getAlbums = function() {
</a>
</td>
</tr>
`;
`
table.appendChild(tr);
table.appendChild(tr)
}
document.getElementById('submitAlbum').addEventListener('click', () => {
panel.submitAlbum();
});
document.getElementById('submitAlbum').addEventListener('click', function () {
panel.submitAlbum()
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.renameAlbum = function(id) {
panel.renameAlbum = function (id) {
swal({
title: 'Rename album',
text: 'New name you want to give the album:',
@ -311,37 +329,37 @@ panel.renameAlbum = function(id) {
closeOnConfirm: false,
animation: 'slide-from-top',
inputPlaceholder: 'My super album'
}, inputValue => {
if (inputValue === false) return false;
}, function (inputValue) {
if (inputValue === false) return false
if (inputValue === '') {
swal.showInputError('You need to write something!');
return false;
swal.showInputError('You need to write something!')
return false
}
axios.post('/api/albums/rename', {
id: id,
name: inputValue
})
.then(response => {
.then(function (response) {
if (response.data.success === false) {
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;
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
}
swal('Success!', `Your album was renamed to: ${inputValue}`, 'success');
panel.getAlbumsSidebar();
panel.getAlbums();
swal('Success!', 'Your album was renamed to: ' + inputValue, 'success')
panel.getAlbumsSidebar()
panel.getAlbums()
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
});
};
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
})
}
panel.deleteAlbum = function(id) {
panel.deleteAlbum = function (id) {
swal({
title: 'Are you sure?',
text: "This won't delete your files, only the album!",
@ -351,93 +369,98 @@ panel.deleteAlbum = function(id) {
confirmButtonText: 'Yes, delete it!',
closeOnConfirm: false
},
() => {
axios.post('/api/albums/delete', { id: id })
.then(response => {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
}
swal('Deleted!', 'Your album has been deleted.', 'success');
panel.getAlbumsSidebar();
panel.getAlbums();
function () {
axios.post('/api/albums/delete', {
id: id
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
}
);
};
panel.submitAlbum = function() {
axios.post('/api/albums', { name: document.getElementById('albumName').value })
.then(response => {
.then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
swal('Woohoo!', 'Album was added successfully', 'success');
panel.getAlbumsSidebar();
panel.getAlbums();
swal('Deleted!', 'Your album has been deleted.', 'success')
panel.getAlbumsSidebar()
panel.getAlbums()
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
)
}
panel.getAlbumsSidebar = function() {
panel.submitAlbum = function () {
axios.post('/api/albums', {
name: document.getElementById('albumName').value
})
.then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
swal('Woohoo!', 'Album was added successfully', 'success')
panel.getAlbumsSidebar()
panel.getAlbums()
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.getAlbumsSidebar = function () {
axios.get('/api/albums/sidebar')
.then(response => {
.then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
var albumsContainer = document.getElementById('albumsContainer');
albumsContainer.innerHTML = '';
var albumsContainer = document.getElementById('albumsContainer')
albumsContainer.innerHTML = ''
if (response.data.albums === undefined) return;
if (response.data.albums === undefined) return
var li, a
for (var album of response.data.albums) {
li = document.createElement('li');
a = document.createElement('a');
a.id = album.id;
a.innerHTML = album.name;
li = document.createElement('li')
a = document.createElement('a')
a.id = album.id
a.innerHTML = album.name
a.addEventListener('click', function() {
panel.getAlbum(this);
});
a.addEventListener('click', function () {
panel.getAlbum(this)
})
li.appendChild(a);
albumsContainer.appendChild(li);
li.appendChild(a)
albumsContainer.appendChild(li)
}
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.getAlbum = function(item) {
panel.setActiveMenu(item);
panel.getUploads(item.id);
};
panel.getAlbum = function (item) {
panel.setActiveMenu(item)
panel.getUploads(item.id)
}
panel.changeToken = function() {
panel.changeToken = function () {
axios.get('/api/tokens')
.then(response => {
.then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
panel.page.innerHTML = '';
var container = document.createElement('div');
container.className = 'container';
panel.page.innerHTML = ''
var container = document.createElement('div')
container.className = 'container'
container.innerHTML = `
<h2 class="subtitle">Manage your token</h2>
@ -446,47 +469,47 @@ panel.changeToken = function() {
<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);
panel.page.appendChild(container)
document.getElementById('getNewToken').addEventListener('click', () => {
panel.getNewToken();
});
document.getElementById('getNewToken').addEventListener('click', function () {
panel.getNewToken()
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.getNewToken = function() {
panel.getNewToken = function () {
axios.post('/api/tokens/change')
.then(response => {
.then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
swal({
title: 'Woohoo!',
text: 'Your token was changed successfully.',
type: 'success'
}, () => {
localStorage.token = response.data.token;
location.reload();
});
}, function () {
localStorage.token = response.data.token
location.reload()
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.changePassword = function() {
panel.page.innerHTML = '';
var container = document.createElement('div');
container.className = 'container';
panel.changePassword = function () {
panel.page.innerHTML = ''
var container = document.createElement('div')
container.className = 'container'
container.innerHTML = `
<h2 class="subtitle">Change your password</h2>
@ -499,55 +522,55 @@ panel.changePassword = function() {
<input id="passwordConfirm" class="input is-expanded" type="password" placeholder="Verify your new password">
<a id="sendChangePassword" class="button is-primary">Set new password</a>
</p>
`;
`
panel.page.appendChild(container);
panel.page.appendChild(container)
document.getElementById('sendChangePassword').addEventListener('click', () => {
document.getElementById('sendChangePassword').addEventListener('click', function () {
if (document.getElementById('password').value === document.getElementById('passwordConfirm').value) {
panel.sendNewPassword(document.getElementById('password').value);
panel.sendNewPassword(document.getElementById('password').value)
} else {
swal({
title: 'Password mismatch!',
text: 'Your passwords do not match, please try again.',
type: 'error'
}, () => {
panel.changePassword();
});
}, function () {
panel.changePassword()
})
}
});
};
})
}
panel.sendNewPassword = function(pass) {
axios.post('/api/password/change', { password: pass })
.then(response => {
panel.sendNewPassword = function (pass) {
axios.post('/api/password/change', {password: pass})
.then(function (response) {
if (response.data.success === false) {
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token);
else return swal('An error ocurred', response.data.description, 'error');
if (response.data.description === 'No token provided') return panel.verifyToken(panel.token)
else return swal('An error ocurred', response.data.description, 'error')
}
swal({
title: 'Woohoo!',
text: 'Your password was changed successfully.',
type: 'success'
}, () => {
location.reload();
});
}, function () {
location.reload()
})
.catch(error => {
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
console.log(error);
});
};
})
.catch(function (error) {
console.log(error)
return swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.setActiveMenu = function(item) {
var menu = document.getElementById('menu');
var items = menu.getElementsByTagName('a');
for (var i = 0; i < items.length; i++) { items[i].className = ''; }
panel.setActiveMenu = function (item) {
var menu = document.getElementById('menu')
var items = menu.getElementsByTagName('a')
for (var i = 0; i < items.length; i++) { items[i].className = '' }
item.className = 'is-active';
};
item.className = 'is-active'
}
window.onload = function() {
panel.preparePage();
};
window.onload = function () {
panel.preparePage()
}

View File

@ -1,33 +1,39 @@
var upload = {};
/* eslint-disable no-unused-expressions */
/* global swal, axios, Dropzone */
upload.isPrivate = true;
upload.token = localStorage.token;
upload.maxFileSize;
var upload = {}
upload.isPrivate = true
upload.token = localStorage.token
upload.maxFileSize
// Add the album var to the upload so we can store the album id in there
upload.album;
upload.myDropzone;
upload.album
upload.myDropzone
upload.checkIfPublic = function() {
upload.checkIfPublic = function () {
axios.get('/api/check')
.then(response => {
upload.isPrivate = response.data.private;
upload.maxFileSize = response.data.maxFileSize;
upload.preparePage();
upload.isPrivate = response.data.private
upload.maxFileSize = response.data.maxFileSize
upload.preparePage()
})
.catch(error => {
swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
return console.log(error);
});
};
swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
return console.log(error)
})
}
upload.preparePage = function() {
if (!upload.isPrivate) return upload.prepareUpload();
if (!upload.token) return document.getElementById('loginToUpload').style.display = 'inline-flex';
upload.verifyToken(upload.token, true);
};
upload.preparePage = function () {
if (!upload.isPrivate) return upload.prepareUpload()
if (!upload.token) {
document.getElementById('loginToUpload').style.display = 'inline-flex'
return 'inline-flex'
}
upload.verifyToken(upload.token, true)
}
upload.verifyToken = function(token, reloadOnError) {
if (reloadOnError === undefined) { reloadOnError = false; }
upload.verifyToken = function (token, reloadOnError) {
if (reloadOnError === undefined) { reloadOnError = false }
axios.post('/api/tokens/verify', { token: token })
.then(response => {
@ -38,76 +44,76 @@ upload.verifyToken = function(token, reloadOnError) {
type: 'error'
}, () => {
if (reloadOnError) {
localStorage.removeItem('token');
location.reload();
localStorage.removeItem('token')
location.reload()
}
});
return;
})
return
}
localStorage.token = token;
upload.token = token;
return upload.prepareUpload();
localStorage.token = token
upload.token = token
return upload.prepareUpload()
})
.catch(error => {
swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
return console.log(error);
});
};
swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
return console.log(error)
})
}
upload.prepareUpload = function() {
upload.prepareUpload = function () {
// I think this fits best here because we need to check for a valid token before we can get the albums
if (upload.token) {
var select = document.getElementById('albumSelect');
var select = document.getElementById('albumSelect')
select.addEventListener('change', () => {
upload.album = select.value;
});
upload.album = select.value
})
axios.get('/api/albums', { headers: { token: upload.token } })
.then(res => {
var albums = res.data.albums;
var albums = res.data.albums
// If the user doesn't have any albums we don't really need to display
// an album selection
if (albums.length === 0) return;
if (albums.length === 0) return
// Loop through the albums and create an option for each album
for (var i = 0; i < albums.length; i++) {
var opt = document.createElement('option');
opt.value = albums[i].id;
opt.innerHTML = albums[i].name;
select.appendChild(opt);
var opt = document.createElement('option')
opt.value = albums[i].id
opt.innerHTML = albums[i].name
select.appendChild(opt)
}
// Display the album selection
document.getElementById('albumDiv').style.display = 'block';
document.getElementById('albumDiv').style.display = 'block'
})
.catch(e => {
swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error');
return console.log(e);
});
swal('An error ocurred', 'There was an error with the request, please check the console for more information.', 'error')
return console.log(e)
})
}
div = document.createElement('div');
div.id = 'dropzone';
div.innerHTML = 'Click here or drag and drop files';
div.style.display = 'flex';
var div = document.createElement('div')
div.id = 'dropzone'
div.innerHTML = 'Click here or drag and drop files'
div.style.display = 'flex'
document.getElementById('maxFileSize').innerHTML = `Maximum upload size per file is ${upload.maxFileSize}`;
document.getElementById('loginToUpload').style.display = 'none';
document.getElementById('maxFileSize').innerHTML = `Maximum upload size per file is ${upload.maxFileSize}`
document.getElementById('loginToUpload').style.display = 'none'
if (upload.token === undefined) { document.getElementById('loginLinkText').innerHTML = 'Create an account and keep track of your uploads'; }
if (upload.token === undefined) { document.getElementById('loginLinkText').innerHTML = 'Create an account and keep track of your uploads' }
document.getElementById('uploadContainer').appendChild(div);
document.getElementById('uploadContainer').appendChild(div)
upload.prepareDropzone();
};
upload.prepareDropzone()
}
upload.prepareDropzone = function() {
var previewNode = document.querySelector('#template');
previewNode.id = '';
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
upload.prepareDropzone = function () {
var previewNode = document.querySelector('#template')
previewNode.id = ''
var previewTemplate = previewNode.parentNode.innerHTML
previewNode.parentNode.removeChild(previewNode)
var dropzone = new Dropzone('div#dropzone', {
url: '/api/upload',
@ -121,52 +127,52 @@ upload.prepareDropzone = function() {
maxFiles: 1000,
autoProcessQueue: true,
headers: { token: upload.token },
init: function() {
upload.myDropzone = this;
init: function () {
upload.myDropzone = this
this.on('addedfile', file => {
document.getElementById('uploads').style.display = 'block';
});
document.getElementById('uploads').style.display = 'block'
})
// Add the selected albumid, if an album is selected, as a header
this.on('sending', (file, xhr) => {
if (upload.album) {
xhr.setRequestHeader('albumid', upload.album);
xhr.setRequestHeader('albumid', upload.album)
}
});
})
}
});
})
// Update the total progress bar
dropzone.on('uploadprogress', (file, progress) => {
file.previewElement.querySelector('.progress').setAttribute('value', progress);
file.previewElement.querySelector('.progress').innerHTML = `${progress}%`;
});
file.previewElement.querySelector('.progress').setAttribute('value', progress)
file.previewElement.querySelector('.progress').innerHTML = `${progress}%`
})
dropzone.on('success', (file, response) => {
// Handle the responseText here. For example, add the text to the preview element:
if (response.success === false) {
var span = document.createElement('span');
span.innerHTML = response.description;
file.previewTemplate.querySelector('.link').appendChild(span);
return;
var span = document.createElement('span')
span.innerHTML = response.description
file.previewTemplate.querySelector('.link').appendChild(span)
return
}
a = document.createElement('a');
a.href = response.files[0].url;
a.target = '_blank';
a.innerHTML = response.files[0].url;
file.previewTemplate.querySelector('.link').appendChild(a);
var a = document.createElement('a')
a.href = response.files[0].url
a.target = '_blank'
a.innerHTML = response.files[0].url
file.previewTemplate.querySelector('.link').appendChild(a)
file.previewTemplate.querySelector('.progress').style.display = 'none';
});
file.previewTemplate.querySelector('.progress').style.display = 'none'
})
upload.prepareShareX();
};
upload.prepareShareX()
}
upload.prepareShareX = function() {
upload.prepareShareX = function () {
if (upload.token) {
var sharex_element = document.getElementById('ShareX');
var sharex_file = `{\r\n\
var sharexElement = document.getElementById('ShareX')
var sharexFile = `{\r\n\
"Name": "${location.hostname}",\r\n\
"DestinationType": "ImageUploader, FileUploader",\r\n\
"RequestType": "POST",\r\n\
@ -178,30 +184,29 @@ upload.prepareShareX = function() {
"ResponseType": "Text",\r\n\
"URL": "$json:files[0].url$",\r\n\
"ThumbnailURL": "$json:files[0].url$"\r\n\
}`;
var sharex_blob = new Blob([sharex_file], { type: 'application/octet-binary' });
sharex_element.setAttribute('href', URL.createObjectURL(sharex_blob));
sharex_element.setAttribute('download', `${location.hostname}.sxcu`);
}`
var sharexBlob = new Blob([sharexFile], { type: 'application/octet-binary' })
sharexElement.setAttribute('href', URL.createObjectURL(sharexBlob))
sharexElement.setAttribute('download', `${location.hostname}.sxcu`)
}
};
}
// Handle image paste event
window.addEventListener('paste', event => {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (index in items) {
var item = items[index];
var items = (event.clipboardData || event.originalEvent.clipboardData).items
for (var 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);
upload.myDropzone.addFile(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)
upload.myDropzone.addFile(file)
}
}
});
window.onload = function() {
upload.checkIfPublic();
};
})
window.onload = function () {
upload.checkIfPublic()
}

View File

@ -1,26 +1,26 @@
const config = require('../config.js');
const routes = require('express').Router();
const db = require('knex')(config.database);
const path = require('path');
const utils = require('../controllers/utilsController.js');
const config = require('../config.js')
const routes = require('express').Router()
const db = require('knex')(config.database)
const path = require('path')
const utils = require('../controllers/utilsController.js')
routes.get('/a/:identifier', async (req, res, next) => {
let identifier = req.params.identifier;
if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' });
let identifier = req.params.identifier
if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' })
const album = await db.table('albums').where({ identifier, enabled: 1 }).first();
if (!album) return res.status(404).sendFile('404.html', { root: './pages/error/' });
const album = await db.table('albums').where({ identifier, enabled: 1 }).first()
if (!album) return res.status(404).sendFile('404.html', { root: './pages/error/' })
const files = await db.table('files').select('name').where('albumid', album.id).orderBy('id', 'DESC');
let thumb = '';
const basedomain = config.domain;
const files = await db.table('files').select('name').where('albumid', album.id).orderBy('id', 'DESC')
let thumb = ''
const basedomain = config.domain
for (let file of files) {
file.file = `${basedomain}/${file.name}`;
file.file = `${basedomain}/${file.name}`
let ext = path.extname(file.name).toLowerCase();
let ext = path.extname(file.name).toLowerCase()
if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) {
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`;
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`
/*
If thumbnail for album is still not set, do it.
@ -29,18 +29,17 @@ routes.get('/a/:identifier', async (req, res, next) => {
*/
if (thumb === '') {
thumb = file.thumb;
thumb = file.thumb
}
file.thumb = `<img src="${file.thumb}"/>`;
file.thumb = `<img src="${file.thumb}"/>`
} else {
file.thumb = `<h1 class="title">.${ext}</h1>`;
file.thumb = `<h1 class="title">.${ext}</h1>`
}
}
let enableDownload = false;
if (config.uploads.generateZips) enableDownload = true;
let enableDownload = false
if (config.uploads.generateZips) enableDownload = true
return res.render('album', {
layout: false,
@ -50,7 +49,7 @@ routes.get('/a/:identifier', async (req, res, next) => {
files,
identifier,
enableDownload
});
});
})
})
module.exports = routes;
module.exports = routes

View File

@ -1,37 +1,37 @@
const config = require('../config.js');
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');
const config = require('../config.js')
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({
private: config.private,
maxFileSize: config.uploads.maxSize
});
});
})
})
routes.post('/login', (req, res, next) => authController.verify(req, res, next));
routes.post('/register', (req, res, next) => authController.register(req, res, next));
routes.post('/password/change', (req, res, next) => authController.changePassword(req, res, next));
routes.get('/uploads', (req, res, next) => uploadController.list(req, res, next));
routes.get('/uploads/:page', (req, res, next) => uploadController.list(req, res, next));
routes.post('/upload', (req, res, next) => uploadController.upload(req, res, next));
routes.post('/upload/delete', (req, res, next) => uploadController.delete(req, res, next));
routes.post('/upload/:albumid', (req, res, next) => uploadController.upload(req, res, next));
routes.get('/album/get/:identifier', (req, res, next) => albumsController.get(req, res, next));
routes.get('/album/zip/:identifier', (req, res, next) => albumsController.generateZip(req, res, next));
routes.get('/album/:id', (req, res, next) => uploadController.list(req, res, next));
routes.get('/album/:id/:page', (req, res, next) => uploadController.list(req, res, next));
routes.get('/albums', (req, res, next) => albumsController.list(req, res, next));
routes.get('/albums/:sidebar', (req, res, next) => albumsController.list(req, res, next));
routes.post('/albums', (req, res, next) => albumsController.create(req, res, next));
routes.post('/albums/delete', (req, res, next) => albumsController.delete(req, res, next));
routes.post('/albums/rename', (req, res, next) => albumsController.rename(req, res, next));
routes.get('/albums/test', (req, res, next) => albumsController.test(req, res, next));
routes.get('/tokens', (req, res, next) => tokenController.list(req, res, next));
routes.post('/tokens/verify', (req, res, next) => tokenController.verify(req, res, next));
routes.post('/tokens/change', (req, res, next) => tokenController.change(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.post('/password/change', (req, res, next) => authController.changePassword(req, res, next))
routes.get('/uploads', (req, res, next) => uploadController.list(req, res, next))
routes.get('/uploads/:page', (req, res, next) => uploadController.list(req, res, next))
routes.post('/upload', (req, res, next) => uploadController.upload(req, res, next))
routes.post('/upload/delete', (req, res, next) => uploadController.delete(req, res, next))
routes.post('/upload/:albumid', (req, res, next) => uploadController.upload(req, res, next))
routes.get('/album/get/:identifier', (req, res, next) => albumsController.get(req, res, next))
routes.get('/album/zip/:identifier', (req, res, next) => albumsController.generateZip(req, res, next))
routes.get('/album/:id', (req, res, next) => uploadController.list(req, res, next))
routes.get('/album/:id/:page', (req, res, next) => uploadController.list(req, res, next))
routes.get('/albums', (req, res, next) => albumsController.list(req, res, next))
routes.get('/albums/:sidebar', (req, res, next) => albumsController.list(req, res, next))
routes.post('/albums', (req, res, next) => albumsController.create(req, res, next))
routes.post('/albums/delete', (req, res, next) => albumsController.delete(req, res, next))
routes.post('/albums/rename', (req, res, next) => albumsController.rename(req, res, next))
routes.get('/albums/test', (req, res, next) => albumsController.test(req, res, next))
routes.get('/tokens', (req, res, next) => tokenController.list(req, res, next))
routes.post('/tokens/verify', (req, res, next) => tokenController.verify(req, res, next))
routes.post('/tokens/change', (req, res, next) => tokenController.change(req, res, next))
module.exports = routes;
module.exports = routes

763
yarn.lock

File diff suppressed because it is too large Load Diff