CEC-2977 Filter portal access based on auth provider (#231)

* fix/fleet-vehicles-search

* fix/fleet-name-update

* Update hasRole logic, create RoleWrap component

* Add MAGNA and MAGNAGROUP env vars

* Add Permissions

Co-authored-by: jwu-fisker <jwu@fiskerinc.com>
This commit is contained in:
arpanetus
2022-11-09 06:46:33 +06:00
committed by GitHub
parent 94950d583e
commit f2f046968e
76 changed files with 1321 additions and 917 deletions

View File

@@ -9,7 +9,7 @@ import { ManifestsProvider } from "../../Contexts/ManifestsContext";
import { UserProvider, setToken } from "../../Contexts/UserContext";
import { StatusProvider } from "../../Contexts/StatusContext";
import ManifestDetails from ".";
import { TEST_AUTH_OBJECT } from "../../../utils/testing";
import { TEST_AUTH_OBJECT_FISKER } from "../../../utils/testing";
import addSnapshotSerializer from "../../../utils/snapshot";
const TestComponent = (opened) => (
@@ -26,7 +26,7 @@ const TestComponent = (opened) => (
describe("Manifest Details Component", () => {
beforeAll(() => {
setToken(TEST_AUTH_OBJECT);
setToken(TEST_AUTH_OBJECT_FISKER);
addSnapshotSerializer(expect);
});

View File

@@ -1,5 +1,3 @@
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import {
Grid,
Table,
@@ -10,28 +8,30 @@ import {
TableRow,
Tooltip,
} from "@material-ui/core";
import DeleteIcon from "@material-ui/icons/Delete";
import SendIcon from "@material-ui/icons/Send";
import VisibilityIcon from "@material-ui/icons/Visibility";
import DeleteIcon from "@material-ui/icons/Delete";
import clsx from "clsx";
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import {
useManifestsContext,
ManifestsProvider,
} from "../../Contexts/ManifestsContext";
import { useUserContext } from "../../Contexts/UserContext";
import { useStatusContext } from "../../Contexts/StatusContext";
import useStyles from "../../useStyles";
import { LocalDateTimeString } from "../../../utils/dates";
import TableHeaderSortable from "../../Table/HeaderSortable";
import SearchField from "../../Controls/SearchField";
import { logger } from "../../../services/monitoring";
import ECUList from "../../Controls/ECUList";
import { Roles, hasRole } from "../../../utils/roles";
import { useLocalStorage } from "../../useLocalStorage";
import { TYPE_MANIFEST_SOFTWARE } from "../../../utils/manifest_types";
import DeleteConfirmation from "../../DeleteConfirmation";
import EditIcon from "@material-ui/icons/Edit";
import { logger } from "../../../services/monitoring";
import { LocalDateTimeString } from "../../../utils/dates";
import { TYPE_MANIFEST_SOFTWARE } from "../../../utils/manifest_types";
import { hasRole, Permissions } from "../../../utils/roles";
import {
ManifestsProvider,
useManifestsContext,
} from "../../Contexts/ManifestsContext";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import ECUList from "../../Controls/ECUList";
import SearchField from "../../Controls/SearchField";
import DeleteConfirmation from "../../DeleteConfirmation";
import TableHeaderSortable from "../../Table/HeaderSortable";
import { useLocalStorage } from "../../useLocalStorage";
import useStyles from "../../useStyles";
const tableColumns = [
{
@@ -71,7 +71,7 @@ const formatManifestType = (type) => {
default:
return "Standard";
}
}
};
const PAGE_SIZE = "MANIFEST_LIST_PAGE_SIZE";
@@ -95,6 +95,7 @@ const MainForm = () => {
idToken: { jwtToken: token },
},
groups,
providers,
} = useUserContext();
const sortHandler = (event, property) => {
@@ -155,7 +156,7 @@ const MainForm = () => {
setDeleteId(id);
setDeleteRowName(`${row.name} ${row.version}`);
setShowDeleteModal(true);
}
};
const onDelete = async (manifest_id) => {
try {
@@ -168,29 +169,30 @@ const MainForm = () => {
const Actions = (row) => {
let actions = [];
if (hasRole([Roles.CREATE, Roles.READ], groups)) {
if (hasRole(groups, Permissions.FiskerMagnaRead, providers)) {
actions.push({
tip: `Status "${row.name} ${row.version}"`,
link: `/package-status/${row.id}`,
icon: (
<VisibilityIcon aria-label={`Status ${row.name} ${row.version}`} />
),
}, {
tip: `Update "${row.name} ${row.version}"`,
link: `/package-update/${row.id}`,
icon: (
<EditIcon aria-label={`Update ${row.name} ${row.version}`} />
),
});
}
if (hasRole([Roles.CREATE], groups)) {
if (hasRole(groups, Permissions.FiskerRead, providers)) {
actions.push({
tip: `Update "${row.name} ${row.version}"`,
link: `/package-update/${row.id}`,
icon: <EditIcon aria-label={`Update ${row.name} ${row.version}`} />,
});
}
if (hasRole(groups, Permissions.FiskerMagnaCreate, providers)) {
actions.push({
tip: `Deploy "${row.name} ${row.version}"`,
link: `/package-deploy/${row.id}`,
icon: <SendIcon aria-label={`Deploy ${row.name} ${row.version}`} />,
});
}
if (hasRole([Roles.DELETE], groups)) {
if (hasRole(groups, Permissions.FiskerDelete, providers)) {
actions.push({
tip: `Delete "${row.name} ${row.version}"`,
id: row.id,
@@ -257,7 +259,9 @@ const MainForm = () => {
)}
</TableCell>
<TableCell align="center">{row.version}</TableCell>
<TableCell align="center">{formatManifestType(row.type)}</TableCell>
<TableCell align="center">
{formatManifestType(row.type)}
</TableCell>
<TableCell align="center">
{LocalDateTimeString(row.created)}
</TableCell>
@@ -290,7 +294,8 @@ const MainForm = () => {
message={deleteRowName}
open={showDeleteModal}
close={() => setShowDeleteModal(false)}
deleteFunction={() => onDelete(deleteId)} />
deleteFunction={() => onDelete(deleteId)}
/>
</div>
);
};

View File

@@ -1,6 +1,3 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router";
import { Link } from "react-router-dom";
import {
LinearProgress,
Table,
@@ -14,22 +11,27 @@ import {
} from "@material-ui/core";
import CancelIcon from "@material-ui/icons/Cancel";
import clsx from "clsx";
import React, { useEffect, useState } from "react";
import { useParams } from "react-router";
import { Link } from "react-router-dom";
import {
ManifestsProvider,
useManifestsContext,
} from "../../Contexts/ManifestsContext";
import { logger } from "../../../services/monitoring";
import { LocalDateTimeString } from "../../../utils/dates";
import { Permissions } from "../../../utils/roles";
import {
CarUpdatesProvider,
useCarUpdatesContext,
} from "../../Contexts/CarUpdatesContext";
import { useUserContext } from "../../Contexts/UserContext";
import {
ManifestsProvider,
useManifestsContext,
} from "../../Contexts/ManifestsContext";
import { useStatusContext } from "../../Contexts/StatusContext";
import useStyles from "../../useStyles";
import { LocalDateTimeString } from "../../../utils/dates";
import { logger } from "../../../services/monitoring";
import ManifestDetails from "../Details";
import { useUserContext } from "../../Contexts/UserContext";
import { RoleWrap } from "../../Controls/RoleWrap";
import { useLocalStorage } from "../../useLocalStorage";
import useStyles from "../../useStyles";
import ManifestDetails from "../Details";
const PAGE_SIZE = "MANIFEST_STATUS_PAGE_SIZE";
@@ -52,6 +54,8 @@ const MainForm = () => {
token: {
idToken: { jwtToken: token },
},
groups,
providers,
} = useUserContext();
useEffect(() => {
@@ -172,11 +176,18 @@ const MainForm = () => {
{LocalDateTimeString(row.updated)}
</TableCell>
<TableCell>
<Tooltip key={row.vin} title={`Send cancel for ${row.vin}`}>
<Link to="#" onClick={() => sendCancel(row)}>
<CancelIcon />
</Link>
</Tooltip>
<RoleWrap
groups={groups}
providers={providers}
rolesPerProvider={Permissions.FiskerCreate}
eitherComponent={<>No action</>}
>
<Tooltip key={row.vin} title={`Send cancel for ${row.vin}`}>
<Link to="#" onClick={() => sendCancel(row)}>
<CancelIcon />
</Link>
</Tooltip>
</RoleWrap>
</TableCell>
</TableRow>
))}

View File

@@ -49,9 +49,7 @@ const MainForm = () => {
const onSubmit = async (e) => {
e.preventDefault();
try {
const data = {name, type};
console.log(data);
const result = await updateManifest(manifest_id, data, token);
const result = await updateManifest(manifest_id, {name, type}, token);
if (!result || result.error) return;
setMessage(`Updated manifest ${manifest_id}`);

View File

@@ -9,7 +9,7 @@ import { ManifestsProvider } from "../../Contexts/ManifestsContext";
import { UserProvider, setToken } from "../../Contexts/UserContext";
import { StatusProvider } from "../../Contexts/StatusContext";
import ManifestUpdate from ".";
import { TEST_AUTH_OBJECT } from "../../../utils/testing";
import { TEST_AUTH_OBJECT_FISKER } from "../../../utils/testing";
import addSnapshotSerializer from "../../../utils/snapshot";
const renderManifestUpdate = async () => {
@@ -33,12 +33,12 @@ const renderManifestUpdate = async () => {
describe("Manifest Details Component", () => {
beforeAll(() => {
setToken(TEST_AUTH_OBJECT);
setToken(TEST_AUTH_OBJECT_FISKER);
addSnapshotSerializer(expect);
});
it("Render", async () => {
setToken(TEST_AUTH_OBJECT);
setToken(TEST_AUTH_OBJECT_FISKER);
const view = await renderManifestUpdate();
expect(view).toMatchSnapshot();
});