chore: remove trailing commas

This commit is contained in:
Zephyrrus 2020-12-24 10:40:50 +02:00
parent 13825ddae6
commit 90001c2df5
102 changed files with 461 additions and 447 deletions

View File

@ -175,7 +175,11 @@
"import/no-extraneous-dependencies": "off",
"no-restricted-syntax": "off",
"no-continue": "off",
"no-await-in-loop": "off"
"no-await-in-loop": "off",
"comma-dangle": [
"error",
"never"
]
},
"settings": {
"import/resolver": {

View File

@ -15,7 +15,7 @@ exports.seed = async (db) => {
createdAt: now,
editedAt: now,
enabled: true,
isAdmin: true,
isAdmin: true
});
console.log();
console.log('=========================================================');

View File

@ -4,31 +4,71 @@
const nodePath = require('path');
const moment = require('moment');
const jetpack = require('fs-jetpack');
const { path } = require('fs-jetpack');
const sharp = require('sharp');
const ffmpeg = require('fluent-ffmpeg');
const imageExtensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png', '.webp'];
const videoExtensions = ['.webm', '.mp4', '.wmv', '.avi', '.mov'];
const generateThumbnailForImage = async (filename, output) => {
try {
const file = await jetpack.readAsync(nodePath.join(__dirname, '../../uploads', filename), 'buffer');
await sharp(file)
.resize(64, 64)
.toFormat('webp')
.toFile(nodePath.join(__dirname, '../../uploads/thumbs/square', output));
await sharp(file)
.resize(225, null)
.toFormat('webp')
.toFile(nodePath.join(__dirname, '../../uploads/thumbs', output));
console.log('finished', filename);
} catch (error) {
console.log('error', filename);
}
};
const generateThumbnailForVideo = (filename) => {
try {
ffmpeg(nodePath.join(__dirname, '../../uploads', filename))
.thumbnail({
timestamps: [0],
filename: '%b.png',
folder: nodePath.join(__dirname, '../../uploads/thumbs/square'),
size: '64x64'
})
.on('error', (error) => console.error(error.message));
ffmpeg(nodePath.join(__dirname, '../../uploads', filename))
.thumbnail({
timestamps: [0],
filename: '%b.png',
folder: nodePath.join(__dirname, '../../uploads/thumbs'),
size: '150x?'
})
.on('error', (error) => console.error(error.message));
console.log('finished', filename);
} catch (error) {
console.log('error', filename);
}
};
const oldDb = require('knex')({
client: 'sqlite3',
connection: {
filename: nodePath.join(__dirname, '..', '..', 'db'),
filename: nodePath.join(__dirname, '../../', 'db')
},
useNullAsDefault: true,
useNullAsDefault: true
});
const newDb = require('knex')({
client: 'sqlite3',
connection: {
filename: nodePath.join(__dirname, '..', '..', 'database.sqlite'),
filename: nodePath.join(__dirname, '../../', 'database.sqlite')
},
postProcessResponse: (result) => {
const booleanFields = [
'enabled',
'enableDownload',
'isAdmin',
'isAdmin'
];
const processResponse = (row) => {
@ -45,15 +85,15 @@ const newDb = require('knex')({
if (typeof result === 'object') return processResponse(result);
return result;
},
useNullAsDefault: true,
useNullAsDefault: true
});
const start = async () => {
console.log('Starting migration, this may take a few minutes...'); // Because I half assed it
console.log('Please do NOT kill the process. Wait for it to finish.');
await jetpack.removeAsync(nodePath.join(__dirname, '..', '..', 'uploads', 'thumbs'));
await jetpack.dirAsync(nodePath.join(__dirname, '..', '..', 'uploads', 'thumbs', 'square'));
await jetpack.removeAsync(nodePath.join(__dirname, '../../uploads/thumbs'));
await jetpack.dirAsync(nodePath.join(__dirname, '../../uploads/thumbs/square'));
console.log('Finished deleting old thumbnails to create new ones');
const users = await oldDb.table('users').where('username', '<>', 'root');
@ -69,7 +109,7 @@ const start = async () => {
passwordEditedAt: now,
apiKeyEditedAt: now,
createdAt: now,
editedAt: now,
editedAt: now
};
await newDb.table('users').insert(userToInsert);
}
@ -85,7 +125,7 @@ const start = async () => {
name: album.name,
zippedAt: album.zipGeneratedAt ? moment.unix(album.zipGeneratedAt).toDate() : null,
createdAt: moment.unix(album.timestamp).toDate(),
editedAt: moment.unix(album.editedAt).toDate(),
editedAt: moment.unix(album.editedAt).toDate()
};
const linkToInsert = {
userId: album.userid,
@ -95,13 +135,13 @@ const start = async () => {
enabled: true,
enableDownload: true,
createdAt: now,
editedAt: now,
editedAt: now
};
await newDb.table('albums').insert(albumToInsert);
const insertedId = await newDb.table('links').insert(linkToInsert);
await newDb.table('albumsLinks').insert({
albumId: album.id,
linkId: insertedId[0],
linkId: insertedId[0]
});
}
console.log('Finished migrating albums...');
@ -120,16 +160,16 @@ const start = async () => {
hash: file.hash,
ip: file.ip,
createdAt: moment.unix(file.timestamp).toDate(),
editedAt: moment.unix(file.timestamp).toDate(),
editedAt: moment.unix(file.timestamp).toDate()
};
filesToInsert.push(fileToInsert);
albumsFilesToInsert.push({
albumId: file.albumid,
fileId: file.id,
fileId: file.id
});
const filename = file.name;
if (!jetpack.exists(nodePath.join(__dirname, '..', '..', 'uploads', filename))) continue;
if (!jetpack.exists(nodePath.join(__dirname, '../../uploads', filename))) continue;
const ext = nodePath.extname(filename).toLowerCase();
const output = `${filename.slice(0, -ext.length)}.webp`;
if (imageExtensions.includes(ext)) await generateThumbnailForImage(filename, output);
@ -143,45 +183,4 @@ const start = async () => {
process.exit(0);
};
const generateThumbnailForImage = async (filename, output) => {
try {
const file = await jetpack.readAsync(nodePath.join(__dirname, '..', '..', 'uploads', filename), 'buffer');
await sharp(file)
.resize(64, 64)
.toFormat('webp')
.toFile(nodePath.join(__dirname, '..', '..', 'uploads', 'thumbs', 'square', output));
await sharp(file)
.resize(225, null)
.toFormat('webp')
.toFile(nodePath.join(__dirname, '..', '..', 'uploads', 'thumbs', output));
console.log('finished', filename);
} catch (error) {
console.log('error', filename);
}
};
const generateThumbnailForVideo = filename => {
try {
ffmpeg(nodePath.join(__dirname, '..', '..', 'uploads', filename))
.thumbnail({
timestamps: [0],
filename: '%b.png',
folder: nodePath.join(__dirname, '..', '..', 'uploads', 'thumbs', 'square'),
size: '64x64'
})
.on('error', error => console.error(error.message));
ffmpeg(nodePath.join(__dirname, '..', '..', 'uploads', filename))
.thumbnail({
timestamps: [0],
filename: '%b.png',
folder: nodePath.join(__dirname, '..', '..', 'uploads', 'thumbs'),
size: '150x?'
})
.on('error', error => console.error(error.message));
console.log('finished', filename);
} catch (error) {
console.log('error', filename);
}
};
start();

View File

@ -6,7 +6,7 @@ const path = require('path');
const ThumbUtil = require('./utils/ThumbUtil');
const start = async () => {
const files = fs.readdirSync(path.join(__dirname, '..', '..', process.env.UPLOAD_FOLDER));
const files = fs.readdirSync(path.join(__dirname, '../../', process.env.UPLOAD_FOLDER));
for (const fileName of files) {
console.log(`Generating thumb for '${fileName}`);
// eslint-disable-next-line no-await-in-loop

View File

@ -17,7 +17,7 @@ class banIP extends Route {
}
return res.json({
message: 'Successfully banned the ip',
message: 'Successfully banned the ip'
});
}
}

View File

@ -24,7 +24,7 @@ class filesGET extends Route {
return res.json({
message: 'Successfully retrieved file',
file,
user,
user
});
}
}

View File

@ -19,7 +19,7 @@ class unBanIP extends Route {
}
return res.json({
message: 'Successfully unbanned the ip',
message: 'Successfully unbanned the ip'
});
}
}

View File

@ -20,7 +20,7 @@ class userDemote extends Route {
}
return res.json({
message: 'Successfully demoted user',
message: 'Successfully demoted user'
});
}
}

View File

