Skip to content
This repository has been archived by the owner on Aug 4, 2020. It is now read-only.

Commit

Permalink
Feature/view refresh vault token (#24)
Browse files Browse the repository at this point in the history
* added button to drop down menu on header

* created modal and displayed token

* added renew token functionality, animation in progress

* added animation with progress button and beautified

* cleaned up VaultSecretForm.scss

* fix some style issues

* changed animation to progress bar from Cerberus login screen

* got rid of extra comments and updated dependency

* beautified placement and length of time of progress bar

* update dashboard token refresh action to respect token refresh limit

* removed extra comment
  • Loading branch information
Melana Hammel authored and fieldju committed Jul 6, 2017
1 parent 5373adc commit 794bec4
Show file tree
Hide file tree
Showing 5 changed files with 310 additions and 6 deletions.
14 changes: 10 additions & 4 deletions app/actions/authenticationActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export function finalizeMfaLogin(otpToken, mfaDeviceId, stateToken) {
*/
export function refreshAuth(token, redirectPath='/', redirect=true) {
return function(dispatch) {
dispatch(loginUserRequest())
return axios({
url: environmentService.getDomain() + cms.USER_AUTH_PATH_REFRESH,
headers: {'X-Vault-Token': token},
Expand All @@ -197,12 +198,17 @@ export function refreshAuth(token, redirectPath='/', redirect=true) {
.then(function (response) {
dispatch(handleRemoveAuthTokenTimeout())
dispatch(handleRemoveSessionWarningTimeout())
handleUserLogin(response, dispatch, false)
if (redirect) {
hashHistory.push(redirectPath)
}
setTimeout(function(){
handleUserLogin(response, dispatch, false)
if (redirect) {
hashHistory.push(redirectPath)
}
}, 2000);

})
.catch(function (response) {
// Clears View Token Modal upon max refresh token limit to prevent errors
dispatch(modalActions.clearAllModals())
log.error('Failed to login user', response)
dispatch(messengerActions.addNewMessage(<ApiError message="Failed to refresh user token" response={response} />))
dispatch(resetAuthState())
Expand Down
10 changes: 9 additions & 1 deletion app/components/Header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import * as headerActions from '../../actions/headerActions'
import * as authActions from '../../actions/authenticationActions'
import './Header.scss'
import '../../assets/images/cerberus-logo-narrow-off-white.svg'
import * as modalActions from '../../actions/modalActions'
import ViewTokenModal from '../ViewTokenModal/ViewTokenModal'

export default class Header extends Component {

Expand Down Expand Up @@ -41,6 +43,11 @@ class UserBox extends Component {
this.props.dispatch(headerActions.mouseOutUsername())
}.bind(this)

this.handleMouseClickViewToken = function() {
this.props.dispatch(modalActions.pushModal(<ViewTokenModal />))
}.bind(this)


this.handleMouseClickLogout = function() {
this.props.dispatch(authActions.logoutUser(this.props.vaultToken))
}.bind(this)
Expand All @@ -61,9 +68,10 @@ class UserBox extends Component {
onMouseEnter={this.handleMouseClickUserName}
onMouseLeave={this.handleMouseLeaveUserMenuContext} >
{isAdmin && <div className='context-menu-button' onClick={() => {hashHistory.push('/admin/sdb-metadata')}}>SDB Summary</div>}
<div className='context-menu-button' onClick={this.handleMouseClickViewToken}>View Token</div>
<div className='context-menu-button' onClick={this.handleMouseClickLogout}>Logout</div>
</div>
</div>
)
}
}
}
104 changes: 104 additions & 0 deletions app/components/ViewTokenModal/ViewTokenModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from 'react'
import { Component } from 'react'
import { connect } from 'react-redux'
import { reduxForm, touch } from 'redux-form'
import * as modalActions from '../../actions/modalActions'
import * as appActions from '../../actions/appActions'
import * as authActions from '../../actions/authenticationActions'
import CopyToClipboard from 'react-copy-to-clipboard';

import './ViewTokenModal.scss'

// connect to the store in order to obtain the current vault token
@connect((state) => {
return {
clientToken: state.auth.vaultToken,
isAuthenticating: state.auth.isAuthenticating
}
})

export default class ViewTokenModal extends Component {

constructor(props) {
super(props)

this.handleRenewTokenClicked = function() {
this.props.dispatch(authActions.refreshAuth(this.props.clientToken, '', false))
}.bind(this)
}

render() {
const {clientToken, dispatch, isAuthenticating} = this.props
let tokenExpiresDate = sessionStorage.getItem('tokenExpiresDate');

return (
<div id='view-token-modal'>
<div id="view-token-modal-description" className="ncss-brand">
<h1>View and Renew Client Token</h1>
<h4>Below is your current client token which can be used for debugging purposes or for local development, e.g. "export CERBERUS_TOKEN=..."</h4>
</div>

<div className="view-token-modal-token-wrapper">
<div className="view-token-modal-token">
<div className="view-token-modal-data-label">Client Token:</div>
<div className="view-token-modal-data-token-value">{clientToken} </div>
</div>

<div className='row-buttons'>
<CopyToClipboard text={clientToken}>
<div className={clientToken.length <= 1 ? 'btn-wrapper btn-wrapper-right' : 'btn-wrapper'}>
<div className='row-btn row-btn-copy'></div>
</div>
</CopyToClipboard>
</div>

</div>
<div className="view-token-modal-date-wrapper">
<div className="view-token-modal-date">
<div className="view-token-modal-data-label">Client Token Expiration Date:</div>
<div className="view-token-modal-data-date-value">{tokenExpiresDate}</div>
</div>
</div>
<div className="view-token-modal-time-left-wrapper">
<div className="view-token-modal-time-left">
<div className="view-token-modal-data-label">Client Token Time Remaining:</div>
<div className="view-token-modal-data-time-left-value">{dateDiffinMin(tokenExpiresDate)} minutes</div>
</div>
</div>

<div id="renew-btn-container">
<div id='fountainG' className={isAuthenticating ? 'show-me' : 'hide-me'}>
<div id='fountainG_1' className='fountainG'></div>
<div id='fountainG_2' className='fountainG'></div>
<div id='fountainG_3' className='fountainG'></div>
<div id='fountainG_4' className='fountainG'></div>
<div id='fountainG_5' className='fountainG'></div>
<div id='fountainG_6' className='fountainG'></div>
<div id='fountainG_7' className='fountainG'></div>
<div id='fountainG_8' className='fountainG'></div>
</div>
<div id='close-btn'
className='btn ncss-btn-dark-grey ncss-brand pt3-sm pr5-sm pb3-sm pl5-sm pt2-lg pb2-lg u-uppercase'
onClick={ () => {
dispatch(modalActions.popModal())
}}>Close
</div>
<div id='renew-btn'
className='btn ncss-btn-dark-grey ncss-brand pt3-sm pr5-sm pb3-sm pl5-sm pt2-lg pb2-lg u-uppercase'
onClick={this.handleRenewTokenClicked}
>Renew Token
</div>
</div>
</div>
)
}
}

export function dateDiffinMin(expiresDate) {
var expDate = new Date(expiresDate)
var currentDate = new Date()
var t2 = expDate.getTime();
var t1 = currentDate.getTime();
var diff = parseInt((t2-t1)/(60*1000));
return diff
}
186 changes: 186 additions & 0 deletions app/components/ViewTokenModal/ViewTokenModal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
@import '../../assets/styles/common.scss';

#view-token-modal {
width: 1050px;

.ncss-label {
padding-bottom: 5px;
padding-top: 5px;
font-weight: bold;
font-size: 16px;
padding-left: 4px;
}

#view-token-modal-description {
display: flex;
justify-content: center;
flex-direction: column;
padding-bottom: 10px;

p {
padding-left: 5px;
}
}

#renew-btn-container {
padding-top: 15px;
display: flex;
justify-content: flex-end;

.btn {
margin-left: 10px;
width: 110px;
}
}

.view-token-modal-token-wrapper {
margin-top: 15px;
padding-top: 5px;
padding-left: 7px;
padding-right: 7px;
padding-bottom: 5px;
display: flex;
flex-direction: row;

.view-token-modal-token {
display: flex;
flex-direction: row;
}
}

.view-token-modal-date-wrapper {
margin-top: 15px;
padding-top: 7px;
padding-left: 7px;
padding-right: 7px;
padding-bottom: 7px;
display: flex;
flex-direction: row;

.view-token-modal-date {
display: flex;
flex-direction: row;
}
}

.view-token-modal-time-left-wrapper {
margin-top: 15px;
padding-top: 7px;
padding-left: 7px;
padding-right: 7px;
padding-bottom: 7px;
display: flex;
flex-direction: row;

.view-token-modal-time-left {
display: flex;
flex-direction: row;
}
}

.view-token-modal-data-label {
font-size: 16px;
font-weight: bold;
}

.view-token-modal-data-token-value {
padding-left: 5px;
margin-left: 140px;
margin-top: 3px;
}

.view-token-modal-data-date-value {
padding-left: 5px;
margin-left: 17px;
margin-top: 3px;
}

.view-token-modal-data-time-left-value {
padding-left: 5px;
margin-left: 12px;
margin-top: 3px;
}
}

.row-buttons {
display: flex;
// margin-left: 6px;
// height: 40px;

.btn-wrapper {
@extend .clickable;
box-shadow: inset 0 1px 0 0 $snkrs_medium_grey,inset -1px 0 0 0 $snkrs_medium_grey,inset 0 -1px 0 0 $snkrs_medium_grey,inset 1px 0 0 0 $snkrs_medium_grey;
// padding: 3px;
// width: 40px;

margin-right: -1px;

&:hover {
background-color: $snkrs_off_white;
}

&:active {
background-color: $snkrs_grey;
}
}

.btn-wrapper-left {
border-top-left-radius: 2px!important;
border-bottom-left-radius: 2px!important;
}

.btn-wrapper-right {
border-top-right-radius: 2px!important;
border-bottom-right-radius: 2px!important;
}

.row-btn {
@extend .clickable;
}

.row-btn-copy {
background: url(../../assets/images/copy.svg);
background-repeat: no-repeat;

// padding: 11px;
// margin-top: 6px;
// margin-left: 7px;

margin-top: 20px;
margin-left: 20px;
}

.row-btn-reveal {
background: url(../../assets/images/eye.svg);
background-repeat: no-repeat;
padding: 12px;
margin-top: 9px;
margin-left: 5px;
}

.row-btn-revealed {
background: url(../../assets/images/eye_closed.svg);
background-repeat: no-repeat;
padding: 12px;

margin-top: 5px;
margin-left: 4px;
}

.row-btn-remove {
background: url(../../assets/images/remove-red.svg);
background-repeat: no-repeat;
padding: 9px;

margin-top: 8px;
margin-left: 8px;
}
}

.secret-value-placeholder {
text-align: center;
font-size: 14px;
font-weight: normal;
border-radius: 2px;
background-color: $snkrs_medium_grey;
}
2 changes: 1 addition & 1 deletion startLocalEnv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ echo
while :
do
sleep 1
done
done

0 comments on commit 794bec4

Please sign in to comment.