Просмотр исходного кода

Merge pull request #336 from smiclea/CORWEB-188

Allow option to type user domain on login page CORWEB-188
Dorin Paslaru 7 лет назад
Родитель
Сommit
2d1377daa5

+ 28 - 8
src/components/organisms/LoginForm/LoginForm.jsx

@@ -27,7 +27,7 @@ import StyleProps from '../../styleUtils/StyleProps'
 
 import errorIcon from './images/error.svg'
 
-import { loginButtons } from '../../../config'
+import { loginButtons, showUserDomainInput } from '../../../config'
 import notificationStore from '../../../stores/NotificationStore'
 
 const Form = styled.form`
@@ -87,7 +87,12 @@ type Props = {
   className: string,
   loading: boolean,
   loginFailedResponse: { status: string, message?: string },
-  onFormSubmit: (credentials: { username: string, password: string }) => void,
+  domain: string,
+  onDomainChange: (domain: string) => void,
+  onFormSubmit: (credentials: {
+    username: string,
+    password: string,
+  }) => void,
 }
 type State = {
   username: string,
@@ -112,13 +117,20 @@ class LoginForm extends React.Component<Props, State> {
     this.setState({ password })
   }
 
+  handleDomainChange(domain: string) {
+    this.props.onDomainChange(domain)
+  }
+
   handleFormSubmit(e: Event) {
     e.preventDefault()
 
-    if (this.state.username.length === 0 || this.state.password.length === 0) {
+    if (!this.state.username.length || !this.state.password.length || !this.props.domain.length) {
       notificationStore.alert('Please fill in all fields')
     } else {
-      this.props.onFormSubmit({ username: this.state.username, password: this.state.password })
+      this.props.onFormSubmit({
+        username: this.state.username,
+        password: this.state.password,
+      })
     }
   }
 
@@ -132,7 +144,7 @@ class LoginForm extends React.Component<Props, State> {
     if (this.props.loginFailedResponse.status) {
       switch (this.props.loginFailedResponse.status) {
         case 401:
-          errorMessage = 'The username or password did not match. Please try again.'
+          errorMessage = 'Incorrect credentials.<br />Please try again.'
           break
         default:
           errorMessage = this.props.loginFailedResponse.message || errorMessage
@@ -142,9 +154,10 @@ class LoginForm extends React.Component<Props, State> {
     return (
       <LoginError>
         <LoginErrorIcon />
-        <LoginErrorText data-test-id="loginForm-errorText">
-          {errorMessage}
-        </LoginErrorText>
+        <LoginErrorText
+          data-test-id="loginForm-errorText"
+          dangerouslySetInnerHTML={{ __html: errorMessage }}
+        />
       </LoginError>
     )
   }
@@ -169,6 +182,13 @@ class LoginForm extends React.Component<Props, State> {
         <LoginOptions />
         {loginSeparator}
         <FormFields>
+          {showUserDomainInput ? (
+            <LoginFormField
+              label="Domain Name"
+              value={this.props.domain}
+              onChange={e => { this.handleDomainChange(e.target.value) }}
+            />
+          ) : null}
           <LoginFormField
             label="Username"
             value={this.state.username}

+ 1 - 1
src/components/organisms/LoginForm/test.jsx

@@ -22,7 +22,7 @@ import LoginForm from '.'
 
 const wrap = props => new TW(shallow(
   // $FlowIgnore
-  <LoginForm {...props} />
+  <LoginForm {...props} domain="default" />
 ), 'loginForm')
 
 describe('LoginForm Component', () => {

+ 22 - 2
src/components/pages/LoginPage/LoginPage.jsx

@@ -82,16 +82,34 @@ const CbsLogo = styled.a`
   cursor: pointer;
 `
 
+type State = {
+  domain: string,
+}
+
 @observer
-class LoginPage extends React.Component<{}> {
+class LoginPage extends React.Component<{}, State> {
+  state = {
+    domain: '',
+  }
+
+  componentWillMount() {
+    this.setState({
+      domain: userStore.domainName,
+    })
+  }
+
   componentDidMount() {
     document.title = 'Log In'
   }
 
-  handleFormSubmit(data: { username: string, password: string }) {
+  handleFormSubmit(data: {
+    username: string,
+    password: string,
+  }) {
     userStore.login({
       name: data.username,
       password: data.password,
+      domain: this.state.domain,
     })
   }
 
@@ -107,6 +125,8 @@ class LoginPage extends React.Component<{}> {
             <Top>
               <Logo />
               <StyledLoginForm
+                domain={this.state.domain}
+                onDomainChange={domain => { this.setState({ domain }) }}
                 onFormSubmit={data => this.handleFormSubmit(data)}
                 loading={userStore.loading}
                 loginFailedResponse={userStore.loginFailedResponse}

+ 2 - 1
src/config.js

@@ -27,7 +27,8 @@ export const servicesUrl = {
   openId: `${coriolisUrl}identity/OS-FEDERATION/identity_providers/google/protocols/openid/auth`,
 }
 
-export const userDomain = 'default'
+export const showUserDomainInput = false
+export const defaultUserDomain = 'default'
 
 // Whether to use Barbican secrets when creating a new endpoint
 export const useSecret = true

+ 10 - 2
src/sources/UserSource.js

@@ -17,7 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import cookie from 'js-cookie'
 
 import Api from '../utils/ApiCaller'
-import { servicesUrl, coriolisUrl, userDomain } from '../config'
+import { servicesUrl, coriolisUrl, defaultUserDomain } from '../config'
 import type { Credentials, User } from '../types/User'
 import type { Role, Project, RoleAssignment } from '../types/Project'
 
@@ -35,6 +35,14 @@ class UserModel {
 }
 
 class UserSource {
+  static saveDomainName(domainName: string) {
+    localStorage.setItem('userDomainName', domainName)
+  }
+
+  static getDomainName(): string {
+    return localStorage.getItem('userDomainName') || defaultUserDomain
+  }
+
   static login(userData: Credentials): Promise<User> {
     let auth = {
       auth: {
@@ -43,7 +51,7 @@ class UserSource {
           password: {
             user: {
               name: userData.name,
-              domain: { name: userDomain },
+              domain: { name: userData.domain },
               password: userData.password,
             },
           },

+ 11 - 1
src/stores/UserStore.js

@@ -27,7 +27,7 @@ import notificationStore from '../stores/NotificationStore'
  * 2. Get user details with unscoped token to see if he has project id
  * 3. Post unscoped token with project id (either from his details or from cookies). Set scoped token and project id in cookies.
  * 4. Get token login on subsequent app reloads to retrieve the user info.
- * 
+ *
  * After token expiration, the app is redirected to login page.
  */
 class UserStore {
@@ -42,12 +42,22 @@ class UserStore {
   @observable projects: Project[] = []
   @observable allUsersLoading: boolean = false
 
+  get domainName(): string {
+    return UserSource.getDomainName()
+  }
+
+  saveDomainName(domainName: string) {
+    UserSource.saveDomainName(domainName)
+  }
+
   @action login(creds: Credentials): Promise<void> {
     this.loading = true
     this.loggedUser = null
     this.loginFailedResponse = null
 
     return UserSource.login(creds).then((auth: any) => {
+      this.saveDomainName(creds.domain)
+
       this.loggedUser = { id: auth.token.user.id, email: '', name: '', project: { id: '', name: '' } }
       return this.getLoggedUserInfo()
     }).then(() => {

+ 1 - 0
src/types/User.js

@@ -33,4 +33,5 @@ export type User = {
 export type Credentials = {
   name: string,
   password: string,
+  domain: string,
 }