Merge branch 'develop' into t3chguy/fix/15182

This commit is contained in:
Travis Ralston 2020-09-18 11:06:32 -06:00
commit 189233447b
69 changed files with 910 additions and 744 deletions

View file

@ -184,7 +184,7 @@ export default class ChangePassword extends React.Component {
_onExportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Export E2E Keys', 'Change Password',
import('../../../async-components/views/dialogs/ExportE2eKeysDialog'),
import('../../../async-components/views/dialogs/security/ExportE2eKeysDialog'),
{
matrixClient: MatrixClientPeg.get(),
},

View file

@ -22,6 +22,7 @@ import * as sdk from '../../../index';
import Modal from '../../../Modal';
import Spinner from '../elements/Spinner';
import InteractiveAuthDialog from '../dialogs/InteractiveAuthDialog';
import ConfirmDestroyCrossSigningDialog from '../dialogs/security/ConfirmDestroyCrossSigningDialog';
export default class CrossSigningPanel extends React.PureComponent {
constructor(props) {
@ -137,7 +138,6 @@ export default class CrossSigningPanel extends React.PureComponent {
}
_resetCrossSigning = () => {
const ConfirmDestroyCrossSigningDialog = sdk.getComponent("dialogs.ConfirmDestroyCrossSigningDialog");
Modal.createDialog(ConfirmDestroyCrossSigningDialog, {
onFinished: (act) => {
if (!act) return;
@ -187,37 +187,46 @@ export default class CrossSigningPanel extends React.PureComponent {
}
const keysExistAnywhere = (
crossSigningPublicKeysOnDevice ||
crossSigningPrivateKeysInStorage ||
crossSigningPublicKeysOnDevice
masterPrivateKeyCached ||
selfSigningPrivateKeyCached ||
userSigningPrivateKeyCached
);
const keysExistEverywhere = (
crossSigningPublicKeysOnDevice &&
crossSigningPrivateKeysInStorage &&
crossSigningPublicKeysOnDevice
masterPrivateKeyCached &&
selfSigningPrivateKeyCached &&
userSigningPrivateKeyCached
);
let resetButton;
if (keysExistAnywhere) {
resetButton = (
<div className="mx_CrossSigningPanel_buttonRow">
<AccessibleButton kind="danger" onClick={this._resetCrossSigning}>
{_t("Reset")}
</AccessibleButton>
</div>
const actions = [];
// TODO: determine how better to expose this to users in addition to prompts at login/toast
if (!keysExistEverywhere && homeserverSupportsCrossSigning) {
actions.push(
<AccessibleButton key="setup" kind="primary" onClick={this._onBootstrapClick}>
{_t("Set up")}
</AccessibleButton>,
);
}
// TODO: determine how better to expose this to users in addition to prompts at login/toast
let bootstrapButton;
if (!keysExistEverywhere && homeserverSupportsCrossSigning) {
bootstrapButton = (
<div className="mx_CrossSigningPanel_buttonRow">
<AccessibleButton kind="primary" onClick={this._onBootstrapClick}>
{_t("Set up")}
</AccessibleButton>
</div>
if (keysExistAnywhere) {
actions.push(
<AccessibleButton key="reset" kind="danger" onClick={this._resetCrossSigning}>
{_t("Reset")}
</AccessibleButton>,
);
}
let actionRow;
if (actions.length) {
actionRow = <div className="mx_CrossSigningPanel_buttonRow">
{actions}
</div>;
}
return (
<div>
{summarisedStatus}
@ -230,7 +239,7 @@ export default class CrossSigningPanel extends React.PureComponent {
</tr>
<tr>
<td>{_t("Cross-signing private keys:")}</td>
<td>{crossSigningPrivateKeysInStorage ? _t("in secret storage") : _t("not found")}</td>
<td>{crossSigningPrivateKeysInStorage ? _t("in secret storage") : _t("not found in storage")}</td>
</tr>
<tr>
<td>{_t("Master private key:")}</td>
@ -251,8 +260,7 @@ export default class CrossSigningPanel extends React.PureComponent {
</tbody></table>
</details>
{errorSection}
{bootstrapButton}
{resetButton}
{actionRow}
</div>
);
}

View file

@ -24,7 +24,7 @@ import { isSecureBackupRequired } from '../../../utils/WellKnownUtils';
import Spinner from '../elements/Spinner';
import AccessibleButton from '../elements/AccessibleButton';
import QuestionDialog from '../dialogs/QuestionDialog';
import RestoreKeyBackupDialog from '../dialogs/keybackup/RestoreKeyBackupDialog';
import RestoreKeyBackupDialog from '../dialogs/security/RestoreKeyBackupDialog';
import { accessSecretStorage } from '../../../SecurityManager';
export default class SecureBackupPanel extends React.PureComponent {
@ -131,7 +131,7 @@ export default class SecureBackupPanel extends React.PureComponent {
const cli = MatrixClientPeg.get();
const secretStorage = cli._crypto._secretStorage;
const backupKeyStored = await cli.isKeyBackupKeyStored();
const backupKeyStored = !!(await cli.isKeyBackupKeyStored());
const backupKeyFromCache = await cli._crypto.getSessionBackupPrivateKey();
const backupKeyCached = !!(backupKeyFromCache);
const backupKeyWellFormed = backupKeyFromCache instanceof Uint8Array;
@ -150,7 +150,7 @@ export default class SecureBackupPanel extends React.PureComponent {
_startNewBackup = () => {
Modal.createTrackedDialogAsync('Key Backup', 'Key Backup',
import('../../../async-components/views/dialogs/keybackup/CreateKeyBackupDialog'),
import('../../../async-components/views/dialogs/security/CreateKeyBackupDialog'),
{
onFinished: () => {
this._loadBackupStatus();
@ -367,14 +367,14 @@ export default class SecureBackupPanel extends React.PureComponent {
</>;
actions.push(
<AccessibleButton kind="primary" onClick={this._restoreBackup}>
<AccessibleButton key="restore" kind="primary" onClick={this._restoreBackup}>
{restoreButtonCaption}
</AccessibleButton>,
);
if (!isSecureBackupRequired()) {
actions.push(
<AccessibleButton kind="danger" onClick={this._deleteBackup}>
<AccessibleButton key="delete" kind="danger" onClick={this._deleteBackup}>
{_t("Delete Backup")}
</AccessibleButton>,
);
@ -388,7 +388,7 @@ export default class SecureBackupPanel extends React.PureComponent {
<p>{_t("Back up your keys before signing out to avoid losing them.")}</p>
</>;
actions.push(
<AccessibleButton kind="primary" onClick={this._startNewBackup}>
<AccessibleButton key="setup" kind="primary" onClick={this._startNewBackup}>
{_t("Set up")}
</AccessibleButton>,
);
@ -396,7 +396,7 @@ export default class SecureBackupPanel extends React.PureComponent {
if (secretStorageKeyInAccount) {
actions.push(
<AccessibleButton kind="danger" onClick={this._resetSecretStorage}>
<AccessibleButton key="reset" kind="danger" onClick={this._resetSecretStorage}>
{_t("Reset")}
</AccessibleButton>,
);

View file

@ -36,6 +36,7 @@ import EventTilePreview from '../../../elements/EventTilePreview';
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
import classNames from 'classnames';
import { SettingLevel } from "../../../../../settings/SettingLevel";
import {UIFeature} from "../../../../../settings/UIFeature";
interface IProps {
}
@ -386,6 +387,8 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
};
private renderAdvancedSection() {
if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null;
const brand = SdkConfig.get().brand;
const toggle = <div
className="mx_AppearanceUserSettingsTab_AdvancedToggle"

View file

@ -37,6 +37,7 @@ import {abbreviateUrl} from "../../../../../utils/UrlUtils";
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';
import Spinner from "../../../elements/Spinner";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import {UIFeature} from "../../../../../settings/UIFeature";
export default class GeneralUserSettingsTab extends React.Component {
static propTypes = {
@ -247,7 +248,9 @@ export default class GeneralUserSettingsTab extends React.Component {
// validate 3PID ownership even if we're just adding to the homeserver only.
// For newer homeservers with separate 3PID add and bind methods (MSC2290),
// there is no such concern, so we can always show the HS account 3PIDs.
if (this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true) {
if (SettingsStore.getValue(UIFeature.ThirdPartyID) &&
(this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true)
) {
const emails = this.state.loading3pids
? <Spinner />
: <EmailAddresses
@ -366,6 +369,8 @@ export default class GeneralUserSettingsTab extends React.Component {
}
_renderIntegrationManagerSection() {
if (!SettingsStore.getValue(UIFeature.Widgets)) return null;
const SetIntegrationManager = sdk.getComponent("views.settings.SetIntegrationManager");
return (
@ -383,17 +388,31 @@ export default class GeneralUserSettingsTab extends React.Component {
width="18" height="18" alt={_t("Warning")} />
: null;
let accountManagementSection;
if (SettingsStore.getValue(UIFeature.Deactivate)) {
accountManagementSection = <>
<div className="mx_SettingsTab_heading">{_t("Deactivate account")}</div>
{this._renderManagementSection()}
</>;
}
let discoverySection;
if (SettingsStore.getValue(UIFeature.IdentityServer)) {
discoverySection = <>
<div className="mx_SettingsTab_heading">{discoWarning} {_t("Discovery")}</div>
{this._renderDiscoverySection()}
</>;
}
return (
<div className="mx_SettingsTab">
<div className="mx_SettingsTab_heading">{_t("General")}</div>
{this._renderProfileSection()}
{this._renderAccountSection()}
{this._renderLanguageSection()}
<div className="mx_SettingsTab_heading">{discoWarning} {_t("Discovery")}</div>
{this._renderDiscoverySection()}
{ discoverySection }
{this._renderIntegrationManagerSection() /* Has its own title */}
<div className="mx_SettingsTab_heading">{_t("Deactivate account")}</div>
{this._renderManagementSection()}
{ accountManagementSection }
</div>
);
}

View file

@ -49,10 +49,10 @@ export default class PreferencesUserSettingsTab extends React.Component {
'showAvatarChanges',
'showDisplaynameChanges',
'showImages',
'Pill.shouldShowPillAvatar',
];
static ADVANCED_SETTINGS = [
'Pill.shouldShowPillAvatar',
static GENERAL_SETTINGS = [
'TagPanel.enableTagPanel',
'promptBeforeInviteUnknownUsers',
// Start automatically after startup (electron-only)
@ -188,8 +188,8 @@ export default class PreferencesUserSettingsTab extends React.Component {
</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Advanced")}</span>
{this._renderGroup(PreferencesUserSettingsTab.ADVANCED_SETTINGS)}
<span className="mx_SettingsTab_subheading">{_t("General")}</span>
{this._renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)}
{minimizeToTrayOption}
{autoHideMenuOption}
{autoLaunchOption}

View file

@ -30,6 +30,8 @@ import dis from "../../../../../dispatcher/dispatcher";
import {privateShouldBeEncrypted} from "../../../../../createRoom";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import SecureBackupPanel from "../../SecureBackupPanel";
import SettingsStore from "../../../../../settings/SettingsStore";
import {UIFeature} from "../../../../../settings/UIFeature";
export class IgnoredUser extends React.Component {
static propTypes = {
@ -103,14 +105,14 @@ export default class SecurityUserSettingsTab extends React.Component {
_onExportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Export E2E Keys', '',
import('../../../../../async-components/views/dialogs/ExportE2eKeysDialog'),
import('../../../../../async-components/views/dialogs/security/ExportE2eKeysDialog'),
{matrixClient: MatrixClientPeg.get()},
);
};
_onImportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Import E2E Keys', '',
import('../../../../../async-components/views/dialogs/ImportE2eKeysDialog'),
import('../../../../../async-components/views/dialogs/security/ImportE2eKeysDialog'),
{matrixClient: MatrixClientPeg.get()},
);
};
@ -311,15 +313,13 @@ export default class SecurityUserSettingsTab extends React.Component {
// can remove this.
const CrossSigningPanel = sdk.getComponent('views.settings.CrossSigningPanel');
const crossSigning = (
<div className='mx_SettingsTab_section'>
<span className="mx_SettingsTab_subheading">{_t("Cross-signing")}</span>
<div className='mx_SettingsTab_subsectionText'>
<CrossSigningPanel />
</div>
<div className='mx_SettingsTab_section'>
<span className="mx_SettingsTab_subheading">{_t("Cross-signing")}</span>
<div className='mx_SettingsTab_subsectionText'>
<CrossSigningPanel />
</div>
);
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
</div>
);
let warning;
if (!privateShouldBeEncrypted()) {
@ -329,6 +329,42 @@ export default class SecurityUserSettingsTab extends React.Component {
</div>;
}
let privacySection;
if (Analytics.canEnable()) {
privacySection = <React.Fragment>
<div className="mx_SettingsTab_heading">{_t("Privacy")}</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Analytics")}</span>
<div className="mx_SettingsTab_subsectionText">
{_t(
"%(brand)s collects anonymous analytics to allow us to improve the application.",
{ brand },
)}
&nbsp;
{_t("Privacy is important to us, so we don't collect any personal or " +
"identifiable data for our analytics.")}
<AccessibleButton className="mx_SettingsTab_linkBtn" onClick={Analytics.showDetailsModal}>
{_t("Learn more about how we use analytics.")}
</AccessibleButton>
</div>
<SettingsFlag name="analyticsOptIn" level={SettingLevel.DEVICE} onChange={this._updateAnalytics} />
</div>
</React.Fragment>;
}
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
let advancedSection;
if (SettingsStore.getValue(UIFeature.AdvancedSettings)) {
advancedSection = <>
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
<div className="mx_SettingsTab_section">
{this._renderIgnoredUsers()}
{this._renderManageInvites()}
<E2eAdvancedPanel />
</div>
</>;
}
return (
<div className="mx_SettingsTab mx_SecurityUserSettingsTab">
{warning}
@ -357,30 +393,8 @@ export default class SecurityUserSettingsTab extends React.Component {
{crossSigning}
{this._renderCurrentDeviceInfo()}
</div>
<div className="mx_SettingsTab_heading">{_t("Privacy")}</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Analytics")}</span>
<div className='mx_SettingsTab_subsectionText'>
{_t(
"%(brand)s collects anonymous analytics to allow us to improve the application.",
{ brand },
)}
&nbsp;
{_t("Privacy is important to us, so we don't collect any personal or " +
"identifiable data for our analytics.")}
<AccessibleButton className="mx_SettingsTab_linkBtn" onClick={Analytics.showDetailsModal}>
{_t("Learn more about how we use analytics.")}
</AccessibleButton>
</div>
<SettingsFlag name='analyticsOptIn' level={SettingLevel.DEVICE}
onChange={this._updateAnalytics} />
</div>
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
<div className="mx_SettingsTab_section">
{this._renderIgnoredUsers()}
{this._renderManageInvites()}
<E2eAdvancedPanel />
</div>
{ privacySection }
{ advancedSection }
</div>
);
}