@ -20,7 +20,7 @@ class userDisable extends Route {
}
return res.json({
message: 'Successfully disabled user',
message: 'Successfully disabled user'
});
}
}

View File

@ -20,7 +20,7 @@ class userEnable extends Route {
}
return res.json({
message: 'Successfully enabled user',
message: 'Successfully enabled user'
});
}
}

View File

@ -26,7 +26,7 @@ class usersGET extends Route {
return res.json({
message: 'Successfully retrieved user',
user,
files,
files
});
} catch (error) {
return super.error(res, error);

View File

@ -20,7 +20,7 @@ class userPromote extends Route {
}
return res.json({
message: 'Successfully promoted user',
message: 'Successfully promoted user'
});
}
}

View File

@ -18,7 +18,7 @@ class userDemote extends Route {
}
return res.json({
message: 'Successfully deleted the user\'s files',
message: 'Successfully deleted the user\'s files'
});
}
}

View File

@ -12,7 +12,7 @@ class usersGET extends Route {
return res.json({
message: 'Successfully retrieved users',
users,
users
});
} catch (error) {
return super.error(res, error);

View File

@ -50,7 +50,7 @@ class albumGET extends Route {
message: 'Successfully retrieved album',
name: album.name,
files,
count,
count
});
}
}

View File

@ -37,7 +37,7 @@ class albumGET extends Route {
message: 'Successfully retrieved files',
name: album.name,
downloadEnabled: link.enableDownload,
files,
files
});
}
}

View File

@ -25,7 +25,7 @@ class albumPOST extends Route {
name,
userId: user.id,
createdAt: now,
editedAt: now,
editedAt: now
};
const dbRes = await db.table('albums').insert(insertObj);

View File

