feat(permissions): gate workspace resources by role

This commit is contained in:
2026-04-25 18:48:49 +03:30
parent c8c689e693
commit 7f0e00f09d
11 changed files with 511 additions and 200 deletions

View File

@@ -15,7 +15,8 @@ import { fetchWorkspaceMemberships } from "../api/workspaces";
import { searchUserByExactMobile, type SearchedUser } from "../api/users";
import { useAppContext } from "../context/AppContext";
import { useWorkspace } from "../context/WorkspaceContext";
import { useTranslation } from "../hooks/useTranslation";
import { useTranslation } from "../hooks/useTranslation";
import { PROJECTS_CREATE, canWorkspace } from "../lib/permissions";
import { Button } from "../components/ui/button";
import { Input } from "../components/ui/input";
import { Select } from "../components/ui/Select";
@@ -57,7 +58,8 @@ export default function ProjectCreate() {
const { t } = useTranslation();
const { user } = useAppContext();
const { activeWorkspace } = useWorkspace();
const currentUserId = user?.id || "";
const currentUserId = user?.id || "";
const canCreateProject = canWorkspace(activeWorkspace?.my_role, PROJECTS_CREATE);
// Project Detail States
const [name, setName] = useState("");
@@ -89,7 +91,14 @@ export default function ProjectCreate() {
const [memberIdToDelete, setMemberIdToDelete] = useState<string | null>(null);
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
const hasUnsavedChanges = name.trim() !== "" || description.trim() !== "" || members.length > 1;
const hasUnsavedChanges = name.trim() !== "" || description.trim() !== "" || members.length > 1;
useEffect(() => {
if (activeWorkspace && !canCreateProject) {
toast.error("You do not have permission to create projects.");
navigate("/projects");
}
}, [activeWorkspace, canCreateProject, navigate]);
useBlocker(({ currentLocation, nextLocation }) => {
if (hasUnsavedChanges && !isSaving && currentLocation.pathname !== nextLocation.pathname) {
@@ -352,9 +361,9 @@ export default function ProjectCreate() {
...filteredWorkspaceMembers.map((m) => ({ listId: m.id || m.user.id, user: m.user }))
];
if (!activeWorkspace) {
return null;
}
if (!activeWorkspace) {
return null;
}
return (
<div className="absolute inset-0 flex flex-col p-4 sm:p-6 bg-slate-50 dark:bg-slate-900 overflow-hidden">