diff options
| author | Kana <[email protected]> | 2021-06-19 02:03:57 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-06-19 02:03:57 +0900 |
| commit | 065c5221a0250838f1d1f9bb7a7922ff4f55e038 (patch) | |
| tree | 8a69a81f00e6bff2752f4f7c59dcbbf21f893b20 /src/api/routes | |
| parent | chore: docs update (diff) | |
| parent | fix: potentially fix the blocked extensions array splitting (diff) | |
| download | host.fuwn.me-065c5221a0250838f1d1f9bb7a7922ff4f55e038.tar.xz host.fuwn.me-065c5221a0250838f1d1f9bb7a7922ff4f55e038.zip | |
Merge pull request #278 from Zephyrrus/Zephyrrus-feature/database_based_settings
Zephyrrus feature/database based settings
Diffstat (limited to 'src/api/routes')
| -rw-r--r-- | src/api/routes/admin/fileGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/admin/userGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/albums/albumFullGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/albums/albumGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/albums/albumZipGET.js | 8 | ||||
| -rw-r--r-- | src/api/routes/albums/albumsGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/albums/link/linkPOST.js | 10 | ||||
| -rw-r--r-- | src/api/routes/auth/loginPOST.js | 3 | ||||
| -rw-r--r-- | src/api/routes/auth/registerPOST.js | 2 | ||||
| -rw-r--r-- | src/api/routes/files/fileGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/files/filesGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/search/searchGET.js | 2 | ||||
| -rw-r--r-- | src/api/routes/service/configAllGET.js | 17 | ||||
| -rw-r--r-- | src/api/routes/service/configGET.js | 21 | ||||
| -rw-r--r-- | src/api/routes/service/configPOST.js | 45 | ||||
| -rw-r--r-- | src/api/routes/service/configSchemaGET.js | 17 | ||||
| -rw-r--r-- | src/api/routes/uploads/uploadPOST.js | 12 |
17 files changed, 110 insertions, 41 deletions
diff --git a/src/api/routes/admin/fileGET.js b/src/api/routes/admin/fileGET.js index 9605da4..72b96f1 100644 --- a/src/api/routes/admin/fileGET.js +++ b/src/api/routes/admin/fileGET.js @@ -15,7 +15,7 @@ class filesGET extends Route { .select('id', 'username', 'enabled', 'createdAt', 'editedAt', 'apiKeyEditedAt', 'isAdmin') .where({ id: file.userId }) .first(); - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); // Additional relevant data const filesFromUser = await db.table('files').where({ userId: user.id }).select('id'); diff --git a/src/api/routes/admin/userGET.js b/src/api/routes/admin/userGET.js index 430dfd7..bf4f912 100644 --- a/src/api/routes/admin/userGET.js +++ b/src/api/routes/admin/userGET.js @@ -37,7 +37,7 @@ class usersGET extends Route { } for (let file of files) { - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); } return res.json({ diff --git a/src/api/routes/albums/albumFullGET.js b/src/api/routes/albums/albumFullGET.js index d25fe15..32c7326 100644 --- a/src/api/routes/albums/albumFullGET.js +++ b/src/api/routes/albums/albumFullGET.js @@ -43,7 +43,7 @@ class albumGET extends Route { // eslint-disable-next-line no-restricted-syntax for (let file of files) { - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); } return res.json({ diff --git a/src/api/routes/albums/albumGET.js b/src/api/routes/albums/albumGET.js index 4ac7089..e121a31 100644 --- a/src/api/routes/albums/albumGET.js +++ b/src/api/routes/albums/albumGET.js @@ -44,7 +44,7 @@ class albumGET extends Route { } for (let file of files) { - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); } // Add 1 more view to the link diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index 22b0b6f..8def099 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -38,13 +38,13 @@ 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, '../../../../uploads', '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 = `${process.env.SERVICE_NAME}-${identifier}.zip`; + const fileName = `${Util.config.serviceName}-${identifier}.zip`; return res.download(filePath, fileName); } } @@ -77,8 +77,8 @@ class albumGET extends Route { .update('zippedAt', db.fn.now()) .wasMutated(); - const filePath = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`); - const fileName = `${process.env.SERVICE_NAME}-${identifier}.zip`; + const filePath = path.join(__dirname, '../../../../uploads', 'zips', `${album.userId}-${album.id}.zip`); + const fileName = `${Util.config.serviceName}-${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 3c18d8f..98cc82e 100644 --- a/src/api/routes/albums/albumsGET.js +++ b/src/api/routes/albums/albumsGET.js @@ -37,7 +37,7 @@ class albumsGET extends Route { // Fetch thumbnails and stuff for (let file of files) { - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); } album.fileCount = fileCount[0].count; diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 42eac58..7bc8051 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -20,16 +20,6 @@ class linkPOST extends Route { .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' }) - .first(); - if (count >= parseInt(process.env.MAX_LINKS_PER_ALBUM, 10)) return res.status(400).json({ message: 'Maximum links per album reached' }); - let { identifier } = req.body; if (identifier) { if (!user.isAdmin) return res.status(401).json({ message: 'Only administrators can create custom links' }); diff --git a/src/api/routes/auth/loginPOST.js b/src/api/routes/auth/loginPOST.js index 373252b..cc72145 100644 --- a/src/api/routes/auth/loginPOST.js +++ b/src/api/routes/auth/loginPOST.js @@ -2,6 +2,7 @@ const bcrypt = require('bcrypt'); const moment = require('moment'); const JWT = require('jsonwebtoken'); const Route = require('../../structures/Route'); +const Util = require('../../utils/Util'); class loginPOST extends Route { constructor() { @@ -37,7 +38,7 @@ class loginPOST extends Route { iss: 'chibisafe', sub: user.id, iat: moment.utc().valueOf() - }, process.env.SECRET, { expiresIn: '30d' }); + }, Util.config.secret, { expiresIn: '30d' }); return res.json({ message: 'Successfully logged in.', diff --git a/src/api/routes/auth/registerPOST.js b/src/api/routes/auth/registerPOST.js index 7b9eb3c..e740c83 100644 --- a/src/api/routes/auth/registerPOST.js +++ b/src/api/routes/auth/registerPOST.js @@ -12,7 +12,7 @@ class registerPOST extends Route { async run(req, res, db) { // Only allow admins to create new accounts if the sign up is deactivated const user = await Util.isAuthorized(req); - if ((!user || !user.isAdmin) && process.env.USER_ACCOUNTS === 'false') return res.status(401).json({ message: 'Creation of new accounts is currently disabled' }); + if ((!user || !user.isAdmin) && !Util.config.userAccounts) return res.status(401).json({ message: 'Creation of new accounts is currently disabled' }); if (!req.body) return res.status(400).json({ message: 'No body provided' }); const { username, password } = req.body; diff --git a/src/api/routes/files/fileGET.js b/src/api/routes/files/fileGET.js index 9ec6f22..2e6f0b8 100644 --- a/src/api/routes/files/fileGET.js +++ b/src/api/routes/files/fileGET.js @@ -16,7 +16,7 @@ class fileGET extends Route { let file = await db.table('files').where({ id, userId: user.id }).first(); if (!file) return res.status(400).json({ message: 'The file doesn\'t exist or doesn\'t belong to the user' }); - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); /* Fetch the albums diff --git a/src/api/routes/files/filesGET.js b/src/api/routes/files/filesGET.js index 9e90633..20ccbc5 100644 --- a/src/api/routes/files/filesGET.js +++ b/src/api/routes/files/filesGET.js @@ -30,7 +30,7 @@ class filesGET extends Route { // For each file, create the public link to be able to display the file for (let file of files) { - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); } return res.json({ diff --git a/src/api/routes/search/searchGET.js b/src/api/routes/search/searchGET.js index 187fcab..3cfcfef 100644 --- a/src/api/routes/search/searchGET.js +++ b/src/api/routes/search/searchGET.js @@ -53,7 +53,7 @@ class configGET extends Route { // For each file, create the public link to be able to display the file for (let file of files) { - file = Util.constructFilePublicLink(file); + file = Util.constructFilePublicLink(req, file); } return res.json({ diff --git a/src/api/routes/service/configAllGET.js b/src/api/routes/service/configAllGET.js new file mode 100644 index 0000000..fe9dae6 --- /dev/null +++ b/src/api/routes/service/configAllGET.js @@ -0,0 +1,17 @@ +const Route = require('../../structures/Route'); +const Util = require('../../utils/Util'); + +class configGET extends Route { + constructor() { + super('/service/config/all', 'get', { adminOnly: true }); + } + + run(req, res) { + return res.json({ + message: 'Successfully retrieved config', + config: Util.config + }); + } +} + +module.exports = configGET; diff --git a/src/api/routes/service/configGET.js b/src/api/routes/service/configGET.js index bc91a7e..c8d88d3 100644 --- a/src/api/routes/service/configGET.js +++ b/src/api/routes/service/configGET.js @@ -1,24 +1,23 @@ const Route = require('../../structures/Route'); +const Util = require('../../utils/Util'); class configGET extends Route { constructor() { - super('/service/config', 'get', { adminOnly: true }); + super('/service/config', 'get', { bypassAuth: true }); } run(req, res) { return res.json({ message: 'Successfully retrieved config', config: { - serviceName: process.env.SERVICE_NAME, - uploadFolder: process.env.UPLOAD_FOLDER, - linksPerAlbum: parseInt(process.env.MAX_LINKS_PER_ALBUM, 10), - maxUploadSize: parseInt(process.env.MAX_SIZE, 10), - filenameLength: parseInt(process.env.GENERATED_FILENAME_LENGTH, 10), - albumLinkLength: parseInt(process.env.GENERATED_ALBUM_LENGTH, 10), - generateThumbnails: process.env.GENERATE_THUMBNAILS === 'true', - generateZips: process.env.GENERATE_ZIPS === 'true', - publicMode: process.env.PUBLIC_MODE === 'true', - enableAccounts: process.env.USER_ACCOUNTS === 'true' + version: process.env.npm_package_version, + serviceName: Util.config.serviceName, + maxUploadSize: Util.config.maxSize, + filenameLength: Util.config.generatedFilenameLength, + albumLinkLength: Util.config.generatedAlbumLength, + chunkSize: Util.config.chunkSize, + publicMode: Util.config.publicMode, + userAccounts: Util.config.userAccounts } }); } diff --git a/src/api/routes/service/configPOST.js b/src/api/routes/service/configPOST.js new file mode 100644 index 0000000..68af467 --- /dev/null +++ b/src/api/routes/service/configPOST.js @@ -0,0 +1,45 @@ +const Route = require('../../structures/Route'); +const Util = require('../../utils/Util'); + +const { schema } = require('../../structures/Setting'); + +const joiOptions = { + abortEarly: false, // include all errors + allowUnknown: true, // ignore unknown props + stripUnknown: true // remove unknown props +}; + +class configGET extends Route { + constructor() { + super('/service/config', 'post', { adminOnly: true }); + } + + async run(req, res) { + const { settings } = req.body; + const { error, value } = schema.validate(settings, joiOptions); + if (error) { + return res.status(400).json({ + errors: error.details.reduce((acc, v) => { + for (const p of v.path) { + acc[p] = (acc[p] || []).concat(v.message); + } + return acc; + }, {}) + }); + } + + await Util.wipeConfigDb(); + + const keys = Object.keys(value); + for await (const item of keys) { + Util.writeConfigToDb({ + key: item, + value: value[item] + }); + } + + return res.status(200).json({ value }); + } +} + +module.exports = configGET; diff --git a/src/api/routes/service/configSchemaGET.js b/src/api/routes/service/configSchemaGET.js new file mode 100644 index 0000000..90befa9 --- /dev/null +++ b/src/api/routes/service/configSchemaGET.js @@ -0,0 +1,17 @@ +const Route = require('../../structures/Route'); +const { configSchema } = require('../../structures/Setting'); + +class configGET extends Route { + constructor() { + super('/service/config/schema', 'get', { adminOnly: true }); + } + + run(req, res) { + return res.json({ + message: 'Successfully retrieved schema', + schema: configSchema + }); + } +} + +module.exports = configGET; diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index a0dba27..4e96c80 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -8,8 +8,8 @@ const multerStorage = require('../../utils/multerStorage'); const chunksData = {}; const chunkedUploadsTimeout = 1800000; -const chunksDir = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'chunks'); -const uploadDir = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER); +const chunksDir = path.join(__dirname, '../../../../uploads/chunks'); +const uploadDir = path.join(__dirname, '../../../../uploads'); const cleanUpChunks = async (uuid, onTimeout) => { @@ -72,7 +72,7 @@ const initChunks = async uuid => { const executeMulter = multer({ // Guide: https://github.com/expressjs/multer#limits limits: { - fileSize: parseInt(process.env.MAX_SIZE, 10) * (1000 * 1000), + fileSize: Util.config.maxSize * (1000 * 1000), // Maximum number of non-file fields. // Dropzone.js will add 6 extra fields for chunked uploads. // We don't use them for anything else. @@ -257,7 +257,7 @@ class uploadPOST extends Route { async run(req, res, db) { const user = await Util.isAuthorized(req); - if (!user && process.env.PUBLIC_MODE === 'false') return res.status(401).json({ message: 'Not authorized to use this resource' }); + if (!user && !Util.config.publicMode) return res.status(401).json({ message: 'Not authorized to use this resource' }); const { finishedchunks } = req.headers; const albumId = req.headers.albumid ? req.headers.albumid === 'null' ? null : req.headers.albumid : null; if (albumId && !user) return res.status(401).json({ message: 'Only registered users can upload files to an album' }); @@ -282,8 +282,8 @@ class uploadPOST extends Route { if (albumId) await Util.saveFileToAlbum(db, albumId, result.id); - result.file = Util.constructFilePublicLink(result.file); - result.deleteUrl = `${process.env.DOMAIN}/api/file/${result.id[0]}`; + result.file = Util.constructFilePublicLink(req, result.file); + result.deleteUrl = `${Util.getHost(req)}/api/file/${result.id[0]}`; return res.status(201).send({ message: 'Sucessfully uploaded the file.', |