@ -21,7 +21,7 @@ class albumGET extends Route {
.where({
identifier,
enabled: true,
enableDownload: true,
enableDownload: true
})
.first();
if (!link) return res.status(400).json({ message: 'The supplied identifier could not be found' });
@ -38,7 +38,7 @@ class albumGET extends Route {
If the date when the album was zipped is greater than the album's last edit, we just send the zip to the user
*/
if (album.zippedAt > album.editedAt) {
const filePath = path.join(__dirname, '..', '..', '..', '..', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`);
const filePath = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`);
const exists = await jetpack.existsAsync(filePath);
/*
Make sure the file exists just in case, and if not, continue to it's generation.
@ -76,7 +76,7 @@ class albumGET extends Route {
.where('id', link.albumId)
.update('zippedAt', db.fn.now());
const filePath = path.join(__dirname, '..', '..', '..', '..', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`);
const filePath = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`);
const fileName = `lolisafe-${identifier}.zip`;
return res.download(filePath, fileName);
} catch (error) {

View File

@ -46,7 +46,7 @@ class albumsGET extends Route {
return res.json({
message: 'Successfully retrieved albums',
albums,
albums
});
}
}
@ -63,7 +63,7 @@ class albumsDropdownGET extends Route {
.select('id', 'name');
return res.json({
message: 'Successfully retrieved albums',
albums,
albums
});
}
}

View File

@ -27,7 +27,7 @@ class linkDELETE extends Route {
}
return res.json({
message: 'Successfully deleted link',
message: 'Successfully deleted link'
});
}
}

View File

@ -22,7 +22,7 @@ class linkEditPOST extends Route {
try {
const updateObj = {
enableDownload: enableDownload || false,
expiresAt, // This one should be null if not supplied
expiresAt // This one should be null if not supplied
};
await db
.table('links')

View File

@ -61,13 +61,13 @@ class linkPOST extends Route {
enabled: true,
enableDownload: true,
expiresAt: null,
views: 0,
views: 0
};
await db.table('links').insert(insertObj);
return res.json({
message: 'The link was created successfully',
data: insertObj,
data: insertObj
});
} catch (error) {
return super.error(res, error);

View File

@ -14,7 +14,7 @@ class linkPOST extends Route {
return res.json({
message: 'Successfully retrieved links',
links,
links
});
}
}

View File

@ -36,7 +36,7 @@ class loginPOST extends Route {
const jwt = JWT.sign({
iss: 'lolisafe',
sub: user.id,
iat: moment.utc().valueOf(),
iat: moment.utc().valueOf()
}, process.env.SECRET, { expiresIn: '30d' });
return res.json({
@ -45,10 +45,10 @@ class loginPOST extends Route {
id: user.id,
username: user.username,
apiKey: user.apiKey,
isAdmin: user.isAdmin,
isAdmin: user.isAdmin
},
token: jwt,
apiKey: user.apiKey,
apiKey: user.apiKey
});
}
}

View File

@ -50,7 +50,7 @@ class registerPOST extends Route {
createdAt: now,
editedAt: now,
enabled: true,
isAdmin: false,
isAdmin: false
});
return res.json({ message: 'The account was created successfully' });
}

View File

@ -25,7 +25,7 @@ class albumAddPOST extends Route {
return res.json({
message: 'Successfully added file to album',
data: { fileId, album: { id: album.id, name: album.name } },
data: { fileId, album: { id: album.id, name: album.name } }
});
}
}

View File

@ -26,7 +26,7 @@ class albumDelPOST extends Route {
return res.json({
message: 'Successfully removed file from album',
data: { fileId, album: { id: album.id, name: album.name } },
data: { fileId, album: { id: album.id, name: album.name } }
});
}
}

View File

@ -38,7 +38,7 @@ class fileGET extends Route {
message: 'Successfully retrieved file',
file,
albums,
tags,
tags
});
}
}

View File

@ -26,7 +26,7 @@ class filesGET extends Route {
return res.json({
message: 'Successfully retrieved file albums',
albums,
albums
});
}
}

View File

@ -36,7 +36,7 @@ class filesGET extends Route {
return res.json({
message: 'Successfully retrieved files',
files,
count,
count
});
}
}

View File

@ -31,7 +31,7 @@ class tagAddBatchPOST extends Route {
return res.json({
message: 'Successfully added tags to file',
data: { fileId, tags: addedTags },
errors,
errors
});
// eslint-disable-next-line consistent-return
}

View File

@ -27,7 +27,7 @@ class tagAddPOST extends Route {
return res.json({
message: 'Successfully added tag to file',
data: { fileId, tag },
data: { fileId, tag }
});
// eslint-disable-next-line consistent-return
}

View File

@ -29,7 +29,7 @@ class tagDelPost extends Route {
return res.json({
message: 'Successfully removed tag from file',
data: { fileId, tag },
data: { fileId, tag }
});
// eslint-disable-next-line consistent-return
}

View File

@ -9,7 +9,7 @@ const options = {
keywords: ['album', 'tag', 'before', 'after', 'file'],
offsets: false,
alwaysArray: true,
tokenize: true,
tokenize: true
};
class configGET extends Route {
@ -55,7 +55,7 @@ class configGET extends Route {
query,
parsed,
files,
count,
count
});
}
}

View File

@ -18,8 +18,8 @@ class configGET extends Route {
generateThumbnails: process.env.GENERATE_THUMBNAILS === 'true',
generateZips: process.env.GENERATE_ZIPS === 'true',
publicMode: process.env.PUBLIC_MODE === 'true',
enableAccounts: process.env.USER_ACCOUNTS === 'true',
},
enableAccounts: process.env.USER_ACCOUNTS === 'true'
}
});
}
}

View File

@ -22,7 +22,7 @@ class tagPOST extends Route {
name,
userId: user.id,
createdAt: now,
editedAt: now,
editedAt: now
};
const dbRes = await db.table('tags').insert(insertObj);

View File

@ -19,7 +19,7 @@ class tagsGET extends Route {
return res.json({
message: 'Successfully retrieved tags',
tags,
tags
});
} catch (error) {
return super.error(res, error);

View File

@ -8,7 +8,7 @@ class uploadPOST extends Route {
constructor() {
super('/upload/chunks', 'post', {
bypassAuth: true,
canApiKey: true,
canApiKey: true
});
}
@ -17,7 +17,7 @@ class uploadPOST extends Route {
// console.log('Files', req.body.files);
const info = {
size: req.body.files[0].size,
url: `${process.env.DOMAIN}/`,
url: `${process.env.DOMAIN}/`
};
for (const chunk of req.body.files) {
@ -56,7 +56,7 @@ class uploadPOST extends Route {
return res.status(201).send({
message: 'Sucessfully merged the chunk(s).',
...info,
...info
/*
name: `${filename}${ext || ''}`,
size: exists.size,

View File

@ -9,7 +9,7 @@ const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: parseInt(process.env.MAX_SIZE, 10) * (1000 * 1000),
files: 1,
files: 1
},
fileFilter: (req, file, cb) =>
// TODO: Enable blacklisting of files/extensions
@ -21,7 +21,7 @@ const upload = multer({
}
*/
cb(null, true)
,
}).array('files[]');
/*
@ -41,7 +41,7 @@ class uploadPOST extends Route {
constructor() {
super('/upload', 'post', {
bypassAuth: true,
canApiKey: true,
canApiKey: true
});
}
@ -100,7 +100,7 @@ class uploadPOST extends Route {
name: filename,
hash,
size: file.buffer.length,
url: filename,
url: filename
};
}
@ -120,7 +120,7 @@ class uploadPOST extends Route {
uploadedFile = Util.constructFilePublicLink(uploadedFile);
return res.status(201).send({
message: 'Sucessfully uploaded the file.',
...uploadedFile,
...uploadedFile
});
});
}
@ -134,7 +134,7 @@ class uploadPOST extends Route {
size: exists.size,
url: `${process.env.DOMAIN}/${exists.name}`,
deleteUrl: `${process.env.DOMAIN}/api/file/${exists.id}`,
repeated: true,
repeated: true
});
return Util.deleteFile(filename);
@ -183,7 +183,7 @@ class uploadPOST extends Route {
hash: file.hash,
ip: req.ip,
createdAt: now,
editedAt: now,
editedAt: now
});
} else {
insertedId = await db.table('files').insert({
@ -195,7 +195,7 @@ class uploadPOST extends Route {
hash: file.hash,
ip: req.ip,
createdAt: now,
editedAt: now,
editedAt: now
}, 'id');
}
return insertedId;

View File

@ -17,7 +17,7 @@ class apiKeyPOST extends Route {
.where({ id: user.id })
.update({
apiKey,
apiKeyEditedAt: now,
apiKeyEditedAt: now
});
} catch (error) {
dump(error);
@ -26,7 +26,7 @@ class apiKeyPOST extends Route {
return res.json({
message: 'Successfully created new api key',
apiKey,
apiKey
});
}
}

View File

@ -36,7 +36,7 @@ class changePasswordPOST extends Route {
const now = moment.utc().toDate();
await db.table('users').where('id', user.id).update({
password: hash,
passwordEditedAt: now,
passwordEditedAt: now
});
return res.json({ message: 'The password was changed successfully' });

View File

@ -12,8 +12,8 @@ class usersGET extends Route {
id: user.id,
username: user.username,
isAdmin: user.isAdmin,
apiKey: user.apiKey,
},
apiKey: user.apiKey
}
});
}
}

View File

@ -11,8 +11,8 @@ class verifyGET extends Route {
user: {
id: user.id,
username: user.username,
isAdmin: user.isAdmin,
},
isAdmin: user.isAdmin
}
});
}
}

View File

@ -7,7 +7,7 @@ const db = require('knex')({
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
filename: nodePath.join(__dirname, '../../../database.sqlite'),
filename: nodePath.join(__dirname, '../../../database.sqlite')
},
postProcessResponse: (result) => {
/*
@ -32,7 +32,7 @@ const db = require('knex')({
if (typeof result === 'object') return processResponse(result);
return result;
},
useNullAsDefault: process.env.DB_CLIENT === 'sqlite3',
useNullAsDefault: process.env.DB_CLIENT === 'sqlite3'
});
const moment = require('moment');
const log = require('../utils/Log');

View File

@ -15,7 +15,7 @@ const ThumbUtil = require('../utils/ThumbUtil');
const rateLimiter = new RateLimit({
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW, 10),
max: parseInt(process.env.RATE_LIMIT_MAX, 10),
delayMs: 0,
delayMs: 0
});
class Server {
@ -52,8 +52,8 @@ class Server {
return false;
},
'stream': {
write(str) { log.debug(str); },
},
write(str) { log.debug(str); }
}
}));
}
// this.server.use(rateLimiter);

View File

@ -4,7 +4,7 @@ class QueryHelper {
static parsers = {
before: (val) => QueryHelper.parseChronoList(val),
after: (val) => QueryHelper.parseChronoList(val),
tag: (val) => QueryHelper.sanitizeTags(val),
tag: (val) => QueryHelper.sanitizeTags(val)
};
static requirementHandlers = {
@ -13,14 +13,14 @@ class QueryHelper {
.join('albums', 'albumsFiles.albumId', '=', 'album.id'),
tag: (knex) => knex
.join('fileTags', 'files.id', '=', 'fileTags.fileId')
.join('tags', 'fileTags.tagId', '=', 'tags.id'),
.join('tags', 'fileTags.tagId', '=', 'tags.id')
}
static fieldToSQLMapping = {
album: 'albums.name',
tag: 'tags.name',
before: 'files.createdAt',
after: 'files.createdAt',
after: 'files.createdAt'
}
static handlers = {
@ -53,7 +53,7 @@ class QueryHelper {
}
}
return knex;
},
}
}
static verify(field, list) {

View File

@ -51,7 +51,7 @@ class ThumbUtil {
timestamps: [0],
filename: '%b.png',
folder: ThumbUtil.squareThumbPath,
size: '64x64',
size: '64x64'
})
.on('error', (error) => log.error(error.message));
@ -60,7 +60,7 @@ class ThumbUtil {
timestamps: [0],
filename: '%b.png',
folder: ThumbUtil.thumbPath,
size: '150x?',
size: '150x?'
})
.on('error', (error) => log.error(error.message));
@ -69,7 +69,7 @@ class ThumbUtil {
input: filePath,
width: 150,
output: path.join(ThumbUtil.videoPreviewPath, output),
log: log.debug,
log: log.debug
});
} catch (e) {
log.error(e);
@ -87,7 +87,7 @@ class ThumbUtil {
if (isVideo) {
return {
thumb: `${filename.slice(0, -ext.length)}.png`,
preview: `${filename.slice(0, -ext.length)}.webm`,
preview: `${filename.slice(0, -ext.length)}.webm`
};
}

View File

@ -10,9 +10,9 @@ const db = require('knex')({
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
filename: path.join(__dirname, '../../../database.sqlite'),
filename: path.join(__dirname, '../../../database.sqlite')
},
useNullAsDefault: process.env.DB_CLIENT === 'sqlite',
useNullAsDefault: process.env.DB_CLIENT === 'sqlite'
});
const moment = require('moment');
const crypto = require('crypto');
@ -25,7 +25,7 @@ const ThumbUtil = require('./ThumbUtil');
const blockedExtensions = process.env.BLOCKED_EXTENSIONS.split(',');
class Util {
static uploadPath = path.join(__dirname, '..', '..', '..', process.env.UPLOAD_FOLDER);
static uploadPath = path.join(__dirname, '../../../', process.env.UPLOAD_FOLDER);
static uuid() {
return uuidv4();
@ -54,7 +54,7 @@ class Util {
const retry = (i = 0) => {
const filename = randomstring.generate({
length: parseInt(process.env.GENERATED_FILENAME_LENGTH, 10),
capitalization: 'lowercase',
capitalization: 'lowercase'
}) + path.extname(name).toLowerCase();
// TODO: Change this to look for the file in the db instead of in the filesystem
@ -71,7 +71,7 @@ class Util {
const retry = async (i = 0) => {
const identifier = randomstring.generate({
length: parseInt(process.env.GENERATED_ALBUM_LENGTH, 10),
capitalization: 'lowercase',
capitalization: 'lowercase'
});
const exists = await db
.table('links')
@ -214,13 +214,11 @@ class Util {
zip.writeZip(
path.join(
__dirname,
'..',
'..',
'..',
'../../../',
process.env.UPLOAD_FOLDER,
'zips',
`${album.userId}-${album.id}.zip`,
),
`${album.userId}-${album.id}.zip`
)
);
} catch (error) {
log.error(error);

View File

@ -38,7 +38,7 @@ module.exports = async (opts) => {
fragmentDurationSecond = 3,
ignoreBeforePercent = 0.25,
ignoreAfterPercent = 0.75,
ignoreAfterPercent = 0.75
} = opts;
const info = await probe(input);

View File

@ -16,7 +16,7 @@ module.exports = async (opts) => {
output,
numFrames,
numFramesPercent = 0.05,
numFramesPercent = 0.05
} = opts;
const info = await probe(input);
@ -32,7 +32,7 @@ module.exports = async (opts) => {
const result = {
output,
numFrames: numFramesToCapture,
numFrames: numFramesToCapture
};
await new Promise((resolve, reject) => {

View File

@ -5,7 +5,7 @@ const qoa = require('qoa');
qoa.config({
prefix: '>',
underlineQuery: false,
underlineQuery: false
});
async function start() {
@ -17,53 +17,53 @@ async function start() {
{
type: 'input',
query: 'Port to run lolisafe in:',
handle: 'SERVER_PORT',
handle: 'SERVER_PORT'
},
{
type: 'input',
query: 'Full domain this instance is gonna be running on (Ex: https://lolisafe.moe):',
handle: 'DOMAIN',
handle: 'DOMAIN'
},
{
type: 'input',
query: 'Name of the service? (Ex: lolisafe):',
handle: 'SERVICE_NAME',
handle: 'SERVICE_NAME'
},
{
type: 'input',
query: 'Maximum allowed upload file size in MB (Ex: 100):',
handle: 'MAX_SIZE',
handle: 'MAX_SIZE'
},
{
type: 'confirm',
query: 'Allow users to download entire albums in ZIP format?',
handle: 'GENERATE_ZIPS',
accept: 'y',
deny: 'n',
deny: 'n'
},
{
type: 'confirm',
query: 'Allow people to upload files without an account?',
handle: 'PUBLIC_MODE',
accept: 'y',
deny: 'n',
deny: 'n'
},
{
type: 'confirm',
query: 'Allow people to create new accounts?',
handle: 'USER_ACCOUNTS',
accept: 'y',
deny: 'n',
deny: 'n'
},
{
type: 'input',
query: 'Name of the admin account?',
handle: 'ADMIN_ACCOUNT',
handle: 'ADMIN_ACCOUNT'
},
{
type: 'secure',
query: 'Type a secure password for the admin account:',
handle: 'ADMIN_PASSWORD',
handle: 'ADMIN_PASSWORD'
},
{
type: 'interactive',
@ -73,29 +73,29 @@ async function start() {
menu: [
'sqlite3',
'pg',
'mysql',
],
'mysql'
]
},
{
type: 'input',
query: 'Database host (Ignore if you selected sqlite3):',
handle: 'DB_HOST',
handle: 'DB_HOST'
},
{
type: 'input',
query: 'Database user (Ignore if you selected sqlite3):',
handle: 'DB_USER',
handle: 'DB_USER'
},
{
type: 'input',
query: 'Database password (Ignore if you selected sqlite3):',
handle: 'DB_PASSWORD',
handle: 'DB_PASSWORD'
},
{
type: 'input',
query: 'Database name (Ignore if you selected sqlite3):',
handle: 'DB_DATABASE',
},
handle: 'DB_DATABASE'
}
];
const response = await qoa.prompt(wizard);
@ -118,7 +118,7 @@ async function start() {
META_THEME_COLOR: '#20222b',
META_DESCRIPTION: 'Blazing fast file uploader and bunker written in node! 🚀',
META_KEYWORDS: 'lolisafe,upload,uploader,file,vue,images,ssr,file uploader,free',
META_TWITTER_HANDLE: '@its_pitu',
META_TWITTER_HANDLE: '@its_pitu'
};
const allSettings = Object.assign(defaultSettings, response);

View File

@ -120,17 +120,17 @@ export default {
props: {
albumId: {
type: Number,
default: 0,
default: 0
},
details: {
type: Object,
default: () => ({}),
},
default: () => ({})
}
},
data() {
return {
isCreatingLink: false,
isDeletingLinks: [],
isDeletingLinks: []
};
},
computed: mapState(['config', 'auth']),
@ -141,20 +141,20 @@ export default {
updateLinkOptionsAction: 'albums/updateLinkOptions',
createLinkAction: 'albums/createLink',
createCustomLinkAction: 'albums/createCustomLink',
alert: 'alert/set',
alert: 'alert/set'
}),
promptDeleteAlbum(id) {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to delete this album?',
onConfirm: () => this.deleteAlbum(id),
onConfirm: () => this.deleteAlbum(id)
});
},
promptDeleteAlbumLink(albumId, identifier) {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to delete this album link?',
onConfirm: () => this.deleteAlbumLink(albumId, identifier),
onConfirm: () => this.deleteAlbumLink(albumId, identifier)
});
},
async deleteAlbum(id) {
@ -204,16 +204,16 @@ export default {
message: 'Custom link identifier',
inputAttrs: {
placeholder: '',
maxlength: 10,
maxlength: 10
},
trapFocus: true,
onConfirm: (value) => this.$handler.executeAction('albums/createCustomLink', { albumId, value }),
onConfirm: (value) => this.$handler.executeAction('albums/createCustomLink', { albumId, value })
});
},
isDeleting(identifier) {
return this.isDeletingLinks.indexOf(identifier) > -1;
},
},
}
}
};
</script>

View File

@ -63,22 +63,22 @@ import AlbumDetails from '~/components/album/AlbumDetails.vue';
export default {
components: {
AlbumDetails,
AlbumDetails
},
props: {
album: {
type: Object,
default: () => ({}),
},
default: () => ({})
}
},
computed: {
...mapGetters({
isExpandedGetter: 'albums/isExpanded',
getDetails: 'albums/getDetails',
getDetails: 'albums/getDetails'
}),
isExpanded() {
return this.isExpandedGetter(this.album.id);
},
}
},
methods: {
async toggleDetails(album) {
@ -86,8 +86,8 @@ export default {
await this.$store.dispatch('albums/fetchDetails', album.id);
}
this.$store.commit('albums/toggleExpandedState', album.id);
},
},
}
}
};
</script>

View File

@ -81,8 +81,8 @@ export default {
...mapState({
version: (state) => state.config.version,
serviceName: (state) => state.config.serviceName,
token: (state) => state.auth.token,
}),
token: (state) => state.auth.token
})
},
methods: {
createShareXThing() {
@ -102,8 +102,8 @@ export default {
}`;
const sharexBlob = new Blob([sharexFile], { type: 'application/octet-binary' });
saveAs(sharexBlob, `${location.hostname}.sxcu`);
},
},
}
}
};
</script>

View File

@ -162,37 +162,37 @@ import ImageInfo from '~/components/image-modal/ImageInfo.vue';
export default {
components: {
Waterfall,
ImageInfo,
ImageInfo
},
props: {
files: {
type: Array,
default: () => [],
default: () => []
},
total: {
type: Number,
default: 0,
default: 0
},
fixed: {
type: Boolean,
default: false,
default: false
},
isPublic: {
type: Boolean,
default: false,
default: false
},
width: {
type: Number,
default: 150,
default: 150
},
enableSearch: {
type: Boolean,
default: true,
default: true
},
enableToolbar: {
type: Boolean,
default: true,
},
default: true
}
},
data() {
return {
@ -208,15 +208,15 @@ export default {
modalData: {
file: null,
tags: null,
albums: null,
},
albums: null
}
};
},
computed: {
...mapState({
user: (state) => state.auth.user,
albums: (state) => state.albums.tinyDetails,
images: (state) => state.images,
images: (state) => state.images
}),
blank() {
// eslint-disable-next-line global-require, import/no-unresolved
@ -224,7 +224,7 @@ export default {
},
gridFiles() {
return (this.files || []).filter((v) => !v.hideFromList);
},
}
},
created() {
// TODO: Create a middleware for this
@ -251,7 +251,7 @@ export default {
} catch (e) {
this.$store.dispatch('alert/set', { text: e.message, error: true }, { root: true });
}
},
}
});
},
isAlbumSelected(id) {
@ -279,12 +279,12 @@ export default {
if (add) {
response = await this.$store.dispatch('images/addToAlbum', {
albumId: id,
fileId: this.showingModalForFile.id,
fileId: this.showingModalForFile.id
});
} else {
response = await this.$store.dispatch('images/removeFromAlbum', {
albumId: id,
fileId: this.showingModalForFile.id,
fileId: this.showingModalForFile.id
});
}
@ -332,8 +332,8 @@ export default {
},
isHovered(id) {
return this.hoveredItems.includes(id);
},
},
}
}
};
</script>

View File

@ -20,29 +20,29 @@ const imagesloaded = isBrowser ? require('imagesloaded') : null;
export default {
name: 'Waterfall',
components: {
WaterfallItem,
WaterfallItem
},
props: {
options: {
type: Object,
default: () => {},
default: () => {}
},
items: {
type: Array,
default: () => [],
default: () => []
},
itemWidth: {
type: Number,
default: 150,
default: 150
},
gutterWidth: {
type: Number,
default: 10,
default: 10
},
gutterHeight: {
type: Number,
default: 4,
},
default: 4
}
},
mounted() {
this.initializeMasonry();
@ -62,7 +62,7 @@ export default {
node,
() => {
this.masonry.layout();
},
}
);
},
performLayout() {
@ -101,7 +101,7 @@ export default {
removed,
appended,
prepended,
moved,
moved
};
},
initializeMasonry() {
@ -111,8 +111,8 @@ export default {
{
columnWidth: this.itemWidth,
gutter: this.gutterWidth,
...this.options,
},
...this.options
}
);
this.domChildren = this.getNewDomChildren();
}
@ -122,8 +122,8 @@ export default {
const children = this.options && this.options.itemSelector
? node.querySelectorAll(this.options.itemSelector) : node.children;
return Array.prototype.slice.call(children);
},
},
}
}
};
</script>

View File

@ -5,6 +5,6 @@
</template>
<script>
export default {
name: 'WaterfallItem',
name: 'WaterfallItem'
};
</script>

View File

@ -1,6 +1,7 @@
<template>
<div class="links">
<a href="https://github.com/WeebDev/lolisafe"
<a
href="https://github.com/WeebDev/lolisafe"
target="_blank"
class="link">
<header class="bd-footer-star-header">
@ -8,15 +9,21 @@
<p class="bd-footer-subtitle">Deploy your own lolisafe</p>
</header>
</a>
<div v-if="loggedIn"
<div
v-if="loggedIn"
class="link"
@click="createShareXThing">
<header class="bd-footer-star-header">
<h4 class="bd-footer-title">ShareX</h4>
<p class="bd-footer-subtitle">Upload from your Desktop</p>
<h4 class="bd-footer-title">
ShareX
</h4>
<p class="bd-footer-subtitle">
Upload from your Desktop
</p>
</header>
</div>
<a href="https://chrome.google.com/webstore/detail/lolisafe-uploader/enkkmplljfjppcdaancckgilmgoiofnj"
<a
href="https://chrome.google.com/webstore/detail/lolisafe-uploader/enkkmplljfjppcdaancckgilmgoiofnj"
target="_blank"
class="link">
<header class="bd-footer-star-header">
@ -24,17 +31,23 @@
<p class="bd-footer-subtitle">Upload from any website</p>
</header>
</a>
<router-link to="/faq"
<router-link
to="/faq"
class="link">
<header class="bd-footer-star-header">
<h4 class="bd-footer-title">FAQ</h4>
<p class="bd-footer-subtitle">We got you covered</p>
<h4 class="bd-footer-title">
FAQ
</h4>
<p class="bd-footer-subtitle">
We got you covered
</p>
</header>
</router-link>
</div>
</template>
<script>
import { saveAs } from 'file-saver';
export default {
computed: {
loggedIn() {

View File

@ -31,21 +31,21 @@ export default {
props: {
imageId: {
type: Number,
default: 0,
default: 0
},
imageAlbums: {
type: Array,
default: () => [],
default: () => []
},
albums: {
type: Array,
default: () => [],
},
default: () => []
}
},
data() {
return {
selectedOptions: [],
orderedAlbums: [],
orderedAlbums: []
};
},
created() {
@ -65,7 +65,7 @@ export default {
return selectedA ? -1 : 1;
}
return a.name.localeCompare(b.name);
},
}
);
},
isAlbumSelected(id) {
@ -78,15 +78,15 @@ export default {
if (this.selectedOptions.indexOf(id) > -1) {
this.$handler.executeAction('images/addToAlbum', {
albumId: id,
fileId: this.imageId,
fileId: this.imageId
});
} else {
this.$handler.executeAction('images/removeFromAlbum', {
albumId: id,
fileId: this.imageId,
fileId: this.imageId
});
}
},
},
}
}
};
</script>

View File

@ -118,25 +118,25 @@ import Taginfo from './TagInfo.vue';
export default {
components: {
Taginfo,
Albuminfo,
Albuminfo
},
props: {
file: {
type: Object,
default: () => ({}),
default: () => ({})
},
albums: {
type: Array,
default: () => ([]),
default: () => ([])
},
tags: {
type: Array,
default: () => ([]),
},
default: () => ([])
}
},
computed: mapState({
images: (state) => state.images,
tinyDetails: (state) => state.albums.tinyDetails,
tinyDetails: (state) => state.albums.tinyDetails
}),
methods: {
formatBytes(bytes, decimals = 2) {
@ -152,8 +152,8 @@ export default {
},
isVideo(type) {
return type.startsWith('video');
},
},
}
}
};
</script>

View File

@ -23,24 +23,24 @@ export default {
props: {
imageId: {
type: Number,
default: 0,
default: 0
},
imageTags: {
type: Array,
default: () => [],
},
default: () => []
}
},
data() {
return {
filteredTags: [],
filteredTags: []
};
},
computed: {
...mapState({
tags: (state) => state.tags.tagsList,
tags: (state) => state.tags.tagsList
}),
selectedTags() { return this.imageTags.map((e) => e.name); },
lowercaseTags() { return this.imageTags.map((e) => e.name.toLowerCase()); },
lowercaseTags() { return this.imageTags.map((e) => e.name.toLowerCase()); }
},
methods: {
getFilteredTags(str) {
@ -78,8 +78,8 @@ export default {
},
tagRemoved(tag) {
this.$handler.executeAction('images/removeTag', { fileId: this.imageId, tagName: tag });
},
},
}
}
};
</script>

View File

@ -9,16 +9,16 @@ export default {
props: {
size: {
type: String,
default: '60px',
default: '60px'
},
background: {
type: String,
default: '#9C27B0',
default: '#9C27B0'
},
duration: {
type: String,
default: '1.8s',
},
default: '1.8s'
}
},
computed: {
styles() {
@ -26,10 +26,10 @@ export default {
width: this.size,
height: this.size,
backgroundColor: this.background,
animationDuration: this.duration,
animationDuration: this.duration
};
},
},
}
}
};
</script>

View File

@ -20,8 +20,8 @@ export default {
props: {
size: {
type: String,
default: '40px',
},
default: '40px'
}
},
computed: {
innerStyles() {
@ -31,10 +31,10 @@ export default {
styles() {
return {
width: this.size,
height: this.size,
height: this.size
};
},
},
}
}
};
</script>

View File

@ -19,8 +19,8 @@ export default {
props: {
size: {
type: String,
default: '60px',
},
default: '60px'
}
},
computed: {
innerStyles() {
@ -30,10 +30,10 @@ export default {
styles() {
return {
width: this.size,
height: this.size,
height: this.size
};
},
},
}
}
};
</script>

View File

@ -9,18 +9,18 @@ export default {
props: {
size: {
type: String,
default: '40px',
},
default: '40px'
}
},
computed: {
styles() {
return {
width: this.size,
height: this.size,
display: 'inline-block',
display: 'inline-block'
};
},
},
}
}
};
</script>

View File

@ -73,22 +73,22 @@ export default {
props: {
isWhite: {
type: Boolean,
default: false,
},
default: false
}
},
data() {
return { hamburger: false };
},
computed: {
...mapGetters({ loggedIn: 'auth/isLoggedIn' }),
...mapState(['config']),
...mapState(['config'])
},
methods: {
async logOut() {
await this.$store.dispatch('auth/logout');
this.$router.replace('/login');
},
},
}
}
};
</script>

View File

@ -90,11 +90,11 @@ export default {
value: [Number, String],
data: {
type: Array,
default: () => [],
default: () => []
},
field: {
type: String,
default: 'value',
default: 'value'
},
keepFirst: Boolean,
clearOnSelect: Boolean,
@ -106,12 +106,12 @@ export default {
maxHeight: [String, Number],
dropdownPosition: {
type: String,
default: 'auto',
default: 'auto'
},
iconRight: String,
iconRightClickable: Boolean,
appendToBody: Boolean,
customSelector: Function,
customSelector: Function
},
data() {
return {
@ -125,7 +125,7 @@ export default {
style: {},
_isAutocomplete: true,
_elementRef: 'input',
_bodyEl: undefined, // Used to append to body
_bodyEl: undefined // Used to append to body
};
},
computed: {
@ -202,9 +202,9 @@ export default {
// eslint-disable-next-line no-nested-ternary
maxHeight: this.maxHeight === undefined
// eslint-disable-next-line no-restricted-globals
? null : (isNaN(this.maxHeight) ? this.maxHeight : `${this.maxHeight}px`),
? null : (isNaN(this.maxHeight) ? this.maxHeight : `${this.maxHeight}px`)
};
},
}
},
watch: {
/**
@ -258,7 +258,7 @@ export default {
if (this.keepFirst) {
this.selectFirstOption(value);
}
},
}
},
created() {
if (typeof window !== 'undefined') {
@ -507,10 +507,10 @@ export default {
left: `${left}px`,
width: `${trigger.clientWidth}px`,
maxWidth: `${trigger.clientWidth}px`,
zIndex: '99',
zIndex: '99'
};
}
},
},
}
}
};
</script>

View File

@ -36,13 +36,13 @@ import SearchInput from '~/components/search-input/SearchInput.vue';
export default {
components: {
SearchInput,
SearchInput
},
props: {
hiddenHints: {
type: Array,
default: () => [],
},
default: () => []
}
},
data() {
return {
@ -51,35 +51,35 @@ export default {
{
'name': 'tag',
'valueFormat': 'name',
'hint': '',
'hint': ''
},
{
'name': 'album',
'valueFormat': 'name',
'hint': '',
'hint': ''
},
{
'name': 'before',
'valueFormat': 'specific date',
'hint': '',
'hint': ''
},
{
'name': 'during',
'valueFormat': 'specific date',
'hint': '',
'hint': ''
},
{
'name': 'after',
'valueFormat': 'specific date',
'hint': '',
'hint': ''
},
{
'name': 'file',
'valueFormat': 'generated name',
'hint': '',
},
'hint': ''
}
],
filteredHints: [],
filteredHints: []
};
},
created() {
@ -122,8 +122,8 @@ export default {
if (/:$/gi.test(this.query)) { return; }
}
this.$emit('search', this.query, event);
},
},
}
}
};
</script>

View File

@ -48,7 +48,7 @@ import { mapState } from 'vuex';
export default {
computed: mapState({
user: (state) => state.auth.user,
user: (state) => state.auth.user
}),
methods: {
isRouteActive(id) {
@ -56,8 +56,8 @@ export default {
return true;
}
return false;
},
},
}
}
};
</script>

View File

@ -88,15 +88,15 @@ export default {
files: [],
dropzoneOptions: {},
showDropzone: false,
selectedAlbum: null,
selectedAlbum: null
};
},
computed: {
...mapState({
config: (state) => state.config,
albums: (state) => state.albums.tinyDetails,
albums: (state) => state.albums.tinyDetails
}),
...mapGetters({ loggedIn: 'auth/isLoggedIn', token: 'auth/getToken' }),
...mapGetters({ loggedIn: 'auth/isLoggedIn', token: 'auth/getToken' })
},
watch: {
loggedIn() {
@ -104,7 +104,7 @@ export default {
},
selectedAlbum() {
this.updateDropzoneConfig();
},
}
},
mounted() {
this.dropzoneOptions = {
@ -127,7 +127,7 @@ export default {
maxFilesize: this.config.maxFileSize,
previewTemplate: this.$refs.template.innerHTML,
dictDefaultMessage: 'Drag & Drop your files or click to browse',
headers: { Accept: 'application/vnd.lolisafe.json' },
headers: { Accept: 'application/vnd.lolisafe.json' }
};
this.showDropzone = true;
if (this.loggedIn) this.getAlbums();
@ -154,7 +154,7 @@ export default {
this.$refs.el.setOption('headers', {
Accept: 'application/vnd.lolisafe.json',
Authorization: this.token ? `Bearer ${this.token}` : '',
albumId: this.selectedAlbum ? this.selectedAlbum : null,
albumId: this.selectedAlbum ? this.selectedAlbum : null
});
},
@ -170,7 +170,7 @@ export default {
dropzoneError(file, message, xhr) {
this.$store.dispatch('alert', {
text: 'There was an error uploading this file. Check the console.',
error: true,
error: true
});
// eslint-disable-next-line no-console
console.error(file, message, xhr);
@ -182,8 +182,8 @@ export default {
original: file.name,
size: file.size,
type: file.type,
count: file.upload.totalChunkCount,
}],
count: file.upload.totalChunkCount
}]
});
this.processResult(file, data);
@ -205,8 +205,8 @@ export default {
this.$clipboard(response.url);
});
*/
},
},
}
}
};
</script>
<style lang="scss" scoped>

