Skip to content

Commit

Permalink
fix: block reservation creating if no permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
joonatank committed Sep 4, 2024
1 parent adca50b commit a0a0de2
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 44 deletions.
22 changes: 5 additions & 17 deletions apps/admin-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "./i18n";
import { PUBLIC_URL } from "./common/const";
import { GlobalContext } from "./context/GlobalContexts";
import { prefixes } from "./common/urls";
import { AuthorizationChecker } from "./common/AuthorizationChecker";
import { withAuthorization } from "@/common/AuthorizationChecker";
import MyUnitsRouter from "./spa/my-units/router";
import ReservationsRouter from "./component/reservations/ReservationRouter";
import NotificationsRouter from "./component/notifications/router";
Expand Down Expand Up @@ -55,21 +55,6 @@ const ApplicationRoundAllocation = dynamic(
import(`./spa/recurring-reservations/application-rounds/[id]/allocation`)
);

const withAuthorization = (
component: JSX.Element,
apiBaseUrl: string,
feedbackUrl: string,
permission?: UserPermissionChoice
) => (
<AuthorizationChecker
permission={permission}
apiUrl={apiBaseUrl}
feedbackUrl={feedbackUrl}
>
{component}
</AuthorizationChecker>
);

type Props = {
reservationUnitPreviewUrl: string;
apiBaseUrl: string;
Expand Down Expand Up @@ -230,7 +215,10 @@ function ClientApp({
<Route
path="/my-units/*"
element={withAuthorization(
<MyUnitsRouter />,
<MyUnitsRouter
apiBaseUrl={apiBaseUrl}
feedbackUrl={feedbackUrl}
/>,
apiBaseUrl,
feedbackUrl
)}
Expand Down
15 changes: 15 additions & 0 deletions apps/admin-ui/src/common/AuthorizationChecker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,18 @@ export function AuthorizationChecker({
</Suspense>
);
}

export const withAuthorization = (
component: JSX.Element,
apiBaseUrl: string,
feedbackUrl: string,
permission?: UserPermissionChoice
) => (
<AuthorizationChecker
permission={permission}
apiUrl={apiBaseUrl}
feedbackUrl={feedbackUrl}
>
{component}
</AuthorizationChecker>
);
33 changes: 26 additions & 7 deletions apps/admin-ui/src/spa/my-units/[id]/UnitCalendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Popup from "reactjs-popup";
import styled, { css } from "styled-components";
import {
ReservationTypeChoice,
UserPermissionChoice,
type ReservationUnitReservationsFragment,
} from "@gql/gql-types";
import { useTranslation } from "react-i18next";
Expand All @@ -30,6 +31,7 @@ import { CELL_BORDER, CELL_BORDER_LEFT, CELL_BORDER_LEFT_ALERT } from "./const";
import { ReservationPopupContent } from "./ReservationPopupContent";
import eventStyleGetter from "./eventStyleGetter";
import { CreateReservationModal } from "./CreateReservationModal";
import { useCheckPermission } from "@/hooks";

type CalendarEventType = CalendarEvent<ReservationUnitReservationsFragment>;
type Resource = {
Expand Down Expand Up @@ -58,12 +60,6 @@ type EventStyleGetter = ({ event }: CalendarEventType) => {
className?: string;
};

type Props = {
date: Date;
resources: Resource[];
refetch: () => void;
};

const FlexContainer = styled.div<{ $numCols: number }>`
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -201,12 +197,14 @@ const Container = styled.div<{ $height: number }>`
function Cells({
cols,
reservationUnitPk,
unitPk,
date,
setModalContent,
onComplete,
}: {
cols: number;
reservationUnitPk: number;
unitPk: number;
date: Date;
setModalContent: (content: JSX.Element | null, isHds?: boolean) => void;
onComplete: () => void;
Expand All @@ -217,8 +215,16 @@ function Cells({
return setHours(date, Math.round(index / 2)) < now;
};

const { hasPermission } = useCheckPermission({
units: [unitPk],
permission: UserPermissionChoice.CanCreateStaffReservations,
});

const onClick =
(offset: number) => (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
if (!hasPermission) {
return;
}
e.preventDefault();
setModalContent(
<CreateReservationModal
Expand Down Expand Up @@ -436,7 +442,19 @@ function sortByDraftStatusAndTitle(resources: Resource[]) {
});
}

export function UnitCalendar({ date, resources, refetch }: Props): JSX.Element {
type Props = {
date: Date;
unitPk: number;
resources: Resource[];
refetch: () => void;
};

export function UnitCalendar({
unitPk,
date,
resources,
refetch,
}: Props): JSX.Element {
const calendarRef = useRef<HTMLDivElement>(null);
// todo find out min and max opening hour of every reservationunit
const [beginHour, endHour] = [0, 24];
Expand Down Expand Up @@ -529,6 +547,7 @@ export function UnitCalendar({ date, resources, refetch }: Props): JSX.Element {
cols={numHours * 2}
date={startDate}
reservationUnitPk={row.pk}
unitPk={unitPk}
setModalContent={setModalContent}
onComplete={refetch}
/>
Expand Down
7 changes: 6 additions & 1 deletion apps/admin-ui/src/spa/my-units/[id]/UnitReservations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ function UnitReservationsInner({
{loading ? (
<Loader />
) : (
<UnitCalendar date={date} resources={resources} refetch={refetch} />
<UnitCalendar
date={date}
resources={resources}
refetch={refetch}
unitPk={Number(unitPk)}
/>
)}
<LegendContainer>
<Legends>
Expand Down
29 changes: 15 additions & 14 deletions apps/admin-ui/src/spa/my-units/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ import { H1 } from "common/src/common/typography";
import styled from "styled-components";
import { useTranslation } from "react-i18next";
import { useParams } from "react-router-dom";
import { Button, Tabs as HDSTabs } from "hds-react";
import { Tabs as HDSTabs } from "hds-react";
import { breakpoints } from "common/src/common/style";
import { parseAddress } from "@/common/util";
import { Container } from "@/styles/layout";
import { getRecurringReservationUrl } from "@/common/urls";
import { BasicLink } from "@/styles/util";
import Loader from "@/component/Loader";
import { ReservationUnitCalendarView } from "./ReservationUnitCalendarView";
import { UnitReservations } from "./UnitReservations";
import { TabHeader, Tabs } from "@/component/Tabs";
import { useUnitViewQuery } from "@gql/gql-types";
import { base64encode, filterNonNullable } from "common/src/helpers";
import { errorToast } from "common/src/common/toast";
import { UserPermissionChoice, useUnitViewQuery } from "@gql/gql-types";
import { useCheckPermission } from "@/hooks";
import { ButtonLikeLink } from "@/component/ButtonLikeLink";

type Params = {
unitId: string;
Expand Down Expand Up @@ -81,6 +82,11 @@ export function MyUnitView() {

const { unit } = data ?? {};

const { hasPermission: canCreateReservations } = useCheckPermission({
units: [Number(pk)],
permission: UserPermissionChoice.CanCreateStaffReservations,
});

if (loading) {
return <Loader />;
}
Expand Down Expand Up @@ -108,18 +114,13 @@ export function MyUnitView() {
</LocationOnlyOnDesktop>
)}
</ContainerWithSpacing>

<ContainerWithSpacing>
<BasicLink to={recurringReservationUrl ?? ""}>
<Button
disabled={!recurringReservationUrl}
variant="secondary"
theme="black"
size="small"
>
{t("MyUnits.Calendar.header.recurringReservation")}
</Button>
</BasicLink>
<ButtonLikeLink
to={canCreateReservations ? recurringReservationUrl : ""}
disabled={!canCreateReservations}
>
{t("MyUnits.Calendar.header.recurringReservation")}
</ButtonLikeLink>
</ContainerWithSpacing>
<Tabs headers={TabHeaders}>
<ReservationTabPanel key="unit-reservations">
Expand Down
41 changes: 36 additions & 5 deletions apps/admin-ui/src/spa/my-units/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,55 @@ import { RecurringReservation } from "./recurring/RecurringReservation";
import { MyUnits } from "./index";
import { MyUnitView } from "./[id]/index";
import { RecurringReservationDone } from "./recurring/RecurringReservationDone";
import { withAuthorization } from "@/common/AuthorizationChecker";
import { UserPermissionChoice } from "@gql/gql-types";

function MyUnitsRouter(): JSX.Element {
function MyUnitsRouter({
apiBaseUrl,
feedbackUrl,
}: {
apiBaseUrl: string;
feedbackUrl: string;
}): JSX.Element {
return (
<Routes>
<Route index element={<MyUnits />} />
<Route path=":unitId" element={<MyUnitView />} />
<Route path=":unitId/recurring" element={<RecurringReservation />} />
<Route
path=":unitId/recurring"
element={withAuthorization(
<RecurringReservation />,
apiBaseUrl,
feedbackUrl,
UserPermissionChoice.CanCreateStaffReservations
)}
/>
<Route
path=":unitId/recurring-reservation"
element={<RecurringReservation />}
element={withAuthorization(
<RecurringReservation />,
apiBaseUrl,
feedbackUrl,
UserPermissionChoice.CanCreateStaffReservations
)}
/>
<Route
path=":unitId/recurring/:pk/completed"
element={<RecurringReservationDone />}
element={withAuthorization(
<RecurringReservationDone />,
apiBaseUrl,
feedbackUrl,
UserPermissionChoice.CanCreateStaffReservations
)}
/>
<Route
path=":unitId/recurring-reservation/completed"
element={<RecurringReservationDone />}
element={withAuthorization(
<RecurringReservationDone />,
apiBaseUrl,
feedbackUrl,
UserPermissionChoice.CanCreateStaffReservations
)}
/>
</Routes>
);
Expand Down

0 comments on commit a0a0de2

Please sign in to comment.