Skip to content

Commit

Permalink
Merge pull request #61 from aldbr/main_FIX-multi-vo-login
Browse files Browse the repository at this point in the history
fix theme and simplify multi-vo login a bit
  • Loading branch information
aldbr authored Jan 25, 2024
2 parents a35ddb6 + 141c59b commit 1c04fb1
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 56 deletions.
18 changes: 5 additions & 13 deletions src/components/applications/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,16 @@ export function LoginForm() {
const { data, error, isLoading } = useMetadata();
const [selectedVO, setSelectedVO] = useState<string | null>(null);
const [selectedGroup, setSelectedGroup] = useState<string | null>(null);
const {
configuration,
setConfiguration,
configurationName,
setConfigurationName,
} = useOIDCContext();
const { isAuthenticated, login } = useOidc(configurationName);
const { configuration, setConfiguration } = useOIDCContext();
const { isAuthenticated, login } = useOidc(configuration?.scope);

// Login if not authenticated
useEffect(() => {
if (configurationName && isAuthenticated === false) {
if (configuration && configuration.scope && isAuthenticated === false) {
sessionStorage.setItem("oidcScope", JSON.stringify(configuration.scope));
login();
}
}, [configurationName, isAuthenticated, login]);
}, [configuration, isAuthenticated, login]);

// Get default group
const getDefaultGroup = (data: Metadata | undefined, vo: string): string => {
Expand Down Expand Up @@ -87,10 +83,6 @@ export function LoginForm() {
...configuration,
scope: newScope,
});
setConfigurationName(newScope);

