github.com/argoproj/argo-cd/v3@v3.2.1/ui/src/app/login/components/login.tsx (about)

     1  import {FormField} from 'argo-ui';
     2  import React, {useContext, useEffect, useState} from 'react';
     3  import {Form, Text} from 'react-form';
     4  import {RouteComponentProps} from 'react-router';
     5  import {AuthSettings} from '../../shared/models';
     6  import {services} from '../../shared/services';
     7  import {Context} from '../../shared/context';
     8  
     9  require('./login.scss');
    10  
    11  export interface LoginForm {
    12      username: string;
    13      password: string;
    14  }
    15  
    16  export function Login(props: RouteComponentProps<{}>) {
    17      const appContext = useContext(Context);
    18  
    19      const search = new URLSearchParams(props.history.location.search);
    20      const returnUrl = search.get('return_url') || '';
    21      const hasSsoLoginError = search.get('has_sso_error') === 'true';
    22  
    23      const [authSettings, setAuthSettings] = useState<AuthSettings | null>(null);
    24      const [loginError, setLoginError] = useState<string | null>(null);
    25      const [loginInProgress, setLoginInProgress] = useState<boolean>(false);
    26  
    27      useEffect(() => {
    28          (async () => {
    29              const authSettings = await services.authService.settings();
    30              setAuthSettings(authSettings);
    31          })();
    32      }, []);
    33  
    34      const login = async (username: string, password: string, returnURL: string) => {
    35          try {
    36              setLoginError('');
    37              setLoginInProgress(true);
    38              appContext.navigation.goto('.', {sso_error: null});
    39              await services.users.login(username, password);
    40              setLoginInProgress(false);
    41              if (returnURL) {
    42                  const url = new URL(returnURL);
    43                  let redirectURL = url.pathname + url.search;
    44                  // return url already contains baseHref, so we need to remove it
    45                  if (appContext.baseHref != '/' && redirectURL.startsWith(appContext.baseHref)) {
    46                      redirectURL = redirectURL.substring(appContext.baseHref.length);
    47                  }
    48                  appContext.navigation.goto(redirectURL);
    49              } else {
    50                  appContext.navigation.goto('/applications');
    51              }
    52          } catch (e) {
    53              setLoginError(e.response.body.error);
    54              setLoginInProgress(false);
    55          }
    56      };
    57  
    58      const ssoConfigured = authSettings && ((authSettings.dexConfig && (authSettings.dexConfig.connectors || []).length > 0) || authSettings.oidcConfig);
    59  
    60      return (
    61          <div className='login'>
    62              <div className='login__content show-for-medium'>
    63                  <div className='login__text'>Let's get stuff deployed!</div>
    64                  <div className='argo__logo' />
    65              </div>
    66              <div className='login__box'>
    67                  <div className='login__logo width-control'>
    68                      <img className='logo-image' src='assets/images/argo_o.svg' alt='argo' />
    69                  </div>
    70                  {ssoConfigured && (
    71                      <div className='login__box_saml width-control'>
    72                          <a href={`auth/login?return_url=${encodeURIComponent(returnUrl)}`}>
    73                              <button className='argo-button argo-button--base argo-button--full-width argo-button--xlg'>
    74                                  {(authSettings.oidcConfig && <span>Log in via {authSettings.oidcConfig.name}</span>) ||
    75                                      (authSettings.dexConfig.connectors.length === 1 && <span>Log in via {authSettings.dexConfig.connectors[0].name}</span>) || (
    76                                          <span>SSO Login</span>
    77                                      )}
    78                              </button>
    79                          </a>
    80                          {hasSsoLoginError && <div className='argo-form-row__error-msg'>Login failed.</div>}
    81                          {authSettings && !authSettings.userLoginsDisabled && (
    82                              <div className='login__saml-separator'>
    83                                  <span>or</span>
    84                              </div>
    85                          )}
    86                      </div>
    87                  )}
    88                  {authSettings && !authSettings.userLoginsDisabled && (
    89                      <Form
    90                          onSubmit={(params: LoginForm) => login(params.username, params.password, returnUrl)}
    91                          validateError={(params: LoginForm) => ({
    92                              username: !params.username && 'Username is required',
    93                              password: !params.password && 'Password is required'
    94                          })}>
    95                          {formApi => (
    96                              <form role='form' className='width-control' onSubmit={formApi.submitForm}>
    97                                  <div className='argo-form-row'>
    98                                      <FormField
    99                                          formApi={formApi}
   100                                          label='Username'
   101                                          field='username'
   102                                          component={Text}
   103                                          componentProps={{name: 'username', autoCapitalize: 'none', autoComplete: 'username'}}
   104                                      />
   105                                  </div>
   106                                  <div className='argo-form-row'>
   107                                      <FormField
   108                                          formApi={formApi}
   109                                          label='Password'
   110                                          field='password'
   111                                          component={Text}
   112                                          componentProps={{name: 'password', type: 'password', autoComplete: 'password'}}
   113                                      />
   114                                      {loginError && <div className='argo-form-row__error-msg'>{loginError}</div>}
   115                                  </div>
   116                                  <div className='login__form-row'>
   117                                      <button disabled={loginInProgress} className='argo-button argo-button--full-width argo-button--xlg' type='submit'>
   118                                          Sign In
   119                                      </button>
   120                                  </div>
   121                              </form>
   122                          )}
   123                      </Form>
   124                  )}
   125                  {authSettings && authSettings.userLoginsDisabled && !ssoConfigured && (
   126                      <div className='argo-form-row__error-msg'>Login is disabled. Please contact your system administrator.</div>
   127                  )}
   128                  <div className='login__footer'>
   129                      <a href='https://argoproj.io' target='_blank'>
   130                          <img className='logo-image' src='assets/images/argologo.svg' alt='argo' />
   131                      </a>
   132                  </div>
   133              </div>
   134          </div>
   135      );
   136  }