Prompt for terms of service on integration manager changes

Part of https://github.com/vector-im/riot-web/issues/10539
This commit is contained in:
Travis Ralston 2019-08-15 13:28:23 -06:00
parent ded2297523
commit 27504e1578
5 changed files with 122 additions and 37 deletions

View file

@ -19,6 +19,10 @@ import {_t} from "../../../languageHandler";
import sdk from '../../../index';
import Field from "../elements/Field";
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
import MatrixClientPeg from "../../../MatrixClientPeg";
import {SERVICE_TYPES} from "matrix-js-sdk";
import {IntegrationManagerInstance} from "../../../integrations/IntegrationManagerInstance";
import Modal from "../../../Modal";
export default class SetIntegrationManager extends React.Component {
constructor() {
@ -31,6 +35,7 @@ export default class SetIntegrationManager extends React.Component {
url: "", // user-entered text
error: null,
busy: false,
checking: false,
};
}
@ -40,14 +45,14 @@ export default class SetIntegrationManager extends React.Component {
};
_getTooltip = () => {
if (this.state.busy) {
if (this.state.checking) {
const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner');
return <div>
<InlineSpinner />
{ _t("Checking server") }
</div>;
} else if (this.state.error) {
return this.state.error;
return <span className="warning">{this.state.error}</span>;
} else {
return null;
}
@ -57,22 +62,7 @@ export default class SetIntegrationManager extends React.Component {
return !!this.state.url && !this.state.busy;
};
_setManager = async (ev) => {
// Don't reload the page when the user hits enter in the form.
ev.preventDefault();
ev.stopPropagation();
this.setState({busy: true});
const manager = await IntegrationManagers.sharedInstance().tryDiscoverManager(this.state.url);
if (!manager) {
this.setState({
busy: false,
error: _t("Integration manager offline or not accessible."),
});
return;
}
_continueTerms = async (manager) => {
try {
await IntegrationManagers.sharedInstance().overwriteManagerOnAccount(manager);
this.setState({
@ -90,6 +80,85 @@ export default class SetIntegrationManager extends React.Component {
}
};
_setManager = async (ev) => {
// Don't reload the page when the user hits enter in the form.
ev.preventDefault();
ev.stopPropagation();
this.setState({busy: true, checking: true, error: null});
let offline = false;
let manager: IntegrationManagerInstance;
try {
manager = await IntegrationManagers.sharedInstance().tryDiscoverManager(this.state.url);
offline = !manager; // no manager implies offline
} catch (e) {
console.error(e);
offline = true; // probably a connection error
}
if (offline) {
this.setState({
busy: false,
checking: false,
error: _t("Integration manager offline or not accessible."),
});
return;
}
// Test the manager (causes terms of service prompt if agreement is needed)
// We also cancel the tooltip at this point so it doesn't collide with the dialog.
this.setState({checking: false});
try {
const client = manager.getScalarClient();
await client.connect();
} catch (e) {
console.error(e);
this.setState({
busy: false,
error: _t("Terms of service not accepted or the integration manager is invalid."),
});
return;
}
// Specifically request the terms of service to see if there are any.
// The above won't trigger a terms of service check if there are no terms to
// sign, so when there's no terms at all we need to ensure we tell the user.
let hasTerms = true;
try {
const terms = await MatrixClientPeg.get().getTerms(SERVICE_TYPES.IM, manager.trimmedApiUrl);
hasTerms = terms && terms['policies'] && Object.keys(terms['policies']).length > 0;
} catch (e) {
// Assume errors mean there are no terms. This could be a 404, 500, etc
console.error(e);
hasTerms = false;
}
if (!hasTerms) {
this.setState({busy: false});
const QuestionDialog = sdk.getComponent("views.dialogs.QuestionDialog");
Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, {
title: _t("Integration manager has no terms of service"),
description: (
<div>
<span className="warning">
{_t("The integration manager you have chosen does not have any terms of service.")}
</span>
<span>
&nbsp;{_t("Only continue if you trust the owner of the server.")}
</span>
</div>
),
button: _t("Continue"),
onFinished: async (confirmed) => {
if (!confirmed) return;
this._continueTerms(manager);
},
});
return;
}
this._continueTerms(manager);
};
render() {
const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton');
@ -120,11 +189,15 @@ export default class SetIntegrationManager extends React.Component {
<span className="mx_SettingsTab_subsectionText">
{bodyText}
</span>
<Field label={_t("Enter a new integration manager")}
<Field
label={_t("Enter a new integration manager")}
id="mx_SetIntegrationManager_newUrl"
type="text" value={this.state.url} autoComplete="off"
type="text" value={this.state.url}
autoComplete="off"
onChange={this._onUrlChanged}
tooltipContent={this._getTooltip()}
disabled={this.state.busy}
flagInvalid={!!this.state.error}
/>
<AccessibleButton
kind="primary_sm"