View File

@ -6,5 +6,5 @@ export default {
ERROR: 'is-danger',
DARK: 'is-dark',
LIGHT: 'is-light',
WHITE: 'is-white',
WHITE: 'is-white'
};

View File

@ -19,7 +19,7 @@ import Footer from '~/components/footer/Footer.vue';
export default {
components: {
Navbar,
Footer,
Footer
},
computed: mapState(['config', 'alert']),
created() {
@ -33,14 +33,14 @@ export default {
duration: 3500,
position: 'is-bottom',
message,
type,
type
});
} else {
this.$buefy.toast.open({
duration: 3500,
position: 'is-bottom',
message,
type,
type
});
}
@ -53,9 +53,9 @@ export default {
`%c lolisafe %c v${this.config.version} %c`,
'background:#35495e ; padding: 1px; border-radius: 3px 0 0 3px; color: #fff',
'background:#ff015b; padding: 1px; border-radius: 0 3px 3px 0; color: #fff',
'background:transparent',
'background:transparent'
);
},
}
};
</script>

View File

@ -23,6 +23,6 @@
import Navbar from '~/components/navbar/Navbar.vue';
export default {
components: { Navbar },
components: { Navbar }
};
</script>

View File

@ -67,7 +67,7 @@ export default {
computed: {
config() {
return this.$store.state.config;
},
}
},
async asyncData({ app, params, error }) {
try {
@ -77,7 +77,7 @@ export default {
name: data.name,
downloadEnabled: data.downloadEnabled,
files: data.files,
downloadLink,
downloadLink
};
} catch (err) {
console.log('Error when retrieving album', err);
@ -100,8 +100,8 @@ export default {
{ vmid: 'og:title', property: 'og:title', content: `Album: ${this.name} | Files: ${this.files.length}` },
{ vmid: 'og:description', property: 'og:description', content: 'A modern and self-hosted file upload service that can handle anything you throw at it. Fast uploads, file manager and sharing capabilities all crafted with a beautiful user experience in mind.' },
{ vmid: 'og:image', property: 'og:image', content: `${this.files.length > 0 ? this.files[0].thumbSquare : '/public/images/share.jpg'}` },
{ vmid: 'og:image:secure_url', property: 'og:image:secure_url', content: `${this.files.length > 0 ? this.files[0].thumbSquare : '/public/images/share.jpg'}` },
],
{ vmid: 'og:image:secure_url', property: 'og:image:secure_url', content: `${this.files.length > 0 ? this.files[0].thumbSquare : '/public/images/share.jpg'}` }
]
};
}
return {
@ -113,9 +113,9 @@ export default {
{ vmid: 'twitter:description', name: 'twitter:description', content: 'A modern and self-hosted file upload service that can handle anything you throw at it. Fast uploads, file manager and sharing capabilities all crafted with a beautiful user experience in mind.' },
{ vmid: 'og:url', property: 'og:url', content: `${this.config.URL}/a/${this.$route.params.identifier}` },
{ vmid: 'og:title', property: 'og:title', content: 'lolisafe' },
{ vmid: 'og:description', property: 'og:description', content: 'A modern and self-hosted file upload service that can handle anything you throw at it. Fast uploads, file manager and sharing capabilities all crafted with a beautiful user experience in mind.' },
],
{ vmid: 'og:description', property: 'og:description', content: 'A modern and self-hosted file upload service that can handle anything you throw at it. Fast uploads, file manager and sharing capabilities all crafted with a beautiful user experience in mind.' }
]
};
},
}
};
</script>

