From 398b0ad033bca264039f8b1251735cbfdf0309bb Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 01:14:15 +0900 Subject: [PATCH 01/10] Change response body of get glueboard --- src/app/http/controllers/GlueBoardController.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/http/controllers/GlueBoardController.ts b/src/app/http/controllers/GlueBoardController.ts index 6d5fd70..4b61948 100644 --- a/src/app/http/controllers/GlueBoardController.ts +++ b/src/app/http/controllers/GlueBoardController.ts @@ -13,6 +13,7 @@ interface IndexResponseBody { name: string color: string } + sharing: boolean }> } @@ -22,6 +23,7 @@ interface GetResponseBody { name: string color: string } + sharing: boolean } export default class GlueBoardController { @@ -51,7 +53,8 @@ export default class GlueBoardController { for (const glueBoard of glueBoards) { responseBody.glueBoards.push({ id: glueBoard.id, - category: glueBoard.category + category: glueBoard.category, + sharing: glueBoard.sharing }) } @@ -143,7 +146,8 @@ export default class GlueBoardController { category: { name: glueBoard.category.name, color: glueBoard.category.color - } + }, + sharing: glueBoard.sharing } return res.status(200).json(responseBody) From ade1fec21130115ae244992e66a44e9822ccfa5e Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 01:15:44 +0900 Subject: [PATCH 02/10] Add new api endpoint: Get the url hash of shared glueboard --- src/app/http/controllers/SharingController.ts | 29 +++++++++++++++++++ src/routes/me.ts | 9 ++++++ 2 files changed, 38 insertions(+) create mode 100644 src/app/http/controllers/SharingController.ts diff --git a/src/app/http/controllers/SharingController.ts b/src/app/http/controllers/SharingController.ts new file mode 100644 index 0000000..543d42d --- /dev/null +++ b/src/app/http/controllers/SharingController.ts @@ -0,0 +1,29 @@ +import { Response, SimpleHandler } from '@/http/RequestHandler' +import { GlueBoardDoc } from '@@/migrate/schemas/glue-board' + +interface GetResponseBody { + hash: string +} + +export default class SharingController { + /** + * Get the url hash of shared GlueBoard + */ + public static get(): SimpleHandler { + return async (req, res): Promise => { + const glueBoard = res.locals.glueBoard as GlueBoardDoc + + // if sharing option is off, turn on. + if (glueBoard.sharing === false) { + glueBoard.sharing = true + await glueBoard.save() + } + + const responseBody: GetResponseBody = { + hash: glueBoard.id + } + + return res.status(200).json(responseBody) + } + } +} diff --git a/src/routes/me.ts b/src/routes/me.ts index 963c2f5..1981566 100644 --- a/src/routes/me.ts +++ b/src/routes/me.ts @@ -7,6 +7,7 @@ import GlueBoardController from '@/http/controllers/GlueBoardController' import CheckGlueBoard from '@/http/middleware/CheckGlueBoard' import FragmentController from '@/http/controllers/FragmentController' import CheckFragment from '@/http/middleware/CheckFragment' +import SharingController from '@/http/controllers/SharingController' const meRouter = express.Router({ mergeParams: true }) @@ -109,4 +110,12 @@ meRouter .delete(FragmentController.delete()) .all(Handle405Error.handler()) +/** + * GET: get the url hash of shared GlueBoard + */ +meRouter + .route('/glueboards/:glueboard/sharing') + .get(SharingController.get()) + .all(Handle405Error.handler()) + export default meRouter From dfd47b5b5ebe64475cd2f076cdcfd95782e85c9b Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 01:48:53 +0900 Subject: [PATCH 03/10] Edit glueboard update api. # Now can update sharing option --- src/app/http/controllers/GlueBoardController.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/app/http/controllers/GlueBoardController.ts b/src/app/http/controllers/GlueBoardController.ts index 4b61948..053f58f 100644 --- a/src/app/http/controllers/GlueBoardController.ts +++ b/src/app/http/controllers/GlueBoardController.ts @@ -202,6 +202,12 @@ export default class GlueBoardController { }, errorMessage: '`color` must be a hex color.' }, + sharing: { + optional: true, + in: 'body', + isBoolean: true, + errorMessage: '`sharing` must be a boolean.' + }, position: { optional: true, in: 'body', @@ -241,6 +247,11 @@ export default class GlueBoardController { glueBoard.category.color = req.body.color } + // update sharing option + if (req.body.sharing !== undefined) { + glueBoard.sharing = req.body.sharing + } + await glueBoard.save() // update relative position in the GlueBoard list From 04bed9b086401f49352f48439d8cbe4bf3dde0ec Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 01:50:39 +0900 Subject: [PATCH 04/10] Edit GlueBoard sharing api. # When sharing option is off, now reject the request --- src/app/http/controllers/SharingController.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/app/http/controllers/SharingController.ts b/src/app/http/controllers/SharingController.ts index 543d42d..6421e11 100644 --- a/src/app/http/controllers/SharingController.ts +++ b/src/app/http/controllers/SharingController.ts @@ -10,13 +10,16 @@ export default class SharingController { * Get the url hash of shared GlueBoard */ public static get(): SimpleHandler { - return async (req, res): Promise => { + return (req, res): Response => { const glueBoard = res.locals.glueBoard as GlueBoardDoc - // if sharing option is off, turn on. + // if sharing option is off, reject this request. if (glueBoard.sharing === false) { - glueBoard.sharing = true - await glueBoard.save() + return res.status(403).json({ + err: { + msg: 'Sharing option for this GlueBoard is off.' + } + }) } const responseBody: GetResponseBody = { From a7066d32fe094bd58fd2639a075c4473e2aefca6 Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 02:59:55 +0900 Subject: [PATCH 05/10] Change method name: `get` => `getHash` --- src/app/http/controllers/SharingController.ts | 6 +++--- src/routes/me.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/http/controllers/SharingController.ts b/src/app/http/controllers/SharingController.ts index 6421e11..3bdaffc 100644 --- a/src/app/http/controllers/SharingController.ts +++ b/src/app/http/controllers/SharingController.ts @@ -1,7 +1,7 @@ import { Response, SimpleHandler } from '@/http/RequestHandler' import { GlueBoardDoc } from '@@/migrate/schemas/glue-board' -interface GetResponseBody { +interface GetHashResponseBody { hash: string } @@ -9,7 +9,7 @@ export default class SharingController { /** * Get the url hash of shared GlueBoard */ - public static get(): SimpleHandler { + public static getHash(): SimpleHandler { return (req, res): Response => { const glueBoard = res.locals.glueBoard as GlueBoardDoc @@ -22,7 +22,7 @@ export default class SharingController { }) } - const responseBody: GetResponseBody = { + const responseBody: GetHashResponseBody = { hash: glueBoard.id } diff --git a/src/routes/me.ts b/src/routes/me.ts index 1981566..484e9df 100644 --- a/src/routes/me.ts +++ b/src/routes/me.ts @@ -115,7 +115,7 @@ meRouter */ meRouter .route('/glueboards/:glueboard/sharing') - .get(SharingController.get()) + .get(SharingController.getHash()) .all(Handle405Error.handler()) export default meRouter From 33ae784b72614c3d9906d89f1d336dd04d759c8e Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 03:01:53 +0900 Subject: [PATCH 06/10] Create new middleware for check sharing request. # Check whether if the GlueBoard is exist # Check whether if hte GlueBoard is shared --- src/app/http/middleware/CheckSharing.ts | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/app/http/middleware/CheckSharing.ts diff --git a/src/app/http/middleware/CheckSharing.ts b/src/app/http/middleware/CheckSharing.ts new file mode 100644 index 0000000..d73f15f --- /dev/null +++ b/src/app/http/middleware/CheckSharing.ts @@ -0,0 +1,34 @@ +import { Response, NextHandler } from '@/http/RequestHandler' +import GlueBoard from '@@/migrate/models/glue-board' +import { GlueBoardDoc } from '@@/migrate/schemas/glue-board' + +export default class CheckSharing { + public static handler(): NextHandler { + return async (req, res, next): Promise => { + const glueBoardID = req.params.glueboard + const glueBoard = (await GlueBoard.findOne({ + id: glueBoardID + })) as GlueBoardDoc + + if (!glueBoard) { + return res.status(404).json({ + err: { + msg: 'Glueboard not found.' + } + }) + } + + if (!glueBoard.sharing) { + return res.status(403).json({ + err: { + msg: 'Unshared GlueBoard.' + } + }) + } + + res.locals.glueBoard = glueBoard + + return next() + } + } +} From 3154a44ef44234fcb393c87d0c534bd7b04142e9 Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 03:03:37 +0900 Subject: [PATCH 07/10] Use check sharing middleware in the endpoints --- src/routes/api.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/routes/api.ts b/src/routes/api.ts index e346cd3..baf5881 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -2,12 +2,27 @@ import express from 'express' import oauth2Router from '@@/routes/oauth2' import meRouter from '@@/routes/me' import mirroringRouter from '@@/routes/mirroring' +import CheckGlueBoard from '@/http/middleware/CheckGlueBoard' +import RequestValidationError from '@/http/middleware/RequestValidationError' +import CheckSharing from '@/http/middleware/CheckSharing' const mainRouter = express.Router() +/** + * Middleware + */ + +mainRouter.use( + '/sharing/:glueboard', + CheckGlueBoard.validate(), + RequestValidationError.handler(), + CheckSharing.handler() +) + /** * Sub router */ + mainRouter.use('/oauth2', oauth2Router) mainRouter.use('/me', meRouter) mainRouter.use('/mirroring', mirroringRouter) From 42e1f9adcee811df4411012ef079c5de8c97cf2b Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 03:05:14 +0900 Subject: [PATCH 08/10] Add new api endpoint for sharing: Access to the shared GlueBoard --- src/app/http/controllers/SharingController.ts | 54 +++++++++++++++++++ src/routes/api.ts | 14 +++++ 2 files changed, 68 insertions(+) diff --git a/src/app/http/controllers/SharingController.ts b/src/app/http/controllers/SharingController.ts index 3bdaffc..5af8c1a 100644 --- a/src/app/http/controllers/SharingController.ts +++ b/src/app/http/controllers/SharingController.ts @@ -1,10 +1,26 @@ import { Response, SimpleHandler } from '@/http/RequestHandler' import { GlueBoardDoc } from '@@/migrate/schemas/glue-board' +import GlueBoard from '@@/migrate/models/glue-board' +import { FragmentDoc } from '@@/migrate/schemas/fragment' interface GetHashResponseBody { hash: string } +interface GetResponseBody { + category: { + name: string + color: string + } + fragments: Array<{ + url: string + selector: string + xPos: number + yPos: number + scale: number + }> +} + export default class SharingController { /** * Get the url hash of shared GlueBoard @@ -29,4 +45,42 @@ export default class SharingController { return res.status(200).json(responseBody) } } + + /** + * Access to the shared GlueBoard + */ + public static get(): SimpleHandler { + return async (req, res): Promise => { + const glueBoard = (await GlueBoard.findById(res.locals.glueBoard._id, { + category: 1, + fragments: 1 + }) + .lean() + .populate({ + path: 'fragments', + select: '-_id -id' + })) as GlueBoardDoc + + const responseBody: GetResponseBody = { + category: { + name: glueBoard.category.name, + color: glueBoard.category.color + }, + fragments: [] + } + + // compose response body + for (const fragment of glueBoard.fragments as FragmentDoc[]) { + responseBody.fragments.push({ + url: fragment.url, + selector: fragment.selector, + xPos: fragment.xPos, + yPos: fragment.yPos, + scale: fragment.scale + }) + } + + return res.status(200).json(responseBody) + } + } } diff --git a/src/routes/api.ts b/src/routes/api.ts index baf5881..5b056ea 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -5,6 +5,8 @@ import mirroringRouter from '@@/routes/mirroring' import CheckGlueBoard from '@/http/middleware/CheckGlueBoard' import RequestValidationError from '@/http/middleware/RequestValidationError' import CheckSharing from '@/http/middleware/CheckSharing' +import SharingController from '@/http/controllers/SharingController' +import Handle405Error from '@/http/middleware/Handle405Error' const mainRouter = express.Router() @@ -27,4 +29,16 @@ mainRouter.use('/oauth2', oauth2Router) mainRouter.use('/me', meRouter) mainRouter.use('/mirroring', mirroringRouter) +/** + * Controller + */ + +/** + * GET: access to the shared GlueBoard + */ +mainRouter + .route('/sharing/:glueboard') + .get(SharingController.get()) + .all(Handle405Error.handler()) + export default mainRouter From 728565468e43252ad1d4b8cb51447d97d697bd85 Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 03:11:07 +0900 Subject: [PATCH 09/10] Change request parameter name: `glueboard` -> `hash` --- src/app/http/middleware/CheckSharing.ts | 15 ++++++++++++++- src/routes/api.ts | 7 +++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/app/http/middleware/CheckSharing.ts b/src/app/http/middleware/CheckSharing.ts index d73f15f..a5f0265 100644 --- a/src/app/http/middleware/CheckSharing.ts +++ b/src/app/http/middleware/CheckSharing.ts @@ -1,11 +1,24 @@ import { Response, NextHandler } from '@/http/RequestHandler' import GlueBoard from '@@/migrate/models/glue-board' import { GlueBoardDoc } from '@@/migrate/schemas/glue-board' +import { checkSchema, ValidationChain } from 'express-validator' export default class CheckSharing { + public static validate(): ValidationChain[] { + return checkSchema({ + hash: { + exists: true, + in: 'params', + isString: true, + trim: true, + errorMessage: '`hash` must be a string.' + } + }) + } + public static handler(): NextHandler { return async (req, res, next): Promise => { - const glueBoardID = req.params.glueboard + const glueBoardID = req.params.hash const glueBoard = (await GlueBoard.findOne({ id: glueBoardID })) as GlueBoardDoc diff --git a/src/routes/api.ts b/src/routes/api.ts index 5b056ea..e41dff6 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -2,7 +2,6 @@ import express from 'express' import oauth2Router from '@@/routes/oauth2' import meRouter from '@@/routes/me' import mirroringRouter from '@@/routes/mirroring' -import CheckGlueBoard from '@/http/middleware/CheckGlueBoard' import RequestValidationError from '@/http/middleware/RequestValidationError' import CheckSharing from '@/http/middleware/CheckSharing' import SharingController from '@/http/controllers/SharingController' @@ -15,8 +14,8 @@ const mainRouter = express.Router() */ mainRouter.use( - '/sharing/:glueboard', - CheckGlueBoard.validate(), + '/sharing/:hash', + CheckSharing.validate(), RequestValidationError.handler(), CheckSharing.handler() ) @@ -37,7 +36,7 @@ mainRouter.use('/mirroring', mirroringRouter) * GET: access to the shared GlueBoard */ mainRouter - .route('/sharing/:glueboard') + .route('/sharing/:hash') .get(SharingController.get()) .all(Handle405Error.handler()) From ae8b547cb7a7f4130e220dbc0fa7a42008582db6 Mon Sep 17 00:00:00 2001 From: ihooni Date: Sat, 16 Nov 2019 03:20:12 +0900 Subject: [PATCH 10/10] chore: Edit comments --- src/app/http/controllers/SharingController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/http/controllers/SharingController.ts b/src/app/http/controllers/SharingController.ts index 5af8c1a..2eb5b4c 100644 --- a/src/app/http/controllers/SharingController.ts +++ b/src/app/http/controllers/SharingController.ts @@ -23,7 +23,7 @@ interface GetResponseBody { export default class SharingController { /** - * Get the url hash of shared GlueBoard + * Get the url hash of the shared GlueBoard */ public static getHash(): SimpleHandler { return (req, res): Response => {