feature/#22-API-Tokens #49

Merged
jkeffects merged 8 commits from feature/#22-API-Tokens into develop 2025-01-22 10:59:46 +00:00
10 changed files with 92 additions and 2 deletions
Showing only changes of commit 0b40b9d92c - Show all commits

View file

@ -17,7 +17,7 @@ import ForbiddenRequestException from "../exceptions/forbiddenRequestException";
* @param res {Response} Express res object * @param res {Response} Express res object
* @returns {Promise<*>} * @returns {Promise<*>}
*/ */
export async function getAccess(req: Request, res: Response): Promise<any> { export async function getWebApiAccess(req: Request, res: Response): Promise<any> {
const bearer = req.headers.authorization?.split(" ")?.[1] ?? undefined; const bearer = req.headers.authorization?.split(" ")?.[1] ?? undefined;
let { expiry } = await ApiService.getByToken(bearer); let { expiry } = await ApiService.getByToken(bearer);

View file

@ -89,6 +89,7 @@ export abstract class JWTHelper {
lastname: "", lastname: "",
isOwner: false, isOwner: false,
permissions: permissionObject, permissions: permissionObject,
sub: "webapi_access_token",
}; };
return await JWTHelper.create(jwtData) return await JWTHelper.create(jwtData)

View file

@ -13,6 +13,7 @@ declare global {
isOwner: boolean; isOwner: boolean;
permissions: PermissionObject; permissions: PermissionObject;
isPWA: boolean; isPWA: boolean;
isWebApiRequest: boolean;
} }
} }
} }

View file

@ -37,6 +37,7 @@ export default async function authenticate(req: Request, res: Response, next: Fu
req.username = decoded.username; req.username = decoded.username;
req.isOwner = decoded.isOwner; req.isOwner = decoded.isOwner;
req.permissions = decoded.permissions; req.permissions = decoded.permissions;
req.isWebApiRequest = decoded?.sub == "webapi_access_token";
next(); next();
} }

View file

@ -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();
}
}

View file

@ -21,6 +21,8 @@ import newsletter from "./club/newsletter";
import role from "./user/role"; import role from "./user/role";
import user from "./user/user"; import user from "./user/user";
import invite from "./user/invite"; import invite from "./user/invite";
import api from "./user/api";
import preventApiAccess from "../../middleware/preventWebApiAccess";
var router = express.Router({ mergeParams: true }); 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("/role", PermissionHelper.passCheckMiddleware("read", "user", "role"), role);
router.use("/user", PermissionHelper.passCheckMiddleware("read", "user", "user"), user); router.use("/user", PermissionHelper.passCheckMiddleware("read", "user", "user"), user);
router.use("/invite", PermissionHelper.passCheckMiddleware("read", "user", "user"), invite); router.use("/invite", PermissionHelper.passCheckMiddleware("read", "user", "user"), invite);
router.use("/webapi", preventApiAccess, PermissionHelper.passCheckMiddleware("read", "user", "webapi"), api);
export default router; export default router;

View file

@ -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;

10
src/routes/api.ts Normal file
View file

@ -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;

View file

@ -14,6 +14,8 @@ import auth from "./auth";
import admin from "./admin/index"; import admin from "./admin/index";
import user from "./user"; import user from "./user";
import detectPWA from "../middleware/detectPWA"; import detectPWA from "../middleware/detectPWA";
import api from "./api";
import authenticateAPI from "../middleware/authenticateAPI";
export default (app: Express) => { export default (app: Express) => {
app.set("query parser", "extended"); app.set("query parser", "extended");
@ -32,6 +34,7 @@ export default (app: Express) => {
app.use("/api/reset", reset); app.use("/api/reset", reset);
app.use("/api/invite", invite); app.use("/api/invite", invite);
app.use("/api/auth", auth); app.use("/api/auth", auth);
app.use("/api/webapi", authenticateAPI, api);
app.use(authenticate); app.use(authenticate);
app.use("/api/admin", admin); app.use("/api/admin", admin);
app.use("/api/user", user); app.use("/api/user", user);

View file

@ -14,6 +14,7 @@ export type PermissionModule =
| "calendar_type" | "calendar_type"
| "user" | "user"
| "role" | "role"
| "webapi"
| "query" | "query"
| "query_store" | "query_store"
| "template" | "template"
@ -55,6 +56,7 @@ export const permissionModules: Array<PermissionModule> = [
"calendar_type", "calendar_type",
"user", "user",
"role", "role",
"webapi",
"query", "query",
"query_store", "query_store",
"template", "template",
@ -75,5 +77,5 @@ export const sectionsAndModules: SectionsAndModulesObject = {
"template_usage", "template_usage",
"newsletter_config", "newsletter_config",
], ],
user: ["user", "role"], user: ["user", "role", "webapi"],
}; };