-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(role based view): implemented a role based view for user groups #175
Changes from 4 commits
68542bf
d661433
bd6cce9
a5da740
b71c930
f2c330c
4eb6b8f
987f041
ff38023
f191132
595f276
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,7 +87,7 @@ | |
] | ||
}, | ||
{ | ||
"username": "onemac-micro-[email protected]", | ||
"username": "[email protected]", | ||
"attributes": [ | ||
{ | ||
"Name": "email", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { OneMacUser, useGetUser } from "@/api/useGetUser"; | ||
import { PropsWithChildren, createContext, useContext } from "react"; | ||
|
||
const initialState = { user: null }; | ||
|
||
export const UserContext = createContext<OneMacUser | undefined>(initialState); | ||
export const UserContextProvider = ({ children }: PropsWithChildren) => { | ||
const { data: userData } = useGetUser(); | ||
return ( | ||
<UserContext.Provider value={userData}>{children}</UserContext.Provider> | ||
); | ||
}; | ||
|
||
export const useUserContext = () => useContext(UserContext); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,9 +9,11 @@ import { AwsCognitoOAuthOpts } from "@aws-amplify/auth/lib-esm/types"; | |
import { Footer } from "../Footer"; | ||
import { UsaBanner } from "../UsaBanner"; | ||
import { FAQ_TARGET } from "@/routes"; | ||
import { useUserContext } from "../Context/userContext"; | ||
import { useOsQuery } from "../Opensearch"; | ||
|
||
const getLinks = (isAuthenticated: boolean) => { | ||
if (isAuthenticated) { | ||
const getLinks = (isAuthenticated: boolean, role?: string) => { | ||
if (isAuthenticated && role !== "onemac-micro-statesubmitter") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure this is right? State Submitters will need Dashboard access as far as I know There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks Keven, This is absolutely not the role we want, i was using this to test. i have a meet to mike at 10. This was what i needed is thought on regarding users. this is also causing e2e to fail because the test is looking for the dashboard to indicate the user is logged in |
||
return [ | ||
{ | ||
name: "Home", | ||
|
@@ -83,14 +85,16 @@ const ResponsiveNav = ({ isDesktop }: ResponsiveNavProps) => { | |
const [prevMediaQuery, setPrevMediaQuery] = useState(isDesktop); | ||
const [isOpen, setIsOpen] = useState(false); | ||
const { isLoading, isError, data } = useGetUser(); | ||
const query = useOsQuery(); | ||
const userContext = useUserContext(); | ||
console.log(userContext, query); | ||
|
||
const handleLogin = () => { | ||
const authConfig = Auth.configure(); | ||
const { domain, redirectSignIn, responseType } = | ||
authConfig.oauth as AwsCognitoOAuthOpts; | ||
const clientId = authConfig.userPoolWebClientId; | ||
const url = `https://${domain}/oauth2/authorize?redirect_uri=${redirectSignIn}&response_type=${responseType}&client_id=${clientId}`; | ||
|
||
window.location.assign(url); | ||
}; | ||
|
||
|
@@ -111,7 +115,7 @@ const ResponsiveNav = ({ isDesktop }: ResponsiveNavProps) => { | |
if (isDesktop) { | ||
return ( | ||
<> | ||
{getLinks(!!data.user).map((link) => ( | ||
{getLinks(!!data.user, data.user?.["custom:cms-roles"]).map((link) => ( | ||
<NavLink | ||
to={link.link} | ||
target={link.link === "/faq" ? FAQ_TARGET : undefined} | ||
|
@@ -149,17 +153,19 @@ const ResponsiveNav = ({ isDesktop }: ResponsiveNavProps) => { | |
{isOpen && ( | ||
<div className="w-full fixed top-[100px] left-0 z-50"> | ||
<ul className="font-medium flex flex-col p-4 md:p-0 mt-2 gap-4 rounded-lg bg-accent"> | ||
{getLinks(!!data.user).map((link) => ( | ||
<li key={link.link}> | ||
<Link | ||
className="block py-2 pl-3 pr-4 text-white rounded" | ||
to={link.link} | ||
target={link.link === "/faq" ? FAQ_TARGET : undefined} | ||
> | ||
{link.name} | ||
</Link> | ||
</li> | ||
))} | ||
{getLinks(!!data.user, data.user?.["custom:cms-roles"]).map( | ||
(link) => ( | ||
<li key={link.link}> | ||
<Link | ||
className="block py-2 pl-3 pr-4 text-white rounded" | ||
to={link.link} | ||
target={link.link === "/faq" ? FAQ_TARGET : undefined} | ||
> | ||
{link.name} | ||
</Link> | ||
</li> | ||
) | ||
)} | ||
<> | ||
{data.user ? ( | ||
<button | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,14 @@ import { LockIcon } from "../LockIcon"; | |
import { GovernmentBuildingIcon } from "../GovernmentBuildingIcon"; | ||
import UsFlag from "@/assets/us_flag_small.png"; | ||
import { useMediaQuery } from "@/hooks"; | ||
import { useUserContext } from "../Context/userContext"; | ||
|
||
export const UsaBanner = () => { | ||
const [isOpen, setIsOpen] = useState(false); | ||
const isDesktop = useMediaQuery("(min-width: 640px)"); | ||
const userContext = useUserContext(); | ||
const role = | ||
userContext?.user?.["custom:cms-roles"] === "onemac-micro-statesubmitter"; | ||
|
||
return ( | ||
<div className="bg-[#f0f0f0]"> | ||
|
@@ -59,6 +63,16 @@ export const UsaBanner = () => { | |
</div> | ||
</button> | ||
)} | ||
{role && ( | ||
<div className="w-full px-4 py-1 lg:px-8 text-xs mx-auto flex gap-2 items-center justify-center bg-red-200 "> | ||
<p className="text-center text-base"> | ||
You do not have access to view the entire application.{" "} | ||
<span className="text-blue-600">Please visit IDM</span> to request | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a link to IDM There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. link from correct link later. |
||
the appropriate user Role(s). | ||
</p> | ||
</div> | ||
)} | ||
|
||
{isOpen && ( | ||
<div className="flex flex-col gap-3 px-3 mt-3 sm:flex-row max-w-screen-lg mx-auto pb-4"> | ||
<div className="flex gap-2"> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { Link, redirect } from "react-router-dom"; | ||
import { Link, redirect, useNavigate } from "react-router-dom"; | ||
import { QueryClient } from "@tanstack/react-query"; | ||
import { getUser, useGetUser } from "@/api/useGetUser"; | ||
import { WaiversList } from "./Lists/waivers"; | ||
|
@@ -13,6 +13,8 @@ import { | |
} from "@/components/Opensearch"; | ||
import { Button } from "@/components/Inputs"; | ||
import { ROUTES } from "@/routes"; | ||
import { useUserContext } from "@/components/Context/userContext"; | ||
import { useEffect } from "react"; | ||
|
||
const loader = (queryClient: QueryClient) => { | ||
return async () => { | ||
|
@@ -33,11 +35,20 @@ const loader = (queryClient: QueryClient) => { | |
return isUser; | ||
}; | ||
}; | ||
|
||
export const dashboardLoader = loader; | ||
|
||
export const Dashboard = () => { | ||
const { data: user } = useGetUser(); | ||
const navigate = useNavigate(); | ||
const userContext = useUserContext(); | ||
const query = useOsQuery(); | ||
const { data } = useGetUser(); | ||
|
||
useEffect(() => { | ||
if (data?.user?.["custom:cms-roles"] === "onemac-micro-reviewer") { | ||
return navigate("/"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if it's worth changing or not, but figured I'd throw a fun fact/tip in. React Router v6 has two ways to navigate! You can use the hook function, or the return data?.user?.["custom:cms-roles"] === "onemac-micro-statesubmitter"
? <Navigate to={ROUTES.HOME} />
: <OsProvider> ... </OsProvider> Again, not sure there's a benefit of one over the other in this case, but it's a nifty tool! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Within the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Navigate is still using the hard string instead of |
||
} | ||
}, []); | ||
|
||
return ( | ||
<OsProvider | ||
|
@@ -51,7 +62,7 @@ export const Dashboard = () => { | |
<div className="max-w-screen-xl mx-auto px-4 lg:px-8"> | ||
<div className="flex items-center justify-between my-4"> | ||
<h1 className="text-xl">Dashboard</h1> | ||
{!user?.isCms && ( | ||
{!userContext?.isCms && ( | ||
<Button> | ||
<Link to={ROUTES.NEW_SUBMISSION_OPTIONS}>New Submission</Link> | ||
</Button> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
satisfies
😎 TypeScript boss right there!