Fix metting pages permissions handling

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-31 18:49:19 +01:00
committed by Bryan Frimin
parent 4d6b33203d
commit 65d3267ab8
10 changed files with 168 additions and 91 deletions

View File

@@ -21,12 +21,11 @@ import {
UpdateMeetingMinutesDialog,
type UpdateMeetingMinutesDialogRef,
} from "./dialogs/UpdateMeetingMinutesDialog";
import { useRef, useState, useEffect, use } from "react";
import { useRef } from "react";
import {
meetingNodeQuery,
useDeleteMeetingMutation,
} from "/hooks/graph/MeetingGraph";
import { PermissionsContext } from "/providers/PermissionsContext";
const meetingFragment = graphql`
fragment MeetingDetailPageMeetingFragment on Meeting {
@@ -34,6 +33,8 @@ const meetingFragment = graphql`
name
date
minutes
canUpdate: permission(action: "core:meeting:update")
canDelete: permission(action: "core:meeting:delete")
attendees {
id
fullName
@@ -54,70 +55,14 @@ export default function MeetingDetailPage(props: Props) {
const { __ } = useTranslate();
const organizationId = useOrganizationId();
const navigate = useNavigate();
const { isAuthorized } = use(PermissionsContext);
const [deleteMeeting, isDeleting] = useDeleteMeetingMutation();
const confirm = useConfirm();
const updateMinutesDialogRef = useRef<UpdateMeetingMinutesDialogRef>(null);
const [canUpdate, setCanUpdate] = useState<boolean>(false);
const [canDelete, setCanDelete] = useState<boolean>(false);
useEffect(() => {
if (!organizationId) {
setCanUpdate(false);
setCanDelete(false);
return;
}
try {
const updateAuth = isAuthorized("Meeting", "updateMeeting");
setCanUpdate(updateAuth);
} catch (promise) {
if (promise instanceof Promise) {
promise
.then(() => {
try {
const updateAuth = isAuthorized("Meeting", "updateMeeting");
setCanUpdate(updateAuth);
} catch {
setCanUpdate(false);
}
})
.catch(() => {
setCanUpdate(false);
});
} else {
setCanUpdate(false);
}
}
try {
const deleteAuth = isAuthorized("Meeting", "deleteMeeting");
setCanDelete(deleteAuth);
} catch (promise) {
if (promise instanceof Promise) {
promise
.then(() => {
try {
const deleteAuth = isAuthorized("Meeting", "deleteMeeting");
setCanDelete(deleteAuth);
} catch {
setCanDelete(false);
}
})
.catch(() => {
setCanDelete(false);
});
} else {
setCanDelete(false);
}
}
}, [organizationId, isAuthorized]);
usePageTitle(meeting.name);
const hasAnyAction = canUpdate || canDelete;
const hasAnyAction = meeting.canUpdate || meeting.canDelete;
const handleDelete = () => {
confirm(
@@ -162,7 +107,7 @@ export default function MeetingDetailPage(props: Props) {
/>
{hasAnyAction && (
<ActionDropdown variant="secondary">
{canUpdate && (
{meeting.canUpdate && (
<DropdownItem
onClick={() => updateMinutesDialogRef.current?.open()}
icon={IconPencil}
@@ -170,7 +115,7 @@ export default function MeetingDetailPage(props: Props) {
{__("Edit minutes")}
</DropdownItem>
)}
{canDelete && (
{meeting.canDelete && (
<DropdownItem
variant="danger"
icon={IconTrashCan}

View File

@@ -42,8 +42,6 @@ import { Link } from "react-router";
import { useState, useEffect, useRef } from "react";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import type { MeetingsPage_UpdateSummaryMutation } from "/__generated__/core/MeetingsPage_UpdateSummaryMutation.graphql";
import { use } from "react";
import { PermissionsContext } from "/providers/PermissionsContext";
const meetingsFragment = graphql`
fragment MeetingsPageListFragment on Organization
@@ -86,7 +84,6 @@ type Props = {
export default function MeetingsPage(props: Props) {
const { __ } = useTranslate();
const { isAuthorized } = use(PermissionsContext);
const organization = usePreloadedQuery(
meetingsQuery,
props.queryRef,
@@ -219,7 +216,7 @@ export default function MeetingsPage(props: Props) {
<h3 className="text-sm font-semibold text-txt-secondary">
{__("Summary")}
</h3>
{isAuthorized("Meeting", "updateMeeting") && (
{organization.canCreateMeeting && (
<Button
variant="quaternary"
icon={IconPencil}
@@ -249,7 +246,7 @@ export default function MeetingsPage(props: Props) {
"Track and manage your organization's meetings and their minutes.",
)}
>
{isAuthorized("Organization", "createMeeting") && (
{organization.canCreateMeeting && (
<CreateMeetingDialog connectionId={connectionId}>
<Button icon={IconPlusLarge}>{__("Add meeting")}</Button>
</CreateMeetingDialog>
@@ -304,6 +301,7 @@ const rowFragment = graphql`
id
fullName
}
canDelete: permission(action: "core:meeting:delete")
}
`;
@@ -321,7 +319,6 @@ function MeetingRow({
const { __ } = useTranslate();
const [deleteMeeting] = useDeleteMeetingMutation();
const confirm = useConfirm();
const { isAuthorized } = use(PermissionsContext);
const handleDelete = () => {
confirm(
() =>
@@ -371,7 +368,7 @@ function MeetingRow({
</span>
)}
</Td>
{isAuthorized("Meeting", "deleteMeeting") && (
{meeting.canDelete && (
<Td noLink width={50} className="text-end w-18">
<ActionDropdown>
<DropdownItem

View File

@@ -34,6 +34,7 @@ const createMeetingMutation = graphql`
id
fullName
}
canDelete: permission(action: "core:meeting:delete")
}
}
}