From 6e3e2426c8907d5e27eda2d341a2b23dc753936b Mon Sep 17 00:00:00 2001 From: monoid Date: Sun, 10 Jan 2021 18:29:49 +0900 Subject: [PATCH] add content permission --- src/permission/permission.ts | 59 ++++++++++++++++++++++++++++++++++++ src/route/contents.ts | 21 +++++++------ 2 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 src/permission/permission.ts diff --git a/src/permission/permission.ts b/src/permission/permission.ts new file mode 100644 index 0000000..b7d5e71 --- /dev/null +++ b/src/permission/permission.ts @@ -0,0 +1,59 @@ +import Koa from 'koa'; +import { UserState } from '../login'; +import { sendError } from '../route/error_handler'; + + +export enum Permission{ + //======== + //not implemented + //admin only + /** remove document */ + //removeContent = 'removeContent', + + /** upload document */ + //uploadContent = 'uploadContent', + + /** modify document except base path, filename, content_hash. but admin can modify all. */ + //modifyContent = 'modifyContent', + + /** add tag into document */ + //addTagContent = 'addTagContent', + /** remove tag from document */ + //removeTagContent = 'removeTagContent', + /** ModifyTagInDoc */ + ModifyTag = 'ModifyTag', + + /** find documents with query */ + //findAllContent = 'findAllContent', + /** find one document. */ + //findOneContent = 'findOneContent', + /** view content*/ + //viewContent = 'viewContent', + QueryContent = 'QueryContent', + + /** modify description about the one tag. */ + modifyTagDesc = 'ModifyTagDesc', +} + +export const createPermissionCheckMiddleware = (...permissions:string[]) => async (ctx: Koa.ParameterizedContext,next:Koa.Next)=>{ + const user = ctx.state['user']; + if(user === undefined){ + return sendError(401,"you are guest. login needed."); + } + if(user.username === "admin"){ + return await next(); + } + const user_permission = user.permission; + //if permissions is not subset of user permission + if(!permissions.map(p=>user_permission.includes(p)).every(x=>x)){ + return sendError(403,"do not have permission"); + } + await next(); +} +export const AdminOnlyMiddleware = async (ctx: Koa.ParameterizedContext,next:Koa.Next)=>{ + const user = ctx.state['user']; + if(user === undefined || user.username !== "admin"){ + return sendError(403,"admin only"); + } + await next(); +} \ No newline at end of file diff --git a/src/route/contents.ts b/src/route/contents.ts index a135bda..e1f5459 100644 --- a/src/route/contents.ts +++ b/src/route/contents.ts @@ -7,6 +7,7 @@ import {sendError} from './error_handler'; import { createContentReferrer } from '../content/mod'; import { join } from 'path'; import {AllContentRouter} from './all'; +import {createPermissionCheckMiddleware as PerCheck, Permission as Per, AdminOnlyMiddleware as AdminOnly} from '../permission/permission'; const ContentIDHandler = (controller: ContentAccessor) => async (ctx: Context,next: Next)=>{ const num = Number.parseInt(ctx.params['num']); @@ -128,17 +129,17 @@ const ContentHandler = (controller : ContentAccessor) => async (ctx:Context, nex export const getContentRouter = (controller: ContentAccessor)=>{ const ret = new Router(); - ret.get("/search",ContentQueryHandler(controller)); - ret.get("/:num(\\d+)",ContentIDHandler(controller)); - ret.post("/:num(\\d+)",UpdateContentHandler(controller)); + ret.get("/search",PerCheck(Per.QueryContent),ContentQueryHandler(controller)); + ret.get("/:num(\\d+)",PerCheck(Per.QueryContent),ContentIDHandler(controller)); + ret.post("/:num(\\d+)",AdminOnly,UpdateContentHandler(controller)); //ret.use("/:num(\\d+)/:content_type"); - ret.post("/",CreateContentHandler(controller)); - ret.get("/:num(\\d+)/tags",ContentTagIDHandler(controller)); - ret.post("/:num(\\d+)/tags/:tag",AddTagHandler(controller)); - ret.del("/:num(\\d+)/tags/:tag",DelTagHandler(controller)); - ret.del("/:num(\\d+)",DeleteContentHandler(controller)); - ret.all("/:num(\\d+)/(.*)",ContentHandler(controller)); - ret.use("/:num",(new AllContentRouter).routes()); + ret.post("/",AdminOnly,CreateContentHandler(controller)); + ret.get("/:num(\\d+)/tags",PerCheck(Per.QueryContent),ContentTagIDHandler(controller)); + ret.post("/:num(\\d+)/tags/:tag",PerCheck(Per.ModifyTag),AddTagHandler(controller)); + ret.del("/:num(\\d+)/tags/:tag",PerCheck(Per.ModifyTag),DelTagHandler(controller)); + ret.del("/:num(\\d+)",AdminOnly,DeleteContentHandler(controller)); + ret.all("/:num(\\d+)/(.*)",PerCheck(Per.QueryContent),ContentHandler(controller)); + ret.use("/:num",PerCheck(Per.QueryContent),(new AllContentRouter).routes()); return ret; }