diff --git a/src/controller/apiController.ts b/src/controller/apiController.ts index 7b9bc82..bb49a8c 100644 --- a/src/controller/apiController.ts +++ b/src/controller/apiController.ts @@ -17,7 +17,7 @@ import ForbiddenRequestException from "../exceptions/forbiddenRequestException"; * @param res {Response} Express res object * @returns {Promise<*>} */ -export async function getAccess(req: Request, res: Response): Promise { +export async function getWebApiAccess(req: Request, res: Response): Promise { const bearer = req.headers.authorization?.split(" ")?.[1] ?? undefined; let { expiry } = await ApiService.getByToken(bearer); diff --git a/src/helpers/jwtHelper.ts b/src/helpers/jwtHelper.ts index 1be67c4..66beaab 100644 --- a/src/helpers/jwtHelper.ts +++ b/src/helpers/jwtHelper.ts @@ -89,6 +89,7 @@ export abstract class JWTHelper { lastname: "", isOwner: false, permissions: permissionObject, + sub: "webapi_access_token", }; return await JWTHelper.create(jwtData) diff --git a/src/index.ts b/src/index.ts index f5a73e6..68eef4f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,7 @@ declare global { isOwner: boolean; permissions: PermissionObject; isPWA: boolean; + isWebApiRequest: boolean; } } } diff --git a/src/middleware/authenticate.ts b/src/middleware/authenticate.ts index 1b59362..9e62bb4 100644 --- a/src/middleware/authenticate.ts +++ b/src/middleware/authenticate.ts @@ -37,6 +37,7 @@ export default async function authenticate(req: Request, res: Response, next: Fu req.username = decoded.username; req.isOwner = decoded.isOwner; req.permissions = decoded.permissions; + req.isWebApiRequest = decoded?.sub == "webapi_access_token"; next(); } diff --git a/src/middleware/preventWebApiAccess.ts b/src/middleware/preventWebApiAccess.ts new file mode 100644 index 0000000..a7b10a5 --- /dev/null +++ b/src/middleware/preventWebApiAccess.ts @@ -0,0 +1,10 @@ +import { Request, Response } from "express"; +import ForbiddenRequestException from "../exceptions/forbiddenRequestException"; + +export default async function preventApiAccess(req: Request, res: Response, next: Function) { + if (req.isWebApiRequest) { + throw new ForbiddenRequestException("This route cannot be accessed via webapi"); + } else { + next(); + } +} diff --git a/src/routes/admin/index.ts b/src/routes/admin/index.ts index cd7c935..3662de9 100644 --- a/src/routes/admin/index.ts +++ b/src/routes/admin/index.ts @@ -21,6 +21,8 @@ import newsletter from "./club/newsletter"; import role from "./user/role"; import user from "./user/user"; import invite from "./user/invite"; +import api from "./user/api"; +import preventApiAccess from "../../middleware/preventWebApiAccess"; var router = express.Router({ mergeParams: true }); @@ -60,5 +62,6 @@ router.use("/newsletter", PermissionHelper.passCheckMiddleware("read", "club", " router.use("/role", PermissionHelper.passCheckMiddleware("read", "user", "role"), role); router.use("/user", PermissionHelper.passCheckMiddleware("read", "user", "user"), user); router.use("/invite", PermissionHelper.passCheckMiddleware("read", "user", "user"), invite); +router.use("/webapi", preventApiAccess, PermissionHelper.passCheckMiddleware("read", "user", "webapi"), api); export default router; diff --git a/src/routes/admin/user/api.ts b/src/routes/admin/user/api.ts new file mode 100644 index 0000000..c5b3089 --- /dev/null +++ b/src/routes/admin/user/api.ts @@ -0,0 +1,59 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; +import { + createApi, + deleteApi, + getAllApis, + getApiById, + getApiPermissions, + updateApi, + updateApiPermissions, +} from "../../../controller/admin/user/apiController"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + await getAllApis(req, res); +}); + +router.get("/:id", async (req: Request, res: Response) => { + await getApiById(req, res); +}); + +router.get("/:id/permissions", async (req: Request, res: Response) => { + await getApiPermissions(req, res); +}); + +router.post( + "/", + PermissionHelper.passCheckMiddleware("create", "user", "webapi"), + async (req: Request, res: Response) => { + await createApi(req, res); + } +); + +router.patch( + "/:id", + PermissionHelper.passCheckMiddleware("update", "user", "webapi"), + async (req: Request, res: Response) => { + await updateApi(req, res); + } +); + +router.patch( + "/:id/permissions", + PermissionHelper.passCheckMiddleware("admin", "user", "webapi"), + async (req: Request, res: Response) => { + await updateApiPermissions(req, res); + } +); + +router.delete( + "/:id", + PermissionHelper.passCheckMiddleware("delete", "user", "webapi"), + async (req: Request, res: Response) => { + await deleteApi(req, res); + } +); + +export default router; diff --git a/src/routes/api.ts b/src/routes/api.ts new file mode 100644 index 0000000..0ded862 --- /dev/null +++ b/src/routes/api.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import { getWebApiAccess } from "../controller/apiController"; + +var router = express.Router({ mergeParams: true }); + +router.get("/retrieve", async (req: Request, res: Response) => { + await getWebApiAccess(req, res); +}); + +export default router; diff --git a/src/routes/index.ts b/src/routes/index.ts index b939d52..06a1063 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -14,6 +14,8 @@ import auth from "./auth"; import admin from "./admin/index"; import user from "./user"; import detectPWA from "../middleware/detectPWA"; +import api from "./api"; +import authenticateAPI from "../middleware/authenticateAPI"; export default (app: Express) => { app.set("query parser", "extended"); @@ -32,6 +34,7 @@ export default (app: Express) => { app.use("/api/reset", reset); app.use("/api/invite", invite); app.use("/api/auth", auth); + app.use("/api/webapi", authenticateAPI, api); app.use(authenticate); app.use("/api/admin", admin); app.use("/api/user", user); diff --git a/src/type/permissionTypes.ts b/src/type/permissionTypes.ts index 95ea543..5ba5cb4 100644 --- a/src/type/permissionTypes.ts +++ b/src/type/permissionTypes.ts @@ -14,6 +14,7 @@ export type PermissionModule = | "calendar_type" | "user" | "role" + | "webapi" | "query" | "query_store" | "template" @@ -55,6 +56,7 @@ export const permissionModules: Array = [ "calendar_type", "user", "role", + "webapi", "query", "query_store", "template", @@ -75,5 +77,5 @@ export const sectionsAndModules: SectionsAndModulesObject = { "template_usage", "newsletter_config", ], - user: ["user", "role"], + user: ["user", "role", "webapi"], };