Updates (WARNING!)

WARNING: Please turn off lolisafe before upgrading, then run "node database/migration.js" once after upgrading. Ignore all errors/warnings about duplicate column name. Afterwards make sure your config.js follows the new format in config.sample.js (specifically fileLength and generateThumbnails options).

* generateImageThumbnails and generateVideoThumbnails options in config.js is now renamed to an object named generateThumbnails, with image and video as its properties.

* fileLength option is now an object with min, max, default and userChangeable as its properties.

* User may now change their preferred file length (following the previous option, of course).

* Updated a bunch of responses messages. Mainly appending a dot to the messages.

* New APIs:
/fileLength/config to get an object of the current fileLength config (exactly what is in the config.js file).
/fileLength/change to change user's preferred file length.

* And maybe some others ...?
This commit is contained in:
Bobby Wibowo 2018-03-24 20:52:47 +07:00
parent 763d06ff95
commit 616124446f
No known key found for this signature in database
GPG Key ID: 51C3A1E1E22D26CF
17 changed files with 179 additions and 70 deletions

View File

@ -64,8 +64,21 @@ module.exports = {
*/
maxSize: '512MB',
// The length of the random generated name for the uploaded files
fileLength: 32,
/*
The length of the random generated name for the uploaded files.
If "userChangeable" is set to true, registered users will be able to change
their preferred file name length from the dashboard. The allowed range will
be set by "min" and "max". Otherwise it will use "default".
Technically it's possible to have "default" outside of the "min" and "max" range,
but please not. Once a user has changed to a number within the range, the user will
no longer be able to use the default value.
*/
fileLength: {
min: 4,
max: 32,
default: 32,
userChangeable: false
},
/*
This option will limit how many times it will try to generate random names
@ -79,8 +92,10 @@ module.exports = {
to install a separate binary called graphicsmagick (http://www.graphicsmagick.org)
for images and ffmpeg (https://ffmpeg.org/) for video files
*/
generateImageThumbnails: true,
generateVideoThumbnails: false,
generateThumbnails: {
image: true,
video: false
},
/*
Allows users to download a .zip file of all files in an album.

View File

@ -46,7 +46,7 @@ albumsController.create = async (req, res, next) => {
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({
@ -56,7 +56,7 @@ albumsController.create = async (req, res, next) => {
}).first()
if (album) {
return res.json({ success: false, description: 'There\'s already an album with that name' })
return res.json({ success: false, description: 'There\'s already an album with that name.' })
}
await db.table('albums').insert({
@ -77,7 +77,7 @@ albumsController.delete = async (req, res, next) => {
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 })
@ -89,17 +89,17 @@ albumsController.rename = async (req, res, next) => {
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
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()
if (album) {
return res.json({ success: false, description: 'Name already in use' })
return res.json({ success: false, description: 'Name already in use.' })
}
await db.table('albums').where({ id: id, userid: user.id }).update({ name: name })
@ -108,10 +108,10 @@ albumsController.rename = async (req, res, next) => {
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' })
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' })
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')
@ -120,7 +120,7 @@ albumsController.get = async (req, res, next) => {
file.file = `${config.domain}/${file.name}`
const ext = path.extname(file.name).toLowerCase()
if ((config.uploads.generateImageThumbnails && utils.imageExtensions.includes(ext)) || (config.uploads.generateVideoThumbnails && utils.videoExtensions.includes(ext))) {
if ((config.uploads.generateThumbnails.image && utils.imageExtensions.includes(ext)) || (config.uploads.generateThumbnails.video && utils.videoExtensions.includes(ext))) {
file.thumb = `${config.domain}/thumbs/${file.name.slice(0, -ext.length)}.png`
}
}
@ -135,11 +135,11 @@ albumsController.get = async (req, res, next) => {
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' })
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' })
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`)
@ -148,7 +148,7 @@ albumsController.generateZip = async (req, res, next) => {
} 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' })
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()

View File

@ -10,53 +10,53 @@ authController.verify = async (req, res, next) => {
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' })
if (!user) return res.json({ success: false, description: 'Username doesn\'t exist.' })
if (user.enabled === false || user.enabled === 0) {
return res.json({
success: false,
description: 'This account has been disabled'
description: 'This account has been disabled.'
})
}
bcrypt.compare(password, user.password, (err, result) => {
if (err) {
console.log(err)
return res.json({ success: false, description: 'There was an error' })
return res.json({ success: false, description: 'There was an error.' })
}
if (result === false) return res.json({ success: false, description: 'Wrong password' })
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
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' })
return res.json({ success: false, description: 'Username must have 4-32 characters.' })
}
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.' })
}
const user = await db.table('users').where('username', username).first()
if (user) return res.json({ success: false, description: 'Username already exists' })
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 (╯°□°)╯︵ ┻━┻' })
return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻.' })
}
const token = randomstring.generate(64)
await db.table('users').insert({
@ -73,16 +73,16 @@ authController.changePassword = async (req, res, next) => {
const user = await utils.authorize(req, res)
let password = req.body.password
if (password === undefined) return res.json({ success: false, description: 'No password provided' })
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 (╯°□°)╯︵ ┻━┻' })
return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻.' })
}
await db.table('users').where('id', user.id).update({ password: hash })
@ -90,4 +90,32 @@ authController.changePassword = async (req, res, next) => {
})
}
authController.getFileLengthConfig = async (req, res, next) => {
const user = await utils.authorize(req, res)
return res.json({ success: true, fileLength: user.fileLength, config: config.uploads.fileLength })
}
authController.changeFileLength = async (req, res, next) => {
if (config.uploads.fileLength.userChangeable === false) {
return res.json({ success: false, description: 'Changing file length is disabled at the moment.' })
}
const user = await utils.authorize(req, res)
let fileLength = parseInt(req.body.fileLength)
if (fileLength === undefined) return res.json({ success: false, description: 'No file length provided.' })
if (isNaN(fileLength)) return res.json({ success: false, description: 'File length is not a valid number.' })
if (fileLength < config.uploads.fileLength.min || fileLength > config.uploads.fileLength.max) {
return res.json({ success: false, description: `File length must be ${config.uploads.fileLength.min} to ${config.uploads.fileLength.max} characters` })
}
if (fileLength === user.fileLength) {
return res.json({ success: true })
}
await db.table('users').where('id', user.id).update({ fileLength })
return res.json({ success: true })
}
module.exports = authController

View File

@ -7,10 +7,10 @@ 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' })
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' })
if (!user) return res.status(401).json({ success: false, description: 'Invalid token.' })
return res.json({ success: true, username: user.username })
}

View File

@ -18,8 +18,10 @@ const storage = multer.diskStorage({
cb(null, uploadDir)
},
filename: function (req, file, cb) {
// If the user has a preferred file length, make sure it follows the allowed range
const fileLength = req.params.fileLength ? Math.min(Math.max(req.params.fileLength, config.uploads.fileLength.min), config.uploads.fileLength.max) : config.uploads.fileLength.default
const access = i => {
const name = randomstring.generate(config.uploads.fileLength) + path.extname(file.originalname)
const name = randomstring.generate(fileLength) + path.extname(file.originalname)
fs.access(path.join(uploadDir, name), err => {
if (err) return cb(null, name)
console.log(`A file named "${name}" already exists (${++i}/${maxTries}).`)
@ -36,12 +38,10 @@ const upload = multer({
storage: storage,
limits: { fileSize: config.uploads.maxSize },
fileFilter: function (req, file, cb) {
if (config.blockedExtensions !== undefined) {
if (config.blockedExtensions.some(extension => path.extname(file.originalname).toLowerCase() === extension)) {
// eslint-disable-next-line standard/no-callback-literal
return cb('This file extension is not allowed')
}
return cb(null, true)
if (config.blockedExtensions === undefined) return cb(null, true)
if (config.blockedExtensions.some(extension => path.extname(file.originalname).toLowerCase() === extension)) {
// eslint-disable-next-line standard/no-callback-literal
return cb('This file extension is not allowed.')
}
return cb(null, true)
}
@ -57,9 +57,12 @@ uploadsController.upload = async (req, res, next) => {
if (user && (user.enabled === false || user.enabled === 0)) {
return res.json({
success: false,
description: 'This account has been disabled'
description: 'This account has been disabled.'
})
}
if (user && user.fileLength) {
req.params.fileLength = user.fileLength
}
const albumid = req.headers.albumid || req.params.albumid
if (albumid && user) {
@ -67,7 +70,7 @@ uploadsController.upload = async (req, res, next) => {
if (!album) {
return res.json({
success: false,
description: 'Album doesn\'t exist or it doesn\'t belong to the user'
description: 'Album doesn\'t exist or it doesn\'t belong to the user.'
})
}
return uploadsController.actuallyUpload(req, res, user, albumid)
@ -167,14 +170,14 @@ uploadsController.processFilesForDisplay = async (req, res, files, existingFiles
for (let file of files) {
let ext = path.extname(file.name).toLowerCase()
if ((config.uploads.generateImageThumbnails && utils.imageExtensions.includes(ext)) || (config.uploads.generateVideoThumbnails && utils.videoExtensions.includes(ext))) {
if ((config.uploads.generateThumbnails.image && utils.imageExtensions.includes(ext)) || (config.uploads.generateThumbnails.video && utils.videoExtensions.includes(ext))) {
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.' }) })
}
}
}
@ -183,7 +186,7 @@ uploadsController.delete = async (req, res) => {
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')
@ -285,7 +288,7 @@ uploadsController.list = async (req, res) => {
}
let ext = path.extname(file.name).toLowerCase()
if ((config.uploads.generateImageThumbnails && utils.imageExtensions.includes(ext)) || (config.uploads.generateVideoThumbnails && utils.videoExtensions.includes(ext))) {
if ((config.uploads.generateThumbnails.image && utils.imageExtensions.includes(ext)) || (config.uploads.generateThumbnails.video && utils.videoExtensions.includes(ext))) {
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`
}
}

View File

@ -23,10 +23,10 @@ utilsController.getPrettyDate = function (date) {
utilsController.authorize = async (req, res) => {
const token = req.headers.token
if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })
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' })
if (!user) return res.status(401).json({ success: false, description: 'Invalid token.' })
return user
}
@ -36,8 +36,8 @@ utilsController.generateThumbs = function (file, basedomain) {
const isImageExt = utilsController.imageExtensions.includes(ext)
if (!isVideoExt && !isImageExt) return
if (isVideoExt && config.uploads.generateVideoThumbnails !== true) return
if (isImageExt && config.uploads.generateImageThumbnails !== true) return
if (isVideoExt && config.uploads.generateThumbnails.video !== true) return
if (isImageExt && config.uploads.generateThumbnails.image !== true) return
let thumbname = path.join(__dirname, '..', config.uploads.folder, 'thumbs', file.name.slice(0, -ext.length) + '.png')
fs.access(thumbname, err => {

View File

@ -3,13 +3,10 @@ const db = require('knex')(config.database)
const migration = {}
migration.start = async () => {
await db.schema.table('albums', table => {
table.dateTime('editedAt')
table.dateTime('zipGeneratedAt')
}).catch(() => {})
await db.schema.table('users', table => {
table.integer('enabled')
}).catch(() => {})
await db.schema.table('albums', t => t.dateTime('editedAt')).catch(err => console.warn(err.message))
await db.schema.table('albums', t => t.dateTime('zipGeneratedAt')).catch(err => console.warn(err.message))
await db.schema.table('users', t => t.dateTime('enabled')).catch(err => console.warn(err.message))
await db.schema.table('users', t => t.dateTime('fileLength')).catch(err => console.warn(err.message))
console.log('Migration finished! Now start lolisafe normally')
process.exit(0)
}

View File

@ -11,7 +11,7 @@
<!-- Stylesheets and scripts -->
<link rel="stylesheet" type="text/css" href="libs/bulma/bulma.min.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="css/style.css?v=wtTfETVFNy">
<link rel="stylesheet" type="text/css" href="css/style.css?v=ugMWEbHDxs">
<script type="text/javascript" src="libs/sweetalert/sweetalert.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="libs/axios/axios.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="js/album.js?v=V2RnA3Mwhh"></script>

View File

@ -12,7 +12,7 @@
<!-- Stylesheets and scripts -->
<link rel="stylesheet" type="text/css" href="libs/bulma/bulma.min.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="libs/fontello/fontello.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="css/style.css?v=wtTfETVFNy">
<link rel="stylesheet" type="text/css" href="css/style.css?v=ugMWEbHDxs">
<script type="text/javascript" src="libs/sweetalert/sweetalert.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="libs/axios/axios.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="js/auth.js?v=V2RnA3Mwhh"></script>

View File

@ -12,8 +12,8 @@
<!-- Stylesheets and scripts -->
<link rel="stylesheet" type="text/css" href="libs/bulma/bulma.min.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="libs/fontello/fontello.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="css/style.css?v=wtTfETVFNy">
<link rel="stylesheet" type="text/css" href="css/dashboard.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="css/style.css?v=ugMWEbHDxs">
<link rel="stylesheet" type="text/css" href="css/dashboard.css?v=ugMWEbHDxs">
<script type="text/javascript" src="libs/sweetalert/sweetalert.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="libs/axios/axios.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="js/dashboard.js?v=29qSkTNt9U"></script>
@ -108,7 +108,10 @@
<p class="menu-label">Administration</p>
<ul class="menu-list">
<li>
<a id="itemTokens" onclick="panel.changeToken()">Change your token</a>
<a id="itemFileLength" onclick="panel.changeFileLength()">Preferred file length</a>
</li>
<li>
<a id="itemTokens" onclick="panel.changeToken()">Manage your token</a>
</li>
<li>
<a id="itemPassword" onclick="panel.changePassword()">Change your password</a>

View File

@ -11,7 +11,7 @@
<!-- Stylesheets and scripts -->
<link rel="stylesheet" type="text/css" href="libs/bulma/bulma.min.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="css/style.css?v=wtTfETVFNy">
<link rel="stylesheet" type="text/css" href="css/style.css?v=ugMWEbHDxs">
<!-- Open Graph tags -->
<meta property="og:type" content="website" />

View File

@ -11,7 +11,7 @@
<!-- Stylesheets and scripts -->
<link rel="stylesheet" type="text/css" href="libs/bulma/bulma.min.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="css/style.css?v=wtTfETVFNy">
<link rel="stylesheet" type="text/css" href="css/style.css?v=ugMWEbHDxs">
<script type="text/javascript" src="libs/sweetalert/sweetalert.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="libs/dropzone/dropzone.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="libs/axios/axios.min.js?v=V2RnA3Mwhh"></script>

View File

@ -207,3 +207,7 @@ section#dashboard div#table div.column .title {
line-height: 200px;
font-weight: normal;
}
.help {
color: #7f8c8d;
}

View File

@ -462,6 +462,63 @@ panel.getAlbum = function (item) {
panel.getUploads(item.id)
}
panel.changeFileLength = function () {
axios.get('api/fileLength/config')
.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 occurred', response.data.description, 'error')
}
panel.page.innerHTML = `
<h2 class="subtitle">Preferred file length</h2>
<div class="field">
<label class="label">Your current file length:</label>
<div class="field has-addons">
<div class="control is-expanded">
<input id="fileLength" class="input" type="text" placeholder="Your file length" value="${response.data.fileLength ? Math.min(Math.max(response.data.fileLength, response.data.config.min), response.data.config.max) : response.data.config.default}">
</div>
<div class="control">
<a id="setFileLength" class="button is-primary">Set file length</a>
</div>
</div>
<p class="help">Default file length is <b>${response.data.config.default}</b> characters. ${response.data.config.userChangeable ? `Range allowed for user is <b>${response.data.config.min}</b> to <b>${response.data.config.max}</b> characters.` : 'Changing file length is disabled at the moment.'}</p>
</div>
`
document.getElementById('setFileLength').addEventListener('click', function () {
panel.setFileLength(document.getElementById('fileLength').value)
})
})
.catch(function (error) {
console.log(error)
return swal('An error occurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.setFileLength = function (fileLength) {
axios.post('api/fileLength/change', { fileLength })
.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 occurred', response.data.description, 'error')
}
swal({
title: 'Woohoo!',
text: 'Your file length was successfully changed.',
icon: 'success'
}).then(() => {
location.reload()
})
})
.catch(function (error) {
console.log(error)
return swal('An error occurred', 'There was an error with the request, please check the console for more information.', 'error')
})
}
panel.changeToken = function () {
axios.get('api/tokens')
.then(function (response) {
@ -506,7 +563,7 @@ panel.getNewToken = function () {
swal({
title: 'Woohoo!',
text: 'Your token was changed successfully.',
text: 'Your token was successfully changed.',
icon: 'success'
}).then(() => {
localStorage.token = response.data.token
@ -567,7 +624,7 @@ panel.sendNewPassword = function (pass) {
swal({
title: 'Woohoo!',
text: 'Your password was changed successfully.',
text: 'Your password was successfully changed.',
icon: 'success'
}).then(() => {
location.reload()

View File

@ -19,7 +19,7 @@ routes.get('/a/:identifier', async (req, res, next) => {
file.file = `${basedomain}/${file.name}`
let ext = path.extname(file.name).toLowerCase()
if ((config.uploads.generateImageThumbnails && utils.imageExtensions.includes(ext)) || (config.uploads.generateVideoThumbnails && utils.videoExtensions.includes(ext))) {
if ((config.uploads.generateThumbnails.image && utils.imageExtensions.includes(ext)) || (config.uploads.generateThumbnails.video && utils.videoExtensions.includes(ext))) {
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`
/*

View File

@ -33,5 +33,7 @@ routes.get('/albums/test', (req, res, next) => albumsController.test(req, res, n
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.get('/fileLength/config', (req, res, next) => authController.getFileLengthConfig(req, res, next))
routes.post('/fileLength/change', (req, res, next) => authController.changeFileLength(req, res, next))
module.exports = routes

View File

@ -11,7 +11,7 @@
<!-- Stylesheets and scripts -->
<link rel="stylesheet" type="text/css" href="../libs/bulma/bulma.min.css?v=V2RnA3Mwhh">
<link rel="stylesheet" type="text/css" href="../css/style.css?v=wtTfETVFNy">
<link rel="stylesheet" type="text/css" href="../css/style.css?v=ugMWEbHDxs">
<script type="text/javascript" src="../libs/sweetalert/sweetalert.min.js?v=V2RnA3Mwhh"></script>
<script type="text/javascript" src="../libs/axios/axios.min.js?v=V2RnA3Mwhh"></script>