diff options
Diffstat (limited to 'src/api/routes/albums')
| -rw-r--r-- | src/api/routes/albums/albumDELETE.js | 1 | ||||
| -rw-r--r-- | src/api/routes/albums/albumFullGET.js | 32 | ||||
| -rw-r--r-- | src/api/routes/albums/albumGET.js | 3 | ||||
| -rw-r--r-- | src/api/routes/albums/albumPOST.js | 19 | ||||
| -rw-r--r-- | src/api/routes/albums/albumZipGET.js | 12 | ||||
| -rw-r--r-- | src/api/routes/albums/albumsGET.js | 28 | ||||
| -rw-r--r-- | src/api/routes/albums/link/linkDELETE.js | 1 | ||||
| -rw-r--r-- | src/api/routes/albums/link/linkEditPOST.js | 22 | ||||
| -rw-r--r-- | src/api/routes/albums/link/linkPOST.js | 47 |
9 files changed, 112 insertions, 53 deletions
diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index 4e6640e..f9c22e6 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -1,5 +1,4 @@ const Route = require('../../structures/Route'); -const Util = require('../../utils/Util'); class albumDELETE extends Route { constructor() { diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index 93b56ce..d25fe15 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -10,15 +10,38 @@ class albumGET extends Route { const { id } = req.params; if (!id) return res.status(400).json({ message: 'Invalid id supplied' }); - const album = await db.table('albums').where({ id, userId: user.id }).first(); + const album = await db + .table('albums') + .where({ id, userId: user.id }) + .first(); if (!album) return res.status(404).json({ message: 'Album not found' }); - const files = await db.table('albumsFiles') + let count = 0; + + let files = db + .table('albumsFiles') .where({ albumId: id }) .join('files', 'albumsFiles.fileId', 'files.id') - .select('files.id', 'files.name') + .select('files.id', 'files.name', 'files.createdAt') .orderBy('files.id', 'desc'); + const { page, limit = 100 } = req.query; + if (page && page >= 0) { + files = await files.offset((page - 1) * limit).limit(limit); + + const dbRes = await db + .table('albumsFiles') + .count('* as count') + .where({ albumId: id }) + .first(); + + count = dbRes.count; + } else { + files = await files; // execute the query + count = files.length; + } + + // eslint-disable-next-line no-restricted-syntax for (let file of files) { file = Util.constructFilePublicLink(file); } @@ -26,7 +49,8 @@ class albumGET extends Route { return res.json({ message: 'Successfully retrieved album', name: album.name, - files + files, + count }); } } diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 1bf3630..950a1fd 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -21,10 +21,11 @@ class albumGET extends Route { const files = await db.table('albumsFiles') .where({ albumId: link.albumId }) .join('files', 'albumsFiles.fileId', 'files.id') - .select('files.name') + .select('files.name', 'files.id') .orderBy('files.id', 'desc'); // Create the links for each file + // eslint-disable-next-line no-restricted-syntax for (let file of files) { file = Util.constructFilePublicLink(file); } diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js index 0d3a44c..52352a1 100644 --- a/src/api/routes/albums/albumPOST.js +++ b/src/api/routes/albums/albumPOST.js @@ -1,5 +1,5 @@ -const Route = require('../../structures/Route'); const moment = require('moment'); +const Route = require('../../structures/Route'); class albumPOST extends Route { constructor() { @@ -14,18 +14,25 @@ class albumPOST extends Route { /* Check that an album with that name doesn't exist yet */ - const album = await db.table('albums').where({ name, userId: user.id }).first(); - if (album) return res.status(401).json({ message: 'There\'s already an album with that name' }); + const album = await db + .table('albums') + .where({ name, userId: user.id }) + .first(); + if (album) return res.status(401).json({ message: "There's already an album with that name" }); const now = moment.utc().toDate(); - await db.table('albums').insert({ + const insertObj = { name, userId: user.id, createdAt: now, editedAt: now - }); + }; + + const dbRes = await db.table('albums').insert(insertObj); + + insertObj.id = dbRes.pop(); - return res.json({ message: 'The album was created successfully' }); + return res.json({ message: 'The album was created successfully', data: insertObj }); } } diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index a6ef6fd..cf1f6f8 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -1,8 +1,8 @@ +const path = require('path'); +const jetpack = require('fs-jetpack'); const Route = require('../../structures/Route'); const Util = require('../../utils/Util'); const log = require('../../utils/Log'); -const path = require('path'); -const jetpack = require('fs-jetpack'); class albumGET extends Route { constructor() { @@ -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. @@ -64,11 +64,11 @@ class albumGET extends Route { /* Get the actual files */ - const fileIds = fileList.map(el => el.fileId); + const fileIds = fileList.map((el) => el.fileId); const files = await db.table('files') .whereIn('id', fileIds) .select('name'); - const filesToZip = files.map(el => el.name); + const filesToZip = files.map((el) => el.name); try { Util.createZip(filesToZip, album); @@ -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) { diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index 1a7db87..93a23e3 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ const Route = require('../../structures/Route'); const Util = require('../../utils/Util'); @@ -12,30 +13,28 @@ class albumsGET extends Route { of the album files for displaying on the dashboard. It's probably useless for anyone consuming the API outside of the lolisafe frontend. */ - const albums = await db.table('albums') + const albums = await db + .table('albums') .where('albums.userId', user.id) - .select('id', 'name', 'editedAt'); + .select('id', 'name', 'createdAt', 'editedAt') + .orderBy('createdAt', 'desc'); for (const album of albums) { - // TODO: Optimize the shit out of this. Ideally a JOIN that grabs all the needed stuff in 1 query instead of 3 - // Fetch the total amount of files each album has. - const fileCount = await db.table('albumsFiles') // eslint-disable-line no-await-in-loop + const fileCount = await db // eslint-disable-line no-await-in-loop + .table('albumsFiles') .where('albumId', album.id) .count({ count: 'id' }); // Fetch the file list from each album but limit it to 5 per album - const filesToFetch = await db.table('albumsFiles') // eslint-disable-line no-await-in-loop + const files = await db // eslint-disable-line no-await-in-loop + .table('albumsFiles') + .join('files', { 'files.id': 'albumsFiles.fileId' }) .where('albumId', album.id) - .select('fileId') - .orderBy('id', 'desc') + .select('files.id', 'files.name') + .orderBy('albumsFiles.id', 'desc') .limit(5); - // Fetch the actual files - const files = await db.table('files') // eslint-disable-line no-await-in-loop - .whereIn('id', filesToFetch.map(el => el.fileId)) - .select('id', 'name'); - // Fetch thumbnails and stuff for (let file of files) { file = Util.constructFilePublicLink(file); @@ -58,7 +57,8 @@ class albumsDropdownGET extends Route { } async run(req, res, db, user) { - const albums = await db.table('albums') + const albums = await db + .table('albums') .where('userId', user.id) .select('id', 'name'); return res.json({ diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index b02d0b4..1af704e 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -1,5 +1,4 @@ const Route = require('../../../structures/Route'); -const { dump } = require('dumper.js'); class linkDELETE extends Route { constructor() { diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 6776b73..97122a2 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -1,5 +1,4 @@ const Route = require('../../../structures/Route'); -const log = require('../../../utils/Log'); class linkEditPOST extends Route { constructor() { @@ -14,17 +13,22 @@ class linkEditPOST extends Route { /* Make sure the link exists */ - const link = await db.table('links').where({ identifier, userId: user.id }).first(); - if (!link) return res.status(400).json({ message: 'The link doesn\'t exist or doesn\'t belong to the user' }); + const link = await db + .table('links') + .where({ identifier, userId: user.id }) + .first(); + if (!link) return res.status(400).json({ message: "The link doesn't exist or doesn't belong to the user" }); try { - await db.table('links') + const updateObj = { + enableDownload: enableDownload || false, + expiresAt // This one should be null if not supplied + }; + await db + .table('links') .where({ identifier }) - .update({ - enableDownload: enableDownload || false, - expiresAt // This one should be null if not supplied - }); - return res.json({ message: 'Editing the link was successful' }); + .update(updateObj); + return res.json({ message: 'Editing the link was successful', data: updateObj }); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 6009922..28e9dfe 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -14,23 +14,47 @@ class linkPOST extends Route { /* Make sure the album exists */ - const exists = await db.table('albums').where({ id: albumId, userId: user.id }).first(); + const exists = await db + .table('albums') + .where({ id: albumId, userId: user.id }) + .first(); if (!exists) return res.status(400).json({ message: 'Album doesn\t exist' }); /* Count the amount of links created for that album already and error out if max was reached */ - const count = await db.table('links').where('albumId', albumId).count({ count: 'id' }); - if (count[0].count >= parseInt(process.env.MAX_LINKS_PER_ALBUM, 10)) return res.status(400).json({ message: 'Maximum links per album reached' }); + const count = await db + .table('links') + .where('albumId', albumId) + .count({ count: 'id' }) + .first(); + if (count >= parseInt(process.env.MAX_LINKS_PER_ALBUM, 10)) return res.status(400).json({ message: 'Maximum links per album reached' }); - /* - Try to allocate a new identifier on the db - */ - const identifier = await Util.getUniqueAlbumIdentifier(); - if (!identifier) return res.status(500).json({ message: 'There was a problem allocating a link for your album' }); + let { identifier } = req.body; + if (identifier) { + if (!user.isAdmin) return res.status(401).json({ message: 'Only administrators can create custom links' }); + + if (!(/^[a-zA-Z0-9-_]+$/.test(identifier))) return res.status(400).json({ message: 'Only alphanumeric, dashes, and underscore characters are allowed' }); + + /* + Make sure that the id doesn't already exists in the database + */ + const idExists = await db + .table('links') + .where({ identifier }) + .first(); + + if (idExists) return res.status(400).json({ message: 'Album with this identifier already exists' }); + } else { + /* + Try to allocate a new identifier in the database + */ + identifier = await Util.getUniqueAlbumIdentifier(); + if (!identifier) return res.status(500).json({ message: 'There was a problem allocating a link for your album' }); + } try { - await db.table('links').insert({ + const insertObj = { identifier, userId: user.id, albumId, @@ -38,11 +62,12 @@ class linkPOST extends Route { enableDownload: true, expiresAt: null, views: 0 - }); + }; + await db.table('links').insert(insertObj); return res.json({ message: 'The link was created successfully', - identifier + data: insertObj }); } catch (error) { return super.error(res, error); |