Refactor required route role

This commit is contained in:
Tom Moor
2024-04-06 21:43:15 -04:00
parent 79899d051c
commit b458bb3af9
8 changed files with 37 additions and 40 deletions

View File

@@ -1,6 +1,7 @@
import Router from "koa-router";
import compact from "lodash/compact";
import isEmpty from "lodash/isEmpty";
import { UserRole } from "@shared/types";
import auth from "@server/middlewares/authentication";
import validate from "@server/middlewares/validate";
import { WebhookSubscription, Event } from "@server/models";
@@ -14,7 +15,7 @@ const router = new Router();
router.post(
"webhookSubscriptions.list",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
pagination(),
async (ctx: APIContext) => {
const { user } = ctx.state.auth;
@@ -37,7 +38,7 @@ router.post(
router.post(
"webhookSubscriptions.create",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.WebhookSubscriptionsCreateSchema),
async (ctx: APIContext<T.WebhookSubscriptionsCreateReq>) => {
const { user } = ctx.state.auth;
@@ -78,7 +79,7 @@ router.post(
router.post(
"webhookSubscriptions.delete",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.WebhookSubscriptionsDeleteSchema),
async (ctx: APIContext<T.WebhookSubscriptionsDeleteReq>) => {
const { id } = ctx.input.body;
@@ -111,7 +112,7 @@ router.post(
router.post(
"webhookSubscriptions.update",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.WebhookSubscriptionsUpdateSchema),
async (ctx: APIContext<T.WebhookSubscriptionsUpdateReq>) => {
const { id, name, url, secret } = ctx.input.body;

View File

@@ -1,4 +1,7 @@
import { Next } from "koa";
import capitalize from "lodash/capitalize";
import { UserRole } from "@shared/types";
import { UserRoleHelper } from "@shared/utils/UserRoleHelper";
import Logger from "@server/logging/Logger";
import tracer, {
addTags,
@@ -14,10 +17,8 @@ import {
} from "../errors";
type AuthenticationOptions = {
/** An admin user role is required to access the route. */
admin?: boolean;
/** A member or admin user role is required to access the route. */
member?: boolean;
/** Role requuired to access the route. */
role?: UserRole;
/** Authentication is parsed, but optional. */
optional?: boolean;
};
@@ -110,16 +111,8 @@ export default function auth(options: AuthenticationOptions = {}) {
});
}
if (options.admin) {
if (!user.isAdmin) {
throw AuthorizationError("Admin role required");
}
}
if (options.member) {
if (user.isViewer) {
throw AuthorizationError("Member role required");
}
if (options.role && UserRoleHelper.isRoleLower(user.role, options.role)) {
throw AuthorizationError(`${capitalize(options.role)} role required`);
}
// not awaiting the promises here so that the request is not blocked

View File

@@ -1,4 +1,5 @@
import Router from "koa-router";
import { UserRole } from "@shared/types";
import auth from "@server/middlewares/authentication";
import validate from "@server/middlewares/validate";
import { ApiKey, Event } from "@server/models";
@@ -12,7 +13,7 @@ const router = new Router();
router.post(
"apiKeys.create",
auth({ member: true }),
auth({ role: UserRole.Member }),
validate(T.APIKeysCreateSchema),
async (ctx: APIContext<T.APIKeysCreateReq>) => {
const { name } = ctx.input.body;
@@ -43,7 +44,7 @@ router.post(
router.post(
"apiKeys.list",
auth({ member: true }),
auth({ role: UserRole.Member }),
pagination(),
async (ctx: APIContext) => {
const { user } = ctx.state.auth;
@@ -65,7 +66,7 @@ router.post(
router.post(
"apiKeys.delete",
auth({ member: true }),
auth({ role: UserRole.Member }),
validate(T.APIKeysDeleteSchema),
async (ctx: APIContext<T.APIKeysDeleteReq>) => {
const { id } = ctx.input.body;

View File

@@ -1,4 +1,5 @@
import Router from "koa-router";
import { UserRole } from "@shared/types";
import auth from "@server/middlewares/authentication";
import { transaction } from "@server/middlewares/transaction";
import validate from "@server/middlewares/validate";
@@ -16,7 +17,7 @@ const router = new Router();
router.post(
"authenticationProviders.info",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.AuthenticationProvidersInfoSchema),
async (ctx: APIContext<T.AuthenticationProvidersInfoReq>) => {
const { id } = ctx.input.body;
@@ -34,7 +35,7 @@ router.post(
router.post(
"authenticationProviders.update",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.AuthenticationProvidersUpdateSchema),
transaction(),
async (ctx: APIContext<T.AuthenticationProvidersUpdateReq>) => {
@@ -79,7 +80,7 @@ router.post(
router.post(
"authenticationProviders.list",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
async (ctx: APIContext) => {
const { user } = ctx.state.auth;
authorize(user, "read", user.team);

View File

@@ -8,7 +8,7 @@ import escapeRegExp from "lodash/escapeRegExp";
import mime from "mime-types";
import { Op, ScopeOptions, Sequelize, WhereOptions } from "sequelize";
import { v4 as uuidv4 } from "uuid";
import { StatusFilter, TeamPreference } from "@shared/types";
import { StatusFilter, TeamPreference, UserRole } from "@shared/types";
import { subtractDate } from "@shared/utils/date";
import slugify from "@shared/utils/slugify";
import documentCreator from "@server/commands/documentCreator";
@@ -203,7 +203,7 @@ router.post(
router.post(
"documents.archived",
auth({ member: true }),
auth({ role: UserRole.Member }),
pagination(),
validate(T.DocumentsArchivedSchema),
async (ctx: APIContext<T.DocumentsArchivedReq>) => {
@@ -247,7 +247,7 @@ router.post(
router.post(
"documents.deleted",
auth({ member: true }),
auth({ role: UserRole.Member }),
pagination(),
validate(T.DocumentsDeletedSchema),
async (ctx: APIContext<T.DocumentsDeletedReq>) => {
@@ -629,7 +629,7 @@ router.post(
router.post(
"documents.restore",
auth({ member: true }),
auth({ role: UserRole.Member }),
validate(T.DocumentsRestoreSchema),
async (ctx: APIContext<T.DocumentsRestoreReq>) => {
const { id, collectionId, revisionId } = ctx.input.body;
@@ -904,7 +904,7 @@ router.post(
router.post(
"documents.templatize",
auth({ member: true }),
auth({ role: UserRole.Member }),
rateLimiter(RateLimiterStrategy.TwentyFivePerMinute),
validate(T.DocumentsTemplatizeSchema),
transaction(),

View File

@@ -1,5 +1,6 @@
import Router from "koa-router";
import { WhereOptions } from "sequelize";
import { UserRole } from "@shared/types";
import fileOperationDeleter from "@server/commands/fileOperationDeleter";
import { ValidationError } from "@server/errors";
import auth from "@server/middlewares/authentication";
@@ -17,7 +18,7 @@ const router = new Router();
router.post(
"fileOperations.info",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.FileOperationsInfoSchema),
async (ctx: APIContext<T.FileOperationsInfoReq>) => {
const { id } = ctx.input.body;
@@ -37,7 +38,7 @@ router.post(
router.post(
"fileOperations.list",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
pagination(),
validate(T.FileOperationsListSchema),
async (ctx: APIContext<T.FileOperationsListReq>) => {
@@ -91,20 +92,20 @@ const handleFileOperationsRedirect = async (
router.get(
"fileOperations.redirect",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.FileOperationsRedirectSchema),
handleFileOperationsRedirect
);
router.post(
"fileOperations.redirect",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.FileOperationsRedirectSchema),
handleFileOperationsRedirect
);
router.post(
"fileOperations.delete",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.FileOperationsDeleteSchema),
transaction(),
async (ctx: APIContext<T.FileOperationsDeleteReq>) => {

View File

@@ -1,6 +1,6 @@
import Router from "koa-router";
import { WhereOptions, Op } from "sequelize";
import { IntegrationType } from "@shared/types";
import { IntegrationType, UserRole } from "@shared/types";
import auth from "@server/middlewares/authentication";
import { transaction } from "@server/middlewares/transaction";
import validate from "@server/middlewares/validate";
@@ -68,7 +68,7 @@ router.post(
router.post(
"integrations.create",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.IntegrationsCreateSchema),
async (ctx: APIContext<T.IntegrationsCreateReq>) => {
const { type, service, settings } = ctx.input.body;
@@ -113,7 +113,7 @@ router.post(
router.post(
"integrations.update",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.IntegrationsUpdateSchema),
async (ctx: APIContext<T.IntegrationsUpdateReq>) => {
const { id, events, settings } = ctx.input.body;

View File

@@ -263,7 +263,7 @@ router.post(
*/
router.post(
"users.promote",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.UsersPromoteSchema),
transaction(),
(ctx: APIContext<T.UsersPromoteReq>) => {
@@ -286,7 +286,7 @@ router.post(
*/
router.post(
"users.demote",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.UsersDemoteSchema),
transaction(),
(ctx: APIContext<T.UsersDemoteReq>) => {
@@ -304,7 +304,7 @@ router.post(
router.post(
"users.update_role",
auth({ admin: true }),
auth({ role: UserRole.Admin }),
validate(T.UsersChangeRoleSchema),
transaction(),
updateRole