sessionStorage.setItem("oidcConfigName", JSON.stringify(newScope));
login();
}
};
// Redirect to dashboard if already authenticated
Expand Down
4 changes: 2 additions & 2 deletions src/components/applications/UserDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { useOIDCContext } from "@/hooks/oidcConfiguration";
*/
export default function UserDashboard() {
const theme = useMUITheme();
const { configurationName } = useOIDCContext();
const { accessTokenPayload } = useOidcAccessToken(configurationName);
const { configuration } = useOIDCContext();
const { accessTokenPayload } = useOidcAccessToken(configuration?.scope);

return (
<React.Fragment>
Expand Down
16 changes: 5 additions & 11 deletions src/components/layout/OIDCProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,16 @@ interface OIDCProviderProps {
* @returns the wrapper around OidcProvider
*/
export function OIDCProvider(props: OIDCProviderProps) {
const {
configuration,
setConfiguration,
configurationName,
setConfigurationName,
} = useOIDCContext();
const { configuration, setConfiguration } = useOIDCContext();
const diracxUrl = useDiracxUrl();

useEffect(() => {
if (!configuration && !configurationName && diracxUrl) {
if (!configuration && diracxUrl) {
// Get the OIDC configuration name from the session storage if it exists
let scope = sessionStorage.getItem("oidcConfigName") || ``;
let scope = sessionStorage.getItem("oidcScope") || ``;

if (scope) {
scope = scope.replace(/^"|"$/g, "");
setConfigurationName(scope);
}

// Set the OIDC configuration
Expand All @@ -41,7 +35,7 @@ export function OIDCProvider(props: OIDCProviderProps) {
redirect_uri: `${diracxUrl}/#authentication-callback`,
});
}
}, [diracxUrl, configuration, setConfiguration]);
}, [diracxUrl, configuration]);

const withCustomHistory = () => {
return {
Expand All @@ -61,7 +55,7 @@ export function OIDCProvider(props: OIDCProviderProps) {
<>
<OidcProvider
configuration={configuration}
configurationName={configurationName}
configurationName={configuration.scope}
withCustomHistory={withCustomHistory}
>
<main>{props.children}</main>
Expand Down
4 changes: 2 additions & 2 deletions src/components/layout/OIDCSecure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ interface OIDCProps {
* @returns The children if the user is authenticated, null otherwise
*/
export function OIDCSecure({ children }: OIDCProps) {
const { configurationName } = useOIDCContext();
const { isAuthenticated } = useOidc(configurationName);
const { configuration } = useOIDCContext();
const { isAuthenticated } = useOidc(configuration?.scope);
const router = useRouter();

// Redirect to login page if not authenticated
Expand Down
4 changes: 2 additions & 2 deletions src/components/ui/DashboardButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Link from "next/link";
* @returns a Button
*/
export function DashboardButton() {
const { configurationName } = useOIDCContext();
const { isAuthenticated } = useOidc(configurationName);
const { configuration } = useOIDCContext();
const { isAuthenticated } = useOidc(configuration?.scope);

// Render null if the OIDC configuration is not ready or no access token is available
if (!isAuthenticated) {
Expand Down
14 changes: 9 additions & 5 deletions src/components/ui/ProfileButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import React from "react";
* @returns a Button
*/
export function ProfileButton() {
const { configurationName, setConfigurationName } = useOIDCContext();
const { accessTokenPayload } = useOidcAccessToken(configurationName);
const { logout, isAuthenticated } = useOidc(configurationName);
const { configuration, setConfiguration } = useOIDCContext();
const { accessTokenPayload } = useOidcAccessToken(configuration?.scope);
const { logout, isAuthenticated } = useOidc(configuration?.scope);

const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
Expand All @@ -35,9 +35,13 @@ export function ProfileButton() {
setAnchorEl(null);
};
const handleLogout = () => {
if (!configuration) {
return;
}

// Remove the OIDC configuration name from the session storage
setConfigurationName(undefined);
sessionStorage.removeItem("oidcConfigName");
setConfiguration({ ...configuration, scope: `` });
sessionStorage.removeItem("oidcScope");
logout();
};

Expand Down
9 changes: 0 additions & 9 deletions src/contexts/OIDCConfigurationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@ import { OIDCProvider } from "@/components/layout/OIDCProvider";
export const OIDCConfigurationContext = createContext<{
configuration: OidcConfiguration | null;
setConfiguration: (config: OidcConfiguration | null) => void;
configurationName: string | undefined;
setConfigurationName: (name: string | undefined) => void;
}>({
configuration: null,
setConfiguration: () => {},
configurationName: undefined,
setConfigurationName: () => {},
});

/**
Expand All @@ -35,17 +31,12 @@ export const OIDCConfigurationProvider = ({
const [configuration, setConfiguration] = useState<OidcConfiguration | null>(
null,
);
const [configurationName, setConfigurationName] = useState<
string | undefined
>(undefined);

return (
<OIDCConfigurationContext.Provider
value={{
configuration,
setConfiguration,
configurationName,
setConfigurationName,
}}
>
<OIDCProvider>{children}</OIDCProvider>
Expand Down
24 changes: 17 additions & 7 deletions src/contexts/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"use client";
import { useMediaQuery } from "@mui/material";
import { createContext, useState } from "react";
import { createContext, useEffect, useState } from "react";

/**
* Theme context type
* @property theme - the current theme mode
* @property toggleTheme - function to toggle the theme mode
*/
type ThemeContextType = {
theme: "light" | "dark";
theme: string;
toggleTheme: () => void;
};

Expand All @@ -30,12 +30,22 @@ export const ThemeContext = createContext<ThemeContextType | undefined>(
* ThemeProvider component to provide the theme context to its children
*/
export const ThemeProvider = ({ children }: ThemeProviderProps) => {
// State to manage the current theme mode
const [theme, setTheme] = useState<"light" | "dark">(
useMediaQuery("(prefers-color-scheme: dark)") ? "dark" : "light",
);
// Read the initial theme from localStorage
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const storedTheme = localStorage.getItem("theme");
const defaultTheme = storedTheme
? storedTheme
: prefersDarkMode
? "dark"
: "light";

const [theme, setTheme] = useState<string>(defaultTheme);

// Update localStorage when the theme changes
useEffect(() => {
localStorage.setItem("theme", theme);
}, [theme]);

// Function to toggle the theme mode
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/jobs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { useOIDCContext } from "./oidcConfiguration";
* @returns the jobs
*/
export function useJobs() {
const { configurationName } = useOIDCContext();
const { configuration } = useOIDCContext();
const diracxUrl = useDiracxUrl();
const { accessToken } = useOidcAccessToken(configurationName);
const { accessToken } = useOidcAccessToken(configuration?.scope);

const url = `${diracxUrl}/api/jobs/search?page=0&per_page=100`;
const { data, error } = useSWR([url, accessToken, "POST"], fetcher);
Expand Down
4 changes: 3 additions & 1 deletion src/hooks/theme.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ThemeContext } from "@/contexts/ThemeProvider";
import { PaletteMode } from "@mui/material";
import { createTheme } from "@mui/material/styles";
import { useContext } from "react";

Expand All @@ -20,13 +21,14 @@ export const useTheme = () => {
* @returns the Material-UI theme
* @throws an error if the hook is not used within a ThemeProvider
*/

export const useMUITheme = () => {
const { theme } = useTheme();

// Create a Material-UI theme based on the current mode
const muiTheme = createTheme({
palette: {
mode: theme,
mode: theme as PaletteMode,
primary: {
main: "#ffffff",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { render, fireEvent } from "@testing-library/react";
import { ProfileButton } from "@/components/ui/ProfileButton";
import { useOidcAccessToken, useOidc } from "@axa-fr/react-oidc";
import { OIDCConfigurationContext } from "@/contexts/OIDCConfigurationProvider";

// Mocking the hooks
jest.mock("@axa-fr/react-oidc");
Expand Down Expand Up @@ -51,11 +52,20 @@ describe("<ProfileButton />", () => {
logout: mockLogout,
});
(useOidcAccessToken as jest.Mock).mockReturnValue({
accessToken: "mockAccessToken",
accessTokenPayload: { preferred_username: "John" },
});

const { getByText } = render(<ProfileButton />);
// Mock context value
const mockContextValue = {
configuration: { scope: "mockScope" },
setConfiguration: jest.fn(),
};

const { getByText } = render(
<OIDCConfigurationContext.Provider value={mockContextValue}>
<ProfileButton />
</OIDCConfigurationContext.Provider>,
);

// Open the menu by clicking the avatar
fireEvent.click(getByText("J"));
Expand Down

0 comments on commit 1c04fb1

Please sign in to comment.