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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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