saleor-dashboard/src/auth/hooks/useAuthProvider.ts

203 lines
5.3 KiB
TypeScript
Raw Normal View History

2021-01-26 22:04:54 +00:00
import { IMessageContext } from "@saleor/components/messages";
import { APP_DEFAULT_URI, APP_MOUNT_URI, DEMO_MODE } from "@saleor/config";
import useNavigator from "@saleor/hooks/useNavigator";
import { commonMessages } from "@saleor/intl";
import {
GetExternalAccessTokenData,
LoginData,
useAuth,
useAuthState
} from "@saleor/sdk";
import {
isSupported as isCredentialsManagementAPISupported,
login as loginWithCredentialsManagementAPI,
saveCredentials
} from "@saleor/utils/credentialsManagement";
2021-01-26 22:04:54 +00:00
import ApolloClient from "apollo-client";
import { useEffect, useRef, useState } from "react";
import { useQuery } from "react-apollo";
2021-01-26 22:04:54 +00:00
import { IntlShape } from "react-intl";
import urlJoin from "url-join";
2021-01-26 22:04:54 +00:00
import { userDetailsQuery } from "../queries";
import {
ExternalLoginInput,
RequestExternalLoginInput,
RequestExternalLogoutInput,
UserContext,
UserContextError
} from "../types";
import { UserDetails } from "../types/UserDetails";
import { displayDemoMessage } from "../utils";
2021-01-26 22:04:54 +00:00
export interface UseAuthProviderOpts {
intl: IntlShape;
notify: IMessageContext;
apolloClient: ApolloClient<any>;
}
export function useAuthProvider({
intl,
notify,
apolloClient
}: UseAuthProviderOpts): UserContext {
const {
login,
getExternalAuthUrl,
getExternalAccessToken,
logout
} = useAuth();
const navigate = useNavigator();
const { authenticated, authenticating, user } = useAuthState();
const [error, setError] = useState<UserContextError>();
const permitCredentialsAPI = useRef(true);
2021-01-26 22:04:54 +00:00
useEffect(() => {
if (authenticating && error) {
setError(undefined);
}
}, [authenticating]);
useEffect(() => {
if (authenticated) {
permitCredentialsAPI.current = true;
}
}, [authenticated]);
useEffect(() => {
if (!authenticated && !authenticating && permitCredentialsAPI.current) {
permitCredentialsAPI.current = false;
loginWithCredentialsManagementAPI(handleLogin);
}
}, [authenticated, authenticating]);
2021-01-26 22:04:54 +00:00
const userDetails = useQuery<UserDetails>(userDetailsQuery, {
client: apolloClient,
skip: !authenticated,
// Don't change this to 'network-only' - update of intl provider's
// state will cause an error
fetchPolicy: "cache-and-network"
2021-01-26 22:04:54 +00:00
});
const handleLogout = async () => {
const path = APP_MOUNT_URI === APP_DEFAULT_URI ? "" : APP_MOUNT_URI;
const returnTo = urlJoin(window.location.origin, path);
const result = await logout({
input: JSON.stringify({
returnTo
} as RequestExternalLogoutInput)
});
if (isCredentialsManagementAPISupported) {
navigator.credentials.preventSilentAccess();
}
// Forget last logged in user data.
// On next login, user details query will be refetched due to cache-and-network fetch policy.
apolloClient.clearStore();
const errors = result?.errors || [];
const externalLogoutUrl = result
? JSON.parse(result.data?.externalLogout?.logoutData || null)?.logoutUrl
: "";
if (!errors.length) {
if (externalLogoutUrl) {
window.location.href = externalLogoutUrl;
} else {
navigate("/");
}
}
return;
};
const handleLogin = async (email: string, password: string) => {
try {
const result = await login({
email,
password
});
if (result && !result.data.tokenCreate.errors.length) {
if (DEMO_MODE) {
displayDemoMessage(intl, notify);
}
saveCredentials(result.data.tokenCreate.user, password);
} else {
setError("loginError");
}
await logoutNonStaffUser(result.data.tokenCreate);
return result.data.tokenCreate;
} catch (error) {
setError("serverError");
}
};
const handleRequestExternalLogin = async (
pluginId: string,
input: RequestExternalLoginInput
) => {
const result = await getExternalAuthUrl({
pluginId,
input: JSON.stringify(input)
});
return result?.data?.externalAuthenticationUrl;
};
const handleExternalLogin = async (
pluginId: string,
input: ExternalLoginInput
) => {
try {
const result = await getExternalAccessToken({
pluginId,
input: JSON.stringify(input)
});
if (result && !result.data?.externalObtainAccessTokens.errors.length) {
if (DEMO_MODE) {
displayDemoMessage(intl, notify);
}
} else {
setError("externalLoginError");
}
await logoutNonStaffUser(result.data.externalObtainAccessTokens);
return result?.data?.externalObtainAccessTokens;
} catch (error) {
setError("serverError");
}
2021-01-26 22:04:54 +00:00
};
const logoutNonStaffUser = async (
data: LoginData | GetExternalAccessTokenData
) => {
if (data.user && !data.user.isStaff) {
notify({
status: "error",
text: intl.formatMessage(commonMessages.unauthorizedDashboardAccess),
title: intl.formatMessage(commonMessages.insufficientPermissions)
});
await handleLogout();
}
};
2021-01-26 22:04:54 +00:00
return {
login: handleLogin,
requestLoginByExternalPlugin: handleRequestExternalLogin,
loginByExternalPlugin: handleExternalLogin,
logout: handleLogout,
authenticating: authenticating && !error,
authenticated: authenticated && user?.isStaff,
user: userDetails.data?.me,
error
2021-01-26 22:04:54 +00:00
};
}