Admin auth (#4101)

* added admin auth

* always decoding token
This commit is contained in:
Jack 2023-03-24 12:17:27 +01:00 committed by GitHub
parent 03d42cef33
commit 317f5b23ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 1 deletions

View File

@ -0,0 +1,5 @@
import { MonkeyResponse } from "../../utils/monkey-response";
export async function test(): Promise<MonkeyResponse> {
return new MonkeyResponse("OK");
}

View File

@ -0,0 +1,18 @@
// import joi from "joi";
import { Router } from "express";
import { authenticateRequest } from "../../middlewares/auth";
import { asyncHandler, checkIfUserIsAdmin } from "../../middlewares/api-utils";
import * as AdminController from "../controllers/admin";
const router = Router();
router.get(
"/",
authenticateRequest({
noCache: true,
}),
checkIfUserIsAdmin(),
asyncHandler(AdminController.test)
);
export default router;

View File

@ -8,6 +8,7 @@ import configs from "./configs";
import results from "./results";
import presets from "./presets";
import apeKeys from "./ape-keys";
import admin from "./admin";
import configuration from "./configuration";
import { version } from "../../version";
import leaderboards from "./leaderboards";
@ -37,6 +38,7 @@ const API_ROUTE_MAP = {
"/leaderboards": leaderboards,
"/quotes": quotes,
"/ape-keys": apeKeys,
"/admin": admin,
};
function addApiRoutes(app: Application): void {

View File

@ -0,0 +1,10 @@
import * as db from "../init/db";
export async function isAdmin(uid: string): Promise<boolean> {
const doc = await db.collection("admin-uids").findOne({ uid });
if (doc) {
return true;
} else {
return false;
}
}

View File

@ -4,6 +4,7 @@ import MonkeyError from "../utils/error";
import { Response, NextFunction, RequestHandler } from "express";
import { handleMonkeyResponse, MonkeyResponse } from "../utils/monkey-response";
import { getUser } from "../dal/user";
import { isAdmin } from "../dal/admin-uids";
interface ValidationOptions<T> {
criteria: (data: T) => boolean;
@ -40,6 +41,31 @@ function validateConfiguration(
};
}
/**
* Check if the user is an admin before handling request.
* Note that this middleware must be used after authentication in the middleware stack.
*/
function checkIfUserIsAdmin(): RequestHandler {
return async (
req: MonkeyTypes.Request,
_res: Response,
next: NextFunction
) => {
try {
const { uid } = req.ctx.decodedToken;
const admin = await isAdmin(uid);
if (!admin) {
throw new MonkeyError(403, "You don't have permission to do this.");
}
} catch (error) {
next(error);
}
next();
};
}
/**
* Check user permissions before handling request.
* Note that this middleware must be used after authentication in the middleware stack.
@ -158,6 +184,7 @@ function useInProduction(middlewares: RequestHandler[]): RequestHandler[] {
export {
validateConfiguration,
checkUserPermissions,
checkIfUserIsAdmin,
asyncHandler,
validateRequest,
useInProduction,

View File

@ -17,6 +17,7 @@ interface RequestAuthenticationOptions {
isPublic?: boolean;
acceptApeKeys?: boolean;
requireFreshToken?: boolean;
noCache?: boolean;
}
const DEFAULT_OPTIONS: RequestAuthenticationOptions = {
@ -149,7 +150,10 @@ async function authenticateWithBearerToken(
options: RequestAuthenticationOptions
): Promise<MonkeyTypes.DecodedToken> {
try {
const decodedToken = await verifyIdToken(token, options.requireFreshToken);
const decodedToken = await verifyIdToken(
token,
options.requireFreshToken || options.noCache
);
if (options.requireFreshToken) {
const now = Date.now();