Updated ESLint rule: curly

No more enforced curly for if/else/for/while/do blocks w/ one statement.

With that said, auto-fixed all JS files to follow the rule.

I'd also like to apologize for the inconveniences this commit cause,
after all it was me who intentionally enforced curly rule back then.

Why the change of heart?
After doing some more non-JS codes recently, I realized it was
pretty stupid of me to enforce that.
This commit is contained in:
Bobby Wibowo 2018-12-19 00:01:28 +07:00
parent bca9169ea4
commit 52d336cc45
No known key found for this signature in database
GPG Key ID: 51C3A1E1E22D26CF
14 changed files with 393 additions and 539 deletions

View File

@ -12,7 +12,7 @@
"rules": {
"curly": [
"error",
"all"
"multi"
],
"prefer-const": [
"error",

View File

@ -28,12 +28,11 @@ class ZipEmitter extends EventEmitter {
albumsController.list = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
let fields = ['id', 'name']
if (req.params.sidebar === undefined) {
if (req.params.sidebar === undefined)
fields = fields.concat(fields, ['timestamp', 'identifier', 'editedAt', 'download', 'public', 'description'])
}
const albums = await db.table('albums')
.select(fields)
@ -42,9 +41,8 @@ albumsController.list = async (req, res, next) => {
userid: user.id
})
if (req.params.sidebar !== undefined) {
if (req.params.sidebar !== undefined)
return res.json({ success: true, albums })
}
const ids = []
for (const album of albums) {
@ -59,21 +57,20 @@ albumsController.list = async (req, res, next) => {
.select('albumid')
const albumsCount = {}
for (const id of ids) { albumsCount[id] = 0 }
for (const file of files) { albumsCount[file.albumid] += 1 }
for (const album of albums) { album.files = albumsCount[album.id] }
for (const id of ids) albumsCount[id] = 0
for (const file of files) albumsCount[file.albumid] += 1
for (const album of albums) album.files = albumsCount[album.id]
return res.json({ success: true, albums, homeDomain })
}
albumsController.create = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const name = utils.escape(req.body.name)
if (name === undefined || name === '') {
if (name === undefined || name === '')
return res.json({ success: false, description: 'No album name specified.' })
}
const album = await db.table('albums')
.where({
@ -83,15 +80,14 @@ albumsController.create = async (req, res, next) => {
})
.first()
if (album) {
if (album)
return res.json({ success: false, description: 'There\'s already an album with that name.' })
}
const identifier = await albumsController.getUniqueRandomName()
.catch(error => {
res.json({ success: false, description: error.toString() })
})
if (!identifier) { return }
if (!identifier) return
const ids = await db.table('albums').insert({
name,
@ -116,9 +112,9 @@ albumsController.getUniqueRandomName = () => {
db.table('albums')
.where('identifier', identifier)
.then(rows => {
if (!rows || !rows.length) { return resolve(identifier) }
if (!rows || !rows.length) return resolve(identifier)
console.log(`An album with identifier ${identifier} already exists (${++i}/${maxTries}).`)
if (i < maxTries) { return select(i) }
if (i < maxTries) return select(i)
// eslint-disable-next-line prefer-promise-reject-errors
return reject('Sorry, we could not allocate a unique random identifier. Try again?')
})
@ -130,13 +126,12 @@ albumsController.getUniqueRandomName = () => {
albumsController.delete = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const id = req.body.id
const purge = req.body.purge
if (id === undefined || id === '') {
if (id === undefined || id === '')
return res.json({ success: false, description: 'No album specified.' })
}
let failed = []
if (purge) {
@ -150,9 +145,8 @@ albumsController.delete = async (req, res, next) => {
const ids = files.map(file => file.id)
failed = await utils.bulkDeleteFiles('id', ids, user)
if (failed.length === ids.length) {
if (failed.length === ids.length)
return res.json({ success: false, description: 'Could not delete any of the files associated with the album.' })
}
}
}
@ -185,17 +179,15 @@ albumsController.delete = async (req, res, next) => {
albumsController.edit = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const id = parseInt(req.body.id)
if (isNaN(id)) {
if (isNaN(id))
return res.json({ success: false, description: 'No album specified.' })
}
const name = utils.escape(req.body.name)
if (name === undefined || name === '') {
if (name === undefined || name === '')
return res.json({ success: false, description: 'No name specified.' })
}
const album = await db.table('albums')
.where({
@ -205,14 +197,13 @@ albumsController.edit = async (req, res, next) => {
})
.first()
if (!album) {
if (!album)
return res.json({ success: false, description: 'Could not get album with the specified ID.' })
} else if (album.id !== id) {
else if (album.id !== id)
return res.json({ success: false, description: 'Name already in use.' })
} else if (req._old && (album.id === id)) {
else if (req._old && (album.id === id))
// Old rename API
return res.json({ success: false, description: 'You did not specify a new name.' })
}
await db.table('albums')
.where({
@ -240,7 +231,7 @@ albumsController.edit = async (req, res, next) => {
.catch(error => {
res.json({ success: false, description: error.toString() })
})
if (!identifier) { return }
if (!identifier) return
await db.table('albums')
.where({
@ -252,9 +243,9 @@ albumsController.edit = async (req, res, next) => {
// Rename zip archive of the album if it exists
const zipPath = path.join(zipsDir, `${oldIdentifier}.zip`)
return fs.access(zipPath, error => {
if (error) { return res.json({ success: true, identifier }) }
if (error) return res.json({ success: true, identifier })
fs.rename(zipPath, path.join(zipsDir, `${identifier}.zip`), error => {
if (!error) { return res.json({ success: true, identifier }) }
if (!error) return res.json({ success: true, identifier })
console.error(error)
res.json({ success: false, description: error.toString() })
})
@ -271,11 +262,10 @@ albumsController.rename = async (req, res, next) => {
}
albumsController.get = async (req, res, next) => {
// TODO: ... what was i supposed to do here?
// TODO: Something, can't remember...
const identifier = req.params.identifier
if (identifier === undefined) {
if (identifier === undefined)
return res.status(401).json({ success: false, description: 'No identifier provided.' })
}
const album = await db.table('albums')
.where({
@ -284,14 +274,13 @@ albumsController.get = async (req, res, next) => {
})
.first()
if (!album) {
if (!album)
return res.json({ success: false, description: 'Album not found.' })
} else if (album.public === 0) {
else if (album.public === 0)
return res.status(401).json({
success: false,
description: 'This album is not available for public.'
})
}
const title = album.name
const files = await db.table('files')
@ -303,9 +292,8 @@ albumsController.get = async (req, res, next) => {
file.file = `${config.domain}/${file.name}`
const extname = utils.extname(file.name)
if (utils.mayGenerateThumb(extname)) {
if (utils.mayGenerateThumb(extname))
file.thumb = `${config.domain}/thumbs/${file.name.slice(0, -extname.length)}.png`
}
}
return res.json({
@ -320,24 +308,22 @@ albumsController.generateZip = async (req, res, next) => {
const versionString = parseInt(req.query.v)
const download = (filePath, fileName) => {
const headers = { 'Access-Control-Allow-Origin': '*' }
if (versionString > 0) {
if (versionString > 0)
// Cache-Control header is useful when using CDN (max-age: 30 days)
headers['Cache-Control'] = 'public, max-age=2592000, must-revalidate, proxy-revalidate, immutable, stale-while-revalidate=86400, stale-if-error=604800'
}
return res.download(filePath, fileName, { headers })
}
const identifier = req.params.identifier
if (identifier === undefined) {
if (identifier === undefined)
return res.status(401).json({
success: false,
description: 'No identifier provided.'
})
}
if (!config.uploads.generateZips) {
if (!config.uploads.generateZips)
return res.status(401).json({ success: false, description: 'Zip generation disabled.' })
}
const album = await db.table('albums')
.where({
@ -346,15 +332,13 @@ albumsController.generateZip = async (req, res, next) => {
})
.first()
if (!album) {
if (!album)
return res.json({ success: false, description: 'Album not found.' })
} else if (album.download === 0) {
else if (album.download === 0)
return res.json({ success: false, description: 'Download for this album is disabled.' })
}
if ((!versionString || versionString <= 0) && album.editedAt) {
if ((!versionString || versionString <= 0) && album.editedAt)
return res.redirect(`${album.identifier}?v=${album.editedAt}`)
}
if (album.zipGeneratedAt > album.editedAt) {
const filePath = path.join(zipsDir, `${identifier}.zip`)
@ -368,11 +352,10 @@ albumsController.generateZip = async (req, res, next) => {
if (albumsController.zipEmitters.has(identifier)) {
console.log(`Waiting previous zip task for album: ${identifier}.`)
return albumsController.zipEmitters.get(identifier).once('done', (filePath, fileName, json) => {
if (filePath && fileName) {
if (filePath && fileName)
download(filePath, fileName)
} else if (json) {
else if (json)
res.json(json)
}
})
}
@ -406,16 +389,15 @@ albumsController.generateZip = async (req, res, next) => {
const archive = new Zip()
let iteration = 0
for (const file of files) {
for (const file of files)
fs.readFile(path.join(uploadsDir, file.name), (error, data) => {
if (error) {
if (error)
console.error(error)
} else {
else
archive.file(file.name, data)
}
iteration++
if (iteration === files.length) {
if (iteration === files.length)
archive
.generateNodeStream({
type: 'nodebuffer',
@ -436,23 +418,20 @@ albumsController.generateZip = async (req, res, next) => {
albumsController.zipEmitters.get(identifier).emit('done', filePath, fileName)
return download(filePath, fileName)
})
}
})
}
}
albumsController.addFiles = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const ids = req.body.ids
if (!ids || !ids.length) {
if (!ids || !ids.length)
return res.json({ success: false, description: 'No files specified.' })
}
let albumid = req.body.albumid
if (typeof albumid !== 'number') { albumid = parseInt(albumid) }
if (isNaN(albumid) || (albumid < 0)) { albumid = null }
if (typeof albumid !== 'number') albumid = parseInt(albumid)
if (isNaN(albumid) || (albumid < 0)) albumid = null
const albumids = []
@ -460,15 +439,13 @@ albumsController.addFiles = async (req, res, next) => {
const album = await db.table('albums')
.where('id', albumid)
.where(function () {
if (user.username !== 'root') {
if (user.username !== 'root')
this.where('userid', user.id)
}
})
.first()
if (!album) {
if (!album)
return res.json({ success: false, description: 'Album doesn\'t exist or it doesn\'t belong to the user.' })
}
albumids.push(albumid)
}
@ -476,9 +453,8 @@ albumsController.addFiles = async (req, res, next) => {
const files = await db.table('files')
.whereIn('id', ids)
.where(function () {
if (user.username !== 'root') {
if (user.username !== 'root')
this.where('userid', user.id)
}
})
const failed = ids.filter(id => !files.find(file => file.id === id))
@ -488,17 +464,15 @@ albumsController.addFiles = async (req, res, next) => {
.update('albumid', albumid)
.catch(console.error)
if (!updateDb) {
if (!updateDb)
return res.json({
success: false,
description: `Could not ${albumid === null ? 'add' : 'remove'} any files ${albumid === null ? 'to' : 'from'} the album.`
})
}
files.forEach(file => {
if (file.albumid && !albumids.includes(file.albumid)) {
if (file.albumid && !albumids.includes(file.albumid))
albumids.push(file.albumid)
}
})
await db.table('albums')

View File

@ -11,47 +11,44 @@ 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) {
if (!user)
return res.json({ success: false, description: 'Username doesn\'t exist.' })
}
if (user.enabled === false || user.enabled === 0) {
if (user.enabled === false || user.enabled === 0)
return res.json({ success: false, description: 'This account has been disabled.' })
}
bcrypt.compare(password, user.password, (error, result) => {
if (error) {
console.error(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) {
if (config.enableUserAccounts === false)
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) {
if (username.length < 4 || username.length > 32)
return res.json({ success: false, description: 'Username must have 4-32 characters.' })
}
if (password.length < 6 || password.length > 64) {
if (password.length < 6 || password.length > 64)
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 (error, hash) => {
if (error) {
@ -72,14 +69,13 @@ authController.register = async (req, res, next) => {
authController.changePassword = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const 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) {
if (password.length < 6 || password.length > 64)
return res.json({ success: false, description: 'Password must have 6-64 characters.' })
}
bcrypt.hash(password, 10, async (error, hash) => {
if (error) {
@ -97,7 +93,7 @@ authController.changePassword = async (req, res, next) => {
authController.getFileLengthConfig = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
return res.json({
success: true,
fileLength: user.fileLength,
@ -106,40 +102,36 @@ authController.getFileLengthConfig = async (req, res, next) => {
}
authController.changeFileLength = async (req, res, next) => {
if (config.uploads.fileLength.userChangeable === false) {
if (config.uploads.fileLength.userChangeable === false)
return res.json({
success: false,
description: 'Changing file name length is disabled at the moment.'
})
}
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const fileLength = parseInt(req.body.fileLength)
if (fileLength === undefined) {
if (fileLength === undefined)
return res.json({
success: false,
description: 'No file name length provided.'
})
}
if (isNaN(fileLength)) {
if (isNaN(fileLength))
return res.json({
success: false,
description: 'File name length is not a valid number.'
})
}
if (fileLength < config.uploads.fileLength.min || fileLength > config.uploads.fileLength.max) {
if (fileLength < config.uploads.fileLength.min || fileLength > config.uploads.fileLength.max)
return res.json({
success: false,
description: `File name length must be ${config.uploads.fileLength.min} to ${config.uploads.fileLength.max} characters.`
})
}
if (fileLength === user.fileLength) {
if (fileLength === user.fileLength)
return res.json({ success: true })
}
await db.table('users')
.where('id', user.id)
@ -150,32 +142,29 @@ authController.changeFileLength = async (req, res, next) => {
authController.editUser = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const id = parseInt(req.body.id)
if (isNaN(id)) {
if (isNaN(id))
return res.json({ success: false, description: 'No user specified.' })
}
const target = await db.table('users')
.where('id', id)
.first()
if (!target) {
if (!target)
return res.json({ success: false, description: 'Could not get user with the specified ID.' })
} else if (!perms.higher(user, target)) {
else if (!perms.higher(user, target))
return res.json({ success: false, description: 'The user is in the same or higher group as you.' })
} else if (target.username === 'root') {
else if (target.username === 'root')
return res.json({ success: false, description: 'Root user may not be edited.' })
}
const username = String(req.body.username)
if (username.length < 4 || username.length > 32) {
if (username.length < 4 || username.length > 32)
return res.json({ success: false, description: 'Username must have 4-32 characters.' })
}
let permission = req.body.group ? perms.permissions[req.body.group] : target.permission
if (typeof permission !== 'number' || permission < 0) { permission = target.permission }
if (typeof permission !== 'number' || permission < 0) permission = target.permission
await db.table('users')
.where('id', id)
@ -185,9 +174,8 @@ authController.editUser = async (req, res, next) => {
permission
})
if (!req.body.resetPassword) {
if (!req.body.resetPassword)
return res.json({ success: true, username })
}
const password = randomstring.generate(16)
bcrypt.hash(password, 10, async (error, hash) => {
@ -206,13 +194,13 @@ authController.editUser = async (req, res, next) => {
authController.listUsers = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const isadmin = perms.is(user, 'admin')
if (!isadmin) { return res.status(403) }
if (!isadmin) return res.status(403)
let offset = req.params.page
if (offset === undefined) { offset = 0 }
if (offset === undefined) offset = 0
const users = await db.table('users')
// .orderBy('id', 'DESC')
@ -220,7 +208,7 @@ authController.listUsers = async (req, res, next) => {
.offset(25 * offset)
.select('id', 'username', 'enabled', 'fileLength', 'permission')
if (!users.length) { return res.json({ success: true, users }) }
if (!users.length) return res.json({ success: true, users })
const userids = []
@ -238,18 +226,18 @@ authController.listUsers = async (req, res, next) => {
for (const upload of uploads) {
// This is the fastest method that I can think of
if (maps[upload.userid] === undefined) {
if (maps[upload.userid] === undefined)
maps[upload.userid] = {
count: 0,
size: 0
}
}
maps[upload.userid].count++
maps[upload.userid].size += parseInt(upload.size)
}
for (const user of users) {
if (!maps[user.id]) { continue }
if (!maps[user.id]) continue
user.uploadsCount = maps[user.id].count
user.diskUsage = maps[user.id].size
}

View File

@ -10,7 +10,7 @@ permissionController.permissions = {
permissionController.is = (user, group) => {
// root bypass
if (user.username === 'root') { return true }
if (user.username === 'root') return true
const permission = user.permission || 0
return permission >= permissionController.permissions[group]
}

View File

@ -8,20 +8,18 @@ const tokenController = {}
tokenController.verify = async (req, res, next) => {
const token = req.body.token
if (token === undefined) {
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) {
if (!user)
return res.status(401).json({
success: false,
description: 'Invalid token.'
})
}
return res.json({
success: true,
@ -32,7 +30,7 @@ tokenController.verify = async (req, res, next) => {
tokenController.list = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
return res.json({
success: true,
token: user.token
@ -41,7 +39,7 @@ tokenController.list = async (req, res, next) => {
tokenController.change = async (req, res, next) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const newtoken = randomstring.generate(64)
await db.table('users').where('token', user.token).update({

View File

@ -22,15 +22,14 @@ const urlMaxSizeBytes = parseInt(config.uploads.urlMaxSize) * 1000000
const storage = multer.diskStorage({
destination (req, file, cb) {
// If chunked uploads is disabled or the uploaded file is not a chunk
if (!chunkedUploads || (req.body.uuid === undefined && req.body.chunkindex === undefined)) {
if (!chunkedUploads || (req.body.uuid === undefined && req.body.chunkindex === undefined))
return cb(null, uploadsDir)
}
const uuidDir = path.join(chunksDir, req.body.uuid)
fs.access(uuidDir, error => {
if (!error) { return cb(null, uuidDir) }
if (!error) return cb(null, uuidDir)
fs.mkdir(uuidDir, error => {
if (!error) { return cb(null, uuidDir) }
if (!error) return cb(null, uuidDir)
console.error(error)
// eslint-disable-next-line standard/no-callback-literal
return cb('Could not process the chunked upload. Try again?')
@ -62,19 +61,18 @@ const upload = multer({
},
fileFilter (req, file, cb) {
const extname = utils.extname(file.originalname)
if (uploadsController.isExtensionFiltered(extname)) {
if (uploadsController.isExtensionFiltered(extname))
// eslint-disable-next-line standard/no-callback-literal
return cb(`${extname ? `${extname.substr(1).toUpperCase()} files` : 'Files with no extension'} are not permitted.`)
}
// Re-map Dropzone keys so people can manually use the API without prepending 'dz'
for (const key in req.body) {
if (!/^dz/.test(key)) { continue }
if (!/^dz/.test(key)) continue
req.body[key.replace(/^dz/, '')] = req.body[key]
delete req.body[key]
}
if (req.body.chunkindex) {
if (req.body.chunkindex)
if (chunkedUploads && parseInt(req.body.totalfilesize) > maxSizeBytes) {
// This will not be true if "totalfilesize" key does not exist, since "NaN > number" is false.
// eslint-disable-next-line standard/no-callback-literal
@ -83,29 +81,26 @@ const upload = multer({
// eslint-disable-next-line standard/no-callback-literal
return cb('Chunked uploads are disabled at the moment.')
}
}
return cb(null, true)
}
}).array('files[]')
uploadsController.isExtensionFiltered = extname => {
if (!extname && config.filterNoExtension) { return true }
if (!extname && config.filterNoExtension) return true
// If there are extensions that have to be filtered
if (extname && config.extensionsFilter && config.extensionsFilter.length) {
const match = config.extensionsFilter.some(extension => extname === extension.toLowerCase())
if ((config.filterBlacklist && match) || (!config.filterBlacklist && !match)) {
if ((config.filterBlacklist && match) || (!config.filterBlacklist && !match))
return true
}
}
return false
}
uploadsController.getFileNameLength = req => {
// If the user has a preferred file length, make sure it is within the allowed range
if (req.headers.filelength) {
if (req.headers.filelength)
return Math.min(Math.max(req.headers.filelength, config.uploads.fileLength.min), config.uploads.fileLength.max)
}
// Let's default it to 32 characters when config key is falsy
return config.uploads.fileLength.default || 32
@ -119,7 +114,7 @@ uploadsController.getUniqueRandomName = (length, extension, set) => {
// Check whether the identifier is already used in cache
if (set.has(identifier)) {
console.log(`Identifier ${identifier} is already in use (${++i}/${maxTries}).`)
if (i < maxTries) { return access(i) }
if (i < maxTries) return access(i)
// eslint-disable-next-line prefer-promise-reject-errors
return reject('Sorry, we could not allocate a unique random name. Try again?')
}
@ -131,9 +126,9 @@ uploadsController.getUniqueRandomName = (length, extension, set) => {
// can be used by multiple different extensions
const name = identifier + extension
fs.access(path.join(uploadsDir, name), error => {
if (error) { return resolve(name) }
if (error) return resolve(name)
console.log(`A file named ${name} already exists (${++i}/${maxTries}).`)
if (i < maxTries) { return access(i) }
if (i < maxTries) return access(i)
// eslint-disable-next-line prefer-promise-reject-errors
return reject('Sorry, we could not allocate a unique random name. Try again?')
})
@ -147,33 +142,29 @@ uploadsController.upload = async (req, res, next) => {
let user
if (config.private === true) {
user = await utils.authorize(req, res)
if (!user) { return }
} else if (req.headers.token) {
if (!user) return
} else if (req.headers.token)
user = await db.table('users').where('token', req.headers.token).first()
}
if (user && (user.enabled === false || user.enabled === 0)) {
if (user && (user.enabled === false || user.enabled === 0))
return res.json({ success: false, description: 'This account has been disabled.' })
}
if (user && user.fileLength && !req.headers.filelength) {
if (user && user.fileLength && !req.headers.filelength)
req.headers.filelength = user.fileLength
}
let albumid = parseInt(req.headers.albumid || req.params.albumid)
if (isNaN(albumid)) { albumid = null }
if (isNaN(albumid)) albumid = null
if (req.body.urls) {
if (req.body.urls)
return uploadsController.actuallyUploadByUrl(req, res, user, albumid)
} else {
else
return uploadsController.actuallyUpload(req, res, user, albumid)
}
}
uploadsController.actuallyUpload = async (req, res, user, albumid) => {
const erred = error => {
const isError = error instanceof Error
if (isError) { console.error(error) }
if (isError) console.error(error)
res.status(400).json({
success: false,
description: isError ? error.toString() : error
@ -186,14 +177,14 @@ uploadsController.actuallyUpload = async (req, res, user, albumid) => {
'LIMIT_FILE_SIZE',
'LIMIT_UNEXPECTED_FILE'
]
if (expected.includes(error.code)) { return erred(error.toString()) }
if (expected.includes(error.code)) return erred(error.toString())
return erred(error)
}
if (!req.files || !req.files.length) { return erred('No files.') }
if (!req.files || !req.files.length) return erred('No files.')
// If chunked uploads is enabled and the uploaded file is a chunk, then just say that it was a success
if (chunkedUploads && req.body.uuid) { return res.json({ success: true }) }
if (chunkedUploads && req.body.uuid) return res.json({ success: true })
const infoMap = req.files.map(file => {
file.albumid = albumid
@ -205,12 +196,12 @@ uploadsController.actuallyUpload = async (req, res, user, albumid) => {
if (config.uploads.scan && config.uploads.scan.enabled) {
const scan = await uploadsController.scanFiles(req, infoMap)
if (scan) { return erred(scan) }
if (scan) return erred(scan)
}
const result = await uploadsController.formatInfoMap(req, res, user, infoMap)
.catch(erred)
if (!result) { return }
if (!result) return
uploadsController.processFilesForDisplay(req, res, result.files, result.existingFiles)
})
@ -219,53 +210,48 @@ uploadsController.actuallyUpload = async (req, res, user, albumid) => {
uploadsController.actuallyUploadByUrl = async (req, res, user, albumid) => {
const erred = error => {
const isError = error instanceof Error
if (isError) { console.error(error) }
if (isError) console.error(error)
res.status(400).json({
success: false,
description: isError ? error.toString() : error
})
}
if (!config.uploads.urlMaxSize) { return erred('Upload by URLs is disabled at the moment.') }
if (!config.uploads.urlMaxSize) return erred('Upload by URLs is disabled at the moment.')
const urls = req.body.urls
if (!urls || !(urls instanceof Array)) { return erred('Missing "urls" property (Array).') }
if (!urls || !(urls instanceof Array)) return erred('Missing "urls" property (Array).')
// DuckDuckGo's proxy
if (config.uploads.urlDuckDuckGoProxy) {
if (config.uploads.urlDuckDuckGoProxy)
return erred('URL uploads unavailable. Please contact the site owner.')
// urls = urls.map(url => `https://proxy.duckduckgo.com/iu/?u=${encodeURIComponent(url)}&f=1`)
}
let iteration = 0
const infoMap = []
for (const url of urls) {
const original = path.basename(url).split(/[?#]/)[0]
const extension = utils.extname(original)
if (uploadsController.isExtensionFiltered(extension)) {
if (uploadsController.isExtensionFiltered(extension))
return erred(`${extension.substr(1).toUpperCase()} files are not permitted due to security reasons.`)
}
try {
const fetchHead = await fetch(url, { method: 'HEAD' })
if (fetchHead.status !== 200) {
if (fetchHead.status !== 200)
return erred(`${fetchHead.status} ${fetchHead.statusText}`)
}
const headers = fetchHead.headers
const size = parseInt(headers.get('content-length'))
if (isNaN(size)) {
if (isNaN(size))
return erred('URLs with missing Content-Length HTTP header are not supported.')
}
if (size > urlMaxSizeBytes) {
if (size > urlMaxSizeBytes)
return erred('File too large.')
}
// limit max response body size with content-length
const fetchFile = await fetch(url, { size })
if (fetchFile.status !== 200) {
if (fetchFile.status !== 200)
return erred(`${fetchHead.status} ${fetchHead.statusText}`)
}
const file = await fetchFile.buffer()
@ -274,7 +260,7 @@ uploadsController.actuallyUploadByUrl = async (req, res, user, albumid) => {
const destination = path.join(uploadsDir, name)
fs.writeFile(destination, file, async error => {
if (error) { return erred(error) }
if (error) return erred(error)
const data = {
filename: name,
@ -293,12 +279,12 @@ uploadsController.actuallyUploadByUrl = async (req, res, user, albumid) => {
if (iteration === urls.length) {
if (config.uploads.scan && config.uploads.scan.enabled) {
const scan = await uploadsController.scanFiles(req, infoMap)
if (scan) { return erred(scan) }
if (scan) return erred(scan)
}
const result = await uploadsController.formatInfoMap(req, res, user, infoMap)
.catch(erred)
if (!result) { return }
if (!result) return
uploadsController.processFilesForDisplay(req, res, result.files, result.existingFiles)
}
@ -308,28 +294,24 @@ uploadsController.actuallyUploadByUrl = async (req, res, user, albumid) => {
}
uploadsController.finishChunks = async (req, res, next) => {
if (!chunkedUploads) {
if (!chunkedUploads)
return res.json({ success: false, description: 'Chunked upload is disabled at the moment.' })
}
let user
if (config.private === true) {
user = await utils.authorize(req, res)
if (!user) { return }
} else if (req.headers.token) {
if (!user) return
} else if (req.headers.token)
user = await db.table('users').where('token', req.headers.token).first()
}
if (user && (user.enabled === false || user.enabled === 0)) {
if (user && (user.enabled === false || user.enabled === 0))
return res.json({ success: false, description: 'This account has been disabled.' })
}
if (user && user.fileLength && !req.headers.filelength) {
if (user && user.fileLength && !req.headers.filelength)
req.headers.filelength = user.fileLength
}
let albumid = parseInt(req.headers.albumid || req.params.albumid)
if (isNaN(albumid)) { albumid = null }
if (isNaN(albumid)) albumid = null
return uploadsController.actuallyFinishChunks(req, res, user, albumid)
}
@ -337,7 +319,7 @@ uploadsController.finishChunks = async (req, res, next) => {
uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
const erred = error => {
const isError = error instanceof Error
if (isError) { console.error(error) }
if (isError) console.error(error)
res.status(400).json({
success: false,
description: isError ? error.toString() : error
@ -345,31 +327,30 @@ uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
}
const files = req.body.files
if (!files || !(files instanceof Array) || !files.length) { return erred('Invalid "files" property (Array).') }
if (!files || !(files instanceof Array) || !files.length) return erred('Invalid "files" property (Array).')
let iteration = 0
const infoMap = []
for (const file of files) {
if (!file.uuid || typeof file.uuid !== 'string') { return erred('Invalid "uuid" property (string).') }
if (typeof file.count !== 'number' || file.count < 1) { return erred('Invalid "count" property (number).') }
if (!file.uuid || typeof file.uuid !== 'string') return erred('Invalid "uuid" property (string).')
if (typeof file.count !== 'number' || file.count < 1) return erred('Invalid "count" property (number).')
const uuidDir = path.join(chunksDir, file.uuid)
fs.readdir(uuidDir, async (error, chunkNames) => {
if (error) {
if (error.code === 'ENOENT') { return erred('UUID is not being used.') }
if (error.code === 'ENOENT') return erred('UUID is not being used.')
return erred(error)
}
if (file.count < chunkNames.length) { return erred('Chunks count mismatch.') }
if (file.count < chunkNames.length) return erred('Chunks count mismatch.')
const extension = typeof file.original === 'string' ? utils.extname(file.original) : ''
if (uploadsController.isExtensionFiltered(extension)) {
if (uploadsController.isExtensionFiltered(extension))
return erred(`${extension.substr(1).toUpperCase()} files are not permitted due to security reasons.`)
}
const length = uploadsController.getFileNameLength(req)
const name = await uploadsController.getUniqueRandomName(length, extension, req.app.get('uploads-set'))
.catch(erred)
if (!name) { return }
if (!name) return
const destination = path.join(uploadsDir, name)
@ -379,12 +360,12 @@ uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
// Get total chunks size
const chunksTotalSize = await uploadsController.getTotalSize(uuidDir, chunkNames)
.catch(erred)
if (typeof chunksTotalSize !== 'number') { return }
if (typeof chunksTotalSize !== 'number') return
if (chunksTotalSize > maxSizeBytes) {
// Delete all chunks and remove chunks dir
const chunksCleaned = await uploadsController.cleanUpChunks(uuidDir, chunkNames)
.catch(erred)
if (!chunksCleaned) { return }
if (!chunksCleaned) return
return erred(`Total chunks size is bigger than ${maxSize}.`)
}
@ -392,12 +373,12 @@ uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
const destFileStream = fs.createWriteStream(destination, { flags: 'a' })
const chunksAppended = await uploadsController.appendToStream(destFileStream, uuidDir, chunkNames)
.catch(erred)
if (!chunksAppended) { return }
if (!chunksAppended) return
// Delete all chunks and remove chunks dir
const chunksCleaned = await uploadsController.cleanUpChunks(uuidDir, chunkNames)
.catch(erred)
if (!chunksCleaned) { return }
if (!chunksCleaned) return
const data = {
filename: name,
@ -407,7 +388,7 @@ uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
}
data.albumid = parseInt(file.albumid)
if (isNaN(data.albumid)) { data.albumid = albumid }
if (isNaN(data.albumid)) data.albumid = albumid
infoMap.push({
path: destination,
@ -418,12 +399,12 @@ uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
if (iteration === files.length) {
if (config.uploads.scan && config.uploads.scan.enabled) {
const scan = await uploadsController.scanFiles(req, infoMap)
if (scan) { return erred(scan) }
if (scan) return erred(scan)
}
const result = await uploadsController.formatInfoMap(req, res, user, infoMap)
.catch(erred)
if (!result) { return }
if (!result) return
uploadsController.processFilesForDisplay(req, res, result.files, result.existingFiles)
}
@ -435,9 +416,9 @@ uploadsController.getTotalSize = (uuidDir, chunkNames) => {
return new Promise((resolve, reject) => {
let size = 0
const stat = i => {
if (i === chunkNames.length) { return resolve(size) }
if (i === chunkNames.length) return resolve(size)
fs.stat(path.join(uuidDir, chunkNames[i]), (error, stats) => {
if (error) { return reject(error) }
if (error) return reject(error)
size += stats.size
stat(i + 1)
})
@ -483,7 +464,7 @@ uploadsController.cleanUpChunks = (uuidDir, chunkNames) => {
})
})).catch(reject)
fs.rmdir(uuidDir, error => {
if (error) { return reject(error) }
if (error) return reject(error)
resolve(true)
})
})
@ -509,11 +490,10 @@ uploadsController.formatInfoMap = (req, res, user, infoMap) => {
const fileHash = hash.digest('hex')
const dbFile = await db.table('files')
.where(function () {
if (user === undefined) {
if (user === undefined)
this.whereNull('userid')
} else {
else
this.where('userid', user.id)
}
})
.where({
hash: fileHash,
@ -555,9 +535,8 @@ uploadsController.formatInfoMap = (req, res, user, infoMap) => {
}
iteration++
if (iteration === infoMap.length) {
if (iteration === infoMap.length)
resolve({ files, existingFiles })
}
})
}
})
@ -567,7 +546,7 @@ uploadsController.scanFiles = (req, infoMap) => {
return new Promise(async (resolve, reject) => {
const scanner = req.app.get('clam-scanner')
let iteration = 0
for (const info of infoMap) {
for (const info of infoMap)
scanner.scanFile(info.path).then(reply => {
if (!reply.includes('OK') || reply.includes('FOUND')) {
// eslint-disable-next-line no-control-regex
@ -577,13 +556,11 @@ uploadsController.scanFiles = (req, infoMap) => {
}
iteration++
if (iteration === infoMap.length) {
if (iteration === infoMap.length)
resolve(null)
}
}).catch(reject)
}
}).then(virus => {
if (!virus) { return false }
if (!virus) return false
// If there is at least one dirty file, then delete all files
const set = req.app.get('uploads-set')
infoMap.forEach(info => {
@ -610,16 +587,13 @@ uploadsController.processFilesForDisplay = async (req, res, files, existingFiles
// Insert new files to DB
await db.table('files').insert(files)
for (const file of files) {
for (const file of files)
responseFiles.push(file)
}
}
if (existingFiles.length) {
for (const file of existingFiles) {
if (existingFiles.length)
for (const file of existingFiles)
responseFiles.push(file)
}
}
// We send response first before generating thumbnails and updating album timestamps
res.json({
@ -635,73 +609,67 @@ uploadsController.processFilesForDisplay = async (req, res, files, existingFiles
const albumids = []
for (const file of files) {
if (file.albumid && !albumids.includes(file.albumid)) {
if (file.albumid && !albumids.includes(file.albumid))
albumids.push(file.albumid)
}
if (utils.mayGenerateThumb(utils.extname(file.name))) {
if (utils.mayGenerateThumb(utils.extname(file.name)))
utils.generateThumbs(file.name)
}
}
if (albumids.length) {
if (albumids.length)
await db.table('albums')
.whereIn('id', albumids)
.update('editedAt', Math.floor(Date.now() / 1000))
.catch(console.error)
}
}
uploadsController.delete = async (req, res) => {
const id = parseInt(req.body.id)
req.body.field = 'id'
req.body.values = isNaN(id) ? undefined : [id]
delete req.body.id
if (req.body.id !== undefined) delete req.body.id
return uploadsController.bulkDelete(req, res)
}
uploadsController.bulkDelete = async (req, res) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
const field = req.body.field || 'id'
const values = req.body.values
if (!values || values.constructor.name !== 'Array' || !values.length) {
if (!values || !Array.isArray(values) || !values.length)
return res.json({ success: false, description: 'No array of files specified.' })
}
const failed = await utils.bulkDeleteFiles(field, values, user, req.app.get('uploads-set'))
if (failed.length < values.length) {
if (failed.length < values.length)
return res.json({ success: true, failed })
}
return res.json({ success: false, description: 'Could not delete any files.' })
}
uploadsController.list = async (req, res) => {
const user = await utils.authorize(req, res)
if (!user) { return }
if (!user) return
let offset = req.params.page
if (offset === undefined) { offset = 0 }
if (offset === undefined) offset = 0
// Headers is string-only, this seem to be the safest and lightest
const all = req.headers.all === '1'
const ismoderator = perms.is(user, 'moderator')
if (all && !ismoderator) { return res.json(403) }
if (all && !ismoderator) return res.json(403)
const files = await db.table('files')
.where(function () {
if (req.params.id === undefined) {
if (req.params.id === undefined)
this.where('id', '<>', '')
} else {
else
this.where('albumid', req.params.id)
}
})
.where(function () {
if (!all || !ismoderator) {
if (!all || !ismoderator)
this.where('userid', user.id)
}
})
.orderBy('id', 'DESC')
.limit(25)
@ -711,9 +679,8 @@ uploadsController.list = async (req, res) => {
const albums = await db.table('albums')
.where(function () {
this.where('enabled', 1)
if (!all || !ismoderator) {
if (!all || !ismoderator)
this.where('userid', user.id)
}
})
const basedomain = config.domain
@ -723,41 +690,33 @@ uploadsController.list = async (req, res) => {
file.file = `${basedomain}/${file.name}`
file.album = ''
if (file.albumid !== undefined) {
for (const album of albums) {
if (file.albumid === album.id) {
if (file.albumid !== undefined)
for (const album of albums)
if (file.albumid === album.id)
file.album = album.name
}
}
}
// Only push usernames if we are a moderator
if (all && ismoderator) {
if (all && ismoderator)
if (file.userid !== undefined && file.userid !== null && file.userid !== '') {
userids.push(file.userid)
}
}
file.extname = utils.extname(file.name)
if (utils.mayGenerateThumb(file.extname)) {
if (utils.mayGenerateThumb(file.extname))
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -file.extname.length)}.png`
}
}
// If we are a normal user, send response
if (!ismoderator) { return res.json({ success: true, files }) }
if (!ismoderator) return res.json({ success: true, files })
// If we are a moderator 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)
for (const dbUser of users) {
for (const file of files) {
if (file.userid === dbUser.id) {
for (const dbUser of users)
for (const file of files)
if (file.userid === dbUser.id)
file.username = dbUser.username
}
}
}
return res.json({ success: true, files })
}

View File

@ -27,7 +27,7 @@ utilsController.preserves = ['.tar.gz', '.tar.z', '.tar.bz2', '.tar.lzma', '.tar
utilsController.extname = filename => {
// Always return blank string if the filename does not seem to have a valid extension
// Files such as .DS_Store (anything that starts with a dot, without any extension after) will still be accepted
if (!/\../.test(filename)) { return '' }
if (!/\../.test(filename)) return ''
let lower = filename.toLowerCase() // due to this, the returned extname will always be lower case
let multi = ''
@ -40,16 +40,14 @@ utilsController.extname = filename => {
}
// check against extensions that must be preserved
for (let i = 0; i < utilsController.preserves.length; i++) {
for (let i = 0; i < utilsController.preserves.length; i++)
if (lower.endsWith(utilsController.preserves[i])) {
extname = utilsController.preserves[i]
break
}
}
if (!extname) {
if (!extname)
extname = lower.slice(lower.lastIndexOf('.') - lower.length) // path.extname(lower)
}
return extname + multi
}
@ -60,12 +58,12 @@ utilsController.escape = string => {
// Copyright(c) 2015 Andreas Lubbe
// Copyright(c) 2015 Tiancheng "Timothy" Gu
if (!string) { return string }
if (!string) return string
const str = '' + string
const match = /["'&<>]/.exec(str)
if (!match) { return str }
if (!match) return str
let escape
let html = ''
@ -93,9 +91,8 @@ utilsController.escape = string => {
continue
}
if (lastIndex !== index) {
if (lastIndex !== index)
html += str.substring(lastIndex, index)
}
lastIndex = index + 1
html += escape
@ -142,15 +139,15 @@ utilsController.generateThumbs = (name, force) => {
// Unlink symlink
const unlink = await new Promise((resolve, reject) => {
fs.unlink(thumbname, error => {
if (error) { return reject(error) }
if (error) return reject(error)
return resolve(true)
})
}).catch(console.error)
if (!unlink) { return resolve(false) }
if (!unlink) return resolve(false)
}
// Only make thumbnail if it does not exist (ENOENT)
if (!error && !stats.isSymbolicLink() && !force) { return resolve(true) }
if (!error && !stats.isSymbolicLink() && !force) return resolve(true)
// If image extension
if (utilsController.imageExtensions.includes(extname)) {
@ -169,10 +166,10 @@ utilsController.generateThumbs = (name, force) => {
.resize(resizeOptions)
.toFile(thumbname)
.catch(error => {
if (!error) { return resolve(true) }
if (!error) return resolve(true)
console.error(`${name}: ${error.message.trim()}`)
fs.symlink(thumbUnavailable, thumbname, error => {
if (error) { console.error(error) }
if (error) console.error(error)
resolve(!error)
})
})
@ -189,7 +186,7 @@ utilsController.generateThumbs = (name, force) => {
.on('error', error => {
console.log(`${name}: ${error.message}`)
fs.symlink(thumbUnavailable, thumbname, error => {
if (error) { console.error(error) }
if (error) console.error(error)
resolve(!error)
})
})
@ -204,12 +201,12 @@ utilsController.deleteFile = file => {
return new Promise((resolve, reject) => {
const extname = utilsController.extname(file)
return fs.unlink(path.join(uploadsDir, file), error => {
if (error && error.code !== 'ENOENT') { return reject(error) }
if (error && error.code !== 'ENOENT') return reject(error)
if (utilsController.imageExtensions.includes(extname) || utilsController.videoExtensions.includes(extname)) {
const thumb = file.substr(0, file.lastIndexOf('.')) + '.png'
return fs.unlink(path.join(thumbsDir, thumb), error => {
if (error && error.code !== 'ENOENT') { return reject(error) }
if (error && error.code !== 'ENOENT') return reject(error)
resolve(true)
})
}
@ -231,15 +228,14 @@ utilsController.deleteFile = file => {
* @return {any[]} failed
*/
utilsController.bulkDeleteFiles = async (field, values, user, set) => {
if (!user || !['id', 'name'].includes(field)) { return }
if (!user || !['id', 'name'].includes(field)) return
const ismoderator = perms.is(user, 'moderator')
const files = await db.table('files')
.whereIn(field, values)
.where(function () {
if (!ismoderator) {
if (!ismoderator)
this.where('userid', user.id)
}
})
// an array of file object
@ -261,7 +257,7 @@ utilsController.bulkDeleteFiles = async (field, values, user, set) => {
})
}))
if (!deletedFiles.length) { return failed }
if (!deletedFiles.length) return failed
// Delete all files from database
const deletedIds = deletedFiles.map(file => file.id)
@ -269,24 +265,23 @@ utilsController.bulkDeleteFiles = async (field, values, user, set) => {
.whereIn('id', deletedIds)
.del()
.catch(console.error)
if (!deleteDb) { return failed }
if (!deleteDb) return failed
if (set) {
if (set)
deletedFiles.forEach(file => {
const identifier = file.name.split('.')[0]
set.delete(identifier)
// console.log(`Removed ${identifier} from identifiers cache (bulkDeleteFiles)`)
})
}
const filtered = files.filter(file => deletedIds.includes(file.id))
// Update albums if necessary
if (deleteDb) {
const albumids = []
filtered.forEach(file => {
if (file.albumid && !albumids.includes(file.albumid)) {
if (file.albumid && !albumids.includes(file.albumid))
albumids.push(file.albumid)
}
})
await db.table('albums')
.whereIn('id', albumids)
@ -304,15 +299,15 @@ utilsController.bulkDeleteFiles = async (field, values, user, set) => {
}
utilsController.purgeCloudflareCache = async names => {
if (!cloudflareAuth) { return }
if (!cloudflareAuth) return
const thumbs = []
names = names.map(name => {
const url = `${config.domain}/${name}`
const extname = utilsController.extname(name)
if (utilsController.mayGenerateThumb(extname)) {
if (utilsController.mayGenerateThumb(extname))
thumbs.push(`${config.domain}/thumbs/${name.slice(0, -extname.length)}.png`)
}
return url
})
@ -328,9 +323,8 @@ utilsController.purgeCloudflareCache = async names => {
}
}).then(res => res.json())
if (fetchPurge.errors) {
if (fetchPurge.errors)
fetchPurge.errors.forEach(error => console.error(`CF: ${error.code}: ${error.message}`))
}
} catch (error) {
console.error(`CF: ${error.toString()}`)
}

View File

@ -12,7 +12,7 @@
"rules": {
"curly": [
"error",
"all"
"multi"
],
"quotes": [
"error",

View File

@ -11,11 +11,11 @@ page.getPrettyBytes = num => {
// MIT License
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
if (!Number.isFinite(num)) { return num }
if (!Number.isFinite(num)) return num
const neg = num < 0
if (neg) { num = -num }
if (num < 1) { return (neg ? '-' : '') + num + ' B' }
if (neg) num = -num
if (num < 1) return (neg ? '-' : '') + num + ' B'
const exponent = Math.min(Math.floor(Math.log10(num) / 3), page.byteUnits.length - 1)
const numStr = Number((num / Math.pow(1000, exponent)).toPrecision(3))
@ -26,9 +26,8 @@ page.getPrettyBytes = num => {
window.onload = function () {
const elements = document.getElementsByClassName('file-size')
for (let i = 0; i < elements.length; i++) {
for (let i = 0; i < elements.length; i++)
elements[i].innerHTML = page.getPrettyBytes(parseInt(elements[i].innerHTML))
}
page.lazyLoad = new LazyLoad()
}

View File

@ -13,21 +13,18 @@ page.do = function (dest) {
const user = page.user.value
const pass = page.pass.value
if (!user) {
if (!user)
return swal('An error occurred!', 'You need to specify a username', 'error')
}
if (!pass) {
if (!pass)
return swal('An error occurred!', 'You need to specify a username', 'error')
}
axios.post(`api/${dest}`, {
username: user,
password: pass
}).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
return swal('An error occurred!', response.data.description, 'error')
}
localStorage.token = response.data.token
window.location = 'dashboard'
@ -38,14 +35,13 @@ page.do = function (dest) {
}
page.verify = function () {
if (!page.token) { return }
if (!page.token) return
axios.post('api/tokens/verify', {
token: page.token
}).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
return swal('An error occurred!', response.data.description, 'error')
}
window.location = 'dashboard'
}).catch(function (error) {

View File

@ -83,17 +83,16 @@ page.preparePage = function () {
page.verifyToken = function (token, reloadOnError) {
axios.post('api/tokens/verify', { token }).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
return swal({
title: 'An error occurred!',
text: response.data.description,
icon: 'error'
}).then(function () {
if (!reloadOnError) { return }
if (!reloadOnError) return
localStorage.removeItem(LS_KEYS.token)
location.location = 'auth'
})
}
axios.defaults.headers.common.token = token
localStorage[LS_KEYS.token] = token
@ -170,7 +169,7 @@ page.prepareDashboard = function () {
page.getAlbumsSidebar()
if (typeof page.prepareShareX === 'function') { page.prepareShareX() }
if (typeof page.prepareShareX === 'function') page.prepareShareX()
}
page.logout = function () {
@ -182,20 +181,20 @@ page.getItemID = function (element) {
// This expects the item's parent to have the item's ID
let parent = element.parentNode
// If the element is part of a set of controls, use the container's parent instead
if (element.parentNode.classList.contains('controls')) { parent = parent.parentNode }
if (element.parentNode.classList.contains('controls')) parent = parent.parentNode
return parseInt(parent.dataset.id)
}
page.domClick = function (event) {
let element = event.target
if (!element) { return }
if (!element) return
// If the clicked element is an icon, delegate event to its A parent; hacky
if (element.tagName === 'I' && element.parentNode.tagName === 'SPAN') { element = element.parentNode }
if (element.tagName === 'SPAN' && element.parentNode.tagName === 'A') { element = element.parentNode }
if (element.tagName === 'I' && element.parentNode.tagName === 'SPAN') element = element.parentNode
if (element.tagName === 'SPAN' && element.parentNode.tagName === 'A') element = element.parentNode
// Skip elements that have no action data
if (!element.dataset || !element.dataset.action) { return }
if (!element.dataset || !element.dataset.action) return
event.stopPropagation() // maybe necessary
const id = page.getItemID(element)
@ -210,16 +209,15 @@ page.domClick = function (event) {
views.album = page.views.uploads.album
views.all = page.views.uploads.all
func = page.getUploads
} else if (page.currentView === 'users') {
} else if (page.currentView === 'users')
func = page.getUsers
}
switch (action) {
case 'page-prev':
views.pageNum = page.views[page.currentView].pageNum - 1
if (views.pageNum < 0) {
if (views.pageNum < 0)
return swal('An error occurred!', 'This is already the first page.', 'error')
}
return func(views, element)
case 'page-next':
views.pageNum = page.views[page.currentView].pageNum + 1
@ -264,8 +262,8 @@ page.domClick = function (event) {
}
page.isLoading = function (element, state) {
if (!element) { return }
if (state) { return element.classList.add('is-loading') }
if (!element) return
if (state) return element.classList.add('is-loading')
element.classList.remove('is-loading')
}
@ -281,32 +279,30 @@ page.fadeIn = function (content) {
}
page.getUploads = function ({ album, pageNum, all } = {}, element) {
if (element) { page.isLoading(element, true) }
if (pageNum === undefined) { pageNum = 0 }
if (element) page.isLoading(element, true)
if (pageNum === undefined) pageNum = 0
let url = `api/uploads/${pageNum}`
if (album !== undefined) { url = `api/album/${album}/${pageNum}` }
if (album !== undefined) url = `api/album/${album}/${pageNum}`
if (all && !page.permissions.moderator) {
if (all && !page.permissions.moderator)
return swal('An error occurred!', 'You can not do this!', 'error')
}
axios.get(url, {
headers: {
all: all ? '1' : '0'
}
}).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
if (pageNum && (response.data.files.length === 0)) {
// Only remove loading class here, since beyond this the entire page will be replaced anyways
if (element) { page.isLoading(element, false) }
if (element) page.isLoading(element, false)
return swal('An error occurred!', 'There are no more uploads.', 'error')
}
@ -374,7 +370,7 @@ page.getUploads = function ({ album, pageNum, all } = {}, element) {
for (let i = 0; i < response.data.files.length; i++) {
const upload = response.data.files[i]
const selected = page.selected.uploads.includes(upload.id)
if (!selected && allSelected) { allSelected = false }
if (!selected && allSelected) allSelected = false
page.cache.uploads[upload.id] = {
name: upload.name,
@ -387,16 +383,15 @@ page.getUploads = function ({ album, pageNum, all } = {}, element) {
upload.prettyDate = page.getPrettyDate(new Date(upload.timestamp * 1000))
let displayAlbumOrUser = upload.album
if (all) { displayAlbumOrUser = upload.username || '' }
if (all) displayAlbumOrUser = upload.username || ''
const div = document.createElement('div')
div.className = 'image-container column is-narrow'
div.dataset.id = upload.id
if (upload.thumb !== undefined) {
if (upload.thumb !== undefined)
div.innerHTML = `<a class="image" href="${upload.file}" target="_blank" rel="noopener"><img alt="${upload.name}" data-src="${upload.thumb}"/></a>`
} else {
else
div.innerHTML = `<a class="image" href="${upload.file}" target="_blank" rel="noopener"><h1 class="title">${upload.extname || 'N/A'}</h1></a>`
}
div.innerHTML += `
<input type="checkbox" class="checkbox" title="Select this file" data-action="select"${selected ? ' checked' : ''}>
@ -435,7 +430,7 @@ page.getUploads = function ({ album, pageNum, all } = {}, element) {
}
} else {
let albumOrUser = 'Album'
if (all) { albumOrUser = 'User' }
if (all) albumOrUser = 'User'
page.dom.innerHTML = `
${pagination}
@ -467,7 +462,7 @@ page.getUploads = function ({ album, pageNum, all } = {}, element) {
for (let i = 0; i < response.data.files.length; i++) {
const upload = response.data.files[i]
const selected = page.selected.uploads.includes(upload.id)
if (!selected && allSelected) { allSelected = false }
if (!selected && allSelected) allSelected = false
page.cache.uploads[upload.id] = {
name: upload.name,
@ -480,7 +475,7 @@ page.getUploads = function ({ album, pageNum, all } = {}, element) {
upload.prettyDate = page.getPrettyDate(new Date(upload.timestamp * 1000))
let displayAlbumOrUser = upload.album
if (all) { displayAlbumOrUser = upload.username || '' }
if (all) displayAlbumOrUser = upload.username || ''
const tr = document.createElement('tr')
tr.dataset.id = upload.id
@ -523,14 +518,14 @@ page.getUploads = function ({ album, pageNum, all } = {}, element) {
if (allSelected && response.data.files.length) {
const selectAll = document.getElementById('selectAll')
if (selectAll) { selectAll.checked = true }
if (selectAll) selectAll.checked = true
}
page.views.uploads.album = album
page.views.uploads.pageNum = response.data.files.length ? pageNum : 0
page.views.uploads.all = all
}).catch(function (error) {
if (element) { page.isLoading(element, false) }
if (element) page.isLoading(element, false)
console.log(error)
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
})
@ -544,7 +539,7 @@ page.setUploadsView = function (view, element) {
page.displayThumbnail = function (id) {
const file = page.cache.uploads[id]
if (!file.thumb) { return }
if (!file.thumb) return
const div = document.createElement('div')
div.innerHTML = `
@ -601,7 +596,7 @@ page.displayThumbnail = function (id) {
buttons: false
}).then(function () {
const video = div.querySelector('#swalVideo')
if (video) { video.remove() }
if (video) video.remove()
// Restore modal size
document.body.querySelector('.swal-overlay .swal-modal.is-expanded').classList.remove('is-expanded')
@ -615,48 +610,45 @@ page.selectAll = function (element) {
for (let i = 0; i < checkboxes.length; i++) {
const id = page.getItemID(checkboxes[i])
if (isNaN(id)) { continue }
if (isNaN(id)) continue
if (checkboxes[i].checked !== element.checked) {
checkboxes[i].checked = element.checked
if (checkboxes[i].checked) {
if (checkboxes[i].checked)
selected.push(id)
} else {
else
selected.splice(selected.indexOf(id), 1)
}
}
}
if (selected.length) {
if (selected.length)
localStorage[LS_KEYS.selected[currentView]] = JSON.stringify(selected)
} else {
else
localStorage.removeItem(LS_KEYS.selected[currentView])
}
page.selected[currentView] = selected
element.title = element.checked ? 'Unselect all uploads' : 'Select all uploads'
}
page.selectInBetween = function (element, lastElement) {
if (!element || !lastElement) { return }
if (element === lastElement) { return }
if (!element || !lastElement) return
if (element === lastElement) return
const currentView = page.currentView
const checkboxes = page.checkboxes[currentView]
if (!checkboxes || !checkboxes.length) { return }
if (!checkboxes || !checkboxes.length) return
const thisIndex = checkboxes.indexOf(element)
const lastIndex = checkboxes.indexOf(lastElement)
const distance = thisIndex - lastIndex
if (distance >= -1 && distance <= 1) { return }
if (distance >= -1 && distance <= 1) return
for (let i = 0; i < checkboxes.length; i++) {
for (let i = 0; i < checkboxes.length; i++)
if ((thisIndex > lastIndex && i > lastIndex && i < thisIndex) ||
(thisIndex < lastIndex && i > thisIndex && i < lastIndex)) {
checkboxes[i].checked = true
page.selected[currentView].push(page.getItemID(checkboxes[i]))
}
}
localStorage[LS_KEYS.selected.uploads] = JSON.stringify(page.selected[currentView])
page.checkboxes[currentView] = checkboxes
@ -665,27 +657,24 @@ page.selectInBetween = function (element, lastElement) {
page.select = function (element, event) {
const currentView = page.currentView
const lastSelected = page.lastSelected[currentView]
if (event.shiftKey && lastSelected) {
if (event.shiftKey && lastSelected)
page.selectInBetween(element, lastSelected)
} else {
else
page.lastSelected[currentView] = element
}
const id = page.getItemID(element)
if (isNaN(id)) { return }
if (isNaN(id)) return
const selected = page.selected[currentView]
if (!selected.includes(id) && element.checked) {
if (!selected.includes(id) && element.checked)
selected.push(id)
} else if (selected.includes(id) && !element.checked) {
else if (selected.includes(id) && !element.checked)
selected.splice(selected.indexOf(id), 1)
}
if (selected.length) {
if (selected.length)
localStorage[LS_KEYS.selected[currentView]] = JSON.stringify(selected)
} else {
else
localStorage.removeItem(LS_KEYS.selected[currentView])
}
page.selected[currentView] = selected
}
@ -694,9 +683,8 @@ page.clearSelection = function () {
const currentView = page.currentView
const selected = page.selected[currentView]
const count = selected.length
if (!count) {
if (!count)
return swal('An error occurred!', `You have not selected any ${currentView}.`, 'error')
}
const suffix = count === 1 ? currentView.substring(0, currentView.length - 1) : currentView
return swal({
@ -704,20 +692,18 @@ page.clearSelection = function () {
text: `You are going to unselect ${count} ${suffix}.`,
buttons: true
}).then(function (proceed) {
if (!proceed) { return }
if (!proceed) return
const checkboxes = page.checkboxes[currentView]
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
for (let i = 0; i < checkboxes.length; i++)
if (checkboxes[i].checked)
checkboxes[i].checked = false
}
}
localStorage.removeItem(LS_KEYS.selected[currentView])
page.selected[currentView] = []
const selectAll = document.getElementById('selectAll')
if (selectAll) { selectAll.checked = false }
if (selectAll) selectAll.checked = false
return swal('Cleared selection!', `Unselected ${count} ${suffix}.`, 'success')
})
@ -738,18 +724,17 @@ page.deleteFile = function (id) {
}
}
}).then(function (proceed) {
if (!proceed) { return }
if (!proceed) return
axios.post('api/upload/delete', { id }).then(function (response) {
if (!response) { return }
if (!response) return
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
swal('Deleted!', 'The file has been deleted.', 'success')
page.getUploads(page.views.uploads)
@ -762,9 +747,8 @@ page.deleteFile = function (id) {
page.deleteSelectedFiles = function () {
const count = page.selected.uploads.length
if (!count) {
if (!count)
return swal('An error occurred!', 'You have not selected any uploads.', 'error')
}
const suffix = `file${count === 1 ? '' : 's'}`
swal({
@ -780,21 +764,20 @@ page.deleteSelectedFiles = function () {
}
}
}).then(function (proceed) {
if (!proceed) { return }
if (!proceed) return
axios.post('api/upload/bulkdelete', {
field: 'id',
values: page.selected.uploads
}).then(function (bulkdelete) {
if (!bulkdelete) { return }
if (!bulkdelete) return
if (bulkdelete.data.success === false) {
if (bulkdelete.data.success === false)
if (bulkdelete.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', bulkdelete.data.description, 'error')
}
}
let deleted = count
if (bulkdelete.data.failed && bulkdelete.data.failed.length) {
@ -802,9 +785,8 @@ page.deleteSelectedFiles = function () {
page.selected.uploads = page.selected.uploads.filter(function (id) {
return bulkdelete.data.failed.includes(id)
})
} else {
} else
page.selected.uploads = []
}
localStorage[LS_KEYS.selected.uploads] = JSON.stringify(page.selected.uploads)
@ -848,9 +830,8 @@ page.deleteFileByNames = function () {
return n.trim().length
})
const count = names.length
if (!count) {
if (!count)
return swal('An error occurred!', 'You have not entered any file names.', 'error')
}
const suffix = `file${count === 1 ? '' : 's'}`
swal({
@ -866,26 +847,24 @@ page.deleteFileByNames = function () {
}
}
}).then(function (proceed) {
if (!proceed) { return }
if (!proceed) return
axios.post('api/upload/bulkdelete', {
field: 'name',
values: names
}).then(function (bulkdelete) {
if (!bulkdelete) { return }
if (!bulkdelete) return
if (bulkdelete.data.success === false) {
if (bulkdelete.data.success === false)
if (bulkdelete.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', bulkdelete.data.description, 'error')
}
}
let deleted = count
if (bulkdelete.data.failed && bulkdelete.data.failed.length) {
if (bulkdelete.data.failed && bulkdelete.data.failed.length)
deleted -= bulkdelete.data.failed.length
}
document.getElementById('names').value = bulkdelete.data.failed.join('\n')
swal('Deleted!', `${deleted} file${deleted === 1 ? ' has' : 's have'} been deleted.`, 'success')
@ -898,19 +877,18 @@ page.deleteFileByNames = function () {
page.addSelectedFilesToAlbum = function () {
const count = page.selected.uploads.length
if (!count) {
if (!count)
return swal('An error occurred!', 'You have not selected any uploads.', 'error')
}
page.addFilesToAlbum(page.selected.uploads, function (failed) {
if (!failed) { return }
if (failed.length) {
if (!failed) return
if (failed.length)
page.selected.uploads = page.selected.uploads.filter(function (id) {
return failed.includes(id)
})
} else {
else
page.selected.uploads = []
}
localStorage[LS_KEYS.selected.uploads] = JSON.stringify(page.selected.uploads)
page.getUploads(page.views.uploads)
})
@ -918,7 +896,7 @@ page.addSelectedFilesToAlbum = function () {
page.addSingleFileToAlbum = function (id) {
page.addFilesToAlbum([id], function (failed) {
if (!failed) { return }
if (!failed) return
page.getUploads(page.views.uploads)
})
}
@ -955,37 +933,34 @@ page.addFilesToAlbum = function (ids, callback) {
}
}
}).then(function (choose) {
if (!choose) { return }
if (!choose) return
const albumid = parseInt(document.getElementById('swalAlbum').value)
if (isNaN(albumid)) {
if (isNaN(albumid))
return swal('An error occurred!', 'You did not choose an album.', 'error')
}
axios.post('api/albums/addfiles', {
ids,
albumid
}).then(function (add) {
if (!add) { return }
if (!add) return
if (add.data.success === false) {
if (add.data.description === 'No token provided') {
if (add.data.description === 'No token provided')
page.verifyToken(page.token)
} else {
else
swal('An error occurred!', add.data.description, 'error')
}
return
}
let added = ids.length
if (add.data.failed && add.data.failed.length) {
if (add.data.failed && add.data.failed.length)
added -= add.data.failed.length
}
const suffix = `file${ids.length === 1 ? '' : 's'}`
if (!added) {
if (!added)
return swal('An error occurred!', `Could not add the ${suffix} to the album.`, 'error')
}
swal('Woohoo!', `Successfully ${albumid < 0 ? 'removed' : 'added'} ${added} ${suffix} ${albumid < 0 ? 'from' : 'to'} the album.`, 'success')
return callback(add.data.failed)
@ -1001,17 +976,17 @@ page.addFilesToAlbum = function (ids, callback) {
// Get albums list then update content of swal
axios.get('api/albums').then(function (list) {
if (list.data.success === false) {
if (list.data.description === 'No token provided') {
if (list.data.description === 'No token provided')
page.verifyToken(page.token)
} else {
else
swal('An error occurred!', list.data.description, 'error')
}
return
}
const select = document.getElementById('swalAlbum')
// If the prompt was replaced, the container would be missing
if (!select) { return }
if (!select) return
select.innerHTML += list.data.albums
.map(function (album) {
return `<option value="${album.id}">${album.name}</option>`
@ -1027,15 +1002,14 @@ page.addFilesToAlbum = function (ids, callback) {
page.getAlbums = function () {
axios.get('api/albums').then(function (response) {
if (!response) { return }
if (!response) return
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
page.cache.albums = {}
@ -1140,7 +1114,7 @@ page.getAlbums = function () {
page.editAlbum = function (id) {
const album = page.cache.albums[id]
if (!album) { return }
if (!album) return
const div = document.createElement('div')
div.innerHTML = `
@ -1191,7 +1165,7 @@ page.editAlbum = function (id) {
}
}
}).then(function (value) {
if (!value) { return }
if (!value) return
axios.post('api/albums/edit', {
id,
@ -1201,23 +1175,21 @@ page.editAlbum = function (id) {
public: document.getElementById('swalPublic').checked,
requestLink: document.getElementById('swalRequestLink').checked
}).then(function (response) {
if (!response) { return }
if (!response) return
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
if (response.data.identifier) {
if (response.data.identifier)
swal('Success!', `Your album's new identifier is: ${response.data.identifier}.`, 'success')
} else if (response.data.name !== album.name) {
else if (response.data.name !== album.name)
swal('Success!', `Your album was renamed to: ${response.data.name}.`, 'success')
} else {
else
swal('Success!', 'Your album was edited!', 'success')
}
page.getAlbumsSidebar()
page.getAlbums()
@ -1248,19 +1220,18 @@ page.deleteAlbum = function (id) {
}
}
}).then(function (proceed) {
if (!proceed) { return }
if (!proceed) return
axios.post('api/albums/delete', {
id,
purge: proceed === 'purge'
}).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
swal('Deleted!', 'Your album has been deleted.', 'success')
page.getAlbumsSidebar()
@ -1279,17 +1250,16 @@ page.submitAlbum = function (element) {
name: document.getElementById('albumName').value,
description: document.getElementById('albumDescription').value
}).then(function (response) {
if (!response) { return }
if (!response) return
page.isLoading(element, false)
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
swal('Woohoo!', 'Album was created successfully', 'success')
page.getAlbumsSidebar()
@ -1303,20 +1273,19 @@ page.submitAlbum = function (element) {
page.getAlbumsSidebar = function () {
axios.get('api/albums/sidebar').then(function (response) {
if (!response) { return }
if (!response) return
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
const albumsContainer = document.getElementById('albumsContainer')
albumsContainer.innerHTML = ''
if (response.data.albums === undefined) { return }
if (response.data.albums === undefined) return
for (let i = 0; i < response.data.albums.length; i++) {
const album = response.data.albums[i]
@ -1345,13 +1314,12 @@ page.getAlbum = function (album) {
page.changeFileLength = function () {
axios.get('api/filelength/config').then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
// Shorter vars
const { max, min } = response.data.config
@ -1397,13 +1365,12 @@ page.setFileLength = function (fileLength, element) {
axios.post('api/filelength/change', { fileLength }).then(function (response) {
page.isLoading(element, false)
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
swal({
title: 'Woohoo!',
@ -1421,13 +1388,12 @@ page.setFileLength = function (fileLength, element) {
page.changeToken = function () {
axios.get('api/tokens').then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
page.dom.innerHTML = `
<h2 class="subtitle">Manage your token</h2>
@ -1463,13 +1429,12 @@ page.getNewToken = function (element) {
axios.post('api/tokens/change').then(function (response) {
page.isLoading(element, false)
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
swal({
title: 'Woohoo!',
@ -1517,15 +1482,14 @@ page.changePassword = function () {
page.fadeIn()
document.getElementById('sendChangePassword').addEventListener('click', function () {
if (document.getElementById('password').value === document.getElementById('passwordConfirm').value) {
if (document.getElementById('password').value === document.getElementById('passwordConfirm').value)
page.sendNewPassword(document.getElementById('password').value, this)
} else {
else
swal({
title: 'Password mismatch!',
text: 'Your passwords do not match, please try again.',
icon: 'error'
})
}
})
}
@ -1535,13 +1499,12 @@ page.sendNewPassword = function (pass, element) {
axios.post('api/password/change', { password: pass }).then(function (response) {
page.isLoading(element, false)
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
swal({
title: 'Woohoo!',
@ -1560,9 +1523,8 @@ page.sendNewPassword = function (pass, element) {
page.setActiveMenu = function (activeItem) {
const menu = document.getElementById('menu')
const items = menu.getElementsByTagName('a')
for (let i = 0; i < items.length; i++) {
for (let i = 0; i < items.length; i++)
items[i].classList.remove('is-active')
}
activeItem.classList.add('is-active')
}
@ -1585,11 +1547,11 @@ page.getPrettyBytes = num => {
// MIT License
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
if (!Number.isFinite(num)) { return num }
if (!Number.isFinite(num)) return num
const neg = num < 0
if (neg) { num = -num }
if (num < 1) { return `${neg ? '-' : ''}${num}B` }
if (neg) num = -num
if (num < 1) return `${neg ? '-' : ''}${num}B`
const exponent = Math.min(Math.floor(Math.log10(num) / 3), page.byteUnits.length - 1)
const numStr = Number((num / Math.pow(1000, exponent)).toPrecision(3))
@ -1599,26 +1561,24 @@ page.getPrettyBytes = num => {
}
page.getUsers = ({ pageNum } = {}, element) => {
if (element) { page.isLoading(element, true) }
if (pageNum === undefined) { pageNum = 0 }
if (element) page.isLoading(element, true)
if (pageNum === undefined) pageNum = 0
if (!page.permissions.admin) {
if (!page.permissions.admin)
return swal('An error occurred!', 'You can not do this!', 'error')
}
const url = `api/users/${pageNum}`
axios.get(url).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
if (pageNum && (response.data.users.length === 0)) {
// Only remove loading class here, since beyond this the entire page will be replaced anyways
if (element) { page.isLoading(element, false) }
if (element) page.isLoading(element, false)
return swal('An error occurred!', 'There are no more users!', 'error')
}
@ -1691,11 +1651,11 @@ page.getUsers = ({ pageNum } = {}, element) => {
for (let i = 0; i < response.data.users.length; i++) {
const user = response.data.users[i]
const selected = page.selected.users.includes(user.id)
if (!selected && allSelected) { allSelected = false }
if (!selected && allSelected) allSelected = false
let displayGroup = null
for (const group of Object.keys(user.groups)) {
if (!user.groups[group]) { break }
if (!user.groups[group]) break
displayGroup = group
}
@ -1744,12 +1704,12 @@ page.getUsers = ({ pageNum } = {}, element) => {
if (allSelected && response.data.users.length) {
const selectAll = document.getElementById('selectAll')
if (selectAll) { selectAll.checked = true }
if (selectAll) selectAll.checked = true
}
page.views.users.pageNum = response.data.users.length ? pageNum : 0
}).catch(function (error) {
if (element) { page.isLoading(element, false) }
if (element) page.isLoading(element, false)
console.log(error)
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
})
@ -1757,7 +1717,7 @@ page.getUsers = ({ pageNum } = {}, element) => {
page.editUser = function (id) {
const user = page.cache.users[id]
if (!user) { return }
if (!user) return
const groupOptions = Object.keys(page.permissions).map((g, i, a) => {
const selected = g === user.displayGroup
@ -1812,7 +1772,7 @@ page.editUser = function (id) {
}
}
}).then(function (value) {
if (!value) { return }
if (!value) return
axios.post('api/users/edit', {
id,
@ -1821,15 +1781,14 @@ page.editUser = function (id) {
enabled: document.getElementById('swalEnabled').checked,
resetPassword: document.getElementById('swalResetPassword').checked
}).then(function (response) {
if (!response) { return }
if (!response) return
if (response.data.success === false) {
if (response.data.success === false)
if (response.data.description === 'No token provided') {
return page.verifyToken(page.token)
} else {
return swal('An error occurred!', response.data.description, 'error')
}
}
if (response.data.password) {
const div = document.createElement('div')
@ -1842,11 +1801,10 @@ page.editUser = function (id) {
icon: 'success',
content: div
})
} else if (response.data.name !== user.name) {
} else if (response.data.name !== user.name)
swal('Success!', `${user.username} was renamed into: ${response.data.name}.`, 'success')
} else {
else
swal('Success!', 'The user was edited!', 'success')
}
page.getUsers(page.views.users)
}).catch(function (error) {
@ -1896,14 +1854,13 @@ page.disableUser = function (id) {
window.onload = function () {
// Add 'no-touch' class to non-touch devices
if (!('ontouchstart' in document.documentElement)) {
if (!('ontouchstart' in document.documentElement))
document.documentElement.classList.add('no-touch')
}
const selectedKeys = ['uploads', 'users']
for (const selectedKey of selectedKeys) {
const ls = localStorage[LS_KEYS.selected[selectedKey]]
if (ls) { page.selected[selectedKey] = JSON.parse(ls) }
if (ls) page.selected[selectedKey] = JSON.parse(ls)
}
page.preparePage()

View File

@ -40,7 +40,7 @@ page.checkIfPublic = function () {
}
page.preparePage = function () {
if (page.private) {
if (page.private)
if (page.token) {
return page.verifyToken(page.token, true)
} else {
@ -48,32 +48,29 @@ page.preparePage = function () {
button.href = 'auth'
button.classList.remove('is-loading')
if (page.enableUserAccounts) {
if (page.enableUserAccounts)
button.innerText = 'Anonymous upload is disabled. Log in to page.'
} else {
else
button.innerText = 'Running in private mode. Log in to page.'
}
}
} else {
else
return page.prepareUpload()
}
}
page.verifyToken = function (token, reloadOnError) {
if (reloadOnError === undefined) { reloadOnError = false }
if (reloadOnError === undefined) reloadOnError = false
axios.post('api/tokens/verify', { token }).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
return swal({
title: 'An error occurred!',
text: response.data.description,
icon: 'error'
}).then(function () {
if (!reloadOnError) { return }
if (!reloadOnError) return
localStorage.removeItem('token')
location.reload()
})
}
localStorage.token = token
page.token = token
@ -102,9 +99,8 @@ page.prepareUpload = function () {
document.getElementById('maxFileSize').innerHTML = `Maximum upload size per file is ${page.maxFileSize}`
document.getElementById('loginToUpload').style.display = 'none'
if (!page.token && page.enableUserAccounts) {
if (!page.token && page.enableUserAccounts)
document.getElementById('loginLinkText').innerHTML = 'Create an account and keep track of your uploads'
}
const previewNode = document.querySelector('#tpl')
page.previewTemplate = previewNode.innerHTML
@ -116,18 +112,17 @@ page.prepareUpload = function () {
if (tabs) {
tabs.style.display = 'flex'
const items = tabs.getElementsByTagName('li')
for (let i = 0; i < items.length; i++) {
for (let i = 0; i < items.length; i++)
items[i].addEventListener('click', function () {
page.setActiveTab(this.dataset.id)
})
}
document.getElementById('uploadUrls').addEventListener('click', function () {
page.uploadUrls(this)
})
page.setActiveTab('tab-files')
} else {
} else
document.getElementById('tab-files').style.display = 'block'
}
}
page.prepareAlbums = function () {
@ -143,13 +138,12 @@ page.prepareAlbums = function () {
token: page.token
}
}).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
return swal('An error occurred!', response.data.description, 'error')
}
// If the user doesn't have any albums we don't really need to display
// an album selection
if (!response.data.albums.length) { return }
if (!response.data.albums.length) return
// Loop through the albums and create an option for each album
for (let i = 0; i < response.data.albums.length; i++) {
@ -230,13 +224,12 @@ page.prepareDropzone = function () {
}).then(function (response) {
file.previewElement.querySelector('.progress').style.display = 'none'
if (response.data.success === false) {
if (response.data.success === false)
file.previewElement.querySelector('.error').innerHTML = response.data.description
}
if (response.data.files && response.data.files[0]) {
if (response.data.files && response.data.files[0])
page.updateTemplate(file, response.data.files[0])
}
return done()
}).catch(function (error) {
return {
@ -254,29 +247,27 @@ page.prepareDropzone = function () {
// Add the selected albumid, if an album is selected, as a header
page.dropzone.on('sending', function (file, xhr) {
if (file.upload.chunked) { return }
if (page.album) { xhr.setRequestHeader('albumid', page.album) }
if (file.upload.chunked) return
if (page.album) xhr.setRequestHeader('albumid', page.album)
})
// Update the total progress bar
page.dropzone.on('uploadprogress', function (file, progress) {
if (file.upload.chunked && progress === 100) { return }
if (file.upload.chunked && progress === 100) return
file.previewElement.querySelector('.progress').setAttribute('value', progress)
file.previewElement.querySelector('.progress').innerHTML = `${progress}%`
})
page.dropzone.on('success', function (file, response) {
if (!response) { return }
if (!response) return
file.previewElement.querySelector('.progress').style.display = 'none'
// file.previewElement.querySelector('.name').innerHTML = file.name
if (response.success === false) {
if (response.success === false)
file.previewElement.querySelector('.error').innerHTML = response.description
}
if (response.files && response.files[0]) {
if (response.files && response.files[0])
page.updateTemplate(file, response.files[0])
}
})
page.dropzone.on('error', function (file, error) {
@ -285,18 +276,18 @@ page.prepareDropzone = function () {
file.previewElement.querySelector('.error').innerHTML = error.description || error
})
if (typeof page.prepareShareX === 'function') { page.prepareShareX() }
if (typeof page.prepareShareX === 'function') page.prepareShareX()
}
page.uploadUrls = function (button) {
const tabDiv = document.getElementById('tab-urls')
if (!tabDiv) { return }
if (!tabDiv) return
if (button.classList.contains('is-loading')) { return }
if (button.classList.contains('is-loading')) return
button.classList.add('is-loading')
function done (error) {
if (error) { swal('An error occurred!', error, 'error') }
if (error) swal('An error occurred!', error, 'error')
button.classList.remove('is-loading')
}
@ -308,10 +299,9 @@ page.uploadUrls = function (button) {
.filter(function (url) { return url.trim().length })
document.getElementById('urls').value = urls.join('\n')
if (!urls.length) {
if (!urls.length)
// eslint-disable-next-line prefer-promise-reject-errors
return done('You have not entered any URLs.')
}
tabDiv.getElementsByClassName('uploads')[0].style.display = 'block'
const files = urls.map(function (url) {
@ -327,17 +317,17 @@ page.uploadUrls = function (button) {
})
function post (i) {
if (i === files.length) { return done() }
if (i === files.length) return done()
const file = files[i]
function posted (result) {
file.previewElement.querySelector('.progress').style.display = 'none'
if (result.success) {
if (result.success)
page.updateTemplate(file, result.files[0])
} else {
else
file.previewElement.querySelector('.error').innerHTML = result.description
}
return post(i + 1)
}
@ -363,7 +353,7 @@ page.uploadUrls = function (button) {
}
page.updateTemplate = function (file, response) {
if (!response.url) { return }
if (!response.url) return
const a = file.previewElement.querySelector('.link > a')
const clipboard = file.previewElement.querySelector('.clipboard-mobile > .clipboard-js')
@ -422,7 +412,7 @@ page.createAlbum = function () {
}
}
}).then(function (value) {
if (!value) { return }
if (!value) return
const name = document.getElementById('swalName').value
axios.post('api/albums', {
@ -435,9 +425,8 @@ page.createAlbum = function () {
token: page.token
}
}).then(function (response) {
if (response.data.success === false) {
if (response.data.success === false)
return swal('An error occurred!', response.data.description, 'error')
}
const option = document.createElement('option')
option.value = response.data.id

View File

@ -46,7 +46,7 @@ page.doRenderSwal = function () {
confirm: true
}
}).then(function (value) {
if (!value) { return }
if (!value) return
const newValue = div.querySelector('#swalRender').checked ? undefined : '0'
if (newValue !== localStorage.render) {
newValue ? localStorage.render = newValue : localStorage.removeItem('render')
@ -60,14 +60,14 @@ page.doRenderSwal = function () {
page.getRenderVersion = function () {
const renderScript = document.getElementById('renderScript')
if (!renderScript) { return '' }
if (!renderScript) return ''
const match = renderScript.src.match(/\?v=\w*$/)
if (!match) { return '' }
if (!match) return ''
return match[0]
}
page.doRender = function () {
if (!page.renderRoot || !page.renderArray || !page.renderArray.length) { return }
if (!page.renderRoot || !page.renderArray || !page.renderArray.length) return
let element
if (localStorage.render === '0') {

View File

@ -1,7 +1,7 @@
/* global page */
page.prepareShareX = function () {
if (!page.token) { return }
if (!page.token) return
const origin = (location.hostname + location.pathname).replace(/\/(dashboard)?$/, '')
const originClean = origin.replace(/\//g, '_')
const sharexElement = document.getElementById('ShareX')