Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
MfaValidatePage.jsx132 linesDownload Raw Back to SecurityPages
1/////////////////////////////////////////////////////////////2//3// pgAdmin 4 - PostgreSQL Tools4//5// Copyright (C) 2013 - 2024, The pgAdmin Development Team6// This software is released under the PostgreSQL Licence7//8//////////////////////////////////////////////////////////////9import React, { useState } from 'react';10import LoginImage from '../../img/login.svg?svgr';11import { InputSelect, InputText, MESSAGE_TYPE, NotifierMessage } from '../components/FormComponents';12import BasePage, { SecurityButton } from './BasePage';13import { useDelayedCaller } from '../custom_hooks';14import gettext from 'sources/gettext';15import PropTypes from 'prop-types';16 17function EmailValidateView({mfaView, sendEmailUrl, csrfHeader, csrfToken}) {18  const [inputValue, setInputValue] = useState('');19  const [error, setError] = useState('');20  const [sentMessage, setSentMessage] = useState('');21  const [sending, setSending] = useState(false);22  const [showResend, setShowResend] = useState(false);23 24  const showResendAfter = useDelayedCaller(()=>{25    setShowResend(true);26  });27 28  const sendCodeToEmail = ()=>{29    setSending(true);30    let accept = 'text/html; charset=utf-8;';31 32    fetch(sendEmailUrl, {33      method: 'POST',34      mode: 'cors',35      cache: 'no-cache',36      headers: {37        'Accept': accept,38        'Content-Type': 'application/json; charset=utf-8;',39        [csrfHeader]: csrfToken,40      },41      redirect: 'follow'42    }).then((resp) => {43      if (!resp.ok) {44        resp.text().then(msg => setError(msg));45        return;46      }47      return resp.json();48    }).then((resp) => {49      if (!resp)50        return;51      setSentMessage(resp.message);52      showResendAfter(20000);53    }).finally(()=>{54      setSending(false);55    });56  };57 58  return <>59    <div style={{textAlign: 'center'}} data-test="email-validate-view">{mfaView.description}</div>60    {sentMessage && <>61      <div>{sentMessage}</div>62      {showResend && <div>63        <span>{gettext('Haven\'t received an email?')} <a style={{color:'inherit', fontWeight: 'bold'}} href="#" onClick={sendCodeToEmail}>{gettext('Send again')}</a></span>64      </div>}65      <InputText value={inputValue} type="password" name="code" placeholder={mfaView.otp_placeholder}66        onChange={setInputValue} autoFocus67      />68      <SecurityButton value='Validate'>{gettext('Validate')}</SecurityButton>69    </>}70    {error && <NotifierMessage message={error} type={MESSAGE_TYPE.ERROR} closable={false} />}71    {!sentMessage &&72    <SecurityButton type="button" name="send_code" onClick={sendCodeToEmail} disabled={sending}>73      {sending ? mfaView.button_label_sending : mfaView.button_label}74    </SecurityButton>}75  </>;76}77 78EmailValidateView.propTypes = {79  mfaView: PropTypes.object,80  sendEmailUrl: PropTypes.string,81  csrfHeader: PropTypes.string,82  csrfToken: PropTypes.string83};84 85function AuthenticatorValidateView({mfaView}) {86  const [inputValue, setInputValue] = useState('');87 88  return <>89    <div data-test="auth-validate-view">{mfaView.auth_description}</div>90    <InputText value={inputValue} type="password" name="code" placeholder={mfaView.otp_placeholder}91      onChange={setInputValue} autoFocus92    />93    <SecurityButton value='Validate'>{gettext('Validate')}</SecurityButton>94  </>;95}96 97AuthenticatorValidateView.propTypes = {98  mfaView: PropTypes.object,99};100 101export default function MfaValidatePage({actionUrl, views, logoutUrl, sendEmailUrl, csrfHeader, csrfToken, ...props}) {102  const [method, setMethod] = useState(Object.values(views).find((v)=>v.selected)?.id);103  return (104    <BasePage title={gettext('Authentication')} pageImage={<LoginImage style={{height: '100%', width: '100%'}} />} {...props}>105      <form style={{display:'flex', gap:'15px', flexDirection:'column', minHeight: 0}} action={actionUrl} method="POST">106        <InputSelect value={method} options={Object.keys(views).map((k)=>({107          label: views[k].label,108          value: views[k].id,109          imageUrl: views[k].icon110        }))} onChange={setMethod} controlProps={{111          allowClear: false,112        }} />113        <div><input type='hidden' name='mfa_method' defaultValue={method} /></div>114        {method == 'email' && <EmailValidateView mfaView={views[method].view} sendEmailUrl={sendEmailUrl} csrfHeader={csrfHeader} csrfToken={csrfToken} />}115        {method == 'authenticator' && <AuthenticatorValidateView mfaView={views[method].view} />}116        <div style={{textAlign: 'right'}}>117          <a style={{color:'inherit'}} href={logoutUrl}>{gettext('Logout')}</a>118        </div>119      </form>120    </BasePage>121  );122}123 124MfaValidatePage.propTypes = {125  actionUrl: PropTypes.string,126  views: PropTypes.object,127  logoutUrl: PropTypes.string,128  sendEmailUrl: PropTypes.string,129  csrfHeader: PropTypes.string,130  csrfToken: PropTypes.string131};132 
codekingpro/portable-devtools · Team Ai