diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index a9dd64219..e3835ef11 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -25,17 +25,18 @@ import { ApiDocs } from './components/ApiDocs' import { Login } from './components/Login' import { NotFound } from './components/NotFound' import PublicLayout from './layouts/PublicLayout' -import { AddEditNotionalTransfers } from '@/views/NotionalTransfers' -import { AddEditOtherUses } from './views/OtherUses/AddEditOtherUses' -import { AddEditFinalSupplyEquipments } from './views/FinalSupplyEquipments/AddEditFinalSupplyEquipments' -import { AddEditFuelSupplies } from './views/FuelSupplies/AddEditFuelSupplies' -import { AddEditFuelExports } from './views/FuelExports/AddEditFuelExports' -import { AddEditAllocationAgreements } from './views/AllocationAgreements/AddEditAllocationAgreements' +import AddEditNotionalTransfersWithAccess from './views/NotionalTransfers/AddEditNotionalTransfers' +import AddEditOtherUsesWithAccess from './views/OtherUses/AddEditOtherUses' +import AddEditFinalSupplyEquipmentsWithAccess from './views/FinalSupplyEquipments/AddEditFinalSupplyEquipments' +import AddEditFuelSuppliesWithAccess from './views/FuelSupplies/AddEditFuelSupplies' +import AddEditFuelExportsWithAccess from './views/FuelExports/AddEditFuelExports' +import AddEditAllocationAgreementsWithAccess from './views/AllocationAgreements/AddEditAllocationAgreements' import { logout } from '@/utils/keycloak.js' import { CompareReports } from '@/views/CompareReports/CompareReports' import { ComplianceReportViewSelector } from '@/views/ComplianceReports/ComplianceReportViewSelector.jsx' import { useCurrentUser } from './hooks/useCurrentUser' import Loading from './components/Loading' +import { Unauthorized } from './components/Unauthorized' const router = createBrowserRouter([ { @@ -47,6 +48,10 @@ const router = createBrowserRouter([ path: ROUTES.LOGIN, element: , handle: { title: 'Login' } + }, + { + path: '/unauthorized', + element: } ] }, @@ -331,7 +336,7 @@ const router = createBrowserRouter([ }, { path: ROUTES.REPORTS_ADD_NOTIONAL_TRANSFERS, - element: , + element: , handle: { title: 'Notional transfer of eligible renewable fuels', mode: 'add' @@ -339,7 +344,7 @@ const router = createBrowserRouter([ }, { path: ROUTES.REPORTS_ADD_ALLOCATION_AGREEMENTS, - element: , + element: , handle: { title: 'Allocation agreements', mode: 'add' @@ -347,7 +352,7 @@ const router = createBrowserRouter([ }, { path: ROUTES.REPORTS_ADD_OTHER_USE_FUELS, - element: , + element: , handle: { title: 'Fuels for other use', mode: 'add' @@ -355,7 +360,7 @@ const router = createBrowserRouter([ }, { path: ROUTES.REPORTS_ADD_FINAL_SUPPLY_EQUIPMENTS, - element: , + element: , handle: { title: 'Final supply equipment', mode: 'add' @@ -363,7 +368,7 @@ const router = createBrowserRouter([ }, { path: ROUTES.REPORTS_ADD_SUPPLY_OF_FUEL, - element: , + element: , handle: { title: 'Supply of fuel', mode: 'add' @@ -371,7 +376,7 @@ const router = createBrowserRouter([ }, { path: ROUTES.REPORTS_ADD_FUEL_EXPORTS, - element: , + element: , handle: { title: 'Export fuels', mode: 'add' diff --git a/frontend/src/utils/withComplianceReportAcess.jsx b/frontend/src/utils/withComplianceReportAcess.jsx new file mode 100644 index 000000000..f1c2214c7 --- /dev/null +++ b/frontend/src/utils/withComplianceReportAcess.jsx @@ -0,0 +1,40 @@ +import { roles } from '@/constants/roles' +import { ROUTES } from '@/constants/routes' +import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses' +import { useGetComplianceReport } from '@/hooks/useComplianceReports.js' +import { useCurrentUser } from '@/hooks/useCurrentUser.js' +import { useEffect } from 'react' +import { useNavigate, useParams } from 'react-router-dom' + + +const withComplianceReportAccess = (WrappedComponent) => { + function WithComplianceReportAccess(props) { + const { compliancePeriod, complianceReportId } = useParams() + const navigate = useNavigate() + const { data: currentUser, isLoading: isUserLoading } = useCurrentUser() + const { data: reportData, isLoading: isReportLoading } = useGetComplianceReport(currentUser?.organization?.organizationId, complianceReportId) + + useEffect(() => { + if (!isUserLoading && !isReportLoading) { + const isGovernmentUser = currentUser?.roles?.some(role => role.name === roles.government) + const reportStatus = reportData?.report?.currentStatus?.status + + // Prevent Analysts from accessing Draft reports + if (isGovernmentUser && reportStatus === COMPLIANCE_REPORT_STATUSES.DRAFT) { + navigate(ROUTES.REPORTS, { replace: true }) + } + } + }, [isUserLoading, isReportLoading, currentUser, reportData, navigate]) + + if (isUserLoading || isReportLoading) { + return
Loading...
+ } + + return + } + + return WithComplianceReportAccess +} + + +export default withComplianceReportAccess \ No newline at end of file diff --git a/frontend/src/views/AllocationAgreements/AddEditAllocationAgreements.jsx b/frontend/src/views/AllocationAgreements/AddEditAllocationAgreements.jsx index 9c9cdd7b9..83fed10f5 100644 --- a/frontend/src/views/AllocationAgreements/AddEditAllocationAgreements.jsx +++ b/frontend/src/views/AllocationAgreements/AddEditAllocationAgreements.jsx @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next' import { useLocation, useNavigate, useParams } from 'react-router-dom' import BCBox from '@/components/BCBox' import { BCGridEditor } from '@/components/BCDataGrid/BCGridEditor' +import withComplianceReportAccess from '@/utils/withComplianceReportAcess' import { defaultColDef, allocationAgreementColDefs, @@ -20,7 +21,7 @@ import { v4 as uuid } from 'uuid' import * as ROUTES from '@/constants/routes/routes.js' import { DEFAULT_CI_FUEL } from '@/constants/common' -export const AddEditAllocationAgreements = () => { +const AddEditAllocationAgreements = () => { const [rowData, setRowData] = useState([]) const gridRef = useRef(null) const [gridApi, setGridApi] = useState() @@ -390,3 +391,7 @@ export const AddEditAllocationAgreements = () => { ) ) } + +const AddEditAllocationAgreementsWithAccess = withComplianceReportAccess(AddEditAllocationAgreements) + +export default AddEditAllocationAgreementsWithAccess \ No newline at end of file diff --git a/frontend/src/views/ComplianceReports/ComplianceReportViewSelector.jsx b/frontend/src/views/ComplianceReports/ComplianceReportViewSelector.jsx index 04cb92111..61c7bd473 100644 --- a/frontend/src/views/ComplianceReports/ComplianceReportViewSelector.jsx +++ b/frontend/src/views/ComplianceReports/ComplianceReportViewSelector.jsx @@ -1,9 +1,9 @@ import { useGetComplianceReport } from '@/hooks/useComplianceReports.js' import { useCurrentUser } from '@/hooks/useCurrentUser.js' import Loading from '@/components/Loading.jsx' -import { ViewLegacyComplianceReport } from '@/views/ComplianceReports/ViewLegacyComplianceReport.jsx' +import ViewLegacyComplianceReportWithAccess from '@/views/ComplianceReports/ViewLegacyComplianceReport.jsx' import { useParams } from 'react-router-dom' -import { EditViewComplianceReport } from '@/views/ComplianceReports/EditViewComplianceReport.jsx' +import EditViewComplianceReportWithAccess from '@/views/ComplianceReports/EditViewComplianceReport.jsx' export const ComplianceReportViewSelector = () => { const { complianceReportId } = useParams() @@ -25,13 +25,13 @@ export const ComplianceReportViewSelector = () => { } return reportData.report.legacyId ? ( - ) : ( - { +const EditViewComplianceReport = ({ reportData, isError, error }) => { const { t } = useTranslation(['common', 'report']) const location = useLocation() const [modalData, setModalData] = useState(null) @@ -321,3 +322,7 @@ export const EditViewComplianceReport = ({ reportData, isError, error }) => { ) } + +const EditViewComplianceReportWithAccess = withComplianceReportAccess(EditViewComplianceReport) + +export default EditViewComplianceReportWithAccess diff --git a/frontend/src/views/ComplianceReports/ViewLegacyComplianceReport.jsx b/frontend/src/views/ComplianceReports/ViewLegacyComplianceReport.jsx index 163591800..418f696e4 100644 --- a/frontend/src/views/ComplianceReports/ViewLegacyComplianceReport.jsx +++ b/frontend/src/views/ComplianceReports/ViewLegacyComplianceReport.jsx @@ -4,6 +4,7 @@ import BCBox from '@/components/BCBox' import BCModal from '@/components/BCModal' import Loading from '@/components/Loading' import { Fab, Stack, Tooltip } from '@mui/material' +import withComplianceReportAccess from '@/utils/withComplianceReportAcess' import BCTypography from '@/components/BCTypography' import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp' import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown' @@ -18,7 +19,7 @@ const iconStyle = { height: '2rem', color: colors.white.main } -export const ViewLegacyComplianceReport = ({ reportData, error, isError }) => { +const ViewLegacyComplianceReport = ({ reportData, error, isError }) => { const { t } = useTranslation(['common', 'report']) const [modalData, setModalData] = useState(null) const alertRef = useRef() @@ -141,3 +142,7 @@ export const ViewLegacyComplianceReport = ({ reportData, error, isError }) => { ) } + +const ViewLegacyComplianceReportWithAccess = withComplianceReportAccess(ViewLegacyComplianceReport); + +export default ViewLegacyComplianceReportWithAccess diff --git a/frontend/src/views/FinalSupplyEquipments/AddEditFinalSupplyEquipments.jsx b/frontend/src/views/FinalSupplyEquipments/AddEditFinalSupplyEquipments.jsx index d866f45a6..cd0c62b5c 100644 --- a/frontend/src/views/FinalSupplyEquipments/AddEditFinalSupplyEquipments.jsx +++ b/frontend/src/views/FinalSupplyEquipments/AddEditFinalSupplyEquipments.jsx @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next' import { useLocation, useNavigate, useParams } from 'react-router-dom' import { BCAlert2 } from '@/components/BCAlert' import BCBox from '@/components/BCBox' +import withComplianceReportAccess from '@/utils/withComplianceReportAcess' import { BCGridEditor } from '@/components/BCDataGrid/BCGridEditor' import { defaultColDef, finalSupplyEquipmentColDefs } from './_schema' import { @@ -16,7 +17,7 @@ import { v4 as uuid } from 'uuid' import * as ROUTES from '@/constants/routes/routes.js' import { isArrayEmpty } from '@/utils/formatters' -export const AddEditFinalSupplyEquipments = () => { +const AddEditFinalSupplyEquipments = () => { const [rowData, setRowData] = useState([]) const gridRef = useRef(null) const [gridApi, setGridApi] = useState(null) @@ -323,3 +324,7 @@ export const AddEditFinalSupplyEquipments = () => { ) ) } + +const AddEditFinalSupplyEquipmentsWithAccess = withComplianceReportAccess(AddEditFinalSupplyEquipments) + +export default AddEditFinalSupplyEquipmentsWithAccess \ No newline at end of file diff --git a/frontend/src/views/FuelExports/AddEditFuelExports.jsx b/frontend/src/views/FuelExports/AddEditFuelExports.jsx index 938a6f837..6dc678146 100644 --- a/frontend/src/views/FuelExports/AddEditFuelExports.jsx +++ b/frontend/src/views/FuelExports/AddEditFuelExports.jsx @@ -7,6 +7,7 @@ import { useSaveFuelExport } from '@/hooks/useFuelExport' import { isArrayEmpty } from '@/utils/formatters' +import withComplianceReportAccess from '@/utils/withComplianceReportAcess' import BCTypography from '@/components/BCTypography' import Grid2 from '@mui/material/Unstable_Grid2/Grid2' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -19,7 +20,7 @@ import { PROVISION_APPROVED_FUEL_CODE } from './_schema' -export const AddEditFuelExports = () => { +const AddEditFuelExports = () => { const [rowData, setRowData] = useState([]) const gridRef = useRef(null) const [, setGridApi] = useState() @@ -316,3 +317,7 @@ export const AddEditFuelExports = () => { ) ) } + +const AddEditFuelExportsWithAccess = withComplianceReportAccess(AddEditFuelExports) + +export default AddEditFuelExportsWithAccess diff --git a/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx b/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx index 872ff1c58..e11816327 100644 --- a/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx +++ b/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx @@ -8,6 +8,7 @@ import { useSaveFuelSupply } from '@/hooks/useFuelSupply' import { isArrayEmpty, cleanEmptyStringValues } from '@/utils/formatters' +import withComplianceReportAccess from '@/utils/withComplianceReportAcess' import BCTypography from '@/components/BCTypography' import Grid2 from '@mui/material/Unstable_Grid2/Grid2' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -20,7 +21,7 @@ import { PROVISION_APPROVED_FUEL_CODE } from './_schema' -export const AddEditFuelSupplies = () => { +const AddEditFuelSupplies = () => { const [rowData, setRowData] = useState([]) const gridRef = useRef(null) const [, setGridApi] = useState() @@ -398,3 +399,7 @@ export const AddEditFuelSupplies = () => { ) ) } + +const AddEditFuelSuppliesWithAccess = withComplianceReportAccess(AddEditFuelSupplies) + +export default AddEditFuelSuppliesWithAccess diff --git a/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx b/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx index fb17e5318..02c58586a 100644 --- a/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx +++ b/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx @@ -2,6 +2,7 @@ import { useState, useEffect, useRef, useCallback } from 'react' import BCTypography from '@/components/BCTypography' import Grid2 from '@mui/material/Unstable_Grid2/Grid2' import { useTranslation } from 'react-i18next' +import withComplianceReportAccess from '@/utils/withComplianceReportAcess' import { useLocation, useNavigate, useParams } from 'react-router-dom' import BCBox from '@/components/BCBox' import Loading from '@/components/Loading' @@ -16,7 +17,7 @@ import { v4 as uuid } from 'uuid' import { BCGridEditor } from '@/components/BCDataGrid/BCGridEditor' import * as ROUTES from '@/constants/routes/routes.js' -export const AddEditNotionalTransfers = () => { +const AddEditNotionalTransfers = () => { const [rowData, setRowData] = useState([]) const [errors, setErrors] = useState({}) const [columnDefs, setColumnDefs] = useState([]) @@ -314,3 +315,7 @@ export const AddEditNotionalTransfers = () => { ) ) } + +const AddEditNotionalTransfersWithAccess = withComplianceReportAccess(AddEditNotionalTransfers) + +export default AddEditNotionalTransfersWithAccess \ No newline at end of file diff --git a/frontend/src/views/OtherUses/AddEditOtherUses.jsx b/frontend/src/views/OtherUses/AddEditOtherUses.jsx index 5f101aeea..c4fcea053 100644 --- a/frontend/src/views/OtherUses/AddEditOtherUses.jsx +++ b/frontend/src/views/OtherUses/AddEditOtherUses.jsx @@ -6,6 +6,7 @@ import { useSaveOtherUses } from '@/hooks/useOtherUses' import { cleanEmptyStringValues } from '@/utils/formatters' +import withComplianceReportAccess from '@/utils/withComplianceReportAcess' import BCTypography from '@/components/BCTypography' import Grid2 from '@mui/material/Unstable_Grid2/Grid2' import { useCallback, useEffect, useRef, useState } from 'react' @@ -19,7 +20,7 @@ import { } from './_schema' import * as ROUTES from '@/constants/routes/routes.js' -export const AddEditOtherUses = () => { +const AddEditOtherUses = () => { const [rowData, setRowData] = useState([]) const [errors, setErrors] = useState({}) @@ -386,3 +387,7 @@ export const AddEditOtherUses = () => { ) ) } + +const AddEditOtherUsesWithAccess = withComplianceReportAccess(AddEditOtherUses) + +export default AddEditOtherUsesWithAccess \ No newline at end of file