11import React , { useContext , useEffect , useState } from 'react' ;
22import { Form , Formik , FormikHelpers } from 'formik' ;
33import { object , string } from 'yup' ;
4- import getTwoFactorTokenUrl from '@/api/account/getTwoFactorTokenUrl ' ;
4+ import getTwoFactorTokenData , { TwoFactorTokenData } from '@/api/account/getTwoFactorTokenData ' ;
55import enableAccountTwoFactor from '@/api/account/enableAccountTwoFactor' ;
66import { Actions , useStoreActions } from 'easy-peasy' ;
77import { ApplicationStore } from '@/state' ;
@@ -12,21 +12,22 @@ import Button from '@/components/elements/Button';
1212import asModal from '@/hoc/asModal' ;
1313import ModalContext from '@/context/ModalContext' ;
1414import QRCode from 'qrcode.react' ;
15+ import CopyOnClick from '@/components/elements/CopyOnClick' ;
1516
1617interface Values {
1718 code : string ;
1819}
1920
2021const SetupTwoFactorModal = ( ) => {
21- const [ token , setToken ] = useState ( '' ) ;
22+ const [ token , setToken ] = useState < TwoFactorTokenData | null > ( null ) ;
2223 const [ recoveryTokens , setRecoveryTokens ] = useState < string [ ] > ( [ ] ) ;
2324
2425 const { dismiss, setPropOverrides } = useContext ( ModalContext ) ;
2526 const updateUserData = useStoreActions ( ( actions : Actions < ApplicationStore > ) => actions . user . updateUserData ) ;
2627 const { clearAndAddHttpError } = useStoreActions ( ( actions : Actions < ApplicationStore > ) => actions . flashes ) ;
2728
2829 useEffect ( ( ) => {
29- getTwoFactorTokenUrl ( )
30+ getTwoFactorTokenData ( )
3031 . then ( setToken )
3132 . catch ( error => {
3233 console . error ( error ) ;
@@ -102,13 +103,17 @@ const SetupTwoFactorModal = () => {
102103 < div css = { tw `flex flex-wrap` } >
103104 < div css = { tw `w-full md:flex-1` } >
104105 < div css = { tw `w-32 h-32 md:w-64 md:h-64 bg-neutral-600 p-2 rounded mx-auto` } >
105- { ! token || ! token . length ?
106+ { ! token ?
106107 < img
107108 src = { 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' }
108109 css = { tw `w-64 h-64 rounded` }
109110 />
110111 :
111- < QRCode renderAs = { 'svg' } value = { token } css = { tw `w-full h-full shadow-none rounded-none` } />
112+ < QRCode
113+ renderAs = { 'svg' }
114+ value = { token . image_url_data }
115+ css = { tw `w-full h-full shadow-none rounded-none` }
116+ />
112117 }
113118 </ div >
114119 </ div >
@@ -121,11 +126,21 @@ const SetupTwoFactorModal = () => {
121126 title = { 'Code From Authenticator' }
122127 description = { 'Enter the code from your authenticator device after scanning the QR image.' }
123128 />
129+ { token &&
130+ < div css = { tw `mt-4 pt-4 border-t border-neutral-500 text-neutral-200` } >
131+ Alternatively, enter the following token into your authenticator application:
132+ < CopyOnClick text = { token . secret } >
133+ < div css = { tw `text-sm bg-neutral-900 rounded mt-2 py-2 px-4 font-mono` } >
134+ < code css = { tw `font-mono` } >
135+ { token . secret }
136+ </ code >
137+ </ div >
138+ </ CopyOnClick >
139+ </ div >
140+ }
124141 </ div >
125142 < div css = { tw `mt-6 md:mt-0 text-right` } >
126- < Button >
127- Setup
128- </ Button >
143+ < Button > Setup</ Button >
129144 </ div >
130145 </ div >
131146 </ div >
0 commit comments