Updates client UI to request token generation from server

This commit is contained in:
Andrew Nicolaou 2019-05-14 11:25:14 +02:00 committed by Cassie Tarakajian
parent 403234ae81
commit 90f34d7a5a
5 changed files with 50 additions and 61 deletions

View file

@ -19,7 +19,7 @@ export const AUTH_ERROR = 'AUTH_ERROR';
export const SETTINGS_UPDATED = 'SETTINGS_UPDATED'; export const SETTINGS_UPDATED = 'SETTINGS_UPDATED';
export const ADDED_API_KEY = 'ADDED_API_KEY'; export const API_KEY_CREATED = 'API_KEY_CREATED';
export const REMOVED_API_KEY = 'REMOVED_API_KEY'; export const REMOVED_API_KEY = 'REMOVED_API_KEY';
export const SET_PROJECT_NAME = 'SET_PROJECT_NAME'; export const SET_PROJECT_NAME = 'SET_PROJECT_NAME';

View file

@ -222,46 +222,22 @@ export function updateSettings(formValues) {
.catch(response => Promise.reject(new Error(response.data.error))); .catch(response => Promise.reject(new Error(response.data.error)));
} }
export function addApiKey(label) { export function createApiKeySuccess(token) {
return ((dispatch) => { return {
crypto.randomBytes(20, (err, buf) => { type: ActionTypes.API_KEY_CREATED,
const key = buf.toString('hex'); token
const encodedKey = Buffer.from(key).toString('base64'); };
axios.put(`${ROOT_URL}/account/api-keys`, { label, encodedKey }, { withCredentials: true }) }
export function createApiKey(label) {
return dispatch =>
axios.post(`${ROOT_URL}/account/api-keys`, { label }, { withCredentials: true })
.then((response) => { .then((response) => {
// window.alert(`Here is your key :\n${key}\nNote it somewhere, you won't be able to see it later !`); const { token } = response.data;
const elt = React.createElement( dispatch(createApiKeySuccess(token));
'tr', { className: 'new-key' }, return token;
React.createElement('td', {}, 'Here is your new key ;\ncopy it somewhere, you won\'t be able to see it later !'),
React.createElement(
'td', {},
React.createElement('input', {
id: 'key-to-copy', type: 'text', value: key, readOnly: true
})
),
React.createElement(
'td', {},
React.createElement('input', {
type: 'submit',
value: 'Copy to clipboard',
className: 'form__table-button-copy',
onClick: () => {
const inputKey = document.getElementById('key-to-copy');
inputKey.select();
document.execCommand('copy');
}
})
)
);
ReactDom.render(elt, document.getElementById('form__table_new_key'));
dispatch({
type: ActionTypes.ADDED_API_KEY,
user: response.data
});
}) })
.catch(response => Promise.reject(new Error(response.data.error))); .catch(response => Promise.reject(new Error(response.data.error)));
});
});
} }
export function removeApiKey(keyId) { export function removeApiKey(keyId) {

View file

@ -12,7 +12,8 @@ class APIKeyForm extends React.Component {
addKey(event) { addKey(event) {
event.preventDefault(); event.preventDefault();
document.getElementById('addKeyForm').reset(); document.getElementById('addKeyForm').reset();
this.props.addApiKey(this.state.keyLabel); this.props.createApiKey(this.state.keyLabel)
.then(newToken => this.setState({ newToken }));
this.state.keyLabel = ''; this.state.keyLabel = '';
return false; return false;
} }
@ -22,10 +23,17 @@ class APIKeyForm extends React.Component {
} }
render() { render() {
return ( const { newToken } = this.state;
const content = newToken ?
(
<div> <div>
<p>Here is your new key. Copy it somewhere, you won't be able to see it later !</p>
<input type="text" readOnly value={newToken} />
<button>Copy to clipboard</button>
</div>) :
(<form id="addKeyForm" className="form" onSubmit={this.addKey}>
<h2 className="form__label">Key label</h2> <h2 className="form__label">Key label</h2>
<form id="addKeyForm" className="form" onSubmit={this.addKey}>
<input <input
type="text" type="text"
className="form__input" className="form__input"
@ -39,6 +47,11 @@ class APIKeyForm extends React.Component {
disabled={this.state.keyLabel === ''} disabled={this.state.keyLabel === ''}
/> />
</form> </form>
);
return (
<div>
{content}
<table className="form__table"> <table className="form__table">
<tbody id="form__table_new_key"></tbody> <tbody id="form__table_new_key"></tbody>
<tbody> <tbody>
@ -56,7 +69,7 @@ class APIKeyForm extends React.Component {
} }
APIKeyForm.propTypes = { APIKeyForm.propTypes = {
addApiKey: PropTypes.func.isRequired, createApiKey: PropTypes.func.isRequired,
removeApiKey: PropTypes.func.isRequired, removeApiKey: PropTypes.func.isRequired,
apiKeys: PropTypes.arrayOf(PropTypes.shape({ apiKeys: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.object.isRequired, id: PropTypes.object.isRequired,

View file

@ -5,7 +5,7 @@ import { bindActionCreators } from 'redux';
import { browserHistory } from 'react-router'; import { browserHistory } from 'react-router';
import InlineSVG from 'react-inlinesvg'; import InlineSVG from 'react-inlinesvg';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { addApiKey, removeApiKey } from '../actions'; import { createApiKey, removeApiKey } from '../actions';
import APIKeyForm from '../components/APIKeyForm'; import APIKeyForm from '../components/APIKeyForm';
const exitUrl = require('../../../images/exit.svg'); const exitUrl = require('../../../images/exit.svg');
@ -64,7 +64,7 @@ function mapStateToProps(state) {
} }
function mapDispatchToProps(dispatch) { function mapDispatchToProps(dispatch) {
return bindActionCreators({ addApiKey, removeApiKey }, dispatch); return bindActionCreators({ createApiKey, removeApiKey }, dispatch);
} }
AdvancedSettingsView.propTypes = { AdvancedSettingsView.propTypes = {

View file

@ -33,7 +33,7 @@ const user = (state = { authenticated: false }, action) => {
return { ...state, ...action.user }; return { ...state, ...action.user };
case ActionTypes.REMOVED_API_KEY: case ActionTypes.REMOVED_API_KEY:
return { ...state, ...action.user }; return { ...state, ...action.user };
case ActionTypes.ADDED_API_KEY: case ActionTypes.API_KEY_CREATED:
return { ...state, ...action.user }; return { ...state, ...action.user };
default: default:
return state; return state;