Skip to content

Commit

Permalink
Merge pull request #336 from smiclea/CORWEB-188
Browse files Browse the repository at this point in the history
Allow option to type user domain on login page CORWEB-188
  • Loading branch information
thenoizz authored Mar 7, 2019
2 parents d46a1de + 87adecb commit 2d1377d
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 15 deletions.
36 changes: 28 additions & 8 deletions src/components/organisms/LoginForm/LoginForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -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,
Expand All @@ -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,
})
}
}

Expand All @@ -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
Expand All @@ -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>
)
}
Expand All @@ -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}
Expand Down
2 changes: 1 addition & 1 deletion src/components/organisms/LoginForm/test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import LoginForm from '.'

const wrap = props => new TW(shallow(
// $FlowIgnore
<LoginForm {...props} />
<LoginForm {...props} domain="default" />
), 'loginForm')

describe('LoginForm Component', () => {
Expand Down
24 changes: 22 additions & 2 deletions src/components/pages/LoginPage/LoginPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
}

Expand All @@ -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}
Expand Down
3 changes: 2 additions & 1 deletion src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions src/sources/UserSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand All @@ -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: {
Expand All @@ -43,7 +51,7 @@ class UserSource {
password: {
user: {
name: userData.name,
domain: { name: userDomain },
domain: { name: userData.domain },
password: userData.password,
},
},
Expand Down
12 changes: 11 additions & 1 deletion src/stores/UserStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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(() => {
Expand Down
1 change: 1 addition & 0 deletions src/types/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ export type User = {
export type Credentials = {
name: string,
password: string,
domain: string,
}

0 comments on commit 2d1377d

Please sign in to comment.