Skip to content

Commit 3d8697b

Browse files
authored
Merge pull request #1247 from IFRCGo/feat/guest-user-permissions
Implement guest user permission check and restrict access
2 parents c1cb0f9 + b6bd6aa commit 3d8697b

File tree

10 files changed

+61
-15
lines changed

10 files changed

+61
-15
lines changed

.changeset/orange-seas-beg.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"go-web-app": minor
3+
---
4+
5+
Implement Guest User Permission in [#1237](https://github.com/IFRCGo/go-web-app/issues/1237)

app/src/App/routes/CountryRoutes.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ const perExport = customWrapRoute({
292292
context: {
293293
title: 'PER Export',
294294
visibility: 'is-authenticated',
295+
permissions: ({ isGuestUser }) => !isGuestUser,
295296
},
296297
});
297298

app/src/App/routes/common.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface Perms {
1919
isPerAdmin: boolean,
2020
isIfrcAdmin: boolean,
2121
isSuperUser: boolean,
22+
isGuestUser: boolean,
2223
}
2324

2425
export type ExtendedProps = {

app/src/App/routes/index.tsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ const newThreeWProject = customWrapRoute({
423423
context: {
424424
title: 'New 3W Project',
425425
visibility: 'is-authenticated',
426+
permissions: ({ isGuestUser }) => !isGuestUser,
426427
},
427428
});
428429

@@ -451,6 +452,7 @@ const threeWProjectEdit = customWrapRoute({
451452
context: {
452453
title: 'Edit 3W Project',
453454
visibility: 'is-authenticated',
455+
permissions: ({ isGuestUser }) => !isGuestUser,
454456
},
455457
});
456458

@@ -465,6 +467,7 @@ const newThreeWActivity = customWrapRoute({
465467
context: {
466468
title: 'New 3W Activity',
467469
visibility: 'is-authenticated',
470+
permissions: ({ isGuestUser }) => !isGuestUser,
468471
},
469472
});
470473

@@ -493,6 +496,7 @@ const threeWActivityEdit = customWrapRoute({
493496
context: {
494497
title: 'Edit 3W Activity',
495498
visibility: 'is-authenticated',
499+
permissions: ({ isGuestUser }) => !isGuestUser,
496500
},
497501
});
498502

@@ -620,6 +624,7 @@ const accountMyFormsLayout = customWrapRoute({
620624
context: {
621625
title: 'Account - My Forms',
622626
visibility: 'is-authenticated',
627+
permissions: ({ isGuestUser }) => !isGuestUser,
623628
},
624629
});
625630

@@ -650,6 +655,7 @@ const accountMyFormsFieldReport = customWrapRoute({
650655
context: {
651656
title: 'Account - Field Report Forms',
652657
visibility: 'is-authenticated',
658+
permissions: ({ isGuestUser }) => !isGuestUser,
653659
},
654660
});
655661

@@ -663,6 +669,7 @@ const accountMyFormsPer = customWrapRoute({
663669
context: {
664670
title: 'Account - PER Forms',
665671
visibility: 'is-authenticated',
672+
permissions: ({ isGuestUser }) => !isGuestUser,
666673
},
667674
});
668675

@@ -676,6 +683,7 @@ const accountMyFormsDref = customWrapRoute({
676683
context: {
677684
title: 'Account - DREF Applications',
678685
visibility: 'is-authenticated',
686+
permissions: ({ isGuestUser }) => !isGuestUser,
679687
},
680688
});
681689

@@ -689,6 +697,7 @@ const accountMyFormsThreeW = customWrapRoute({
689697
context: {
690698
title: 'Account - 3W',
691699
visibility: 'is-authenticated',
700+
permissions: ({ isGuestUser }) => !isGuestUser,
692701
},
693702
});
694703

@@ -799,7 +808,8 @@ const allFieldReports = customWrapRoute({
799808
wrapperComponent: Auth,
800809
context: {
801810
title: 'All Field Reports',
802-
visibility: 'anything',
811+
visibility: 'is-authenticated',
812+
permissions: ({ isGuestUser }) => !isGuestUser,
803813
},
804814
});
805815

@@ -814,7 +824,7 @@ const allFlashUpdates = customWrapRoute({
814824
context: {
815825
title: 'All Flash Updates',
816826
visibility: 'is-authenticated',
817-
permissions: ({ isIfrcAdmin }) => isIfrcAdmin,
827+
permissions: ({ isIfrcAdmin, isGuestUser }) => !isGuestUser && isIfrcAdmin,
818828
},
819829
});
820830

@@ -829,7 +839,7 @@ const flashUpdateFormNew = customWrapRoute({
829839
context: {
830840
title: 'New Flash Update',
831841
visibility: 'is-authenticated',
832-
permissions: ({ isIfrcAdmin }) => isIfrcAdmin,
842+
permissions: ({ isIfrcAdmin, isGuestUser }) => !isGuestUser && isIfrcAdmin,
833843
},
834844
});
835845

@@ -844,7 +854,7 @@ const flashUpdateFormEdit = customWrapRoute({
844854
context: {
845855
title: 'Edit Flash Update',
846856
visibility: 'is-authenticated',
847-
permissions: ({ isIfrcAdmin }) => isIfrcAdmin,
857+
permissions: ({ isIfrcAdmin, isGuestUser }) => !isGuestUser && isIfrcAdmin,
848858
},
849859
});
850860

@@ -860,7 +870,7 @@ const flashUpdateFormDetails = customWrapRoute({
860870
context: {
861871
title: 'Flash Update Details',
862872
visibility: 'anything',
863-
permissions: ({ isIfrcAdmin }) => isIfrcAdmin,
873+
permissions: ({ isIfrcAdmin, isGuestUser }) => !isGuestUser && isIfrcAdmin,
864874
},
865875
});
866876

@@ -889,6 +899,7 @@ const newDrefApplicationForm = customWrapRoute({
889899
context: {
890900
title: 'New DREF Application Form',
891901
visibility: 'is-authenticated',
902+
permissions: ({ isGuestUser }) => !isGuestUser,
892903
},
893904
});
894905

@@ -903,6 +914,7 @@ const drefApplicationForm = customWrapRoute({
903914
context: {
904915
title: 'Edit DREF Application Form',
905916
visibility: 'is-authenticated',
917+
permissions: ({ isGuestUser }) => !isGuestUser,
906918
},
907919
});
908920

@@ -917,6 +929,7 @@ const drefApplicationExport = customWrapRoute({
917929
context: {
918930
title: 'DREF Application Export',
919931
visibility: 'is-authenticated',
932+
permissions: ({ isGuestUser }) => !isGuestUser,
920933
},
921934
});
922935

@@ -931,6 +944,7 @@ const drefOperationalUpdateForm = customWrapRoute({
931944
context: {
932945
title: 'Edit DREF Operational Update Form',
933946
visibility: 'is-authenticated',
947+
permissions: ({ isGuestUser }) => !isGuestUser,
934948
},
935949
});
936950

@@ -945,6 +959,7 @@ const drefOperationalUpdateExport = customWrapRoute({
945959
context: {
946960
title: 'DREF Operational Update Export',
947961
visibility: 'is-authenticated',
962+
permissions: ({ isGuestUser }) => !isGuestUser,
948963
},
949964
});
950965
const drefFinalReportForm = customWrapRoute({
@@ -958,6 +973,7 @@ const drefFinalReportForm = customWrapRoute({
958973
context: {
959974
title: 'Edit DREF Final Report Form',
960975
visibility: 'is-authenticated',
976+
permissions: ({ isGuestUser }) => !isGuestUser,
961977
},
962978
});
963979

@@ -972,6 +988,7 @@ const drefFinalReportExport = customWrapRoute({
972988
context: {
973989
title: 'DREF Final Report Export',
974990
visibility: 'is-authenticated',
991+
permissions: ({ isGuestUser }) => !isGuestUser,
975992
},
976993
});
977994

@@ -986,6 +1003,7 @@ const fieldReportFormNew = customWrapRoute({
9861003
context: {
9871004
title: 'New Field Report Form',
9881005
visibility: 'is-authenticated',
1006+
permissions: ({ isGuestUser }) => !isGuestUser,
9891007
},
9901008
});
9911009

@@ -1000,6 +1018,7 @@ const fieldReportFormEdit = customWrapRoute({
10001018
context: {
10011019
title: 'Edit Field Report Form',
10021020
visibility: 'is-authenticated',
1021+
permissions: ({ isGuestUser }) => !isGuestUser,
10031022
},
10041023
});
10051024

@@ -1013,7 +1032,8 @@ const fieldReportDetails = customWrapRoute({
10131032
wrapperComponent: Auth,
10141033
context: {
10151034
title: 'Field Report Details',
1016-
visibility: 'anything',
1035+
visibility: 'is-authenticated',
1036+
permissions: ({ isGuestUser }) => !isGuestUser,
10171037
},
10181038
});
10191039

@@ -1030,6 +1050,7 @@ const perProcessLayout = customWrapRoute({
10301050
context: {
10311051
title: 'PER Process',
10321052
visibility: 'is-authenticated',
1053+
permissions: ({ isGuestUser }) => !isGuestUser,
10331054
},
10341055
});
10351056

@@ -1064,7 +1085,8 @@ const newPerOverviewForm = customWrapRoute({
10641085
permissions: ({
10651086
isSuperUser,
10661087
isPerAdmin,
1067-
}) => isSuperUser || isPerAdmin,
1088+
isGuestUser,
1089+
}) => !isGuestUser && (isSuperUser || isPerAdmin),
10681090
},
10691091
});
10701092

@@ -1079,6 +1101,7 @@ const perOverviewForm = customWrapRoute({
10791101
context: {
10801102
title: 'Edit PER Overview',
10811103
visibility: 'is-authenticated',
1104+
permissions: ({ isGuestUser }) => !isGuestUser,
10821105
},
10831106
});
10841107

@@ -1093,6 +1116,7 @@ const perAssessmentForm = customWrapRoute({
10931116
context: {
10941117
title: 'Edit PER Assessment',
10951118
visibility: 'is-authenticated',
1119+
permissions: ({ isGuestUser }) => !isGuestUser,
10961120
},
10971121
});
10981122

@@ -1107,6 +1131,7 @@ const perPrioritizationForm = customWrapRoute({
11071131
context: {
11081132
title: 'Edit PER Prioritization',
11091133
visibility: 'is-authenticated',
1134+
permissions: ({ isGuestUser }) => !isGuestUser,
11101135
},
11111136
});
11121137

@@ -1121,6 +1146,7 @@ const perWorkPlanForm = customWrapRoute({
11211146
context: {
11221147
title: 'Edit PER Work Plan',
11231148
visibility: 'is-authenticated',
1149+
permissions: ({ isGuestUser }) => !isGuestUser,
11241150
},
11251151
});
11261152

app/src/hooks/domain/usePermissions.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ function usePermissions() {
2727
const isPerAdmin = (userMe?.is_per_admin_for_countries.length ?? 0) > 0
2828
|| (userMe?.is_admin_for_regions.length ?? 0) > 0;
2929

30+
const isGuestUser = (userMe?.limit_access_to_guest);
31+
3032
return {
3133
isDrefRegionalCoordinator,
3234
isRegionAdmin,
@@ -36,6 +38,7 @@ function usePermissions() {
3638
isPerAdmin,
3739
isIfrcAdmin: !!userMe?.is_ifrc_admin || !!userMe?.email?.toLowerCase().endsWith('@ifrc.org'),
3840
isSuperUser: !!userMe?.is_superuser,
41+
isGuestUser,
3942
};
4043
},
4144
[userMe],

app/src/views/Country/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { adminUrl } from '#config';
3030
import RouteContext from '#contexts/route';
3131
import useAuth from '#hooks/domain/useAuth';
3232
import useCountry from '#hooks/domain/useCountry';
33+
import usePermissions from '#hooks/domain/usePermissions';
3334
import useRegion from '#hooks/domain/useRegion';
3435
import {
3536
countryIdToRegionIdMap,
@@ -67,6 +68,7 @@ export function Component() {
6768
});
6869

6970
const { isAuthenticated } = useAuth();
71+
const { isGuestUser } = usePermissions();
7072

7173
const outletContext = useMemo<CountryOutletContext>(
7274
() => ({
@@ -180,7 +182,7 @@ export function Component() {
180182
</Link>
181183
)
182184
}
183-
actions={isAuthenticated && (
185+
actions={!isGuestUser && isAuthenticated && (
184186
<Link
185187
external
186188
href={resolveUrl(adminUrl, `api/country/${countryId}/change/`)}

app/src/views/CountryNsOverviewContextAndStructure/NationalSocietyLocalUnits/LocalUnitsTable/LocalUnitTableActions/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ function LocalUnitsTableActions(props: Props) {
3434
onActionSuccess,
3535
} = props;
3636

37-
const { isCountryAdmin, isSuperUser } = usePermissions();
37+
const { isCountryAdmin, isSuperUser, isGuestUser } = usePermissions();
3838
const strings = useTranslation(i18n);
3939

40-
const hasValidatePermission = isSuperUser || isCountryAdmin(countryId);
40+
const hasValidatePermission = !isGuestUser && (isSuperUser || isCountryAdmin(countryId));
4141

4242
const [showLocalUnitViewModal, {
4343
setTrue: setShowLocalUnitViewModalTrue,

app/src/views/CountryNsOverviewContextAndStructure/NationalSocietyLocalUnits/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function NationalSocietyLocalUnits(props: Props) {
5252
const [activeTab, setActiveTab] = useState<'map'| 'table'>('map');
5353
const { isAuthenticated } = useAuth();
5454
const { countryResponse } = useOutletContext<CountryOutletContext>();
55-
const { isSuperUser, isCountryAdmin } = usePermissions();
55+
const { isSuperUser, isCountryAdmin, isGuestUser } = usePermissions();
5656
const containerRef = useRef<HTMLDivElement>(null);
5757

5858
// NOTE: key is used to refresh the page when local unit data is updated
@@ -111,7 +111,8 @@ function NationalSocietyLocalUnits(props: Props) {
111111

112112
const strings = useTranslation(i18n);
113113

114-
const hasAddLocalUnitPermission = isCountryAdmin(countryResponse?.id) || isSuperUser;
114+
const hasAddLocalUnitPermission = !isGuestUser
115+
&& (isCountryAdmin(countryResponse?.id) || isSuperUser);
115116

116117
useEffect(() => {
117118
document.addEventListener('fullscreenchange', handleFullScreenChange);

app/src/views/CountryOngoingActivitiesEmergencies/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import WikiLink from '#components/WikiLink';
6969
import { adminUrl } from '#config';
7070
import useAuth from '#hooks/domain/useAuth';
7171
import useCountryRaw from '#hooks/domain/useCountryRaw';
72+
import usePermissions from '#hooks/domain/usePermissions';
7273
import useFilterState from '#hooks/useFilterState';
7374
import useInputState from '#hooks/useInputState';
7475
import {
@@ -141,6 +142,7 @@ export function Component(props: BaseProps) {
141142

142143
const strings = useTranslation(i18n);
143144
const { isAuthenticated } = useAuth();
145+
const { isGuestUser } = usePermissions();
144146

145147
const {
146148
countryId,
@@ -460,7 +462,7 @@ export function Component(props: BaseProps) {
460462
return (
461463
<Container
462464
className={styles.countryOngoingActivities}
463-
actions={isAuthenticated && (
465+
actions={!isGuestUser && isAuthenticated && (
464466
<>
465467
<Link
466468
external

app/src/views/CountryPreparedness/index.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@ import PublicCountryPreparedness from './PublicCountryPreparedness';
99
// eslint-disable-next-line import/prefer-default-export
1010
export function Component() {
1111
const { countryId } = useParams<{ perId: string, countryId: string }>();
12-
const { isCountryPerAdmin, isSuperUser, isRegionPerAdmin } = usePermissions();
12+
const {
13+
isCountryPerAdmin,
14+
isSuperUser,
15+
isRegionPerAdmin,
16+
isGuestUser,
17+
} = usePermissions();
1318

1419
const countryDetails = useCountry({ id: Number(countryId) });
1520

16-
const hasPermission = (
21+
const hasPermission = !isGuestUser && (
1722
isSuperUser
1823
|| isCountryPerAdmin(Number(countryId))
1924
|| isRegionPerAdmin(Number(countryDetails?.region))

0 commit comments

Comments
 (0)