Skip to content

Commit

Permalink
fix: login without reload (#678) (#679) (#914)
Browse files Browse the repository at this point in the history
* fix: login without reload (#678) (#679)

* fix: implements code review suggestions (#914)

* refactor: adds scope to the app

* refactor: handles null value from localstorage for username

* refactor: removes text type from <Input />

* refactor: replaces isNull with isNil

* refactor: improves makeLogin method

* refactor: adds error from api constant

* fix: updates error using API_ERROR constant in tests

* refactor: updates regex for moduleMapper in jest config
  • Loading branch information
ayusharma authored and juanpicado committed Aug 20, 2018
1 parent 1fc1a33 commit 9cd3ccb
Show file tree
Hide file tree
Showing 28 changed files with 1,030 additions and 660 deletions.
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
}], "flow", "react"],
"plugins": [
"transform-class-properties",
"transform-object-rest-spread"
"transform-object-rest-spread",
"babel-plugin-dynamic-import-node"
]
},
"testOldEnv": {
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module.exports = {
'<rootDir>/test',
],
moduleNameMapper: {
'\\.(scss)$': '<rootDir>/node_modules/identity-obj-proxy',
'\\.(s?css)$': '<rootDir>/node_modules/identity-obj-proxy',
'github-markdown-css': '<rootDir>/node_modules/identity-obj-proxy',
'\\.(png)$': '<rootDir>/node_modules/identity-obj-proxy',
'\\.(svg)$': '<rootDir>/test/unit/empty.js'
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"babel-eslint": "8.2.6",
"babel-jest": "23.4.0",
"babel-loader": "7.1.5",
"babel-plugin-dynamic-import-node": "2.0.0",
"babel-plugin-flow-runtime": "0.17.0",
"babel-plugin-syntax-dynamic-import": "6.18.0",
"babel-plugin-transform-async-to-generator": "6.24.1",
Expand All @@ -77,8 +78,8 @@
"babel-register": "6.26.0",
"babel-runtime": "6.26.0",
"bundlesize": "0.17.0",
"cross-env": "5.1.4",
"codecov": "3.0.4",
"cross-env": "5.1.4",
"css-loader": "0.28.10",
"element-react": "1.4.8",
"element-theme-default": "1.4.13",
Expand Down Expand Up @@ -114,8 +115,8 @@
"ora": "1.4.0",
"prop-types": "15.6.1",
"puppeteer": "1.1.1",
"react": "16.2.0",
"react-dom": "16.2.0",
"react": "16.4.2",
"react-dom": "16.4.2",
"react-hot-loader": "4.2.0",
"react-router-dom": "4.2.2",
"react-syntax-highlighter": "5.8.0",
Expand Down
2 changes: 1 addition & 1 deletion src/lib/crypto-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function generateRandomHexString(length: number = 8) {

export function signPayload(payload: JWTPayload, secret: string, options: JWTSignOptions) {
return jwt.sign(payload, secret, {
notBefore: '1000', // Make sure the time will not rollback :)
notBefore: '1', // Make sure the time will not rollback :)
...options,
});
}
Expand Down
152 changes: 149 additions & 3 deletions src/webui/app.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,165 @@
import React from 'react';
import React, {Component} from 'react';
import isNil from 'lodash/isNil';
import 'element-theme-default';
import {i18n} from 'element-react';
import locale from 'element-react/src/locale/lang/en';

import storage from './utils/storage';
import logo from './utils/logo';
import {makeLogin, isTokenExpire} from './utils/login';

import Header from './components/Header';
import Footer from './components/Footer';
import LoginModal from './components/Login';

i18n.use(locale);

import Route from './router';

import './styles/main.scss';
import 'normalize.css';

export default class App extends React.Component {
export default class App extends Component {
state = {
error: {},
logoUrl: '',
user: {},
scope: (window.VERDACCIO_SCOPE) ? `${window.VERDACCIO_SCOPE}:` : '',
showLoginModal: false,
isUserLoggedIn: false
};

constructor(props) {
super(props);
this.handleLogout = this.handleLogout.bind(this);
this.toggleLoginModal = this.toggleLoginModal.bind(this);
this.doLogin = this.doLogin.bind(this);
this.loadLogo = this.loadLogo.bind(this);
this.isUserAlreadyLoggedIn = this.isUserAlreadyLoggedIn.bind(this);
}

componentDidMount() {
this.loadLogo();
this.isUserAlreadyLoggedIn();
}

isUserAlreadyLoggedIn() {
// checks for token validity
const token = storage.getItem('token');
const username = storage.getItem('username');

if (isTokenExpire(token) || isNil(username)) {
this.handleLogout();
} else {
this.setState({
user: {username, token},
isUserLoggedIn: true
});
}
}

async loadLogo() {
const logoUrl = await logo();
this.setState({logoUrl});
}

/**
* Toogles the login modal
* Required by: <LoginModal /> <Header />
*/
toggleLoginModal() {
this.setState((prevState) => ({
showLoginModal: !prevState.showLoginModal,
error: {}
}));
}

/**
* handles login
* Required by: <Header />
*/
async doLogin(usernameValue, passwordValue) {
const {username, token, error} = await makeLogin(
usernameValue,
passwordValue
);

if (username && token) {
this.setState({
user: {
username,
token
}
});
storage.setItem('username', username);
storage.setItem('token', token);
// close login modal after successful login
// set userLoggined to true
this.setState({
isUserLoggedIn: true,
showLoginModal: false
});
}

if (error) {
this.setState({
user: {},
error
});
}
}

/**
* Logouts user
* Required by: <Header />
*/
handleLogout() {
storage.removeItem('username');
storage.removeItem('token');
this.setState({
user: {},
isUserLoggedIn: false
});
}

renderHeader() {
const {
logoUrl,
user,
scope,
} = this.state;
return <Header
logo={logoUrl}
username={user.username}
scope={scope}
toggleLoginModal={this.toggleLoginModal}
handleLogout={this.handleLogout}
/>;
}

renderLoginModal() {
const {
error,
showLoginModal
} = this.state;
return <LoginModal
visibility={showLoginModal}
error={error}
onChange={this.setUsernameAndPassword}
onCancel={this.toggleLoginModal}
onSubmit={this.doLogin}
/>;
}

render() {
const {isUserLoggedIn} = this.state;
return (
<Route />
<div className="page-full-height">
{this.renderHeader()}
{this.renderLoginModal()}
<Route isUserLoggedIn={isUserLoggedIn} />
<Footer />
</div>
);
}
}
4 changes: 4 additions & 0 deletions src/webui/components/Header/header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
background-color: $saltpan;
}
}

.usernameField {
margin-right: 10px;
}
}

Loading

0 comments on commit 9cd3ccb

Please sign in to comment.