Skip to content

Commit 87adecb

Browse files
author
Sergiu Miclea
committed
Allow option to type user domain on login page
The user domain input can be toggled on / off in config file. The last user domain used is saved in local storage, after a successful login. This means you can disable the input anytime after the first login. A default value is used the first time the user loads the page.
1 parent d46a1de commit 87adecb

7 files changed

Lines changed: 75 additions & 15 deletions

File tree

src/components/organisms/LoginForm/LoginForm.jsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import StyleProps from '../../styleUtils/StyleProps'
2727

2828
import errorIcon from './images/error.svg'
2929

30-
import { loginButtons } from '../../../config'
30+
import { loginButtons, showUserDomainInput } from '../../../config'
3131
import notificationStore from '../../../stores/NotificationStore'
3232

3333
const Form = styled.form`
@@ -87,7 +87,12 @@ type Props = {
8787
className: string,
8888
loading: boolean,
8989
loginFailedResponse: { status: string, message?: string },
90-
onFormSubmit: (credentials: { username: string, password: string }) => void,
90+
domain: string,
91+
onDomainChange: (domain: string) => void,
92+
onFormSubmit: (credentials: {
93+
username: string,
94+
password: string,
95+
}) => void,
9196
}
9297
type State = {
9398
username: string,
@@ -112,13 +117,20 @@ class LoginForm extends React.Component<Props, State> {
112117
this.setState({ password })
113118
}
114119

120+
handleDomainChange(domain: string) {
121+
this.props.onDomainChange(domain)
122+
}
123+
115124
handleFormSubmit(e: Event) {
116125
e.preventDefault()
117126

118-
if (this.state.username.length === 0 || this.state.password.length === 0) {
127+
if (!this.state.username.length || !this.state.password.length || !this.props.domain.length) {
119128
notificationStore.alert('Please fill in all fields')
120129
} else {
121-
this.props.onFormSubmit({ username: this.state.username, password: this.state.password })
130+
this.props.onFormSubmit({
131+
username: this.state.username,
132+
password: this.state.password,
133+
})
122134
}
123135
}
124136

@@ -132,7 +144,7 @@ class LoginForm extends React.Component<Props, State> {
132144
if (this.props.loginFailedResponse.status) {
133145
switch (this.props.loginFailedResponse.status) {
134146
case 401:
135-
errorMessage = 'The username or password did not match. Please try again.'
147+
errorMessage = 'Incorrect credentials.<br />Please try again.'
136148
break
137149
default:
138150
errorMessage = this.props.loginFailedResponse.message || errorMessage
@@ -142,9 +154,10 @@ class LoginForm extends React.Component<Props, State> {
142154
return (
143155
<LoginError>
144156
<LoginErrorIcon />
145-
<LoginErrorText data-test-id="loginForm-errorText">
146-
{errorMessage}
147-
</LoginErrorText>
157+
<LoginErrorText
158+
data-test-id="loginForm-errorText"
159+
dangerouslySetInnerHTML={{ __html: errorMessage }}
160+
/>
148161
</LoginError>
149162
)
150163
}
@@ -169,6 +182,13 @@ class LoginForm extends React.Component<Props, State> {
169182
<LoginOptions />
170183
{loginSeparator}
171184
<FormFields>
185+
{showUserDomainInput ? (
186+
<LoginFormField
187+
label="Domain Name"
188+
value={this.props.domain}
189+
onChange={e => { this.handleDomainChange(e.target.value) }}
190+
/>
191+
) : null}
172192
<LoginFormField
173193
label="Username"
174194
value={this.state.username}

src/components/organisms/LoginForm/test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import LoginForm from '.'
2222

2323
const wrap = props => new TW(shallow(
2424
// $FlowIgnore
25-
<LoginForm {...props} />
25+
<LoginForm {...props} domain="default" />
2626
), 'loginForm')
2727

2828
describe('LoginForm Component', () => {

src/components/pages/LoginPage/LoginPage.jsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,34 @@ const CbsLogo = styled.a`
8282
cursor: pointer;
8383
`
8484

85+
type State = {
86+
domain: string,
87+
}
88+
8589
@observer
86-
class LoginPage extends React.Component<{}> {
90+
class LoginPage extends React.Component<{}, State> {
91+
state = {
92+
domain: '',
93+
}
94+
95+
componentWillMount() {
96+
this.setState({
97+
domain: userStore.domainName,
98+
})
99+
}
100+
87101
componentDidMount() {
88102
document.title = 'Log In'
89103
}
90104

91-
handleFormSubmit(data: { username: string, password: string }) {
105+
handleFormSubmit(data: {
106+
username: string,
107+
password: string,
108+
}) {
92109
userStore.login({
93110
name: data.username,
94111
password: data.password,
112+
domain: this.state.domain,
95113
})
96114
}
97115

@@ -107,6 +125,8 @@ class LoginPage extends React.Component<{}> {
107125
<Top>
108126
<Logo />
109127
<StyledLoginForm
128+
domain={this.state.domain}
129+
onDomainChange={domain => { this.setState({ domain }) }}
110130
onFormSubmit={data => this.handleFormSubmit(data)}
111131
loading={userStore.loading}
112132
loginFailedResponse={userStore.loginFailedResponse}

src/config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ export const servicesUrl = {
2727
openId: `${coriolisUrl}identity/OS-FEDERATION/identity_providers/google/protocols/openid/auth`,
2828
}
2929

30-
export const userDomain = 'default'
30+
export const showUserDomainInput = false
31+
export const defaultUserDomain = 'default'
3132

3233
// Whether to use Barbican secrets when creating a new endpoint
3334
export const useSecret = true

src/sources/UserSource.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
import cookie from 'js-cookie'
1818

1919
import Api from '../utils/ApiCaller'
20-
import { servicesUrl, coriolisUrl, userDomain } from '../config'
20+
import { servicesUrl, coriolisUrl, defaultUserDomain } from '../config'
2121
import type { Credentials, User } from '../types/User'
2222
import type { Role, Project, RoleAssignment } from '../types/Project'
2323

@@ -35,6 +35,14 @@ class UserModel {
3535
}
3636

3737
class UserSource {
38+
static saveDomainName(domainName: string) {
39+
localStorage.setItem('userDomainName', domainName)
40+
}
41+
42+
static getDomainName(): string {
43+
return localStorage.getItem('userDomainName') || defaultUserDomain
44+
}
45+
3846
static login(userData: Credentials): Promise<User> {
3947
let auth = {
4048
auth: {
@@ -43,7 +51,7 @@ class UserSource {
4351
password: {
4452
user: {
4553
name: userData.name,
46-
domain: { name: userDomain },
54+
domain: { name: userData.domain },
4755
password: userData.password,
4856
},
4957
},

src/stores/UserStore.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import notificationStore from '../stores/NotificationStore'
2727
* 2. Get user details with unscoped token to see if he has project id
2828
* 3. Post unscoped token with project id (either from his details or from cookies). Set scoped token and project id in cookies.
2929
* 4. Get token login on subsequent app reloads to retrieve the user info.
30-
*
30+
*
3131
* After token expiration, the app is redirected to login page.
3232
*/
3333
class UserStore {
@@ -42,12 +42,22 @@ class UserStore {
4242
@observable projects: Project[] = []
4343
@observable allUsersLoading: boolean = false
4444

45+
get domainName(): string {
46+
return UserSource.getDomainName()
47+
}
48+
49+
saveDomainName(domainName: string) {
50+
UserSource.saveDomainName(domainName)
51+
}
52+
4553
@action login(creds: Credentials): Promise<void> {
4654
this.loading = true
4755
this.loggedUser = null
4856
this.loginFailedResponse = null
4957

5058
return UserSource.login(creds).then((auth: any) => {
59+
this.saveDomainName(creds.domain)
60+
5161
this.loggedUser = { id: auth.token.user.id, email: '', name: '', project: { id: '', name: '' } }
5262
return this.getLoggedUserInfo()
5363
}).then(() => {

src/types/User.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ export type User = {
3333
export type Credentials = {
3434
name: string,
3535
password: string,
36+
domain: string,
3637
}

0 commit comments

Comments
 (0)