From e7767ac7095f93393a627fd5e867af4a1ca4b011 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Sun, 16 Sep 2018 00:56:13 -0300 Subject: Routes --- src/api/routes/albums/albumDELETE.js | 35 +++++++++++ src/api/routes/albums/albumGET.js | 52 ++++++++++++++++ src/api/routes/albums/albumPOST.js | 44 ++++++++++++++ src/api/routes/albums/albumsGET.js | 86 +++++++++++++++++++++++++++ src/api/routes/albums/link/linkEnabledPOST.js | 34 +++++++++++ src/api/routes/albums/link/linkPOST.js | 43 ++++++++++++++ 6 files changed, 294 insertions(+) create mode 100644 src/api/routes/albums/albumDELETE.js create mode 100644 src/api/routes/albums/albumGET.js create mode 100644 src/api/routes/albums/albumPOST.js create mode 100644 src/api/routes/albums/albumsGET.js create mode 100644 src/api/routes/albums/link/linkEnabledPOST.js create mode 100644 src/api/routes/albums/link/linkPOST.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js new file mode 100644 index 0000000..ef98137 --- /dev/null +++ b/src/api/routes/albums/albumDELETE.js @@ -0,0 +1,35 @@ +const Route = require('../../structures/Route'); +const config = require('../../../../config'); +const db = require('knex')(config.server.database); +const Util = require('../../utils/Util'); +const log = require('../../utils/Log'); + +class albumDELETE extends Route { + constructor() { + super('/album/:id/:purge*?', 'delete'); + } + + async run(req, res, user) { + const { id, purge } = req.params; + if (!id) return res.status(400).json({ message: 'Invalid album ID supplied' }); + + const album = await db.table('albums').where({ + id, + userId: user.id + }).first(); + + if (!album) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); + try { + if (purge) { + await Util.deleteAllFilesFromAlbum(id); + } + await db.table('albums').where({ id }).delete(); + return res.json({ message: 'The album was deleted successfully' }); + } catch (error) { + log.error(error); + return res.json({ message: 'There was a problem deleting the album' }); + } + } +} + +module.exports = albumDELETE; diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js new file mode 100644 index 0000000..80affd2 --- /dev/null +++ b/src/api/routes/albums/albumGET.js @@ -0,0 +1,52 @@ +const Route = require('../../structures/Route'); +const config = require('../../../../config'); +const db = require('knex')(config.server.database); + +class albumGET extends Route { + constructor() { + super('/album/:identifier', 'get', { bypassAuth: true }); + } + + async run(req, res) { + const { identifier } = req.params; + if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); + + const link = await db.table('links').where({ + identifier, + enabled: true + }).first(); + if (!link) return res.status(400).json({ message: 'The identifier supplied could not be found' }); + + const album = await db.table('albums').where('id', link.albumId).first(); + if (!album) return res.status(400).json({ message: 'Album not found' }); + + const fileList = await db.table('albumsFiles').where('albumId', link.albumId); + const fileIds = fileList.filter(el => el.file.fileId); + const files = await db.table('files') + .where('id', fileIds) + .select('name'); + + return res.json({ + message: 'Successfully retrieved files', + files + }); + } +} + +class albumsDropdownGET extends Route { + constructor() { + super('/albums/:identifier', 'get'); + } + + async run(req, res, user) { + const albums = await db.table('albums') + .where('userId', user.id) + .select('id', 'name'); + return res.json({ + message: 'Successfully retrieved albums', + albums + }); + } +} + +module.exports = [albumGET, albumsDropdownGET]; diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js new file mode 100644 index 0000000..24ccca8 --- /dev/null +++ b/src/api/routes/albums/albumPOST.js @@ -0,0 +1,44 @@ +const Route = require('../../structures/Route'); +const config = require('../../../../config'); +const db = require('knex')(config.server.database); +const moment = require('moment'); + +class albumPOST extends Route { + constructor() { + super('/album/new', 'post'); + } + + async run(req, res, user) { + if (!req.body) return res.status(400).json({ message: 'No body provided' }); + const { name } = req.body; + if (!name) return res.status(400).json({ message: 'No name provided' }); + + const album = await db.table('albums').where({ + name, + enabled: true, + 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(); + /* + const identifier = await Util.getUniqueAlbumIdentifier(); + if (!identifier) { + console.error('Couldn\'t allocate an identifier for an album'); + return res.status(500).json({ message: 'There was a problem allocating an identifier to the album' }); + } + */ + await db.table('albums').insert({ + name, + enabled: true, + userId: user.id, + createdAt: now, + editedAt: now + }); + + return res.json({ message: 'The album was created successfully' }); + } +} + +module.exports = albumPOST; diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js new file mode 100644 index 0000000..b19e03a --- /dev/null +++ b/src/api/routes/albums/albumsGET.js @@ -0,0 +1,86 @@ +const Route = require('../../structures/Route'); +const config = require('../../../../config'); +const db = require('knex')(config.server.database); +const Util = require('../../utils/Util'); + +class albumsGET extends Route { + constructor() { + super('/albums/mini', 'get'); + } + + async run(req, res, user) { + /* + Let's fetch the albums. This route will only return a small portion + 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') + .where('userId', user.id) + // .where('enabled', true) + .select('id', 'name', 'createdAt', 'editedAt'); + + for (const album of albums) { + /* + Fetch every public link the album has + */ + const links = await db.table('links').where('albumId', album.id); // eslint-disable-line no-await-in-loop + + /* + Fetch the total amount of files each album has. + */ + const fileCount = await db.table('albumsFiles') // eslint-disable-line no-await-in-loop + .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 + .where('albumId', album.id) + .select('fileId') + .orderBy('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', 'hash', 'original', 'size', 'type', 'createdAt', 'editedAt'); + + /* + Fetch thumbnails and stuff + */ + for (let file of files) { + file = Util.constructFilePublicLink(file); + } + + album.links = links; + album.fileCount = fileCount[0].count; + album.files = files; + } + + return res.json({ + message: 'Successfully retrieved albums', + albums + }); + } +} + +class albumsDropdownGET extends Route { + constructor() { + super('/albums/dropdown', 'get'); + } + + async run(req, res, user) { + const albums = await db.table('albums') + .where('userId', user.id) + .select('id', 'name'); + return res.json({ + message: 'Successfully retrieved albums', + albums + }); + } +} + +module.exports = [albumsGET, albumsDropdownGET]; diff --git a/src/api/routes/albums/link/linkEnabledPOST.js b/src/api/routes/albums/link/linkEnabledPOST.js new file mode 100644 index 0000000..863fe0b --- /dev/null +++ b/src/api/routes/albums/link/linkEnabledPOST.js @@ -0,0 +1,34 @@ +const Route = require('../../../structures/Route'); +const config = require('../../../../../config'); +const db = require('knex')(config.server.database); +const log = require('../../../utils/Log'); + +class linkEnabledPOST extends Route { + constructor() { + super('/album/link/enabled', 'post'); + } + + async run(req, res, user) { + if (!req.body) return res.status(400).json({ message: 'No body provided' }); + const { identifier, enabled } = req.body; + if (!identifier) return res.status(400).json({ message: 'Invalid album identifier supplied' }); + + 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') + .where({ identifier }) + .update({ enabled }); + return res.json({ message: 'The link status was changed successfully' }); + } catch (error) { + log.error(error); + return res.json({ message: 'There was a problem changing the status of the link' }); + } + } +} + +module.exports = linkEnabledPOST; diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js new file mode 100644 index 0000000..e8f3731 --- /dev/null +++ b/src/api/routes/albums/link/linkPOST.js @@ -0,0 +1,43 @@ +const Route = require('../../../structures/Route'); +const config = require('../../../../../config'); +const db = require('knex')(config.server.database); +const Util = require('../../../utils/Util'); +const log = require('../../../utils/Log'); + +class linkPOST extends Route { + constructor() { + super('/album/link/new', 'post'); + } + + async run(req, res) { + if (!req.body) return res.status(400).json({ message: 'No body provided' }); + const { albumId, enabled, enableDownload, expiresAt } = req.body; + if (!albumId) return res.status(400).json({ message: 'No album provided' }); + + const exists = await db.table('albums').where('id', albumId).first(); + if (!exists) return res.status(400).json({ message: 'Album doesn\t exist' }); + + const identifier = 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({ + identifier, + albumId, + enabled, + enableDownload, + expiresAt + }); + + return res.json({ + message: 'The link was created successfully', + identifier + }); + } catch (error) { + log.error(error); + return res.status(500).json({ message: 'There was a problem creating the link' }); + } + } +} + +module.exports = linkPOST; -- cgit v1.2.3 From 04cb6dcce574efbaecf80071acd8219a8b5fd6f7 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Sun, 16 Sep 2018 01:10:46 -0300 Subject: We dont need the second one, probably --- src/api/routes/albums/albumGET.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 80affd2..f9e5208 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -33,20 +33,4 @@ class albumGET extends Route { } } -class albumsDropdownGET extends Route { - constructor() { - super('/albums/:identifier', 'get'); - } - - async run(req, res, user) { - const albums = await db.table('albums') - .where('userId', user.id) - .select('id', 'name'); - return res.json({ - message: 'Successfully retrieved albums', - albums - }); - } -} - -module.exports = [albumGET, albumsDropdownGET]; +module.exports = albumGET; -- cgit v1.2.3 From 90011334147eaa3b480e0dc9f80cc83bb83b3cd5 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Sun, 16 Sep 2018 05:42:38 -0300 Subject: Links are managed elsewhere, so there's no point in this --- src/api/routes/albums/albumPOST.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js index 24ccca8..c2e7c4e 100644 --- a/src/api/routes/albums/albumPOST.js +++ b/src/api/routes/albums/albumPOST.js @@ -15,7 +15,7 @@ class albumPOST extends Route { const album = await db.table('albums').where({ name, - enabled: true, + // enabled: true, userId: user.id }).first(); @@ -31,7 +31,7 @@ class albumPOST extends Route { */ await db.table('albums').insert({ name, - enabled: true, + // enabled: true, userId: user.id, createdAt: now, editedAt: now -- cgit v1.2.3 From e073fb4317ae8bd55dfcd0531de10e67383aa408 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Sun, 16 Sep 2018 17:52:46 -0300 Subject: Links can now be created --- src/api/routes/albums/link/linkPOST.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index e8f3731..26a527a 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -11,22 +11,22 @@ class linkPOST extends Route { async run(req, res) { if (!req.body) return res.status(400).json({ message: 'No body provided' }); - const { albumId, enabled, enableDownload, expiresAt } = req.body; + const { albumId } = req.body; if (!albumId) return res.status(400).json({ message: 'No album provided' }); const exists = await db.table('albums').where('id', albumId).first(); if (!exists) return res.status(400).json({ message: 'Album doesn\t exist' }); - const identifier = Util.getUniqueAlbumIdentifier(); + const 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({ identifier, albumId, - enabled, - enableDownload, - expiresAt + enabled: true, + enableDownload: true, + expiresAt: null }); return res.json({ -- cgit v1.2.3 From 46ed1c6a824252fc5ae0dad5b5c2a369bad9ad39 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Mon, 17 Sep 2018 04:37:27 -0300 Subject: This route should handle more stuff, so it does now --- src/api/routes/albums/link/linkEditPOST.js | 38 +++++++++++++++++++++++++++ src/api/routes/albums/link/linkEnabledPOST.js | 34 ------------------------ 2 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 src/api/routes/albums/link/linkEditPOST.js delete mode 100644 src/api/routes/albums/link/linkEnabledPOST.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js new file mode 100644 index 0000000..46b851a --- /dev/null +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -0,0 +1,38 @@ +const Route = require('../../../structures/Route'); +const config = require('../../../../../config'); +const db = require('knex')(config.server.database); +const log = require('../../../utils/Log'); + +class linkEditPOST extends Route { + constructor() { + super('/album/link/edit', 'post'); + } + + async run(req, res, user) { + if (!req.body) return res.status(400).json({ message: 'No body provided' }); + const { identifier, enabled, enableDownload, expiresAt } = req.body; + if (!identifier) return res.status(400).json({ message: 'Invalid album identifier supplied' }); + + 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') + .where({ identifier }) + .update({ + enabled: enabled || false, + enableDownload: enableDownload || false, + expiresAt // This one should be null if not supplied + }); + return res.json({ message: 'Editing the link was successfully' }); + } catch (error) { + log.error(error); + return res.json({ message: 'There was a problem editing the link' }); + } + } +} + +module.exports = linkEditPOST; diff --git a/src/api/routes/albums/link/linkEnabledPOST.js b/src/api/routes/albums/link/linkEnabledPOST.js deleted file mode 100644 index 863fe0b..0000000 --- a/src/api/routes/albums/link/linkEnabledPOST.js +++ /dev/null @@ -1,34 +0,0 @@ -const Route = require('../../../structures/Route'); -const config = require('../../../../../config'); -const db = require('knex')(config.server.database); -const log = require('../../../utils/Log'); - -class linkEnabledPOST extends Route { - constructor() { - super('/album/link/enabled', 'post'); - } - - async run(req, res, user) { - if (!req.body) return res.status(400).json({ message: 'No body provided' }); - const { identifier, enabled } = req.body; - if (!identifier) return res.status(400).json({ message: 'Invalid album identifier supplied' }); - - 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') - .where({ identifier }) - .update({ enabled }); - return res.json({ message: 'The link status was changed successfully' }); - } catch (error) { - log.error(error); - return res.json({ message: 'There was a problem changing the status of the link' }); - } - } -} - -module.exports = linkEnabledPOST; -- cgit v1.2.3 From c2c6e99878853fafdbd5e708c3163921f8529ae1 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Mon, 17 Sep 2018 04:38:25 -0300 Subject: Public albums wooo! --- src/api/routes/albums/albumGET.js | 11 +++++++++-- src/api/routes/albums/link/linkPOST.js | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index f9e5208..655db13 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -1,6 +1,7 @@ const Route = require('../../structures/Route'); const config = require('../../../../config'); const db = require('knex')(config.server.database); +const Util = require('../../utils/Util'); class albumGET extends Route { constructor() { @@ -21,13 +22,19 @@ class albumGET extends Route { if (!album) return res.status(400).json({ message: 'Album not found' }); const fileList = await db.table('albumsFiles').where('albumId', link.albumId); - const fileIds = fileList.filter(el => el.file.fileId); + const fileIds = fileList.map(el => el.fileId); const files = await db.table('files') - .where('id', fileIds) + .whereIn('id', fileIds) + .orderBy('id', 'desc') .select('name'); + for (let file of files) { + file = Util.constructFilePublicLink(file); + } return res.json({ message: 'Successfully retrieved files', + name: album.name, + downloadEnabled: link.enableDownload, files }); } diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 26a527a..9c8c0bc 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -17,6 +17,9 @@ class linkPOST extends Route { const exists = await db.table('albums').where('id', albumId).first(); if (!exists) return res.status(400).json({ message: 'Album doesn\t exist' }); + const count = await db.table('links').where('albumId', albumId).count({ count: 'id' }); + if (count[0].count >= config.albums.maxLinksPerAlbum) return res.status(400).json({ message: 'Maximum links per album reached' }); + const identifier = await Util.getUniqueAlbumIdentifier(); if (!identifier) return res.status(500).json({ message: 'There was a problem allocating a link for your album' }); -- cgit v1.2.3 From f2c885b718528d42df412e612520fb471c46d0bd Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Mon, 17 Sep 2018 04:55:42 -0300 Subject: Commented all the code --- src/api/routes/albums/albumDELETE.js | 16 +++++++++++----- src/api/routes/albums/albumGET.js | 25 ++++++++++++++++++++----- src/api/routes/albums/albumPOST.js | 18 ++++-------------- src/api/routes/albums/link/linkEditPOST.js | 10 +++++----- src/api/routes/albums/link/linkPOST.js | 9 +++++++++ 5 files changed, 49 insertions(+), 29 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index ef98137..eefbf41 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -13,16 +13,22 @@ class albumDELETE extends Route { const { id, purge } = req.params; if (!id) return res.status(400).json({ message: 'Invalid album ID supplied' }); - const album = await db.table('albums').where({ - id, - userId: user.id - }).first(); - + /* + Check fi the album exists + */ + const album = await db.table('albums').where({ id, userId: user.id }).first(); if (!album) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); + try { + /* + Should we also delete every file of that album? + */ if (purge) { await Util.deleteAllFilesFromAlbum(id); } + /* + Delete the album + */ await db.table('albums').where({ id }).delete(); return res.json({ message: 'The album was deleted successfully' }); } catch (error) { diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 655db13..b63811c 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -12,25 +12,40 @@ class albumGET extends Route { const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); - const link = await db.table('links').where({ - identifier, - enabled: true - }).first(); + /* + Make sure it exists and it's enabled + */ + const link = await db.table('links').where({ identifier, enabled: true }).first(); if (!link) return res.status(400).json({ message: 'The identifier supplied could not be found' }); + /* + Same with the album, just to make sure is not a deleted album and a leftover link + */ const album = await db.table('albums').where('id', link.albumId).first(); if (!album) return res.status(400).json({ message: 'Album not found' }); - const fileList = await db.table('albumsFiles').where('albumId', link.albumId); + /* + Grab the files in a very unoptimized way. (This should be a join between both tables) + */ + const fileList = await db.table('albumsFiles').where('albumId', link.albumId).select('fileId'); const fileIds = fileList.map(el => el.fileId); const files = await db.table('files') .whereIn('id', fileIds) .orderBy('id', 'desc') .select('name'); + /* + Create the links for each file + */ for (let file of files) { file = Util.constructFilePublicLink(file); } + + /* + Add 1 more view to the link + */ + await db.table('links').where({ identifier }).update('views', Number(link.views) + 1); + return res.json({ message: 'Successfully retrieved files', name: album.name, diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js index c2e7c4e..12b88fa 100644 --- a/src/api/routes/albums/albumPOST.js +++ b/src/api/routes/albums/albumPOST.js @@ -13,25 +13,15 @@ class albumPOST extends Route { const { name } = req.body; if (!name) return res.status(400).json({ message: 'No name provided' }); - const album = await db.table('albums').where({ - name, - // enabled: true, - userId: user.id - }).first(); - + /* + 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 now = moment.utc().toDate(); - /* - const identifier = await Util.getUniqueAlbumIdentifier(); - if (!identifier) { - console.error('Couldn\'t allocate an identifier for an album'); - return res.status(500).json({ message: 'There was a problem allocating an identifier to the album' }); - } - */ await db.table('albums').insert({ name, - // enabled: true, userId: user.id, createdAt: now, editedAt: now diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 46b851a..d9dbcac 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -13,12 +13,12 @@ class linkEditPOST extends Route { const { identifier, enabled, enableDownload, expiresAt } = req.body; if (!identifier) return res.status(400).json({ message: 'Invalid album identifier supplied' }); - const link = await db.table('links').where({ - identifier, - userId: user.id - }).first(); - + /* + 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' }); + try { await db.table('links') .where({ identifier }) diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 9c8c0bc..4b24eae 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -14,12 +14,21 @@ class linkPOST extends Route { const { albumId } = req.body; if (!albumId) return res.status(400).json({ message: 'No album provided' }); + /* + Make sure the album exists + */ const exists = await db.table('albums').where('id', albumId).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 >= config.albums.maxLinksPerAlbum) 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' }); -- cgit v1.2.3 From 4b2b02110b457d8ebeee78e1bdf99eb0660d0626 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Tue, 18 Sep 2018 03:34:00 -0300 Subject: We can now download albums yayyyy --- src/api/routes/albums/albumZipGET.js | 78 ++++++++++++++++++++++++++++++++++ src/api/routes/albums/link/linkPOST.js | 3 +- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/api/routes/albums/albumZipGET.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js new file mode 100644 index 0000000..7a853cd --- /dev/null +++ b/src/api/routes/albums/albumZipGET.js @@ -0,0 +1,78 @@ +const Route = require('../../structures/Route'); +const config = require('../../../../config'); +const db = require('knex')(config.server.database); +const Util = require('../../utils/Util'); +const log = require('../../utils/Log'); +const path = require('path'); +const jetpack = require('fs-jetpack'); + +class albumGET extends Route { + constructor() { + super('/album/:identifier/zip', 'get', { bypassAuth: true }); + } + + async run(req, res) { + const { identifier } = req.params; + if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); + + /* + Make sure it exists and it's enabled + */ + const link = await db.table('links').where({ identifier, enabled: true }).first(); + if (!link) return res.status(400).json({ message: 'The identifier supplied could not be found' }); + + /* + Same with the album, just to make sure is not a deleted album and a leftover link + */ + const album = await db.table('albums').where('id', link.albumId).first(); + if (!album) return res.status(400).json({ message: 'Album not found' }); + + /* + 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, '..', '..', '..', '..', config.uploads.uploadFolder, '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. + */ + if (exists) { + const fileName = `lolisafe-${identifier}.zip`; + return res.download(filePath, fileName); + } + } + + /* + Grab the files in a very unoptimized way. (This should be a join between both tables) + */ + const fileList = await db.table('albumsFiles').where('albumId', link.albumId).select('fileId'); + + /* + If there are no files, stop here + */ + if (!fileList) return res.status(400).json({ message: 'Can\'t download an empty album' }); + + /* + Get the actual files + */ + 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); + + try { + Util.createZip(filesToZip, album); + await db.table('albums').where('id', link.albumId).update('zippedAt', db.fn.now()); + + const filePath = path.join(__dirname, '..', '..', '..', '..', config.uploads.uploadFolder, 'zips', `${album.userId}-${album.id}.zip`); + const fileName = `lolisafe-${identifier}.zip`; + return res.download(filePath, fileName); + } catch (error) { + log.error(error); + return res.status(500).json({ message: 'There was a problem downloading the album' }); + } + } +} + +module.exports = albumGET; diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 4b24eae..1edf891 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -9,7 +9,7 @@ class linkPOST extends Route { super('/album/link/new', 'post'); } - async run(req, res) { + async run(req, res, user) { if (!req.body) return res.status(400).json({ message: 'No body provided' }); const { albumId } = req.body; if (!albumId) return res.status(400).json({ message: 'No album provided' }); @@ -35,6 +35,7 @@ class linkPOST extends Route { try { await db.table('links').insert({ identifier, + userId: user.id, albumId, enabled: true, enableDownload: true, -- cgit v1.2.3 From 8ca6784eec8d8f1e4a9c4f6875704f09aae1103a Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Tue, 18 Sep 2018 03:52:49 -0300 Subject: Better error handling on invalid links --- src/api/routes/albums/albumGET.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index b63811c..f5e339f 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -16,13 +16,13 @@ class albumGET extends Route { Make sure it exists and it's enabled */ const link = await db.table('links').where({ identifier, enabled: true }).first(); - if (!link) return res.status(400).json({ message: 'The identifier supplied could not be found' }); + if (!link) return res.status(404).json({ message: 'The identifier supplied could not be found' }); /* Same with the album, just to make sure is not a deleted album and a leftover link */ const album = await db.table('albums').where('id', link.albumId).first(); - if (!album) return res.status(400).json({ message: 'Album not found' }); + if (!album) return res.status(404).json({ message: 'Album not found' }); /* Grab the files in a very unoptimized way. (This should be a join between both tables) -- cgit v1.2.3 From 89a271818ed25b0a17a17dd1d6804e34d1f2ec0f Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 19 Feb 2019 23:52:24 +0900 Subject: Switch config to .env --- src/api/routes/albums/albumDELETE.js | 4 +--- src/api/routes/albums/albumGET.js | 4 +--- src/api/routes/albums/albumPOST.js | 4 +--- src/api/routes/albums/albumZipGET.js | 8 +++----- src/api/routes/albums/albumsGET.js | 6 ++---- src/api/routes/albums/link/linkEditPOST.js | 4 +--- src/api/routes/albums/link/linkPOST.js | 6 ++---- 7 files changed, 11 insertions(+), 25 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index eefbf41..3fdf209 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -1,6 +1,4 @@ const Route = require('../../structures/Route'); -const config = require('../../../../config'); -const db = require('knex')(config.server.database); const Util = require('../../utils/Util'); const log = require('../../utils/Log'); @@ -9,7 +7,7 @@ class albumDELETE extends Route { super('/album/:id/:purge*?', 'delete'); } - async run(req, res, user) { + async run(req, res, db, user) { const { id, purge } = req.params; if (!id) return res.status(400).json({ message: 'Invalid album ID supplied' }); diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index f5e339f..59398a1 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -1,6 +1,4 @@ const Route = require('../../structures/Route'); -const config = require('../../../../config'); -const db = require('knex')(config.server.database); const Util = require('../../utils/Util'); class albumGET extends Route { @@ -8,7 +6,7 @@ class albumGET extends Route { super('/album/:identifier', 'get', { bypassAuth: true }); } - async run(req, res) { + async run(req, res, db) { const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js index 12b88fa..0d3a44c 100644 --- a/src/api/routes/albums/albumPOST.js +++ b/src/api/routes/albums/albumPOST.js @@ -1,6 +1,4 @@ const Route = require('../../structures/Route'); -const config = require('../../../../config'); -const db = require('knex')(config.server.database); const moment = require('moment'); class albumPOST extends Route { @@ -8,7 +6,7 @@ class albumPOST extends Route { super('/album/new', 'post'); } - async run(req, res, user) { + async run(req, res, db, user) { if (!req.body) return res.status(400).json({ message: 'No body provided' }); const { name } = req.body; if (!name) return res.status(400).json({ message: 'No name provided' }); diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index 7a853cd..9419654 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -1,6 +1,4 @@ const Route = require('../../structures/Route'); -const config = require('../../../../config'); -const db = require('knex')(config.server.database); const Util = require('../../utils/Util'); const log = require('../../utils/Log'); const path = require('path'); @@ -11,7 +9,7 @@ class albumGET extends Route { super('/album/:identifier/zip', 'get', { bypassAuth: true }); } - async run(req, res) { + async run(req, res, db) { const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); @@ -31,7 +29,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, '..', '..', '..', '..', config.uploads.uploadFolder, '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. @@ -65,7 +63,7 @@ class albumGET extends Route { Util.createZip(filesToZip, album); await db.table('albums').where('id', link.albumId).update('zippedAt', db.fn.now()); - const filePath = path.join(__dirname, '..', '..', '..', '..', config.uploads.uploadFolder, '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 b19e03a..3be1213 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -1,6 +1,4 @@ const Route = require('../../structures/Route'); -const config = require('../../../../config'); -const db = require('knex')(config.server.database); const Util = require('../../utils/Util'); class albumsGET extends Route { @@ -8,7 +6,7 @@ class albumsGET extends Route { super('/albums/mini', 'get'); } - async run(req, res, user) { + async run(req, res, db, user) { /* Let's fetch the albums. This route will only return a small portion of the album files for displaying on the dashboard. It's probably useless @@ -72,7 +70,7 @@ class albumsDropdownGET extends Route { super('/albums/dropdown', 'get'); } - async run(req, res, user) { + async run(req, res, db, user) { const albums = await db.table('albums') .where('userId', user.id) .select('id', 'name'); diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index d9dbcac..753c496 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -1,6 +1,4 @@ const Route = require('../../../structures/Route'); -const config = require('../../../../../config'); -const db = require('knex')(config.server.database); const log = require('../../../utils/Log'); class linkEditPOST extends Route { @@ -8,7 +6,7 @@ class linkEditPOST extends Route { super('/album/link/edit', 'post'); } - async run(req, res, user) { + async run(req, res, db, user) { if (!req.body) return res.status(400).json({ message: 'No body provided' }); const { identifier, enabled, enableDownload, expiresAt } = req.body; if (!identifier) return res.status(400).json({ message: 'Invalid album identifier supplied' }); diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 1edf891..91e1521 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -1,6 +1,4 @@ const Route = require('../../../structures/Route'); -const config = require('../../../../../config'); -const db = require('knex')(config.server.database); const Util = require('../../../utils/Util'); const log = require('../../../utils/Log'); @@ -9,7 +7,7 @@ class linkPOST extends Route { super('/album/link/new', 'post'); } - async run(req, res, user) { + async run(req, res, db, user) { if (!req.body) return res.status(400).json({ message: 'No body provided' }); const { albumId } = req.body; if (!albumId) return res.status(400).json({ message: 'No album provided' }); @@ -24,7 +22,7 @@ class linkPOST extends Route { 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 >= config.albums.maxLinksPerAlbum) return res.status(400).json({ message: 'Maximum links per album reached' }); + if (count[0].count >= process.env.MAX_LINKS_PER_ALBUM) return res.status(400).json({ message: 'Maximum links per album reached' }); /* Try to allocate a new identifier on the db -- cgit v1.2.3 From fc95cb7b0f047806937c25f0fc1104c72b0a32cb Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 23 Feb 2019 00:45:45 +0900 Subject: Better DB handling and stuff --- src/api/routes/albums/link/linkPOST.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 91e1521..968e57d 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -37,7 +37,8 @@ class linkPOST extends Route { albumId, enabled: true, enableDownload: true, - expiresAt: null + expiresAt: null, + views: 0 }); return res.json({ -- cgit v1.2.3 From 73d85e8c7938e1db30da3cc4354b143d4a078473 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 2 Mar 2019 02:08:11 +0900 Subject: Enviroment variables parsing fix --- src/api/routes/albums/link/linkPOST.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 968e57d..e929c89 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -22,7 +22,7 @@ class linkPOST extends Route { 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 >= process.env.MAX_LINKS_PER_ALBUM) return res.status(400).json({ message: 'Maximum links per album reached' }); + if (count[0].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 -- cgit v1.2.3 From 789f5fc259b90dd6a3b21fd2aef1a9e54a19506e Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 2 Mar 2019 22:16:35 +0900 Subject: Removed google analytics --- src/api/routes/albums/link/linkEditPOST.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 753c496..bb3c41b 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -25,7 +25,7 @@ class linkEditPOST extends Route { enableDownload: enableDownload || false, expiresAt // This one should be null if not supplied }); - return res.json({ message: 'Editing the link was successfully' }); + return res.json({ message: 'Editing the link was successfull' }); } catch (error) { log.error(error); return res.json({ message: 'There was a problem editing the link' }); -- cgit v1.2.3 From 3ce7657871bfe392d73ab67a6c1a8a10543e3d98 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 2 Mar 2019 22:36:28 +0900 Subject: wip --- src/api/routes/albums/albumGET.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 59398a1..fae7dd1 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -14,7 +14,7 @@ class albumGET extends Route { Make sure it exists and it's enabled */ const link = await db.table('links').where({ identifier, enabled: true }).first(); - if (!link) return res.status(404).json({ message: 'The identifier supplied could not be found' }); + if (!link) return res.status(404).json({ message: 'The album could not be found' }); /* Same with the album, just to make sure is not a deleted album and a leftover link -- cgit v1.2.3 From 71f24504317a8391209789275549a94be5c99e4e Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 8 Mar 2019 00:47:30 +0900 Subject: WIP --- src/api/routes/albums/link/linkDELETE.js | 36 ++++++++++++++++++++++++++++++ src/api/routes/albums/link/linkEditPOST.js | 3 +-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/api/routes/albums/link/linkDELETE.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js new file mode 100644 index 0000000..4f948ba --- /dev/null +++ b/src/api/routes/albums/link/linkDELETE.js @@ -0,0 +1,36 @@ +const Route = require('../../../structures/Route'); + +class linkDELETE extends Route { + constructor() { + super('/album/link/delete/:identifier', 'delete'); + } + + async run(req, res, db) { + const { identifier } = req.params; + if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); + + try { + const link = await db.table('links') + .where({ identifier }) + .first(); + + if (!link) return res.status(400).json({ message: 'Identifier doesn\'t exist' }); + + await db.table('links') + .where({ id: link.id }) + .delete(); + await db.table('albumsLinks') + .where({ linkId: link.id }) + .delete(); + } catch (error) { + console.log(error); + return super.error(res, error); + } + + return res.json({ + message: 'Successfully deleted link' + }); + } +} + +module.exports = linkDELETE; diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index bb3c41b..1db0a53 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -8,7 +8,7 @@ class linkEditPOST extends Route { async run(req, res, db, user) { if (!req.body) return res.status(400).json({ message: 'No body provided' }); - const { identifier, enabled, enableDownload, expiresAt } = req.body; + const { identifier, enableDownload, expiresAt } = req.body; if (!identifier) return res.status(400).json({ message: 'Invalid album identifier supplied' }); /* @@ -21,7 +21,6 @@ class linkEditPOST extends Route { await db.table('links') .where({ identifier }) .update({ - enabled: enabled || false, enableDownload: enableDownload || false, expiresAt // This one should be null if not supplied }); -- cgit v1.2.3 From 85ac74483764de66d2be0f6ea1ff84626e32ffff Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 12 Mar 2019 05:31:55 +0000 Subject: Typo --- src/api/routes/albums/link/linkEditPOST.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 1db0a53..0586f08 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -24,7 +24,7 @@ class linkEditPOST extends Route { enableDownload: enableDownload || false, expiresAt // This one should be null if not supplied }); - return res.json({ message: 'Editing the link was successfull' }); + return res.json({ message: 'Editing the link was successful' }); } catch (error) { log.error(error); return res.json({ message: 'There was a problem editing the link' }); -- cgit v1.2.3 From dd98cecfebff9f98383d604b9a20fa8a8f32380a Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 12 Mar 2019 05:38:13 +0000 Subject: Error consistency --- src/api/routes/albums/albumDELETE.js | 3 +-- src/api/routes/albums/link/linkDELETE.js | 1 - src/api/routes/albums/link/linkEditPOST.js | 3 +-- src/api/routes/albums/link/linkPOST.js | 3 +-- 4 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index 3fdf209..23dcf40 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -30,8 +30,7 @@ class albumDELETE extends Route { await db.table('albums').where({ id }).delete(); return res.json({ message: 'The album was deleted successfully' }); } catch (error) { - log.error(error); - return res.json({ message: 'There was a problem deleting the album' }); + return super.error(res, error); } } } diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index 4f948ba..d6d98c4 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -23,7 +23,6 @@ class linkDELETE extends Route { .where({ linkId: link.id }) .delete(); } catch (error) { - console.log(error); return super.error(res, error); } diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 0586f08..6776b73 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -26,8 +26,7 @@ class linkEditPOST extends Route { }); return res.json({ message: 'Editing the link was successful' }); } catch (error) { - log.error(error); - return res.json({ message: 'There was a problem editing the link' }); + return super.error(res, error); } } } diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index e929c89..297348c 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -46,8 +46,7 @@ class linkPOST extends Route { identifier }); } catch (error) { - log.error(error); - return res.status(500).json({ message: 'There was a problem creating the link' }); + return super.error(res, error); } } } -- cgit v1.2.3 From 00058e9915a09f5abcd8d130a144f5c68d10428a Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 12 Mar 2019 06:03:15 +0000 Subject: stuff --- src/api/routes/albums/albumDELETE.js | 2 +- src/api/routes/albums/albumZipGET.js | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index 23dcf40..adaa02f 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -12,7 +12,7 @@ class albumDELETE extends Route { if (!id) return res.status(400).json({ message: 'Invalid album ID supplied' }); /* - Check fi the album exists + Check if the album exists */ const album = await db.table('albums').where({ id, userId: user.id }).first(); if (!album) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index 9419654..b2c9fa7 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -16,13 +16,17 @@ class albumGET extends Route { /* Make sure it exists and it's enabled */ - const link = await db.table('links').where({ identifier, enabled: true }).first(); + const link = await db.table('links') + .where({ identifier, enabled: true }) + .first(); if (!link) return res.status(400).json({ message: 'The identifier supplied could not be found' }); /* Same with the album, just to make sure is not a deleted album and a leftover link */ - const album = await db.table('albums').where('id', link.albumId).first(); + const album = await db.table('albums') + .where('id', link.albumId) + .first(); if (!album) return res.status(400).json({ message: 'Album not found' }); /* @@ -43,12 +47,14 @@ class albumGET extends Route { /* Grab the files in a very unoptimized way. (This should be a join between both tables) */ - const fileList = await db.table('albumsFiles').where('albumId', link.albumId).select('fileId'); + const fileList = await db.table('albumsFiles') + .where('albumId', link.albumId) + .select('fileId'); /* If there are no files, stop here */ - if (!fileList) return res.status(400).json({ message: 'Can\'t download an empty album' }); + if (!fileList || !fileList.length) return res.status(400).json({ message: 'Can\'t download an empty album' }); /* Get the actual files @@ -61,7 +67,9 @@ class albumGET extends Route { try { Util.createZip(filesToZip, album); - await db.table('albums').where('id', link.albumId).update('zippedAt', db.fn.now()); + await db.table('albums') + .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 fileName = `lolisafe-${identifier}.zip`; -- cgit v1.2.3 From 771a5c2bf7480b6e023d8eeeded1c6f698b779e8 Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 12 Mar 2019 06:32:10 +0000 Subject: Not tested, but should delete an album --- src/api/routes/albums/albumDELETE.js | 1 - 1 file changed, 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index adaa02f..b43d046 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -1,6 +1,5 @@ const Route = require('../../structures/Route'); const Util = require('../../utils/Util'); -const log = require('../../utils/Log'); class albumDELETE extends Route { constructor() { -- cgit v1.2.3 From f11cb56db87c297d72c18bf967ebdacd9959ef64 Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 12 Mar 2019 07:02:26 +0000 Subject: Clicking on album title takes you to the album now --- src/api/routes/albums/albumFullGET.js | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/api/routes/albums/albumFullGET.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js new file mode 100644 index 0000000..629f57a --- /dev/null +++ b/src/api/routes/albums/albumFullGET.js @@ -0,0 +1,55 @@ +const Route = require('../../structures/Route'); +const Util = require('../../utils/Util'); + +class albumGET extends Route { + constructor() { + super('/album/:id/full', 'get'); + } + + async run(req, res, db) { + 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(); + if (!album) return res.status(404).json({ message: 'Album not found' }); + + /* + Grab the files in a very unoptimized way. (This should be a join between both tables) + */ + const fileList = await db.table('albumsFiles').where('albumId', id).select('fileId'); + const fileIds = fileList.map(el => el.fileId); + const files = await db.table('files') + .whereIn('id', fileIds) + .orderBy('id', 'desc'); + + for (const file of files) { + file.albums = []; + const albumFiles = await db.table('albumsFiles') + .where('fileId', file.id); + if (!albumFiles.length) continue; + + for (const albumFile of albumFiles) { + const album = await db.table('albums') + .where('id', albumFile.albumId) + .select('id', 'name') + .first(); + if (!album) continue; + file.albums.push(album); + } + } + /* + For each file, create the public link to be able to display the file + */ + for (let file of files) { + file = Util.constructFilePublicLink(file); + } + + return res.json({ + message: 'Successfully retrieved album', + name: album.name, + files + }); + } +} + +module.exports = albumGET; -- cgit v1.2.3 From 79eb00f71cc18dbb195a29bd79871d35176f33d1 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 14 Mar 2019 23:14:24 +0900 Subject: Small fixes --- src/api/routes/albums/albumFullGET.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index 629f57a..f92f9ae 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -6,7 +6,7 @@ class albumGET extends Route { super('/album/:id/full', 'get'); } - async run(req, res, db) { + async run(req, res, db, user) { const { id } = req.params; if (!id) return res.status(400).json({ message: 'Invalid id supplied' }); -- cgit v1.2.3 From f06c8c9d336cbee561d9a80abc78568c28463e52 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 14 Mar 2019 23:14:45 +0900 Subject: dunno what's wrong here yet --- src/api/routes/albums/link/linkDELETE.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index d6d98c4..3ec4d9d 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -1,4 +1,5 @@ const Route = require('../../../structures/Route'); +const { dump } = require('dumper.js'); class linkDELETE extends Route { constructor() { @@ -6,6 +7,10 @@ class linkDELETE extends Route { } async run(req, res, db) { + console.log('------------------------------'); + console.log('YES HI'); + console.log('------------------------------'); + console.log('WHO NEEDS FANCY DEBUGGING TOOLS ANYWAYS'); const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); @@ -14,6 +19,8 @@ class linkDELETE extends Route { .where({ identifier }) .first(); + dump(link); + if (!link) return res.status(400).json({ message: 'Identifier doesn\'t exist' }); await db.table('links') -- cgit v1.2.3 From 8e4f1b7838e3c43320f2e25e691c1808ae3c4089 Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 30 Sep 2019 07:06:22 +0000 Subject: feature: album links --- src/api/routes/albums/albumZipGET.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index b2c9fa7..d1d3e16 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -17,9 +17,13 @@ class albumGET extends Route { Make sure it exists and it's enabled */ const link = await db.table('links') - .where({ identifier, enabled: true }) + .where({ + identifier, + enabled: true, + enableDownload: true + }) .first(); - if (!link) return res.status(400).json({ message: 'The identifier supplied could not be found' }); + if (!link) return res.status(400).json({ message: 'The supplied identifier could not be found' }); /* Same with the album, just to make sure is not a deleted album and a leftover link -- cgit v1.2.3 From 4db167ec43806e20cc40932a292efc2909e69328 Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 30 Sep 2019 07:24:37 +0000 Subject: Fix deletion of albums and links --- src/api/routes/albums/albumDELETE.js | 10 ++-------- src/api/routes/albums/albumPurgeDELETE.js | 29 +++++++++++++++++++++++++++++ src/api/routes/albums/link/linkDELETE.js | 4 ---- 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 src/api/routes/albums/albumPurgeDELETE.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index b43d046..2aa9942 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -3,11 +3,11 @@ const Util = require('../../utils/Util'); class albumDELETE extends Route { constructor() { - super('/album/:id/:purge*?', 'delete'); + super('/album/:id', 'delete'); } async run(req, res, db, user) { - const { id, purge } = req.params; + const { id } = req.params; if (!id) return res.status(400).json({ message: 'Invalid album ID supplied' }); /* @@ -17,12 +17,6 @@ class albumDELETE extends Route { if (!album) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); try { - /* - Should we also delete every file of that album? - */ - if (purge) { - await Util.deleteAllFilesFromAlbum(id); - } /* Delete the album */ diff --git a/src/api/routes/albums/albumPurgeDELETE.js b/src/api/routes/albums/albumPurgeDELETE.js new file mode 100644 index 0000000..5a67c8e --- /dev/null +++ b/src/api/routes/albums/albumPurgeDELETE.js @@ -0,0 +1,29 @@ +const Route = require('../../structures/Route'); +const Util = require('../../utils/Util'); + +class albumDELETE extends Route { + constructor() { + super('/album/:id/purge', 'delete'); + } + + async run(req, res, db, user) { + const { id } = req.params; + if (!id) return res.status(400).json({ message: 'Invalid album ID supplied' }); + + /* + Check if the album exists + */ + const album = await db.table('albums').where({ id, userId: user.id }).first(); + if (!album) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); + + try { + await Util.deleteAllFilesFromAlbum(id); + await db.table('albums').where({ id }).delete(); + return res.json({ message: 'The album was deleted successfully' }); + } catch (error) { + return super.error(res, error); + } + } +} + +module.exports = albumDELETE; diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index 3ec4d9d..7adcaac 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -7,10 +7,6 @@ class linkDELETE extends Route { } async run(req, res, db) { - console.log('------------------------------'); - console.log('YES HI'); - console.log('------------------------------'); - console.log('WHO NEEDS FANCY DEBUGGING TOOLS ANYWAYS'); const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); -- cgit v1.2.3 From bca8fbcd839d2239e3f6f141f662fbbc74726835 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 12 Oct 2019 21:14:19 +0900 Subject: refactor: removed useless code, cleaned up, fixed permissions --- src/api/routes/albums/albumDELETE.js | 2 +- src/api/routes/albums/albumPurgeDELETE.js | 2 +- src/api/routes/albums/albumsGET.js | 2 ++ src/api/routes/albums/link/linkDELETE.js | 4 ++-- src/api/routes/albums/link/linkPOST.js | 3 +-- 5 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index 2aa9942..96698b4 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -14,7 +14,7 @@ class albumDELETE extends Route { Check if the album exists */ const album = await db.table('albums').where({ id, userId: user.id }).first(); - if (!album) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); + if (!album) return res.status(400).json({ message: 'The album doesn\'t exist or doesn\'t belong to the user' }); try { /* diff --git a/src/api/routes/albums/albumPurgeDELETE.js b/src/api/routes/albums/albumPurgeDELETE.js index 5a67c8e..a63eafc 100644 --- a/src/api/routes/albums/albumPurgeDELETE.js +++ b/src/api/routes/albums/albumPurgeDELETE.js @@ -14,7 +14,7 @@ class albumDELETE extends Route { Check if the album exists */ const album = await db.table('albums').where({ id, userId: user.id }).first(); - if (!album) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); + if (!album) return res.status(400).json({ message: 'The album doesn\'t exist or doesn\'t belong to the user' }); try { await Util.deleteAllFilesFromAlbum(id); diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index 3be1213..c61ad03 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -18,6 +18,8 @@ class albumsGET extends Route { .select('id', 'name', 'createdAt', 'editedAt'); for (const album of albums) { + // TODO: Optimize the shit out of this. + /* Fetch every public link the album has */ diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index 7adcaac..904687f 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -6,13 +6,13 @@ class linkDELETE extends Route { super('/album/link/delete/:identifier', 'delete'); } - async run(req, res, db) { + async run(req, res, db, user) { const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); try { const link = await db.table('links') - .where({ identifier }) + .where({ identifier, userId: user.id }) .first(); dump(link); diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 297348c..6009922 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -1,6 +1,5 @@ const Route = require('../../../structures/Route'); const Util = require('../../../utils/Util'); -const log = require('../../../utils/Log'); class linkPOST extends Route { constructor() { @@ -15,7 +14,7 @@ class linkPOST extends Route { /* Make sure the album exists */ - const exists = await db.table('albums').where('id', albumId).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' }); /* -- cgit v1.2.3 From b27b4c47f79071d3aa336b8f9a6578103df56fe9 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sun, 10 May 2020 21:22:25 +0900 Subject: feat: Proper deleting of albums --- src/api/routes/albums/albumDELETE.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index 96698b4..4e6640e 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -17,10 +17,18 @@ class albumDELETE extends Route { if (!album) return res.status(400).json({ message: 'The album doesn\'t exist or doesn\'t belong to the user' }); try { - /* - Delete the album - */ + // Delete the album await db.table('albums').where({ id }).delete(); + + // Delete the relation of any files attached to this album + await db.table('albumsFiles').where({ albumId: id }).delete(); + + // Delete the relation of any links attached to this album + await db.table('albumsLinks').where({ albumId: id }).delete(); + + // Delete any album links created for this album + await db.table('links').where({ albumId: id }).delete(); + return res.json({ message: 'The album was deleted successfully' }); } catch (error) { return super.error(res, error); -- cgit v1.2.3 From b886fda0793b8a26de58cd462acf6676a0a8e7ed Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 11 May 2020 00:19:10 +0900 Subject: chore: cleanup and todo --- src/api/routes/albums/albumZipGET.js | 1 + src/api/routes/albums/link/linkDELETE.js | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index d1d3e16..a6ef6fd 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -13,6 +13,7 @@ class albumGET extends Route { const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); + // TODO: Do we really want to let anyone create a zip of an album? /* Make sure it exists and it's enabled */ diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index 904687f..23db411 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -15,8 +15,6 @@ class linkDELETE extends Route { .where({ identifier, userId: user.id }) .first(); - dump(link); - if (!link) return res.status(400).json({ message: 'Identifier doesn\'t exist' }); await db.table('links') -- cgit v1.2.3 From 496477ebda3f6c347a9944e22daae447d15ebc31 Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 11 May 2020 00:57:56 +0900 Subject: Feature: enable apiKey access to uploads and album fetching for the uploader/sharex/3rd party --- src/api/routes/albums/albumsGET.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index c61ad03..bbd3cae 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -69,7 +69,7 @@ class albumsGET extends Route { class albumsDropdownGET extends Route { constructor() { - super('/albums/dropdown', 'get'); + super('/albums/dropdown', 'get', { canApiKey: true }); } async run(req, res, db, user) { -- cgit v1.2.3 From b526d8803696161961ffb9eb912cb4b83a3c9eff Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 25 Jun 2020 01:35:52 +0900 Subject: Optimize the queries fetching albums/files --- src/api/routes/albums/albumFullGET.js | 31 +++++-------------------------- src/api/routes/albums/albumsGET.js | 32 ++++++++++---------------------- src/api/routes/albums/link/linksGET.js | 22 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 48 deletions(-) create mode 100644 src/api/routes/albums/link/linksGET.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index f92f9ae..93b56ce 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -13,33 +13,12 @@ class albumGET extends Route { const album = await db.table('albums').where({ id, userId: user.id }).first(); if (!album) return res.status(404).json({ message: 'Album not found' }); - /* - Grab the files in a very unoptimized way. (This should be a join between both tables) - */ - const fileList = await db.table('albumsFiles').where('albumId', id).select('fileId'); - const fileIds = fileList.map(el => el.fileId); - const files = await db.table('files') - .whereIn('id', fileIds) - .orderBy('id', 'desc'); + const files = await db.table('albumsFiles') + .where({ albumId: id }) + .join('files', 'albumsFiles.fileId', 'files.id') + .select('files.id', 'files.name') + .orderBy('files.id', 'desc'); - for (const file of files) { - file.albums = []; - const albumFiles = await db.table('albumsFiles') - .where('fileId', file.id); - if (!albumFiles.length) continue; - - for (const albumFile of albumFiles) { - const album = await db.table('albums') - .where('id', albumFile.albumId) - .select('id', 'name') - .first(); - if (!album) continue; - file.albums.push(album); - } - } - /* - For each file, create the public link to be able to display the file - */ for (let file of files) { file = Util.constructFilePublicLink(file); } diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index bbd3cae..bbaa518 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -13,49 +13,37 @@ class albumsGET extends Route { for anyone consuming the API outside of the lolisafe frontend. */ const albums = await db.table('albums') - .where('userId', user.id) - // .where('enabled', true) - .select('id', 'name', 'createdAt', 'editedAt'); + .where('albums.userId', user.id) + .select('id', 'name', 'editedAt'); for (const album of albums) { - // TODO: Optimize the shit out of this. + // TODO: Optimize the shit out of this. Ideally a JOIN that grabs all the needed stuff in 1 query instead of 3 - /* - Fetch every public link the album has - */ - const links = await db.table('links').where('albumId', album.id); // eslint-disable-line no-await-in-loop + // Fetch every public link the album has + // const links = await db.table('links').where('albumId', album.id); // eslint-disable-line no-await-in-loop - /* - Fetch the total amount of files each album has. - */ + // Fetch the total amount of files each album has. const fileCount = await db.table('albumsFiles') // eslint-disable-line no-await-in-loop .where('albumId', album.id) .count({ count: 'id' }); - /* - Fetch the file list from each album but limit it to 5 per album - */ + // 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 .where('albumId', album.id) .select('fileId') .orderBy('id', 'desc') .limit(5); - /* - Fetch the actual files - */ + // 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', 'hash', 'original', 'size', 'type', 'createdAt', 'editedAt'); + .select('id', 'name'); - /* - Fetch thumbnails and stuff - */ + // Fetch thumbnails and stuff for (let file of files) { file = Util.constructFilePublicLink(file); } - album.links = links; album.fileCount = fileCount[0].count; album.files = files; } diff --git a/src/api/routes/albums/link/linksGET.js b/src/api/routes/albums/link/linksGET.js new file mode 100644 index 0000000..edab49a --- /dev/null +++ b/src/api/routes/albums/link/linksGET.js @@ -0,0 +1,22 @@ +const Route = require('../../../structures/Route'); + +class linkPOST extends Route { + constructor() { + super('/album/:id/links', 'get'); + } + + async run(req, res, db, user) { + const { id } = req.params; + if (!id) return res.status(400).json({ message: 'Invalid id supplied' }); + + const links = await db.table('links') + .where({ albumId: id, userId: user.id }); + + return res.json({ + message: 'Successfully retrieved links', + links + }); + } +} + +module.exports = linkPOST; -- cgit v1.2.3 From a9fe08f9e577de8df0f742a428214c42e532d04c Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 25 Jun 2020 01:36:04 +0900 Subject: Update error message --- src/api/routes/albums/link/linkDELETE.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index 23db411..b02d0b4 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -15,7 +15,7 @@ class linkDELETE extends Route { .where({ identifier, userId: user.id }) .first(); - if (!link) return res.status(400).json({ message: 'Identifier doesn\'t exist' }); + if (!link) return res.status(400).json({ message: 'Identifier doesn\'t exist or doesnt\'t belong to the user' }); await db.table('links') .where({ id: link.id }) -- cgit v1.2.3 From f189ddf9e6e1dda0c8e56afd367bc378ee19b8fd Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 25 Jun 2020 02:05:48 +0900 Subject: Cleanup --- src/api/routes/albums/albumsGET.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index bbaa518..1a7db87 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -19,9 +19,6 @@ class albumsGET extends Route { 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 every public link the album has - // const links = await db.table('links').where('albumId', album.id); // eslint-disable-line no-await-in-loop - // Fetch the total amount of files each album has. const fileCount = await db.table('albumsFiles') // eslint-disable-line no-await-in-loop .where('albumId', album.id) -- cgit v1.2.3 From d1340c26b5f72a45fb577ad7879addcb548dcf12 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 25 Jun 2020 02:06:00 +0900 Subject: Optimize album view --- src/api/routes/albums/albumGET.js | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index fae7dd1..1bf3630 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -10,38 +10,26 @@ class albumGET extends Route { const { identifier } = req.params; if (!identifier) return res.status(400).json({ message: 'Invalid identifier supplied' }); - /* - Make sure it exists and it's enabled - */ + // Make sure it exists and it's enabled const link = await db.table('links').where({ identifier, enabled: true }).first(); if (!link) return res.status(404).json({ message: 'The album could not be found' }); - /* - Same with the album, just to make sure is not a deleted album and a leftover link - */ + // Same with the album, just to make sure is not a deleted album and a leftover link const album = await db.table('albums').where('id', link.albumId).first(); if (!album) return res.status(404).json({ message: 'Album not found' }); - /* - Grab the files in a very unoptimized way. (This should be a join between both tables) - */ - const fileList = await db.table('albumsFiles').where('albumId', link.albumId).select('fileId'); - const fileIds = fileList.map(el => el.fileId); - const files = await db.table('files') - .whereIn('id', fileIds) - .orderBy('id', 'desc') - .select('name'); - - /* - Create the links for each file - */ + const files = await db.table('albumsFiles') + .where({ albumId: link.albumId }) + .join('files', 'albumsFiles.fileId', 'files.id') + .select('files.name') + .orderBy('files.id', 'desc'); + + // Create the links for each file for (let file of files) { file = Util.constructFilePublicLink(file); } - /* - Add 1 more view to the link - */ + // Add 1 more view to the link await db.table('links').where({ identifier }).update('views', Number(link.views) + 1); return res.json({ -- cgit v1.2.3 From e9ef148d7498b7068274a4141d5591cc8a64016e Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 1 Jul 2020 20:40:10 +0300 Subject: feat: backend pagination for albums --- src/api/routes/albums/albumFullGET.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index 93b56ce..cf434e4 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -13,12 +13,29 @@ class albumGET extends Route { 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') .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; + } + for (let file of files) { file = Util.constructFilePublicLink(file); } @@ -26,7 +43,8 @@ class albumGET extends Route { return res.json({ message: 'Successfully retrieved album', name: album.name, - files + files, + count }); } } -- cgit v1.2.3 From b620aa981546cb42e19f64d5349a9372e3d0c269 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sat, 4 Jul 2020 03:25:04 +0300 Subject: feat: refactor some of the queries to returned added/updated data --- src/api/routes/albums/albumFullGET.js | 13 +++++++++---- src/api/routes/albums/albumPOST.js | 17 ++++++++++++----- src/api/routes/albums/albumsGET.js | 25 +++++++++++++------------ src/api/routes/albums/link/linkEditPOST.js | 21 +++++++++++++-------- src/api/routes/albums/link/linkPOST.js | 24 +++++++++++++++++------- 5 files changed, 64 insertions(+), 36 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index cf434e4..a5c9707 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -10,22 +10,27 @@ 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' }); let count = 0; - let files = db.table('albumsFiles') + 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') + const dbRes = await db + .table('albumsFiles') .count('* as count') .where({ albumId: id }) .first(); diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js index 0d3a44c..841da3d 100644 --- a/src/api/routes/albums/albumPOST.js +++ b/src/api/routes/albums/albumPOST.js @@ -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 - }); + }; - return res.json({ message: 'The album was created successfully' }); + const dbRes = await db.table('albums').insert(insertObj); + + insertObj.id = dbRes.pop(); + + return res.json({ message: 'The album was created successfully', data: insertObj }); } } diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index 1a7db87..569128c 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -12,30 +12,30 @@ 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 + .table('albumsFiles') // eslint-disable-line no-await-in-loop .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 + .table('albumsFiles') // eslint-disable-line no-await-in-loop + .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 +58,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/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 6776b73..0c7233b 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -14,17 +14,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..7ecc5cb 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -14,23 +14,32 @@ 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' }); + 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 +47,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); -- cgit v1.2.3 From 04fdd63cee5327f49e5e11d5837a9031027c34ef Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sun, 5 Jul 2020 04:17:09 +0300 Subject: feat: refactor single album page to use vuex --- src/api/routes/albums/albumGET.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 1bf3630..f40750b 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -21,7 +21,7 @@ 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 @@ -36,7 +36,7 @@ class albumGET extends Route { message: 'Successfully retrieved files', name: album.name, downloadEnabled: link.enableDownload, - files + files, }); } } -- cgit v1.2.3 From fb0bc57542a44dcc94149f393d8a4ff0c2e7902b Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Tue, 7 Jul 2020 02:02:59 +0300 Subject: feat: try fixing THE SHITTY WATERFALL --- src/api/routes/albums/albumFullGET.js | 3 ++- src/api/routes/albums/albumGET.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index a5c9707..2c3a790 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -41,6 +41,7 @@ class albumGET extends Route { count = files.length; } + // eslint-disable-next-line no-restricted-syntax for (let file of files) { file = Util.constructFilePublicLink(file); } @@ -49,7 +50,7 @@ class albumGET extends Route { message: 'Successfully retrieved album', name: album.name, files, - count + count, }); } } diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index f40750b..81edc95 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -25,6 +25,7 @@ class albumGET extends Route { .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); } -- cgit v1.2.3 From 1a8b6602e094289a4f477c33e432e0f5e1587b45 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 03:13:51 +0300 Subject: refactor: change uploader component to use vuex --- src/api/routes/albums/albumsGET.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index 569128c..c9ab025 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'); @@ -19,17 +20,15 @@ class albumsGET extends Route { .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 files = 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('files.id', 'files.name') @@ -47,7 +46,7 @@ class albumsGET extends Route { return res.json({ message: 'Successfully retrieved albums', - albums + albums, }); } } @@ -64,7 +63,7 @@ class albumsDropdownGET extends Route { .select('id', 'name'); return res.json({ message: 'Successfully retrieved albums', - albums + albums, }); } } -- cgit v1.2.3 From ad852de51a0d2dd5d29c08838d5a430c58849e74 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 04:00:12 +0300 Subject: chore: linter the entire project using the new rules --- src/api/routes/albums/albumDELETE.js | 1 - src/api/routes/albums/albumPOST.js | 4 ++-- src/api/routes/albums/albumZipGET.js | 10 +++++----- src/api/routes/albums/link/linkDELETE.js | 3 +-- src/api/routes/albums/link/linkEditPOST.js | 3 +-- src/api/routes/albums/link/linkPOST.js | 10 ++++------ src/api/routes/albums/link/linksGET.js | 2 +- 7 files changed, 14 insertions(+), 19 deletions(-) (limited to 'src/api/routes/albums') 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/albumPOST.js b/src/api/routes/albums/albumPOST.js index 841da3d..94ee8a7 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() { @@ -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); diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index a6ef6fd..bd74ef3 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() { @@ -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' }); @@ -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); diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index b02d0b4..0381b50 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() { @@ -28,7 +27,7 @@ class linkDELETE extends Route { } return res.json({ - message: 'Successfully deleted link' + message: 'Successfully deleted link', }); } } diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 0c7233b..4e0e0e1 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() { @@ -23,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') diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 7ecc5cb..d58598a 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -28,15 +28,13 @@ class linkPOST extends Route { .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' }); + 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' }); + if (!identifier) return res.status(500).json({ message: 'There was a problem allocating a link for your album' }); try { const insertObj = { @@ -46,13 +44,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); diff --git a/src/api/routes/albums/link/linksGET.js b/src/api/routes/albums/link/linksGET.js index edab49a..4487c26 100644 --- a/src/api/routes/albums/link/linksGET.js +++ b/src/api/routes/albums/link/linksGET.js @@ -14,7 +14,7 @@ class linkPOST extends Route { return res.json({ message: 'Successfully retrieved links', - links + links, }); } } -- cgit v1.2.3 From 151c360740aac5733759888220d91a1d3713b6e1 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Fri, 2 Oct 2020 22:16:34 +0300 Subject: feat: allow administrators to create custom links for albums --- src/api/routes/albums/link/linkPOST.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index d58598a..ba247b5 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -30,11 +30,28 @@ class linkPOST extends Route { .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 { const insertObj = { -- cgit v1.2.3 From 90001c2df56d58e69fd199a518ae7f3e4ed327fc Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 24 Dec 2020 10:40:50 +0200 Subject: chore: remove trailing commas --- src/api/routes/albums/albumFullGET.js | 2 +- src/api/routes/albums/albumGET.js | 2 +- src/api/routes/albums/albumPOST.js | 2 +- src/api/routes/albums/albumZipGET.js | 6 +++--- src/api/routes/albums/albumsGET.js | 4 ++-- src/api/routes/albums/link/linkDELETE.js | 2 +- src/api/routes/albums/link/linkEditPOST.js | 2 +- src/api/routes/albums/link/linkPOST.js | 4 ++-- src/api/routes/albums/link/linksGET.js | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index 2c3a790..d25fe15 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -50,7 +50,7 @@ class albumGET extends Route { message: 'Successfully retrieved album', name: album.name, files, - count, + count }); } } diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 81edc95..950a1fd 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -37,7 +37,7 @@ class albumGET extends Route { message: 'Successfully retrieved files', name: album.name, downloadEnabled: link.enableDownload, - files, + files }); } } diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js index 94ee8a7..52352a1 100644 --- a/src/api/routes/albums/albumPOST.js +++ b/src/api/routes/albums/albumPOST.js @@ -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); diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index bd74ef3..cf1f6f8 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -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) { diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index c9ab025..93a23e3 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -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 }); } } diff --git a/src/api/routes/albums/link/linkDELETE.js b/src/api/routes/albums/link/linkDELETE.js index 0381b50..1af704e 100644 --- a/src/api/routes/albums/link/linkDELETE.js +++ b/src/api/routes/albums/link/linkDELETE.js @@ -27,7 +27,7 @@ class linkDELETE extends Route { } return res.json({ - message: 'Successfully deleted link', + message: 'Successfully deleted link' }); } } diff --git a/src/api/routes/albums/link/linkEditPOST.js b/src/api/routes/albums/link/linkEditPOST.js index 4e0e0e1..97122a2 100644 --- a/src/api/routes/albums/link/linkEditPOST.js +++ b/src/api/routes/albums/link/linkEditPOST.js @@ -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') diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index ba247b5..28e9dfe 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -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); diff --git a/src/api/routes/albums/link/linksGET.js b/src/api/routes/albums/link/linksGET.js index 4487c26..edab49a 100644 --- a/src/api/routes/albums/link/linksGET.js +++ b/src/api/routes/albums/link/linksGET.js @@ -14,7 +14,7 @@ class linkPOST extends Route { return res.json({ message: 'Successfully retrieved links', - links, + links }); } } -- cgit v1.2.3 From fb2c27086f570fec60f4d52dcc9ca80e53186293 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 24 Dec 2020 23:45:16 +0900 Subject: Fix ESLint rules once and for all --- src/api/routes/albums/albumZipGET.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index cf1f6f8..26da2ba 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -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); -- cgit v1.2.3 From ec2f9e0d989792c1760b48e063467cf6e59c580a Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 25 Dec 2020 20:45:22 +0900 Subject: Rebrand --- src/api/routes/albums/albumZipGET.js | 4 ++-- src/api/routes/albums/albumsGET.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index 26da2ba..0722f80 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -44,7 +44,7 @@ class albumGET extends Route { Make sure the file exists just in case, and if not, continue to it's generation. */ if (exists) { - const fileName = `lolisafe-${identifier}.zip`; + const fileName = `chibisafe-${identifier}.zip`; return res.download(filePath, fileName); } } @@ -77,7 +77,7 @@ class albumGET extends Route { .update('zippedAt', db.fn.now()); const filePath = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`); - const fileName = `lolisafe-${identifier}.zip`; + const fileName = `chibisafe-${identifier}.zip`; return res.download(filePath, fileName); } catch (error) { log.error(error); diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index 93a23e3..8d238a9 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -11,7 +11,7 @@ class albumsGET extends Route { /* Let's fetch the albums. This route will only return a small portion of the album files for displaying on the dashboard. It's probably useless - for anyone consuming the API outside of the lolisafe frontend. + for anyone consuming the API outside of the chibisafe frontend. */ const albums = await db .table('albums') -- cgit v1.2.3 From 726f47f301795dccebb75ac90e7ce15480693288 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sun, 27 Dec 2020 01:59:38 +0900 Subject: chore: use instance name for album download --- src/api/routes/albums/albumZipGET.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index 0722f80..c560cff 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -44,7 +44,7 @@ class albumGET extends Route { Make sure the file exists just in case, and if not, continue to it's generation. */ if (exists) { - const fileName = `chibisafe-${identifier}.zip`; + const fileName = `${process.env.SERVICE_NAME}-${identifier}.zip`; return res.download(filePath, fileName); } } @@ -77,7 +77,7 @@ class albumGET extends Route { .update('zippedAt', db.fn.now()); const filePath = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`); - const fileName = `chibisafe-${identifier}.zip`; + const fileName = `${process.env.SERVICE_NAME}-${identifier}.zip`; return res.download(filePath, fileName); } catch (error) { log.error(error); -- cgit v1.2.3 From edb3bed98864e34695a5ae0093c414a2b578073a Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 28 Dec 2020 00:10:59 +0900 Subject: feat: Add warning to nsfw albums --- src/api/routes/albums/albumEditPOST.js | 33 +++++++++++++++++++++++++++++++++ src/api/routes/albums/albumGET.js | 1 + src/api/routes/albums/albumsGET.js | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/api/routes/albums/albumEditPOST.js (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumEditPOST.js b/src/api/routes/albums/albumEditPOST.js new file mode 100644 index 0000000..f104cc1 --- /dev/null +++ b/src/api/routes/albums/albumEditPOST.js @@ -0,0 +1,33 @@ +const Route = require('../../structures/Route'); + +class albumEditPOST extends Route { + constructor() { + super('/album/edit', 'post'); + } + + async run(req, res, db, user) { + if (!req.body) return res.status(400).json({ message: 'No body provided' }); + const { id, name, nsfw } = req.body; + if (!id) return res.status(400).json({ message: 'Invalid album identifier supplied' }); + + + const album = await db.table('albums').where({ id, userId: user.id }).first(); + if (!album) return res.status(400).json({ message: 'The album doesn\'t exist or doesn\'t belong to the user' }); + + try { + const updateObj = { + name: name ? name : album.name, + nsfw: nsfw === true ? true : nsfw === false ? false : album.nsfw + }; + await db + .table('albums') + .where({ id }) + .update(updateObj); + return res.json({ message: 'Editing the album was successful', data: updateObj }); + } catch (error) { + return super.error(res, error); + } + } +} + +module.exports = albumEditPOST; diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 950a1fd..c9f6763 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -37,6 +37,7 @@ class albumGET extends Route { message: 'Successfully retrieved files', name: album.name, downloadEnabled: link.enableDownload, + isNsfw: album.nsfw, files }); } diff --git a/src/api/routes/albums/albumsGET.js b/src/api/routes/albums/albumsGET.js index 8d238a9..3c18d8f 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -16,7 +16,7 @@ class albumsGET extends Route { const albums = await db .table('albums') .where('albums.userId', user.id) - .select('id', 'name', 'createdAt', 'editedAt') + .select('id', 'name', 'nsfw', 'createdAt', 'editedAt') .orderBy('createdAt', 'desc'); for (const album of albums) { -- cgit v1.2.3 From 13058d99d658c0920ce75b79d6b24df18a873ea9 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sun, 27 Dec 2020 18:18:06 +0200 Subject: fix: nsfw album toggle doesn't propagate the changes properly fix: add nsfw flag to the booleanFields in knex postProcessResponse --- src/api/routes/albums/albumEditPOST.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/routes/albums') diff --git a/src/api/routes/albums/albumEditPOST.js b/src/api/routes/albums/albumEditPOST.js index f104cc1..1022bbd 100644 --- a/src/api/routes/albums/albumEditPOST.js +++ b/src/api/routes/albums/albumEditPOST.js @@ -16,7 +16,7 @@ class albumEditPOST extends Route { try { const updateObj = { - name: name ? name : album.name, + name: name || album.name, nsfw: nsfw === true ? true : nsfw === false ? false : album.nsfw }; await db -- cgit v1.2.3