View File

@ -102,7 +102,7 @@ import Sidebar from '~/components/sidebar/Sidebar.vue';
export default {
components: {
Sidebar,
Sidebar
},
middleware: ['auth', ({ store }) => {
store.dispatch('auth/fetchCurrentUser');
@ -111,21 +111,21 @@ export default {
return {
password: '',
newPassword: '',
reNewPassword: '',
reNewPassword: ''
};
},
computed: {
...mapGetters({ 'apiKey': 'auth/getApiKey' }),
...mapState({
user: (state) => state.auth.user,
}),
user: (state) => state.auth.user
})
},
metaInfo() {
return { title: 'Account' };
},
methods: {
...mapActions({
getUserSetttings: 'auth/fetchCurrentUser',
getUserSetttings: 'auth/fetchCurrentUser'
}),
async changePassword() {
const { password, newPassword, reNewPassword } = this;
@ -133,21 +133,21 @@ export default {
if (!password || !newPassword || !reNewPassword) {
this.$store.dispatch('alert/set', {
text: 'One or more fields are missing',
error: true,
error: true
});
return;
}
if (newPassword !== reNewPassword) {
this.$store.dispatch('alert/set', {
text: 'Passwords don\'t match',
error: true,
error: true
});
return;
}
const response = await this.$store.dispatch('auth/changePassword', {
password,
newPassword,
newPassword
});
if (response) {
@ -158,7 +158,7 @@ export default {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to regenerate your API key? Previously generated API keys will stop working. Make sure to write the new key down as this is the only time it will be displayed to you.',
onConfirm: () => this.requestNewAPIKey(),
onConfirm: () => this.requestNewAPIKey()
});
},
copyKey() {
@ -168,7 +168,7 @@ export default {
async requestNewAPIKey() {
const response = await this.$store.dispatch('auth/requestAPIKey');
this.$buefy.toast.open(response.message);
},
},
}
}
};
</script>

View File

@ -127,7 +127,7 @@ import Sidebar from '~/components/sidebar/Sidebar.vue';
export default {
components: {
Sidebar,
Sidebar
},
middleware: ['auth', 'admin', ({ route, store }) => {
try {
@ -143,7 +143,7 @@ export default {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to disable the account of the user that uploaded this file?',
onConfirm: () => this.disableUser(),
onConfirm: () => this.disableUser()
});
},
disableUser() {
@ -153,7 +153,7 @@ export default {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to ban the IP this file was uploaded from?',
onConfirm: () => this.banIP(),
onConfirm: () => this.banIP()
});
},
banIP() {
@ -169,7 +169,7 @@ export default {
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
},
},
}
}
};
</script>

