diff --git a/pages/api/auth/[...nextauth].ts b/pages/api/auth/[...nextauth].ts index cafdf9731..88bf96f6c 100644 --- a/pages/api/auth/[...nextauth].ts +++ b/pages/api/auth/[...nextauth].ts @@ -128,7 +128,6 @@ const createOptions = (req: NextApiRequest) => ({ // e.g. domain, username, password, 2FA token, etc. credentials: { token: { label: 'Token', type: 'text' }, - rpcUrl: { label: 'rpc url', type: 'text' }, instanceURL: { label: 'Instance url', type: 'text' }, }, async authorize(credentials) { @@ -137,10 +136,7 @@ const createOptions = (req: NextApiRequest) => ({ // Initialize instance api url initialize({ apiURL: credentials.instanceURL }); - const data = await AuthLinkAPI.loginWithAccessToken( - credentials.token, - credentials.rpcUrl, - ); + const data = await AuthLinkAPI.loginWithAccessToken(credentials.token); if (!data?.token?.accessToken) throw Error('Failed to authorize user!'); diff --git a/src/components/Login/Login.tsx b/src/components/Login/Login.tsx index f3da341c9..85da63381 100644 --- a/src/components/Login/Login.tsx +++ b/src/components/Login/Login.tsx @@ -18,6 +18,7 @@ import { Accounts } from './render/Accounts'; import CreateAccounts from './render/CreateAccounts/CreateAccounts'; import LoginByEmail from './render/Email/LoginByEmail'; import { Options } from './render/Options'; +import LoginByPAT from './render/PAT/LoginByPAT'; import { Profile } from './render/Profile'; import SigninMethod from './render/SignInMethod/SigninMethod'; @@ -345,6 +346,12 @@ export const Login: React.FC = props => { element={} /> + } + /> + + createStyles({ + root: { + position: 'relative', + maxHeight: 'fit-content', + maxWidth: 508, + background: '#FFFFFF', + borderRadius: 10, + padding: 40, + boxShadow: '0px 2px 10px rgba(0, 0, 0, 0.05)', + display: 'flex', + flexDirection: 'column', + gap: 24, + '& .MuiFormControl-root': { + marginBottom: 0, + }, + }, + title: { + fontSize: 18, + fontWeight: 'bold', + color: 'black', + textAlign: 'center', + }, + subtitle: { + fontSize: 14, + fontWeight: 'normal', + color: 'black', + textAlign: 'center', + }, + actionWrapper: { + display: 'flex', + flexDirection: 'row', + gap: 24, + }, + }), +); diff --git a/src/components/Login/render/PAT/LoginByPAT.tsx b/src/components/Login/render/PAT/LoginByPAT.tsx new file mode 100644 index 000000000..73e52c294 --- /dev/null +++ b/src/components/Login/render/PAT/LoginByPAT.tsx @@ -0,0 +1,122 @@ +import { useState } from 'react'; +import { useCookies } from 'react-cookie'; +import { useNavigate } from 'react-router'; + +import { signIn } from 'next-auth/react'; +import getConfig from 'next/config'; +import { useRouter } from 'next/router'; + +import { Button, TextField, Typography } from '@material-ui/core'; + +import { useStyles } from './LoginByPAT.style'; + +import { COOKIE_INSTANCE_URL } from 'components/SelectServer'; +import SelectServer from 'src/components/SelectServer'; +import { useAlertHook } from 'src/hooks/use-alert.hook'; +import { ServerListProps } from 'src/interfaces/server-list'; +import i18n from 'src/locale'; + +type LoginByPATProps = { + onNext: ( + successCallback: () => void, + failedCallback: () => void, + email: string, + ) => Promise; +}; + +const LoginByPAT = ({ onNext }: LoginByPATProps) => { + const styles = useStyles(); + const router = useRouter(); + const { publicRuntimeConfig } = getConfig(); + const { showAlert } = useAlertHook(); + const [cookies] = useCookies([COOKIE_INSTANCE_URL]); + + const [token, setToken] = useState(''); + const [error] = useState({ + isError: false, + message: '', + }); + const [, setDisableSignIn] = useState(false); + + const handleChange = (event: React.ChangeEvent) => { + const input = event.target.value; + setToken(input); + }; + + const navigate = useNavigate(); + + const handleNext = () => { + signIn('tokenCredentials', { + token, + instanceURL: cookies[COOKIE_INSTANCE_URL], + redirect: false, + callbackUrl: publicRuntimeConfig.appAuthURL, + }).then(response => { + if (response.ok) { + router.reload(); + router.push('/'); + } + + if (response.error) { + showAlert({ + message: token + ? i18n.t('Login.Alert.Invalid_OTP') + : i18n.t('Login.Alert.Message'), + severity: 'error', + title: i18n.t('Login.Alert.Title'), + }); + setDisableSignIn(false); + } + }); + }; + + const handleBack = () => { + navigate('/'); + }; + + const handleSwitchInstance = ( + server: ServerListProps, + callback?: () => void, + ) => { + callback && callback(); + }; + + return ( +
+
+ + {i18n.t('Login.Email.LoginByEmail.Title')} + + + {i18n.t('Login.Email.LoginByEmail.Subtitle')} + +
+ + +
+ + +
+
+ ); +}; + +export default LoginByPAT; diff --git a/src/components/Login/render/SignInMethod/SigninMethod.tsx b/src/components/Login/render/SignInMethod/SigninMethod.tsx index bae4d3b73..e0648f306 100644 --- a/src/components/Login/render/SignInMethod/SigninMethod.tsx +++ b/src/components/Login/render/SignInMethod/SigninMethod.tsx @@ -20,6 +20,8 @@ export default function SigninMethod({ const handleSelected = ({ method }: { method: string }) => { if (method === 'web2') { navigate('/email'); + } else if (method === 'pat') { + navigate('/pat'); } else { navigate('/options'); } @@ -87,6 +89,15 @@ export default function SigninMethod({ disabled={disableSignIn} tooltip={i18n.t('Sign_In.Email.tooltip')} /> +
or
+ } + onClick={() => handleSelected({ method: 'pat' })} + disabled={disableSignIn} + tooltip={i18n.t('Sign_In.Token.tooltip')} + /> diff --git a/src/components/Settings/SharingSettings.tsx b/src/components/Settings/SharingSettings.tsx index 509aeeb64..0cdba393e 100644 --- a/src/components/Settings/SharingSettings.tsx +++ b/src/components/Settings/SharingSettings.tsx @@ -6,7 +6,6 @@ import { useSelector } from 'react-redux'; import { Button, - TextField, Paper, Grid, CircularProgress, @@ -17,6 +16,7 @@ import { Modal } from '../atoms/Modal'; import { useStyles } from './Settings.styles'; import { sha256 } from 'js-sha256'; +import * as AccessTokenAPI from 'src/lib/api/access-token'; import i18n from 'src/locale'; import { RootState } from 'src/reducers'; import { v4 as uuidv4 } from 'uuid'; @@ -28,21 +28,8 @@ const SharingSetting = () => { ); const [tokenValue, setToken] = useState(''); const [modalOpen, setModalOpen] = useState(false); - const [error, setError] = useState({ - isError: false, - message: '', - }); - const onChangeToken = (event: React.ChangeEvent) => { - const input = event.target.value; - - if (!input.length) { - setError({ isError: false, message: '' }); - } - setToken(event.target.value); - }; - - const onClickAddToken = () => { + const onClickAddToken = async () => { const token = uuidv4(); const tokenHash = sha256(token); const first = token.slice(0, 4); @@ -50,7 +37,12 @@ const SharingSetting = () => { const replacement = 'xxxx-xxxx-xxxx-xxxx-xxxxxxxx'; const disguise = first + replacement + second; console.log(tokenHash, disguise); - setModalOpen(true); + try { + await AccessTokenAPI.postToken(tokenHash, disguise); + setModalOpen(true); + } catch (error) { + console.error(error); + } // TODO create access token on blockchain // await createAccessToken(hash, wallet) @@ -81,36 +73,6 @@ const SharingSetting = () => { Token is {tokenValue} - Input Code Here -
- <> - - - -