diff --git a/src/domain/application/applicationView/ApplicationView.tsx b/src/domain/application/applicationView/ApplicationView.tsx
index 542c89730..817c21c5d 100644
--- a/src/domain/application/applicationView/ApplicationView.tsx
+++ b/src/domain/application/applicationView/ApplicationView.tsx
@@ -38,7 +38,7 @@ import { ApplicationCancel } from '../components/ApplicationCancel';
import AttachmentSummary from '../components/AttachmentSummary';
import useAttachments from '../hooks/useAttachments';
import FeatureFlags from '../../../common/components/featureFlags/FeatureFlags';
-import UserRightsCheck from '../../hanke/hankeUsers/UserRightsCheck';
+import { CheckRightsByHanke } from '../../hanke/hankeUsers/UserRightsCheck';
type Props = {
application: Application;
@@ -120,7 +120,7 @@ function ApplicationView({ application, hanke, onEditApplication }: Props) {
{isPending ? (
-
+
}
@@ -128,17 +128,17 @@ function ApplicationView({ application, hanke, onEditApplication }: Props) {
>
{t('hakemus:buttons:editApplication')}
-
+
) : null}
{hanke ? (
-
+
}
/>
-
+
) : null}
diff --git a/src/domain/hanke/accessRights/AccessRightsViewContainer.tsx b/src/domain/hanke/accessRights/AccessRightsViewContainer.tsx
index cf5c08827..1ff2a100f 100644
--- a/src/domain/hanke/accessRights/AccessRightsViewContainer.tsx
+++ b/src/domain/hanke/accessRights/AccessRightsViewContainer.tsx
@@ -7,7 +7,7 @@ import ErrorLoadingText from '../../../common/components/errorLoadingText/ErrorL
import { useHankeUsers } from '../hankeUsers/hooks/useHankeUsers';
import useHanke from '../hooks/useHanke';
import AccessRightsView from './AccessRightsView';
-import useUserRightsForHanke from '../hankeUsers/hooks/useUserRightsForHanke';
+import { useSignedInUserRightsForHanke } from '../hankeUsers/hooks/useUserRightsForHanke';
type Props = {
hankeTunnus: string;
@@ -17,7 +17,7 @@ function AccessRightsViewContainer({ hankeTunnus }: Props) {
const { t } = useTranslation();
const { data: hankeUsers, isLoading, isError, error } = useHankeUsers(hankeTunnus);
const { data: hankeData } = useHanke(hankeTunnus);
- const { data: signedInUser } = useUserRightsForHanke(hankeTunnus);
+ const { data: signedInUser } = useSignedInUserRightsForHanke(hankeTunnus);
if (isLoading) {
return (
diff --git a/src/domain/hanke/hankeUsers/UserRightsCheck.test.tsx b/src/domain/hanke/hankeUsers/UserRightsCheck.test.tsx
index 06be23cfb..14b884fb2 100644
--- a/src/domain/hanke/hankeUsers/UserRightsCheck.test.tsx
+++ b/src/domain/hanke/hankeUsers/UserRightsCheck.test.tsx
@@ -3,13 +3,13 @@ import { rest } from 'msw';
import { render, screen, waitFor } from '../../../testUtils/render';
import { server } from '../../mocks/test-server';
import { SignedInUser } from './hankeUser';
-import UserRightsCheck from './UserRightsCheck';
+import { CheckRightsByHanke } from './UserRightsCheck';
test('Should render children if user has required right', async () => {
render(
-
+
Children
- ,
+ ,
);
await waitFor(() => {
@@ -32,9 +32,9 @@ test('Should not render children if user does not have required right', async ()
);
render(
-
+
Children
- ,
+ ,
);
await waitFor(() => {
@@ -47,9 +47,9 @@ test('Should render children when access right feature is not enabled', async ()
window._env_.REACT_APP_FEATURE_ACCESS_RIGHTS = 0;
render(
-
+
Children
- ,
+ ,
);
await waitFor(() => {
diff --git a/src/domain/hanke/hankeUsers/UserRightsCheck.tsx b/src/domain/hanke/hankeUsers/UserRightsCheck.tsx
index a6189086f..eea493c3e 100644
--- a/src/domain/hanke/hankeUsers/UserRightsCheck.tsx
+++ b/src/domain/hanke/hankeUsers/UserRightsCheck.tsx
@@ -1,13 +1,13 @@
import React from 'react';
-import useUserRightsForHanke from './hooks/useUserRightsForHanke';
-import { Rights } from './hankeUser';
+import { Rights, SignedInUser } from './hankeUser';
import { useFeatureFlags } from '../../../common/components/featureFlags/FeatureFlagsContext';
+import { useSignedInUserRightsForHanke } from './hooks/useUserRightsForHanke';
/**
* Check that user has required rights.
* If they have, render children.
*/
-function UserRightsCheck({
+export function CheckRightsByHanke({
requiredRight,
hankeTunnus,
children,
@@ -18,7 +18,7 @@ function UserRightsCheck({
hankeTunnus?: string;
children: React.ReactElement | null;
}) {
- const { data: signedInUser } = useUserRightsForHanke(hankeTunnus);
+ const { data: signedInUser } = useSignedInUserRightsForHanke(hankeTunnus);
const features = useFeatureFlags();
if (!features.accessRights) {
@@ -32,4 +32,24 @@ function UserRightsCheck({
return null;
}
-export default UserRightsCheck;
+/**
+ * Check that user has required rights. Verified by SignedInUser data.
+ * If permitted, render children.
+ */
+export function CheckRightsByUser({
+ requiredRight,
+ signedUser,
+ children,
+}: {
+ requiredRight: keyof typeof Rights;
+ signedUser: SignedInUser | undefined;
+ children: React.ReactElement | null;
+}) {
+ const features = useFeatureFlags();
+
+ if (!features.accessRights) {
+ return children;
+ }
+
+ return signedUser?.kayttooikeudet.includes(requiredRight) ? children : null;
+}
diff --git a/src/domain/hanke/hankeUsers/hankeUser.ts b/src/domain/hanke/hankeUsers/hankeUser.ts
index fd18b105f..b831cffdd 100644
--- a/src/domain/hanke/hankeUsers/hankeUser.ts
+++ b/src/domain/hanke/hankeUsers/hankeUser.ts
@@ -34,6 +34,10 @@ export type SignedInUser = {
kayttooikeudet: UserRights;
};
+export type SignedInUserByHanke = {
+ [hankeTunnus: string]: SignedInUser;
+};
+
export type IdentificationResponse = {
kayttajaId: string;
hankeTunnus: string;
diff --git a/src/domain/hanke/hankeUsers/hankeUsersApi.ts b/src/domain/hanke/hankeUsers/hankeUsersApi.ts
index 5ae8bd20c..6d176e769 100644
--- a/src/domain/hanke/hankeUsers/hankeUsersApi.ts
+++ b/src/domain/hanke/hankeUsers/hankeUsersApi.ts
@@ -1,5 +1,5 @@
import api from '../../api/api';
-import { HankeUser, IdentificationResponse, SignedInUser } from './hankeUser';
+import { HankeUser, IdentificationResponse, SignedInUser, SignedInUserByHanke } from './hankeUser';
export async function getHankeUsers(hankeTunnus: string) {
const { data } = await api.get<{ kayttajat: HankeUser[] }>(`hankkeet/${hankeTunnus}/kayttajat`);
@@ -23,6 +23,11 @@ export async function getSignedInUserForHanke(hankeTunnus?: string): Promise {
+ const { data } = await api.get('hankkeet/my-permissions');
+ return data;
+}
+
export async function identifyUser(id: string) {
const { data } = await api.post('kayttajat', { tunniste: id });
return data;
diff --git a/src/domain/hanke/hankeUsers/hooks/useUserRightsForHanke.ts b/src/domain/hanke/hankeUsers/hooks/useUserRightsForHanke.ts
index a883f8407..6189acf9e 100644
--- a/src/domain/hanke/hankeUsers/hooks/useUserRightsForHanke.ts
+++ b/src/domain/hanke/hankeUsers/hooks/useUserRightsForHanke.ts
@@ -1,9 +1,9 @@
import { useQuery } from 'react-query';
-import { SignedInUser } from '../hankeUser';
-import { getSignedInUserForHanke } from '../hankeUsersApi';
+import { SignedInUser, SignedInUserByHanke } from '../hankeUser';
+import { getSignedInUserForHanke, getSignedInUserByHanke } from '../hankeUsersApi';
import { useFeatureFlags } from '../../../../common/components/featureFlags/FeatureFlagsContext';
-export default function useSignedInUserRightsForHanke(hankeTunnus?: string) {
+export function useSignedInUserRightsForHanke(hankeTunnus?: string) {
const features = useFeatureFlags();
return useQuery(
@@ -14,3 +14,11 @@ export default function useSignedInUserRightsForHanke(hankeTunnus?: string) {
},
);
}
+
+export function useSignedInUserRightsByHanke() {
+ const features = useFeatureFlags();
+
+ return useQuery(['signedUserByHanke'], () => getSignedInUserByHanke(), {
+ enabled: features.accessRights,
+ });
+}
diff --git a/src/domain/hanke/hankeView/HankeView.tsx b/src/domain/hanke/hankeView/HankeView.tsx
index 743266378..d5ff5f386 100644
--- a/src/domain/hanke/hankeView/HankeView.tsx
+++ b/src/domain/hanke/hankeView/HankeView.tsx
@@ -52,7 +52,7 @@ import {
import FeatureFlags from '../../../common/components/featureFlags/FeatureFlags';
import { useFeatureFlags } from '../../../common/components/featureFlags/FeatureFlagsContext';
import { SignedInUser } from '../hankeUsers/hankeUser';
-import UserRightsCheck from '../hankeUsers/UserRightsCheck';
+import { CheckRightsByHanke } from '../hankeUsers/UserRightsCheck';
type AreaProps = {
area: HankeAlue;
@@ -217,7 +217,7 @@ const HankeView: React.FC = ({
-
+
-
-
+
+
{isHankePublic ? (
) : null}
-
+
-
+
} theme="black">
{t('hankeList:buttons:endHanke')}
-
+
{!isLoading && isCancelPossible && (
-
+
-
+
)}
diff --git a/src/domain/hanke/hankeView/HankeViewContainer.tsx b/src/domain/hanke/hankeView/HankeViewContainer.tsx
index 1f1346ec5..04efec249 100644
--- a/src/domain/hanke/hankeView/HankeViewContainer.tsx
+++ b/src/domain/hanke/hankeView/HankeViewContainer.tsx
@@ -5,7 +5,7 @@ import { ROUTES } from '../../../common/types/route';
import HankeDelete from '../edit/components/HankeDelete';
import useHanke from '../hooks/useHanke';
import HankeView from './HankeView';
-import useUserRightsForHanke from '../hankeUsers/hooks/useUserRightsForHanke';
+import { useSignedInUserRightsForHanke } from '../hankeUsers/hooks/useUserRightsForHanke';
type Props = {
hankeTunnus?: string;
@@ -13,7 +13,7 @@ type Props = {
const HankeViewContainer: React.FC = ({ hankeTunnus }) => {
const { data: hankeData } = useHanke(hankeTunnus);
- const { data: signedInUser } = useUserRightsForHanke(hankeTunnus);
+ const { data: signedInUser } = useSignedInUserRightsForHanke(hankeTunnus);
const getEditHankePath = useLinkPath(ROUTES.EDIT_HANKE);
const getEditRightsPath = useLinkPath(ROUTES.ACCESS_RIGHTS);
const navigate = useNavigate();
diff --git a/src/domain/hanke/portfolio/HankePortfolio.test.tsx b/src/domain/hanke/portfolio/HankePortfolio.test.tsx
index 9afaab508..507c67509 100644
--- a/src/domain/hanke/portfolio/HankePortfolio.test.tsx
+++ b/src/domain/hanke/portfolio/HankePortfolio.test.tsx
@@ -6,6 +6,8 @@ import HankePortfolioComponent from './HankePortfolioComponent';
import { render, screen, waitFor } from '../../../testUtils/render';
import hankeList from '../../mocks/hankeList';
import { changeFilterDate } from '../../../testUtils/helperFunctions';
+import { USER_VIEW, signedInUserByHanke } from '../../mocks/signedInUser';
+import { SignedInUserByHanke } from '../hankeUsers/hankeUser';
const startDateLabel = 'Ajanjakson alku';
const endDateLabel = 'Ajanjakson loppu';
@@ -16,7 +18,7 @@ jest.setTimeout(30000);
describe.only('HankePortfolio', () => {
test('Changing search text filters correct number of projects', async () => {
- const { user } = render();
+ const { user } = render();
await user.type(screen.getByLabelText('Haku'), 'Mannerheimintie autottomaksi');
await waitFor(() => {
@@ -41,7 +43,9 @@ describe.only('HankePortfolio', () => {
});
test('Changing filter startDates filters correct number of projects', async () => {
- const renderedComponent = render();
+ const renderedComponent = render(
+ ,
+ );
expect(renderedComponent.getByTestId('numberOfFilteredRows')).toHaveTextContent('2');
changeFilterDate(startDateLabel, renderedComponent, '02.10.2022');
expect(renderedComponent.getByTestId('numberOfFilteredRows')).toHaveTextContent('2');
@@ -56,7 +60,9 @@ describe.only('HankePortfolio', () => {
});
test('Changing filter endDates filters correct number of projects', async () => {
- const renderedComponent = render();
+ const renderedComponent = render(
+ ,
+ );
expect(renderedComponent.getByTestId('numberOfFilteredRows')).toHaveTextContent('2');
changeFilterDate(endDateLabel, renderedComponent, '01.10.2022');
expect(renderedComponent.getByTestId('numberOfFilteredRows')).toHaveTextContent('0');
@@ -72,7 +78,9 @@ describe.only('HankePortfolio', () => {
});
test('Changing Hanke type filters correct number of projects', async () => {
- const renderedComponent = render();
+ const renderedComponent = render(
+ ,
+ );
expect(renderedComponent.getByTestId('numberOfFilteredRows')).toHaveTextContent('2');
await renderedComponent.user.click(
renderedComponent.getByRole('button', { name: 'Tyƶn tyyppi' }),
@@ -98,13 +106,19 @@ describe.only('HankePortfolio', () => {
});
test('Having no projects renders correct text', () => {
- render();
+ render();
expect(screen.queryByText('Hankesalkussasi ei ole hankkeita')).toBeInTheDocument();
});
test('Should render edit hanke links for hankkeet that user has edit rights', async () => {
- render();
+ const hankeTunnusList = hankeList.map((hanke) => hanke.hankeTunnus);
+ const signedUserData: SignedInUserByHanke = {
+ ...signedInUserByHanke(hankeTunnusList),
+ [hankeTunnusList[0]]: USER_VIEW,
+ };
+
+ render();
await waitFor(() => {
expect(screen.queryAllByTestId('hankeEditLink')).toHaveLength(1);
@@ -112,7 +126,7 @@ describe.only('HankePortfolio', () => {
});
test('Should show draft state notification for hankkeet that are in draft state', async () => {
- render();
+ render();
expect(
screen.getAllByText(
diff --git a/src/domain/hanke/portfolio/HankePortfolioComponent.tsx b/src/domain/hanke/portfolio/HankePortfolioComponent.tsx
index c16c344d7..a11a4376a 100644
--- a/src/domain/hanke/portfolio/HankePortfolioComponent.tsx
+++ b/src/domain/hanke/portfolio/HankePortfolioComponent.tsx
@@ -39,13 +39,18 @@ import { SKIP_TO_ELEMENT_ID } from '../../../common/constants/constants';
import useHankeViewPath from '../hooks/useHankeViewPath';
import { useNavigateToApplicationList } from '../hooks/useNavigateToApplicationList';
import FeatureFlags from '../../../common/components/featureFlags/FeatureFlags';
-import UserRightsCheck from '../hankeUsers/UserRightsCheck';
+import { CheckRightsByUser } from '../hankeUsers/UserRightsCheck';
+import { SignedInUser, SignedInUserByHanke } from '../hankeUsers/hankeUser';
type CustomAccordionProps = {
hanke: HankeData;
+ signedUser: SignedInUser | undefined;
};
-const CustomAccordion: React.FC> = ({ hanke }) => {
+const CustomAccordion: React.FC> = ({
+ hanke,
+ signedUser,
+}) => {
const getEditHankePath = useLinkPath(ROUTES.EDIT_HANKE);
const hankeViewPath = useHankeViewPath(hanke?.hankeTunnus);
const navigateToApplications = useNavigateToApplicationList(hanke?.hankeTunnus);
@@ -115,7 +120,7 @@ const CustomAccordion: React.FC> =
-
+
> =
>
-
+