View File

@ -131,7 +131,7 @@ import Sidebar from '~/components/sidebar/Sidebar.vue';
export default {
components: {
Sidebar,
Sidebar
},
middleware: ['auth', 'admin', ({ store }) => {
try {
@ -145,18 +145,18 @@ export default {
return { title: 'Settings' };
},
computed: mapState({
settings: (state) => state.admin.settings,
settings: (state) => state.admin.settings
}),
methods: {
promptRestartService() {
this.$buefy.dialog.confirm({
message: 'Keep in mind that restarting only works if you have PM2 or something similar set up. Continue?',
onConfirm: () => this.restartService(),
onConfirm: () => this.restartService()
});
},
restartService() {
this.$handler.executeAction('admin/restartService');
},
},
}
}
};
</script>

View File

@ -76,7 +76,7 @@ import Grid from '~/components/grid/Grid.vue';
export default {
components: {
Sidebar,
Grid,
Grid
},
middleware: ['auth', 'admin', ({ route, store }) => {
try {
@ -88,25 +88,25 @@ export default {
}],
data() {
return {
options: {},
options: {}
};
},
computed: mapState({
user: (state) => state.admin.user,
user: (state) => state.admin.user
}),
methods: {
promptDisableUser() {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to disable the account of this user?',
onConfirm: () => this.disableUser(),
onConfirm: () => this.disableUser()
});
},
promptEnableUser() {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to enable the account of this user?',
onConfirm: () => this.enableUser(),
onConfirm: () => this.enableUser()
});
},
disableUser() {
@ -114,7 +114,7 @@ export default {
},
enableUser() {
this.$handler.executeAction('admin/enableUser', this.user.id);
},
},
}
}
};
</script>

