Skip to content

Commit

Permalink
feat(deploy): remember authentication details
Browse files Browse the repository at this point in the history
Closes #1067
  • Loading branch information
barmac authored and nikku committed Nov 15, 2019
1 parent 8848acc commit e144cd9
Show file tree
Hide file tree
Showing 9 changed files with 424 additions and 120 deletions.
4 changes: 4 additions & 0 deletions client/src/app/__tests__/mocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,10 @@ export class Config extends Mock {
getForPlugin() {}

setForPlugin() {}

getCredentials() {}

setCredentials() {}
}

export class Log extends Mock {
Expand Down
28 changes: 11 additions & 17 deletions client/src/plugins/deployment-tool/DeploymentDetailsModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import AuthTypes from './AuthTypes';
import {
AuthBasic,
AuthBearer,
CheckBox,
FormControl
} from './components';

Expand All @@ -38,16 +39,6 @@ import {
import { ConnectionErrorMessages } from './errors';


const initialFormValues = {
endpointUrl: 'http://localhost:8080/engine-rest',
tenantId: '',
deploymentName: 'diagram',
authType: AuthTypes.none,
username: '',
password: '',
bearer: ''
};

export default class DeploymentDetailsModal extends React.PureComponent {

state = {
Expand All @@ -64,7 +55,7 @@ export default class DeploymentDetailsModal extends React.PureComponent {
this.mounted = true;

// check connection with pre-validated initial form values
const initialValues = this.getInitialValues();
const initialValues = this.props.details;
const errors = this.props.validate(initialValues);

this.checkConnectionIfNeeded(initialValues, errors, true);
Expand All @@ -74,10 +65,6 @@ export default class DeploymentDetailsModal extends React.PureComponent {
this.mounted = false;
}

getInitialValues() {
return { ...initialFormValues, ...this.props.details };
}

checkConnection = async values => {
if (!this.mounted || this.state.checkingConnection) {
return;
Expand Down Expand Up @@ -203,11 +190,10 @@ export default class DeploymentDetailsModal extends React.PureComponent {

render() {
const {
details: initialValues,
onFocusChange
} = this.props;

const initialValues = this.getInitialValues();

const {
checkingConnection,
connectionChecked,
Expand Down Expand Up @@ -315,6 +301,14 @@ export default class DeploymentDetailsModal extends React.PureComponent {
{ values.authType === AuthTypes.bearer && (
<AuthBearer onFocusChange={ onFocusChange } />) }

{ values.authType !== AuthTypes.none && (
<Field
name="rememberCredentials"
component={ CheckBox }
label={ `Save ${ values.authType === AuthTypes.basic ? 'password' : 'token' }` }
onFocusChange={ onFocusChange }
/>
)}
</div>
</fieldset>
</Modal.Body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@
width: 10px;
}

label {
text-align: right;
label:only-child {
width: 100%;
display: inline-block;
text-align: right;
}

input,
input:not([type="checkbox"]),
select {
width: 100%;
padding: 6px;
Expand Down
136 changes: 106 additions & 30 deletions client/src/plugins/deployment-tool/DeploymentTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ const VALIDATED_FIELDS = [
'endpointUrl'
];

const CONFIG_KEY = 'deployment-config';

const CONFIG_KEY = 'deployment-tool';

const defaultDeploymentDetails = {
endpointUrl: 'http://localhost:8080/engine-rest',
tenantId: '',
authType: AuthTypes.none,
username: '',
password: '',
bearer: '',
rememberCredentials: false
};

export default class DeploymentTool extends PureComponent {

Expand Down Expand Up @@ -59,25 +68,7 @@ export default class DeploymentTool extends PureComponent {
activeTab
} = this.state;

this.deployTab(activeTab);
}

async saveDetails(tab, details) {
const {
config
} = this.props;

const savedDetails = this.getDetailsToSave(details);

return config.setForFile(tab.file, CONFIG_KEY, savedDetails);
}

async getSavedDetails(tab) {
const {
config
} = this.props;

return config.getForFile(tab.file, CONFIG_KEY);
return this.deployTab(activeTab);
}

async deployTab(tab) {
Expand Down Expand Up @@ -117,8 +108,10 @@ export default class DeploymentTool extends PureComponent {
displayNotification
} = this.props;

const payload = this.getDeploymentPayload(details);

try {
await this.deployWithDetails(tab, details);
await this.deployWithDetails(tab, payload);

displayNotification({
type: 'success',
Expand All @@ -136,6 +129,93 @@ export default class DeploymentTool extends PureComponent {
}
}

saveDetails(tab, details) {
return Promise.all([
this.saveDeploymentDetails(tab, details),
this.saveAuthDetails(details)
]);
}

saveDeploymentDetails(tab, details) {
const {
config
} = this.props;

const detailsForFile = this.getDetailsToSave(details);

return config.setForFile(tab.file, CONFIG_KEY, detailsForFile);
}

saveAuthDetails(details) {
const {
config
} = this.props;

// skip saving if user did not opt in
if (!details.rememberCredentials) {
return;
}

const accountName = this.getAccountName(details);

// skip saving if can't determine account name
if (!accountName) {
return;
}

const auth = this.getAuth(details);
const authWithoutUsername = omit(auth, 'username');

return config.setCredentials(CONFIG_KEY, accountName, authWithoutUsername);
}

async getSavedDetails(tab) {
const {
config
} = this.props;

const detailsForFile = await config.getForFile(tab.file, CONFIG_KEY);

const auth = await this.getSavedAuthDetails(detailsForFile);

return {
...detailsForFile,
...auth
};
}

getSavedAuthDetails(deploymentConfig) {
const {
config
} = this.props;

const accountName = this.getAccountName(deploymentConfig);

if (accountName) {
return config.getCredentials(CONFIG_KEY, accountName);
}
}

getAccountName(config) {
if (!config) {
return null;
}

const {
authType,
endpointUrl,
username
} = config;

if (!endpointUrl || !authType || authType === AuthTypes.none) {
return null;
}

return authType === AuthTypes.basic ?
`${authType}.${username}.${endpointUrl}` :
`${authType}.${endpointUrl}`;
}

deployWithDetails(tab, details) {

const payload = this.getDeploymentPayload(details);
Expand Down Expand Up @@ -165,11 +245,7 @@ export default class DeploymentTool extends PureComponent {

// contract: if details provided, user closed with O.K.
// otherwise they canceled it
if (result) {
return resolve(this.getDetailsFromForm(result));
}

resolve();
return resolve(result);
};

this.setState({
Expand All @@ -183,7 +259,7 @@ export default class DeploymentTool extends PureComponent {
}

getDetailsToSave(rawDetails) {
return omit(rawDetails, 'auth');
return omit(rawDetails, [ 'bearer', 'password' ]);
}

validateDetails = values => {
Expand Down Expand Up @@ -216,7 +292,7 @@ export default class DeploymentTool extends PureComponent {
}

getInitialDetails(tab, providedDetails) {
const details = { ...providedDetails };
const details = { ...defaultDeploymentDetails, ...providedDetails };

if (!details.deploymentName) {
details.deploymentName = withoutExtension(tab.name);
Expand All @@ -236,7 +312,7 @@ export default class DeploymentTool extends PureComponent {
}
}

getDetailsFromForm(values) {
getDeploymentPayload(values) {
const endpointUrl = this.getBaseUrl(values.endpointUrl);

const payload = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ describe('<DeploymentDetailsModal>', () => {
// helpers //////////
function createModal(props, renderFn = shallow) {
props = {
details: getDefaultDeploymentDetails(),
checkConnection: noop,
validate: () => ({}),
...props
Expand All @@ -151,3 +152,15 @@ function createModal(props, renderFn = shallow) {
}

function noop() {}

function getDefaultDeploymentDetails() {
return {
deploymentName: 'diagram',
endpointUrl: 'http://localhost:8080/engine-rest',
tenantId: '',
authType: AuthTypes.none,
username: '',
password: '',
bearer: ''
};
}
Loading

0 comments on commit e144cd9

Please sign in to comment.