-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(frontend): authenticate with google (#82)
Adding google authentication to Nesis. This introduces a google login button which will allow users to sign in with their google credentials. _Given the recommended way of implementing the google Oauth SDK, the Google button will only display once the google client id is specified in the configurations and the google oath flag is set to true._
- Loading branch information
Showing
17 changed files
with
969 additions
and
34 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import React from 'react'; | ||
import { GoogleOAuthProvider } from '@react-oauth/google'; | ||
import { useConfig } from './ConfigContext'; | ||
|
||
const DefaultConfigContext = React.createContext({}); | ||
|
||
export default function GoogleContextProvider({ children }) { | ||
const config = useConfig(); | ||
const google_client_id = config?.auth?.OAUTH_GOOGLE_CLIENT_ID; | ||
const googleAuthEnabled = | ||
google_client_id && config?.auth?.OAUTH_GOOGLE_ENABLED; | ||
return ( | ||
<> | ||
{googleAuthEnabled ? ( | ||
<GoogleOAuthProvider | ||
value={google_client_id} | ||
clientId={google_client_id} | ||
> | ||
{children} | ||
</GoogleOAuthProvider> | ||
) : ( | ||
<DefaultConfigContext.Provider value={googleAuthEnabled}> | ||
{children} | ||
</DefaultConfigContext.Provider> | ||
)} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import React, { useEffect } from 'react'; | ||
import { useGoogleLogin } from '@react-oauth/google'; | ||
import useClient from '../utils/useClient'; | ||
import parseApiErrorMessage from '../utils/parseApiErrorMessage'; | ||
import GoogleIcon from '../images/GoogleIcon.png'; | ||
import classes from '../styles/SignInPage.module.css'; | ||
import { useConfig } from '../ConfigContext'; | ||
|
||
export default function GoogleButton({ onFailure, onSuccess }) { | ||
const client = useClient(); | ||
const config = useConfig(); | ||
|
||
const googleLogin = useGoogleLogin({ | ||
ux_mode: 'redirect', | ||
flow: 'auth-code', | ||
redirect_uri: config?.auth?.OAUTH_GOOGLE_REDIRECTURI, | ||
}); | ||
|
||
useEffect(() => { | ||
const queryString = window.location.search; | ||
const urlParams = new URLSearchParams(queryString); | ||
const codeParam = urlParams.get('code'); | ||
|
||
if (codeParam) { | ||
client | ||
.post('sessions', { | ||
google: codeParam, | ||
}) | ||
.then((response) => { | ||
onSuccess(response?.body?.email, response); | ||
}) | ||
.catch((error) => { | ||
onFailure(parseApiErrorMessage(error)); | ||
}); | ||
} else { | ||
const error = 'Failed to Login'; | ||
handleFailure(error); | ||
} | ||
}, []); | ||
|
||
function handleFailure(error) { | ||
onFailure('Could not login using Google'); | ||
} | ||
|
||
return ( | ||
<> | ||
<button className={`${classes.orloginbutton} my-3`} onClick={googleLogin}> | ||
<img | ||
alt="Sign in with Google" | ||
className={`${classes.loginorimg} mx-1`} | ||
src={GoogleIcon} | ||
/> | ||
Sign in with Google | ||
</button> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from 'react'; | ||
import { renderWithContext, renderWithRouter } from '../utils/testUtils'; | ||
import GoogleButton from './GoogleButton'; | ||
|
||
describe('<GoogleButton>', () => { | ||
it('render google authenticate option on login and register screen', async () => { | ||
const { getByText } = renderWithContext(<GoogleButton />); | ||
const buttonComponent = getByText('Sign in With Google'); | ||
expect(buttonComponent).toBeInTheDocument(); | ||
}); | ||
}); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import React from 'react'; | ||
import { createMemoryHistory } from 'history'; | ||
import { Router } from 'react-router-dom'; | ||
import { render } from '@testing-library/react'; | ||
import { ToasterContextProvider } from '../ToasterContext'; | ||
import { QueryClient, QueryClientProvider } from 'react-query'; | ||
import { ConfigContextProvider } from '../ConfigContext'; | ||
import GoogleContextProvider from './GoogleAuthContext'; | ||
|
||
export function renderWithRouter( | ||
ui, | ||
{ | ||
route = '/', | ||
history = createMemoryHistory({ initialEntries: [route] }), | ||
} = {}, | ||
) { | ||
const Wrapper = ({ children }) => ( | ||
<Router history={history}>{children}</Router> | ||
); | ||
return { | ||
...render(ui, { wrapper: Wrapper }), | ||
history, | ||
}; | ||
} | ||
|
||
const queryClient = new QueryClient(); | ||
|
||
export function renderWithContext(ui, options) { | ||
return { | ||
...renderWithRouter( | ||
<ToasterContextProvider> | ||
<ConfigContextProvider> | ||
<GoogleContextProvider>{ui}</GoogleContextProvider> | ||
</ConfigContextProvider> | ||
</ToasterContextProvider>, | ||
options, | ||
), | ||
}; | ||
} | ||
|
||
export function mockGetImplementation(config) { | ||
return function get(path) { | ||
if (config[path]) { | ||
return Promise.resolve({ | ||
body: config[path], | ||
}); | ||
} else { | ||
throw new Error('Unexpected request path=' + path); | ||
} | ||
}; | ||
} |
Oops, something went wrong.