diff --git a/frontend/src/component/user/authentication-component.jsx b/frontend/src/component/user/authentication-component.jsx
index 8259d228b9..a9f684861d 100644
--- a/frontend/src/component/user/authentication-component.jsx
+++ b/frontend/src/component/user/authentication-component.jsx
@@ -4,8 +4,10 @@ import { Card, CardTitle, CardText } from 'react-mdl';
import Modal from 'react-modal';
import AuthenticationSimpleComponent from './authentication-simple-component';
import AuthenticationCustomComponent from './authentication-custom-component';
+import AuthenticationPasswordComponent from './authentication-password-component';
const SIMPLE_TYPE = 'unsecure';
+const PASSWORD_TYPE = 'password';
const customStyles = {
overlay: {
@@ -34,7 +36,9 @@ class AuthComponent extends React.Component {
static propTypes = {
user: PropTypes.object.isRequired,
unsecureLogin: PropTypes.func.isRequired,
+ passwordLogin: PropTypes.func.isRequired,
fetchFeatureToggles: PropTypes.func.isRequired,
+ fetchUIConfig: PropTypes.func.isRequired,
history: PropTypes.object.isRequired,
};
@@ -43,7 +47,17 @@ class AuthComponent extends React.Component {
if (!authDetails) return null;
let content;
- if (authDetails.type === SIMPLE_TYPE) {
+ if (authDetails.type === PASSWORD_TYPE) {
+ content = (
+
+ );
+ } else if (authDetails.type === SIMPLE_TYPE) {
content = (
- Action required!
+ Action Required
{content}
diff --git a/frontend/src/component/user/authentication-container.jsx b/frontend/src/component/user/authentication-container.jsx
index edc26c530e..1dee4e0885 100644
--- a/frontend/src/component/user/authentication-container.jsx
+++ b/frontend/src/component/user/authentication-container.jsx
@@ -1,11 +1,14 @@
import { connect } from 'react-redux';
import AuthenticationComponent from './authentication-component';
-import { unsecureLogin } from '../../store/user/actions';
+import { unsecureLogin, passwordLogin } from '../../store/user/actions';
import { fetchFeatureToggles } from '../../store/feature-actions';
+import { fetchUIConfig } from '../../store/ui-config/actions';
const mapDispatchToProps = {
unsecureLogin,
+ passwordLogin,
fetchFeatureToggles,
+ fetchUIConfig,
};
const mapStateToProps = state => ({
diff --git a/frontend/src/component/user/authentication-password-component.jsx b/frontend/src/component/user/authentication-password-component.jsx
new file mode 100644
index 0000000000..dd1c1c4ce3
--- /dev/null
+++ b/frontend/src/component/user/authentication-password-component.jsx
@@ -0,0 +1,87 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { CardActions, Button, Textfield } from 'react-mdl';
+
+class EnterpriseAuthenticationComponent extends React.Component {
+ static propTypes = {
+ authDetails: PropTypes.object.isRequired,
+ passwordLogin: PropTypes.func.isRequired,
+ fetchFeatureToggles: PropTypes.func.isRequired,
+ fetchUIConfig: PropTypes.func.isRequired,
+ history: PropTypes.object.isRequired,
+ };
+
+ constructor() {
+ super();
+ this.state = {};
+ }
+
+ handleSubmit = async evt => {
+ evt.preventDefault();
+ const { username, password } = this.state;
+
+ if (!username) {
+ this.setState({ usernameError: 'This is a required field' });
+ return;
+ }
+ if (!password) {
+ this.setState({ passwordError: 'This is a required field' });
+ return;
+ }
+ const user = { username, password };
+ const path = evt.target.action;
+
+ try {
+ await this.props.passwordLogin(path, user);
+ await this.props.fetchFeatureToggles();
+ await this.props.fetchUIConfig();
+ this.props.history.push(`/`);
+ } catch (error) {
+ if (error.statusCode === 404) {
+ this.setState({ error: 'User not found', password: '' });
+ } else if (error.statusCode === 400) {
+ this.setState({ error: 'Wrong password', password: '' });
+ } else {
+ this.setState({ error: 'Could not sign in at the moment.' });
+ }
+ }
+ };
+
+ render() {
+ const authDetails = this.props.authDetails;
+ const { username, usernameError, password, passwordError, error } = this.state;
+ return (
+
+ );
+ }
+}
+
+export default EnterpriseAuthenticationComponent;
diff --git a/frontend/src/data/helper.js b/frontend/src/data/helper.js
index 00d18e8fde..31d3874ae4 100644
--- a/frontend/src/data/helper.js
+++ b/frontend/src/data/helper.js
@@ -8,9 +8,10 @@ function extractLegacyMsg(body) {
}
class ServiceError extends Error {
- constructor() {
+ constructor(statusCode = 500) {
super(defaultErrorMessage);
this.name = 'ServiceError';
+ this.statusCode = statusCode;
}
}
@@ -52,7 +53,7 @@ export function throwIfNotSuccess(response) {
});
});
} else {
- return Promise.reject(new ServiceError());
+ return Promise.reject(new ServiceError(response.status));
}
}
return Promise.resolve(response);
diff --git a/frontend/src/data/user-api.js b/frontend/src/data/user-api.js
index ccab844390..4463f166ac 100644
--- a/frontend/src/data/user-api.js
+++ b/frontend/src/data/user-api.js
@@ -20,8 +20,18 @@ function unsecureLogin(path, user) {
.then(response => response.json());
}
+function passwordLogin(path, data) {
+ return fetch(path, {
+ method: 'POST',
+ credentials: 'include',
+ headers,
+ body: JSON.stringify(data),
+ }).then(throwIfNotSuccess);
+}
+
export default {
fetchUser,
unsecureLogin,
logoutUser,
+ passwordLogin,
};
diff --git a/frontend/src/store/user/actions.js b/frontend/src/store/user/actions.js
index 67ee98d574..cd47bf68d6 100644
--- a/frontend/src/store/user/actions.js
+++ b/frontend/src/store/user/actions.js
@@ -38,6 +38,14 @@ export function unsecureLogin(path, user) {
};
}
+export function passwordLogin(path, user) {
+ return dispatch => {
+ dispatch({ type: START_FETCH_USER });
+
+ return api.passwordLogin(path, user).then(json => dispatch(updateUser(json)));
+ };
+}
+
export function logoutUser() {
return dispatch => {
dispatch({ type: USER_LOGOUT });
diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js
index 60244e5585..274c8dc0a4 100644
--- a/frontend/webpack.config.js
+++ b/frontend/webpack.config.js
@@ -115,6 +115,11 @@ module.exports = {
changeOrigin: true,
secure: false,
},
+ '/auth': {
+ target: process.env.UNLEASH_API || 'http://localhost:4242',
+ changeOrigin: true,
+ secure: false,
+ },
},
port: process.env.PORT || 3000,
},