View File

@ -91,7 +91,7 @@ import Sidebar from '~/components/sidebar/Sidebar.vue';
export default {
components: {
Sidebar,
Sidebar
},
middleware: ['auth', 'admin', ({ route, store }) => {
try {
@ -103,7 +103,7 @@ export default {
}],
computed: mapState({
users: (state) => state.admin.users,
config: (state) => state.config,
config: (state) => state.config
}),
metaInfo() {
return { title: 'Uploads' };
@ -126,13 +126,13 @@ export default {
promptPurgeFiles(row) {
this.$buefy.dialog.confirm({
message: 'Are you sure you want to delete this user\'s files?',
onConfirm: () => this.purgeFiles(row),
onConfirm: () => this.purgeFiles(row)
});
},
async purgeFiles(row) {
this.$handler.executeAction('admin/purgeUserFiles', row.id);
},
},
}
}
};
</script>

View File

@ -72,7 +72,7 @@ export default {
components: {
Sidebar,
Grid,
Search,
Search
},
middleware: ['auth', ({ route, store }) => {
store.commit('images/resetState');
@ -80,34 +80,34 @@ export default {
}],
data() {
return {
current: 1,
current: 1
};
},
computed: {
...mapGetters({
totalFiles: 'images/getTotalFiles',
shouldPaginate: 'images/shouldPaginate',
limit: 'images/getLimit',
limit: 'images/getLimit'
}),
...mapState(['images']),
id() {
return this.$route.params.id;
},
}
},
metaInfo() {
return { title: 'Album' };
},
watch: {
current: 'fetchPaginate',
current: 'fetchPaginate'
},
methods: {
...mapActions({
fetch: 'images/fetchByAlbumId',
fetch: 'images/fetchByAlbumId'
}),
fetchPaginate() {
this.fetch({ id: this.id, page: this.current });
},
},
}
}
};
</script>

View File

@ -53,7 +53,7 @@ import AlbumEntry from '~/components/album/AlbumEntry.vue';
export default {
components: {
Sidebar,
AlbumEntry,
AlbumEntry
},
middleware: ['auth', ({ store }) => {
try {
@ -65,7 +65,7 @@ export default {
data() {
return {
newAlbumName: null,
isCreatingAlbum: false,
isCreatingAlbum: false
};
},
computed: mapState(['config', 'albums']),
@ -74,7 +74,7 @@ export default {
},
methods: {
...mapActions({
'alert': 'alert/set',
'alert': 'alert/set'
}),
async createAlbum() {
if (!this.newAlbumName || this.newAlbumName === '') return;
@ -90,8 +90,8 @@ export default {
this.isCreatingAlbum = false;
this.newAlbumName = null;
}
},
},
}
}
};
</script>

View File

@ -64,7 +64,7 @@ export default {
components: {
Sidebar,
Grid,
Search,
Search
},
middleware: ['auth', ({ store }) => {
store.commit('images/resetState');
@ -74,29 +74,29 @@ export default {
return {
current: 1,
isLoading: false,
search: '',
search: ''
};
},
computed: {
...mapGetters({
totalFiles: 'images/getTotalFiles',
shouldPaginate: 'images/shouldPaginate',
limit: 'images/getLimit',
limit: 'images/getLimit'
}),
...mapState(['images']),
...mapState(['images'])
},
metaInfo() {
return { title: 'Uploads' };
},
watch: {
current: 'fetchPaginate',
current: 'fetchPaginate'
},
created() {
this.filteredHints = this.hints; // fixes the issue where on pageload, suggestions wont load
},
methods: {
...mapActions({
fetch: 'images/fetch',
fetch: 'images/fetch'
}),
async fetchPaginate() {
this.isLoading = true;
@ -111,10 +111,10 @@ export default {
onSearch(query) {
this.search = query;
this.$handler.executeAction('images/search', {
q: this.sanitizeQuery(query),
q: this.sanitizeQuery(query)
});
},
},
}
}
};
</script>

View File

@ -215,19 +215,19 @@ import Sidebar from '~/components/sidebar/Sidebar.vue';
export default {
components: {
Sidebar,
Sidebar
},
middleware: 'auth',
data() {
return {
tags: [],
newTagName: null,
newTagName: null
};
},
computed: {
config() {
return this.$store.state.config;
},
}
},
metaInfo() {
return { title: 'Tags' };
@ -240,7 +240,7 @@ export default {
this.$buefy.dialog.confirm({
type: 'is-danger',
message: 'Are you sure you want to delete this tag?',
onConfirm: () => this.promptPurgeTag(id),
onConfirm: () => this.promptPurgeTag(id)
});
},
promptPurgeTag(id) {
@ -250,7 +250,7 @@ export default {
cancelText: 'No',
confirmText: 'Yes',
onConfirm: () => this.deleteTag(id, true),
onCancel: () => this.deleteTag(id, false),
onCancel: () => this.deleteTag(id, false)
});
},
async deleteTag(id, purge) {
@ -272,7 +272,7 @@ export default {
tag.isDetailsOpen = false;
}
this.tags = response.tags;
},
},
}
}
};
</script>

View File

@ -56,7 +56,7 @@ export default {
},
metaInfo() {
return { title: 'Faq' };
},
}
};
</script>

View File

@ -41,15 +41,15 @@ export default {
components: {
Logo,
Uploader,
Links,
Links
},
data() {
return { albums: [] };
},
computed: {
...mapGetters({ loggedIn: 'auth/isLoggedIn' }),
...mapState(['config']),
},
...mapState(['config'])
}
};
</script>
<style lang="scss" scoped>

View File

