From e16c429aa6d3ae86c0dd174dce3d560491d25f14 Mon Sep 17 00:00:00 2001 From: WubzyGD Date: Tue, 2 May 2023 03:58:54 -0400 Subject: [PATCH] start edits --- .idea/modules.xml | 1 + .idea/natsuki-api.iml | 1 + api/ani/v1/routes/series/add.js | 14 ++++++---- api/ani/v1/routes/series/edits.js | 46 +++++++++++++++++++++++++++++++ api/ani/v1/routes/series/queue.js | 7 +++++ api/util/auth/authorize.js | 3 +- api/util/startup/cache/series.js | 2 ++ 7 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 api/ani/v1/routes/series/edits.js create mode 100644 api/ani/v1/routes/series/queue.js diff --git a/.idea/modules.xml b/.idea/modules.xml index 9f580c9..a708547 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,6 +3,7 @@ + \ No newline at end of file diff --git a/.idea/natsuki-api.iml b/.idea/natsuki-api.iml index 0c8867d..0cc0458 100644 --- a/.idea/natsuki-api.iml +++ b/.idea/natsuki-api.iml @@ -8,5 +8,6 @@ + \ No newline at end of file diff --git a/api/ani/v1/routes/series/add.js b/api/ani/v1/routes/series/add.js index f54a8f8..a723893 100644 --- a/api/ani/v1/routes/series/add.js +++ b/api/ani/v1/routes/series/add.js @@ -28,7 +28,7 @@ module.exports = (app, router) => { || !req.body.name || !req.body.romaji || !req.params.id || !req.authenticatedUser || !req.authenticatedUser.id || !req.body.name.match(/^[\w_\- ]+$/gm) || req.body.name.length > 150 || req.body.romaji.length > 150 - || !req.params.id.match(/^[\w_\-]+$/gm) || req.params.id.length > 25 + || !req.params.id.match(/^(?=.*[a-zA-Z])[\w\-]+$/gm) || req.params.id.length > 25 ) {return res.status(400).send("The server cannot accept your request as your body is missing fields or is malformed. Ensure fields aren't too long and that they don't contain illegal characters.");} let series = new Anime({ @@ -97,17 +97,21 @@ module.exports = (app, router) => { tags: series.tags }; app.cache.seriesCount++; + if (series.meta.submitted) {app.cache.seriesQueue.push({id: series.id, submitter: series.submitted});} return res.send(`Your series was successfully ${series.meta.submitted ? 'submitted' : "added"}.`); }).catch((e) => {console.error(e); res.status(500).send("There was an error trying to process your request. It's likely that our database found something wrong with your body fields, and the server didn't realize. Check your request and try again.");}); //TODO remove console error }) - .get(app.auth.tokenPass, app.auth.permsPass('series-approve'), async (req, res) => { - const series = await Anime.findOne({id: req.params.id}); - if (!series || (series && !series.meta.completed && req.unauthorized)) {return res.status(400).send("A series with that ID doesn't exist!");} + .get(app.auth.tokenPass, app.auth.permsPass('series-approve'), async (req, res, next) => { + const series = await Anime.findOne({$or: [{id: req.params.id.toLowerCase()}, {numericalId: req.params.id}]}); //TODO make sure all ID calls are lowercased + if (!series || (series && !series.meta.completed && req.unauthorized)) { + if (req.params.id.toLowerCase() === 'queue') {return next();} + return res.status(400).send("A series with that ID doesn't exist!"); + } let {name, id, romaji, kanji, air, rating, likes, seasons, characters, altNames, genres, tags, nsfw, nsfwReason, synopsis, numericalId, completed, publishers, studios} = series; return res.json({ name, id, romaji, kanji, air, rating, likes, seasons, characters, altNames, genres, tags, nsfw, nsfwReason, synopsis, numericalId, completed, publishers, studios, meta: {completed: series.meta.completed, creator: series.meta.creator, locked: series.meta.locked} }); }); -}; \ No newline at end of file +}; //TODO check that series can be submitted but not completed. consider making this not allowed, or figure out what to do about the fact that editing all the fields is a complete pain \ No newline at end of file diff --git a/api/ani/v1/routes/series/edits.js b/api/ani/v1/routes/series/edits.js new file mode 100644 index 0000000..d8b9801 --- /dev/null +++ b/api/ani/v1/routes/series/edits.js @@ -0,0 +1,46 @@ +module.exports = (app, router) => { + const Anime = app.db.models.ani.series; + + const editCheck = (series, req, res) => { + if (!series) {res.status(400).send("A series with that ID doesn't exist!"); return 0;} + if (series.meta.locked) {res.status(401).send("This series has been locked. Nobody can edit it unless it has been unlocked. Please contact API admin to have it unlocked if you believe there is erroneous information."); return 0;} + if (series.meta.approved && !series.meta.locked && req.unauthorized) {res.status(401).send("This series has been approved, so you must have series approval permissions in order to do that."); return 0;} + if (series.meta.creator !== req.authenticatedUser && req.unauthorized) {res.status(401).send("You must have series approval permissions or be the series' creator to do that !"); return 0;} + if (!req.authenticatedUser || !req.authenticatedUser.id) {res.status(401).send("You are not authorized to do that!"); return 0;} + return true; + } + + router.route('/:id/synopsis') //completed i think? + .patch(app.auth.token, app.auth.perms('series-submit'), async (req, res, next) => { + const series = await Anime.findOne({id: req.params.id.toLowerCase()}); + if (!editCheck(series, req, res)) {return;} + if (!req.body.synopsis) {return res.status(400).send("You did not provide a new synopsis in your body.");} + if (req.body.synopsis.length > 1000) {return res.status(400).send("Your new synopsis is too long!");} + try { + series.synopsis.synopsis = req.body.synopsis; + if (!series.synopsis.by) {series.synopsis.by = req.authenticatedUser.id;} + if (req.body.updateAuthor === true && series.synopsis.by !== req.authenticatedUser.id) {series.synopsis.by = req.authenticatedUser.id;} + } + catch {return res.status(500).send("There was an error trying to update your synopsis. Please try again.");} + series.meta.edits.push({ + user: req.authenticatedUser.id, + timestamp: new Date().getTime(), + action: "Updated synopsis" + }); + series.markModified('synopsis.synopsis'); + series.markModified('meta.edits'); + return series.save() + .then(() => res.send("Synopsis updated.")) + .catch(() => res.status(500).send("There was an error trying to update your synopsis. Please try again.")); + }) + .get(app.auth.tokenPass, app.auth.permsPass('series-approve'), async (req, res) => { //working + const series = await Anime.findOne({id: req.params.id.toLowerCase()}); + if (!series || (series && !series.meta.completed && req.unauthorized)) {return res.status(400).send("A series with that ID doesn't exist!");} + return res.send({synopsis: series.synopsis.synopsis, by: series.synopsis.by}); + }); + + //router.route() + + router.use('/:id/altnames', app.auth.tokenPass, app.auth.permsPass('series-approve')) + +}; \ No newline at end of file diff --git a/api/ani/v1/routes/series/queue.js b/api/ani/v1/routes/series/queue.js new file mode 100644 index 0000000..e674066 --- /dev/null +++ b/api/ani/v1/routes/series/queue.js @@ -0,0 +1,7 @@ +module.exports = (app, router) => { + router.use('/queue', app.auth.token, app.auth.perms('series-approve'), + (req, res, next) => {req.listData = app.cache.seriesQueue; next();}, + app.util.list(router, '/queue') + ); + //i dont know why i made a whole file for this but oh well here we are +}; \ No newline at end of file diff --git a/api/util/auth/authorize.js b/api/util/auth/authorize.js index 5a37eec..98d13e5 100644 --- a/api/util/auth/authorize.js +++ b/api/util/auth/authorize.js @@ -2,7 +2,8 @@ module.exports = (app, passAuth) => { return requiredPermissions => { if (!Array.isArray(requiredPermissions)) {requiredPermissions = [requiredPermissions];} return (req, res, next) => { - if (!req.authenticatedUser) {return next();} + if (!req.authenticatedUser && passAuth) {return next();} + if (!req.authenticatedUser) {return res.status(401).send("You are not authenticated!");} if (req.authenticatedUser.permissions.includes("admin")) {return next();} else { let hasAllPerms = true; diff --git a/api/util/startup/cache/series.js b/api/util/startup/cache/series.js index 3e8e002..d09dbdc 100644 --- a/api/util/startup/cache/series.js +++ b/api/util/startup/cache/series.js @@ -12,6 +12,8 @@ module.exports = async (app, spinner) => { let {id, name, romaji, kanji, altNames, genres, tags} = series; app.cache.series[series.id] = {id, name, romaji, kanji, altNames, genres, tags}; //keep an in-memory index of series' searchable items app.cache.series[series.id].synopsis = series.synopsis.synopsis; + app.cache.seriesQueue = []; + if (series.meta.submitted) {app.cache.seriesQueue.push({id: series.id, submitter: series.meta.submitted});} spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`ani DB series.`)}`}); app.cache.seriesCount++; amount++;