component based on enumScope

This commit is contained in:
eglehelms
2022-11-24 16:22:19 +01:00
parent 5af7471886
commit 1666703c13
6 changed files with 96 additions and 11 deletions
+2
View File
@@ -1,4 +1,5 @@
import type { Vendor } from "src/vendor/types";
import type { Scope } from "src/store/types";
/** Simple types */
@@ -116,6 +117,7 @@ export interface User {
service_provider_sid?: string | null;
initial_password?: string;
permissions?: UserPermissions;
enumScope: Scope;
}
export interface UserLogin extends User {
+43
View File
@@ -0,0 +1,43 @@
import React from "react";
import { H1, H2 } from "jambonz-ui";
import { TestProvider } from "src/test";
import { ScopedAccess } from "./scoped-access";
import type { ScopedAccessProps } from "./scoped-access";
/** Wrapper to pass different user scopes as enum values */
const ScopedAccessTestWrapper = (props: Partial<ScopedAccessProps>) => {
return (
<TestProvider>
<ScopedAccess
enumScope={props.enumScope!}
noAccessRender={<H2>{"noAccessRender"}</H2>}
>
<div className="scope-div">
<H1>ScopedAccess: {props.enumScope}</H1>
</div>
</ScopedAccess>
</TestProvider>
);
};
describe("<ScopedAccess>", () => {
it("has sufficient scope - admin", () => {
cy.mount(<ScopedAccessTestWrapper enumScope={0} />);
cy.get(".scope-div").should("exist");
cy.get("h1").should("exist");
});
it("has insufficient scope - service_provider", () => {
cy.mount(<ScopedAccessTestWrapper enumScope={1} />);
cy.get(".scope-div").should("not.exist");
cy.get("h2").should("exist");
});
it("has insufficient scope - account", () => {
cy.mount(<ScopedAccessTestWrapper enumScope={2} />);
cy.get(".scope-div").should("not.exist");
cy.get("h2").should("exist");
});
});
+29
View File
@@ -0,0 +1,29 @@
import React from "react";
import { useSelectState } from "src/store";
import type { Scope } from "src/store/types";
export type ScopedAccessProps = {
enumScope: Scope;
children: React.ReactNode;
noAccessRender?: React.ReactNode;
};
export const ScopedAccess = ({
enumScope,
children,
noAccessRender,
}: ScopedAccessProps) => {
const user = useSelectState("user");
if (user && user.enumScope <= enumScope) {
return <>{children}</>;
}
if (user && user.enumScope >= enumScope && noAccessRender) {
return <>{noAccessRender}</>;
}
return null;
};
+12 -9
View File
@@ -16,6 +16,7 @@ import { postServiceProviders } from "src/api";
import type { NaviItem } from "./items";
import "./styles.scss";
import { ScopedAccess } from "src/components/scoped-access";
type CommonProps = {
handleMenu: () => void;
@@ -149,7 +150,7 @@ export const Navi = ({
);
})
) : (
<option>&nbsp;</option>
<option>currentServiceProvider.name</option>
)}
</select>
<span>
@@ -158,14 +159,16 @@ export const Navi = ({
</span>
</div>
</div>
<button
type="button"
onClick={() => setModal(true)}
title="Add service provider"
className="btnty"
>
<Icons.PlusCircle />
</button>
<ScopedAccess enumScope={0}>
<button
type="button"
onClick={() => setModal(true)}
title="Add service provider"
className="btnty"
>
<Icons.PlusCircle />
</button>
</ScopedAccess>
</div>
{/* Intentionally hiding this as we will need to work this out as we go... */}
{/* ACL component will need to be updated for new user scope/permissions handling */}
+4 -2
View File
@@ -3,7 +3,8 @@ import { sortLocaleName } from "src/utils";
import { getToken, parseJwt } from "src/router/auth";
import type { State, Action } from "./types";
import type { ServiceProvider, User } from "src/api/types";
import { Scope } from "./types";
import { ServiceProvider, User } from "src/api/types";
/** A generic action assumes action.type is ALWAYS our state key */
/** Since this is how we're designing our state interface we cool */
@@ -63,7 +64,8 @@ export const currentServiceProviderAction = (
export const userAsyncAction = async (): Promise<User> => {
const token = getToken();
return parseJwt(token);
const userData = parseJwt(token);
return { ...userData, enumScope: Scope[userData.scope] };
};
export const serviceProvidersAsyncAction = async (): Promise<
+6
View File
@@ -14,6 +14,12 @@ export interface ACL {
hasMSTeamsFqdn: boolean;
}
export enum Scope {
"admin" = 0,
"service_provider" = 1,
"account" = 2,
}
export interface FeatureFlag {
development: boolean;
}