@ -95,7 +95,7 @@ export default {
password: null,
mfaCode: null,
isMfaModalActive: false,
isLoading: false,
isLoading: false
};
},
computed: mapState(['config', 'auth']),
@ -150,7 +150,7 @@ export default {
return;
}
this.$router.push('/dashboard');
},
},
}
}
};
</script>

View File

@ -3,6 +3,6 @@ export default {
async created() {
await this.$store.dispatch('auth/logout');
this.$router.replace('/login');
},
}
};
</script>

View File

@ -74,7 +74,7 @@ export default {
username: null,
password: null,
rePassword: null,
isLoading: false,
isLoading: false
};
},
computed: mapState(['config', 'auth']),
@ -98,7 +98,7 @@ export default {
try {
const response = await this.$store.dispatch('auth/register', {
username: this.username,
password: this.password,
password: this.password
});
this.$notifier.success(response.message);
@ -109,7 +109,7 @@ export default {
} finally {
this.isLoading = false;
}
},
},
}
}
};
</script>

View File

@ -14,12 +14,12 @@ export default function ({ $axios, store }) {
if (error.response?.data?.message) {
store.dispatch('alert/set', {
text: error.response.data.message,
error: true,
error: true
});
} else {
store.dispatch('alert/set', {
text: `[AXIOS]: ${error.message}`,
error: true,
error: true
});
}
}

View File

@ -13,5 +13,5 @@ Vue.prototype.$search = {
do: async (term, field) => {
const results = await search.search(term, { field });
return results;
},
}
};

View File

@ -8,18 +8,18 @@ export default ({ store }, inject) => {
store.commit('alert/set', {
message: response?.message ?? 'Executed sucesfully',
type: AlertTypes.SUCCESS,
type: AlertTypes.SUCCESS
});
return response;
} catch (e) {
store.commit('alert/set', {
message: e.message,
type: AlertTypes.ERROR,
type: AlertTypes.ERROR
});
return null;
}
},
}
});
};

View File

@ -20,6 +20,6 @@ export default ({ store }, inject) => {
error(message, snackbar) {
this.showMessage({ message, type: AlertTypes.ERROR, snackbar });
},
types: AlertTypes,
types: AlertTypes
});
};

View File

@ -3,5 +3,5 @@ import VueIsYourPasswordSafe from 'vue-isyourpasswordsafe';
Vue.use(VueIsYourPasswordSafe, {
minLength: 6,
maxLength: 64,
maxLength: 64
});

View File

@ -4,5 +4,5 @@ import VueTimeago from 'vue-timeago';
Vue.use(VueTimeago, {
name: 'timeago',
locale: 'en-US',
locales: { 'en-US': require('vue-timeago/locales/en-US.json') },
locales: { 'en-US': require('vue-timeago/locales/en-US.json') }
});

View File

@ -8,10 +8,10 @@ export const state = () => ({
editedAt: null,
apiKeyEditedAt: null,
isAdmin: null,
files: [],
files: []
},
file: {},
settings: {},
settings: {}
});
export const actions = {
@ -82,7 +82,7 @@ export const actions = {
const response = await this.$axios.$post('service/restart');
return response;
},
}
};
export const mutations = {
@ -118,5 +118,5 @@ export const mutations = {
state.user.isAdmin = isAdmin;
}
}
},
}
};

View File

@ -5,12 +5,12 @@ export const state = () => ({
isListLoading: false,
albumDetails: {},
expandedAlbums: [],
tinyDetails: [],
tinyDetails: []
});
export const getters = {
isExpanded: (state) => (id) => state.expandedAlbums.indexOf(id) > -1,
getDetails: (state) => (id) => state.albumDetails[id] || {},
getDetails: (state) => (id) => state.albumDetails[id] || {}
};
export const actions = {
@ -28,8 +28,8 @@ export const actions = {
commit('setDetails', {
id: albumId,
details: {
links: response.links,
},
links: response.links
}
});
return response;
@ -66,7 +66,7 @@ export const actions = {
const response = await this.$axios.$post('album/link/edit', {
identifier: linkOpts.identifier,
enableDownload: linkOpts.enableDownload,
enabled: linkOpts.enabled,
enabled: linkOpts.enabled
});
commit('updateAlbumLinkOpts', { albumId, linkOpts: response.data });
@ -86,7 +86,7 @@ export const actions = {
commit('setTinyDetails', response);
return response;
},
}
};
export const mutations = {
@ -113,7 +113,7 @@ export const mutations = {
},
updateAlbumLinkOpts(state, { albumId, linkOpts }) {
const foundIndex = state.albumDetails[albumId].links.findIndex(
({ identifier }) => identifier === linkOpts.identifier,
({ identifier }) => identifier === linkOpts.identifier
);
const link = state.albumDetails[albumId].links[foundIndex];
state.albumDetails[albumId].links[foundIndex] = { ...link, ...linkOpts };
@ -132,5 +132,5 @@ export const mutations = {
},
setTinyDetails(state, { albums }) {
state.tinyDetails = albums;
},
}
};

View File

@ -3,7 +3,7 @@ import AlertTypes from '~/constants/alertTypes';
const getDefaultState = () => ({
message: null,
type: null,
snackbar: false,
snackbar: false
});
export const state = getDefaultState;
@ -18,7 +18,7 @@ export const actions = {
},
clear({ commit }) {
commit('clear');
},
}
};
export const mutations = {
@ -29,5 +29,5 @@ export const mutations = {
},
clear(state) {
Object.assign(state, getDefaultState());
},
}
};

View File

@ -3,9 +3,9 @@ const getDefaultState = () => ({
user: {
id: null,
isAdmin: false,
username: null,
username: null
},
token: null,
token: null
});
export const state = getDefaultState;
@ -13,7 +13,7 @@ export const state = getDefaultState;
export const getters = {
isLoggedIn: (state) => state.loggedIn,
getApiKey: (state) => state.user?.apiKey,
getToken: (state) => state.token,
getToken: (state) => state.token
};
export const actions = {
@ -37,7 +37,7 @@ export const actions = {
async register(_, { username, password }) {
return this.$axios.$post('auth/register', {
username,
password,
password
});
},
async fetchCurrentUser({ commit, dispatch }) {
@ -52,7 +52,7 @@ export const actions = {
try {
const response = await this.$axios.$post('user/password/change', {
password,
newPassword,
newPassword
});
return response;
@ -76,7 +76,7 @@ export const actions = {
},
logout({ commit }) {
commit('logout');
},
}
};
export const mutations = {
@ -102,5 +102,5 @@ export const mutations = {
this.$cookies.remove('token', { path: '/' });
// reset state to default
Object.assign(state, getDefaultState());
},
}
};

View File

@ -8,11 +8,11 @@ export const state = () => ({
chunkSize: 90,
maxLinksPerAlbum: 5,
publicMode: false,
userAccounts: false,
userAccounts: false
});
export const mutations = {
set(state, config) {
Object.assign(state, config);
},
}
};

View File

@ -6,14 +6,14 @@ export const getDefaultState = () => ({
pagination: {
page: 1,
limit: 30,
totalFiles: 0,
totalFiles: 0
},
search: '',
albumName: null,
albumDownloadEnabled: false,
fileExtraInfoMap: {}, // information about the selected file
fileAlbumsMap: {}, // map of file ids with a list of album objects the file is in
fileTagsMap: {}, // map of file ids with a list of tag objects for the file
fileTagsMap: {} // map of file ids with a list of tag objects for the file
});
export const state = getDefaultState;
@ -23,7 +23,7 @@ export const getters = {
getFetchedCount: ({ files }) => files.length,
shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit,
getLimit: ({ pagination }) => pagination.limit,
getName: ({ name }) => name,
getName: ({ name }) => name
};
export const actions = {
@ -50,7 +50,7 @@ export const actions = {
page = page || 1;
const response = await this.$axios.$get(`album/${id}/full`, {
params: { limit: state.pagination.limit, page },
params: { limit: state.pagination.limit, page }
});
commit('setFilesAndMeta', { ...response, page });
@ -113,7 +113,7 @@ export const actions = {
const response = await this.$axios.$get(`search/?q=${encodeURI(q)}${optionalAlbum}`);
return response;
},
}
};
export const mutations = {
@ -121,7 +121,7 @@ export const mutations = {
state.isLoading = true;
},
setFilesAndMeta(state, {
files, name, page, count, downloadEnabled,
files, name, page, count, downloadEnabled
}) {
state.files = files || [];
state.albumName = name ?? null;
@ -174,5 +174,5 @@ export const mutations = {
},
resetState(state) {
Object.assign(state, getDefaultState());
},
}
};

Some files were not shown because too many files have changed in this diff Show More