feat: customisable workspace role permissions (#345)
* feat: setup schema for workspace roles * chore: regen migration * feat: add publicId to workspace roles * feat: setup default permissions * feat: add repo funcs * feat: setup basic router interactions * feat: add card permissions * feat: assert permissions for lists * feat: assert board permissions * feat: assert permission for remaining routes * feat: add permissions page to settings * feat: enable updating member roles * feat: order members by role and createdAt * feat: allow editing individual permissions * feat: reset role defaults * feat: clear all permission overrides * feat: allow users to delete entities they have created * feat: set roleId when inviting new members * feat: disable UI elements if user does not have permissions * feat: allow admins to assign the admin role to other users * feat: allow delete:list as default * refactor: centre permissions modal * chore: translations
This commit is contained in:
@@ -7,7 +7,7 @@ import * as workspaceSlugRepo from "@kan/db/repository/workspaceSlug.repo";
|
||||
import { generateUID } from "@kan/shared/utils";
|
||||
|
||||
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
||||
import { assertUserInWorkspace } from "../utils/auth";
|
||||
import { assertPermission } from "../utils/permissions";
|
||||
|
||||
export const workspaceRouter = createTRPCRouter({
|
||||
all: protectedProcedure
|
||||
@@ -74,8 +74,7 @@ export const workspaceRouter = createTRPCRouter({
|
||||
message: `Workspace not found`,
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
|
||||
await assertUserInWorkspace(ctx.db, userId, result.id);
|
||||
await assertPermission(ctx.db, userId, result.id, "workspace:view");
|
||||
|
||||
// Check if user is an admin
|
||||
const userMember = result.members.find(
|
||||
@@ -84,7 +83,8 @@ export const workspaceRouter = createTRPCRouter({
|
||||
const isAdmin = userMember?.role === "admin";
|
||||
|
||||
// Show emails if user is admin OR workspace setting allows it
|
||||
const shouldShowEmails = isAdmin || result.showEmailsToMembers === true;
|
||||
const shouldShowEmails =
|
||||
isAdmin || result.showEmailsToMembers === true;
|
||||
|
||||
// If emails should be hidden, filter them out
|
||||
if (!shouldShowEmails) {
|
||||
@@ -164,8 +164,7 @@ export const workspaceRouter = createTRPCRouter({
|
||||
message: `Workspace not found`,
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
|
||||
await assertUserInWorkspace(ctx.db, userId, result.id);
|
||||
await assertPermission(ctx.db, userId, result.id, "workspace:view");
|
||||
|
||||
return result;
|
||||
}),
|
||||
@@ -296,8 +295,7 @@ export const workspaceRouter = createTRPCRouter({
|
||||
message: `Workspace not found`,
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
|
||||
await assertUserInWorkspace(ctx.db, userId, workspace.id, "admin");
|
||||
await assertPermission(ctx.db, userId, workspace.id, "workspace:edit");
|
||||
|
||||
if (input.slug) {
|
||||
const reservedOrPremiumWorkspaceSlug =
|
||||
@@ -379,8 +377,7 @@ export const workspaceRouter = createTRPCRouter({
|
||||
message: `Workspace not found`,
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
|
||||
await assertUserInWorkspace(ctx.db, userId, workspace.id, "admin");
|
||||
await assertPermission(ctx.db, userId, workspace.id, "workspace:delete");
|
||||
|
||||
const result = await workspaceRepo.hardDelete(
|
||||
ctx.db,
|
||||
@@ -518,8 +515,7 @@ export const workspaceRouter = createTRPCRouter({
|
||||
message: `Workspace not found`,
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
|
||||
await assertUserInWorkspace(ctx.db, userId, workspace.id);
|
||||
await assertPermission(ctx.db, userId, workspace.id, "workspace:view");
|
||||
|
||||
const result = await workspaceRepo.searchBoardsAndCards(
|
||||
ctx.db,
|
||||
|
||||
Reference in New Issue
Block a user