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

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