Merge pull request #3059 from Bilb/fix-dont-password-protect-settings

feat: dont password protect the settings except the seed one
pull/3067/head
Audric Ackermann 1 year ago committed by GitHub
commit 5f6af1e2cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -25,13 +25,9 @@ const StyledButtonContainer = styled.div`
padding-inline-start: var(--margins-lg); padding-inline-start: var(--margins-lg);
`; `;
export const SessionNotificationGroupSettings = (props: { hasPassword: boolean | null }) => { export const SessionNotificationGroupSettings = () => {
const forceUpdate = useUpdate(); const forceUpdate = useUpdate();
if (props.hasPassword === null) {
return null;
}
const initialNotificationEnabled = const initialNotificationEnabled =
window.getSettingValue(SettingsKey.settingsNotification) || NOTIFICATION.MESSAGE; window.getSettingValue(SettingsKey.settingsNotification) || NOTIFICATION.MESSAGE;

@ -1,23 +1,24 @@
import { shell } from 'electron'; import { shell } from 'electron';
import React from 'react'; import React, { useState } from 'react';
import autoBind from 'auto-bind';
import styled from 'styled-components'; import styled from 'styled-components';
import { useDispatch } from 'react-redux';
import useMount from 'react-use/lib/useMount';
import { SettingsHeader } from './SessionSettingsHeader'; import { SettingsHeader } from './SessionSettingsHeader';
import { SessionIconButton } from '../icon'; import { SessionIconButton } from '../icon';
import { SessionNotificationGroupSettings } from './SessionNotificationGroupSettings'; import { SessionNotificationGroupSettings } from './SessionNotificationGroupSettings';
import { CategoryConversations } from './section/CategoryConversations';
import { SettingsCategoryPrivacy } from './section/CategoryPrivacy';
import { SettingsCategoryAppearance } from './section/CategoryAppearance';
import { Data } from '../../data/data'; import { Data } from '../../data/data';
import { SettingsCategoryPermissions } from './section/CategoryPermissions';
import { SettingsCategoryHelp } from './section/CategoryHelp';
import { sessionPassword } from '../../state/ducks/modalDialog'; import { sessionPassword } from '../../state/ducks/modalDialog';
import { PasswordAction } from '../dialog/SessionPasswordDialog';
import { SectionType, showLeftPaneSection } from '../../state/ducks/section'; import { SectionType, showLeftPaneSection } from '../../state/ducks/section';
import { PasswordAction } from '../dialog/SessionPasswordDialog';
import { SettingsCategoryAppearance } from './section/CategoryAppearance';
import { CategoryConversations } from './section/CategoryConversations';
import { SettingsCategoryHelp } from './section/CategoryHelp';
import { SettingsCategoryPermissions } from './section/CategoryPermissions';
import { SettingsCategoryPrivacy } from './section/CategoryPrivacy';
export function displayPasswordModal( export function displayPasswordModal(
passwordAction: PasswordAction, passwordAction: PasswordAction,
@ -57,11 +58,6 @@ export interface SettingsViewProps {
category: SessionSettingCategory; category: SessionSettingCategory;
} }
interface State {
hasPassword: boolean | null;
shouldLockSettings: boolean | null;
}
const StyledVersionInfo = styled.div` const StyledVersionInfo = styled.div`
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -110,30 +106,27 @@ const SessionInfo = () => {
const SettingInCategory = (props: { const SettingInCategory = (props: {
category: SessionSettingCategory; category: SessionSettingCategory;
hasPassword: boolean;
onPasswordUpdated: (action: string) => void; onPasswordUpdated: (action: string) => void;
hasPassword: boolean;
}) => { }) => {
const { category, hasPassword, onPasswordUpdated } = props; const { category, onPasswordUpdated, hasPassword } = props;
if (hasPassword === null) {
return null;
}
switch (category) { switch (category) {
// special case for blocked user // special case for blocked user
case SessionSettingCategory.Conversations: case SessionSettingCategory.Conversations:
return <CategoryConversations />; return <CategoryConversations />;
case SessionSettingCategory.Appearance: case SessionSettingCategory.Appearance:
return <SettingsCategoryAppearance hasPassword={hasPassword} />; return <SettingsCategoryAppearance />;
case SessionSettingCategory.Notifications: case SessionSettingCategory.Notifications:
return <SessionNotificationGroupSettings hasPassword={hasPassword} />; return <SessionNotificationGroupSettings />;
case SessionSettingCategory.Privacy: case SessionSettingCategory.Privacy:
return ( return (
<SettingsCategoryPrivacy onPasswordUpdated={onPasswordUpdated} hasPassword={hasPassword} /> <SettingsCategoryPrivacy onPasswordUpdated={onPasswordUpdated} hasPassword={hasPassword} />
); );
case SessionSettingCategory.Help: case SessionSettingCategory.Help:
return <SettingsCategoryHelp hasPassword={hasPassword} />; return <SettingsCategoryHelp />;
case SessionSettingCategory.Permissions: case SessionSettingCategory.Permissions:
return <SettingsCategoryPermissions hasPassword={hasPassword} />; return <SettingsCategoryPermissions />;
// these three down there have no options, they are just a button // these three down there have no options, they are just a button
case SessionSettingCategory.ClearData: case SessionSettingCategory.ClearData:
@ -159,87 +152,48 @@ const StyledSettingsList = styled.div`
flex-direction: column; flex-direction: column;
`; `;
export class SessionSettingsView extends React.Component<SettingsViewProps, State> { export const SessionSettingsView = (props: SettingsViewProps) => {
public settingsViewRef: React.RefObject<HTMLDivElement>; const { category } = props;
const dispatch = useDispatch();
public constructor(props: any) {
super(props);
this.state = {
hasPassword: null,
shouldLockSettings: true,
};
this.settingsViewRef = React.createRef();
autoBind(this);
const [hasPassword, setHasPassword] = useState(true);
useMount(() => {
let isMounted = true;
// eslint-disable-next-line more/no-then // eslint-disable-next-line more/no-then
void Data.getPasswordHash().then(hash => { void Data.getPasswordHash().then(hash => {
this.setState({ if (isMounted) {
hasPassword: !!hash, setHasPassword(!!hash);
}); }
}); });
} return () => {
isMounted = false;
public componentDidUpdate(_: SettingsViewProps, _prevState: State) { };
const oldShouldRenderPasswordLock = _prevState.shouldLockSettings && _prevState.hasPassword; });
const newShouldRenderPasswordLock = this.state.shouldLockSettings && this.state.hasPassword;
if (
newShouldRenderPasswordLock &&
newShouldRenderPasswordLock !== oldShouldRenderPasswordLock
) {
displayPasswordModal('enter', action => {
if (action === 'enter') {
// Unlocked settings
this.setState({
shouldLockSettings: false,
});
}
});
}
}
public render() {
const { category } = this.props;
const shouldRenderPasswordLock = this.state.shouldLockSettings && this.state.hasPassword;
return (
<div className="session-settings">
{shouldRenderPasswordLock ? (
<></>
) : (
<>
<SettingsHeader category={category} />
<StyledSettingsView>
<StyledSettingsList ref={this.settingsViewRef}>
<SettingInCategory
category={category}
onPasswordUpdated={this.onPasswordUpdated}
hasPassword={Boolean(this.state.hasPassword)}
/>
</StyledSettingsList>
<SessionInfo />
</StyledSettingsView>
</>
)}
</div>
);
}
public onPasswordUpdated(action: string) { function onPasswordUpdated(action: string) {
if (action === 'set' || action === 'change') { if (action === 'set' || action === 'change') {
this.setState({ setHasPassword(true);
hasPassword: true, dispatch(showLeftPaneSection(SectionType.Message));
shouldLockSettings: true,
});
window.inboxStore?.dispatch(showLeftPaneSection(SectionType.Message));
} }
if (action === 'remove') { if (action === 'remove') {
this.setState({ setHasPassword(false);
hasPassword: false,
});
} }
} }
}
return (
<div className="session-settings">
<SettingsHeader category={category} />
<StyledSettingsView>
<StyledSettingsList>
<SettingInCategory
category={category}
onPasswordUpdated={onPasswordUpdated}
hasPassword={hasPassword}
/>
</StyledSettingsList>
<SessionInfo />
</StyledSettingsView>
</div>
);
};

@ -2,54 +2,51 @@ import React from 'react';
import useUpdate from 'react-use/lib/useUpdate'; import useUpdate from 'react-use/lib/useUpdate';
import { SettingsKey } from '../../../data/settings-key'; import { SettingsKey } from '../../../data/settings-key';
import { isHideMenuBarSupported } from '../../../types/Settings';
import { useHasFollowSystemThemeEnabled } from '../../../state/selectors/settings'; import { useHasFollowSystemThemeEnabled } from '../../../state/selectors/settings';
import { ensureThemeConsistency } from '../../../themes/SessionTheme'; import { ensureThemeConsistency } from '../../../themes/SessionTheme';
import { isHideMenuBarSupported } from '../../../types/Settings';
import { SessionToggleWithDescription } from '../SessionSettingListItem'; import { SessionToggleWithDescription } from '../SessionSettingListItem';
import { SettingsThemeSwitcher } from '../SettingsThemeSwitcher'; import { SettingsThemeSwitcher } from '../SettingsThemeSwitcher';
import { ZoomingSessionSlider } from '../ZoomingSessionSlider'; import { ZoomingSessionSlider } from '../ZoomingSessionSlider';
export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null }) => { export const SettingsCategoryAppearance = () => {
const forceUpdate = useUpdate(); const forceUpdate = useUpdate();
const isFollowSystemThemeEnabled = useHasFollowSystemThemeEnabled(); const isFollowSystemThemeEnabled = useHasFollowSystemThemeEnabled();
if (props.hasPassword !== null) { const isHideMenuBarActive =
const isHideMenuBarActive = window.getSettingValue(SettingsKey.settingsMenuBar) === undefined
window.getSettingValue(SettingsKey.settingsMenuBar) === undefined ? true
? true : window.getSettingValue(SettingsKey.settingsMenuBar);
: window.getSettingValue(SettingsKey.settingsMenuBar);
return ( return (
<> <>
<SettingsThemeSwitcher /> <SettingsThemeSwitcher />
<ZoomingSessionSlider /> <ZoomingSessionSlider />
{isHideMenuBarSupported() && ( {isHideMenuBarSupported() && (
<SessionToggleWithDescription
onClickToggle={() => {
window.toggleMenuBar();
forceUpdate();
}}
title={window.i18n('hideMenuBarTitle')}
description={window.i18n('hideMenuBarDescription')}
active={isHideMenuBarActive}
/>
)}
<SessionToggleWithDescription <SessionToggleWithDescription
// eslint-disable-next-line @typescript-eslint/no-misused-promises onClickToggle={() => {
onClickToggle={async () => { window.toggleMenuBar();
const toggledValue = !isFollowSystemThemeEnabled; forceUpdate();
await window.setSettingValue(SettingsKey.hasFollowSystemThemeEnabled, toggledValue);
if (!isFollowSystemThemeEnabled) {
await ensureThemeConsistency();
}
}} }}
title={window.i18n('matchThemeSystemSettingTitle')} title={window.i18n('hideMenuBarTitle')}
description={window.i18n('matchThemeSystemSettingDescription')} description={window.i18n('hideMenuBarDescription')}
active={isFollowSystemThemeEnabled} active={isHideMenuBarActive}
dataTestId="enable-follow-system-theme"
/> />
</> )}
); <SessionToggleWithDescription
} // eslint-disable-next-line @typescript-eslint/no-misused-promises
return null; onClickToggle={async () => {
const toggledValue = !isFollowSystemThemeEnabled;
await window.setSettingValue(SettingsKey.hasFollowSystemThemeEnabled, toggledValue);
if (!isFollowSystemThemeEnabled) {
await ensureThemeConsistency();
}
}}
title={window.i18n('matchThemeSystemSettingTitle')}
description={window.i18n('matchThemeSystemSettingDescription')}
active={isFollowSystemThemeEnabled}
dataTestId="enable-follow-system-theme"
/>
</>
);
}; };

@ -4,38 +4,35 @@ import { SessionButtonShape, SessionButtonType } from '../../basic/SessionButton
import { SessionSettingButtonItem, SessionSettingsTitleWithLink } from '../SessionSettingListItem'; import { SessionSettingButtonItem, SessionSettingsTitleWithLink } from '../SessionSettingListItem';
export const SettingsCategoryHelp = (props: { hasPassword: boolean | null }) => { export const SettingsCategoryHelp = () => {
if (props.hasPassword !== null) { return (
return ( <>
<> <SessionSettingButtonItem
<SessionSettingButtonItem onClick={() => {
onClick={() => { ipcRenderer.send('show-debug-log');
ipcRenderer.send('show-debug-log'); }}
}} buttonShape={SessionButtonShape.Square}
buttonShape={SessionButtonShape.Square} buttonType={SessionButtonType.Solid}
buttonType={SessionButtonType.Solid} buttonText={window.i18n('showDebugLog')}
buttonText={window.i18n('showDebugLog')} title={window.i18n('reportIssue')}
title={window.i18n('reportIssue')} description={window.i18n('shareBugDetails')}
description={window.i18n('shareBugDetails')} />
/> <SessionSettingsTitleWithLink
<SessionSettingsTitleWithLink title={window.i18n('surveyTitle')}
title={window.i18n('surveyTitle')} onClick={() => void shell.openExternal('https://getsession.org/survey')}
onClick={() => void shell.openExternal('https://getsession.org/survey')} />
/> <SessionSettingsTitleWithLink
<SessionSettingsTitleWithLink title={window.i18n('helpUsTranslateSession')}
title={window.i18n('helpUsTranslateSession')} onClick={() => void shell.openExternal('https://crowdin.com/project/session-desktop/')}
onClick={() => void shell.openExternal('https://crowdin.com/project/session-desktop/')} />
/> <SessionSettingsTitleWithLink
<SessionSettingsTitleWithLink title={window.i18n('faq')}
title={window.i18n('faq')} onClick={() => void shell.openExternal('https://getsession.org/faq')}
onClick={() => void shell.openExternal('https://getsession.org/faq')} />
/> <SessionSettingsTitleWithLink
<SessionSettingsTitleWithLink title={window.i18n('support')}
title={window.i18n('support')} onClick={() => void shell.openExternal('https://sessionapp.zendesk.com/hc/en-us')}
onClick={() => void shell.openExternal('https://sessionapp.zendesk.com/hc/en-us')} />
/> </>
</> );
);
}
return null;
}; };

@ -53,54 +53,51 @@ async function toggleStartInTray() {
} }
} }
export const SettingsCategoryPermissions = (props: { hasPassword: boolean | null }) => { export const SettingsCategoryPermissions = () => {
const forceUpdate = useUpdate(); const forceUpdate = useUpdate();
const isStartInTrayActive = Boolean(window.getSettingValue(SettingsKey.settingsStartInTray)); const isStartInTrayActive = Boolean(window.getSettingValue(SettingsKey.settingsStartInTray));
if (props.hasPassword !== null) { return (
return ( <>
<> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={async () => {
onClickToggle={async () => { await window.toggleMediaPermissions();
await window.toggleMediaPermissions(); forceUpdate();
forceUpdate(); }}
}} title={window.i18n('mediaPermissionsTitle')}
title={window.i18n('mediaPermissionsTitle')} description={window.i18n('mediaPermissionsDescription')}
description={window.i18n('mediaPermissionsDescription')} active={Boolean(window.getSettingValue('media-permissions'))}
active={Boolean(window.getSettingValue('media-permissions'))} dataTestId="enable-microphone"
dataTestId="enable-microphone" />
/> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={async () => {
onClickToggle={async () => { await toggleCallMediaPermissions(forceUpdate);
await toggleCallMediaPermissions(forceUpdate); forceUpdate();
forceUpdate(); }}
}} title={window.i18n('callMediaPermissionsTitle')}
title={window.i18n('callMediaPermissionsTitle')} description={window.i18n('callMediaPermissionsDescription')}
description={window.i18n('callMediaPermissionsDescription')} active={Boolean(window.getCallMediaPermissions())}
active={Boolean(window.getCallMediaPermissions())} dataTestId="enable-calls"
dataTestId="enable-calls" />
/> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={async () => {
onClickToggle={async () => { const old = Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate));
const old = Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate)); await window.setSettingValue(SettingsKey.settingsAutoUpdate, !old);
await window.setSettingValue(SettingsKey.settingsAutoUpdate, !old); forceUpdate();
forceUpdate(); }}
}} title={window.i18n('autoUpdateSettingTitle')}
title={window.i18n('autoUpdateSettingTitle')} description={window.i18n('autoUpdateSettingDescription')}
description={window.i18n('autoUpdateSettingDescription')} active={Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate))}
active={Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate))} />
/> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={async () => {
onClickToggle={async () => { await toggleStartInTray();
await toggleStartInTray(); forceUpdate();
forceUpdate(); }}
}} title={window.i18n('startInTrayTitle')}
title={window.i18n('startInTrayTitle')} description={window.i18n('startInTrayDescription')}
description={window.i18n('startInTrayDescription')} active={isStartInTrayActive}
active={isStartInTrayActive} />
/> </>
</> );
);
}
return null;
}; };

@ -61,66 +61,66 @@ export const SettingsCategoryPrivacy = (props: {
const isLinkPreviewsOn = useHasLinkPreviewEnabled(); const isLinkPreviewsOn = useHasLinkPreviewEnabled();
const areBlindedRequestsEnabled = useHasBlindedMsgRequestsEnabled(); const areBlindedRequestsEnabled = useHasBlindedMsgRequestsEnabled();
if (props.hasPassword !== null) { return (
return ( <>
<> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={async () => {
onClickToggle={async () => { const old = Boolean(window.getSettingValue(SettingsKey.settingsReadReceipt));
const old = Boolean(window.getSettingValue(SettingsKey.settingsReadReceipt)); await window.setSettingValue(SettingsKey.settingsReadReceipt, !old);
await window.setSettingValue(SettingsKey.settingsReadReceipt, !old); forceUpdate();
forceUpdate(); }}
}} title={window.i18n('readReceiptSettingTitle')}
title={window.i18n('readReceiptSettingTitle')} description={window.i18n('readReceiptSettingDescription')}
description={window.i18n('readReceiptSettingDescription')} active={window.getSettingValue(SettingsKey.settingsReadReceipt)}
active={window.getSettingValue(SettingsKey.settingsReadReceipt)} dataTestId="enable-read-receipts"
dataTestId="enable-read-receipts" />
/> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={async () => {
onClickToggle={async () => { const old = Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator));
const old = Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator)); await window.setSettingValue(SettingsKey.settingsTypingIndicator, !old);
await window.setSettingValue(SettingsKey.settingsTypingIndicator, !old); forceUpdate();
forceUpdate(); }}
}} title={window.i18n('typingIndicatorsSettingTitle')}
title={window.i18n('typingIndicatorsSettingTitle')} description={window.i18n('typingIndicatorsSettingDescription')}
description={window.i18n('typingIndicatorsSettingDescription')} active={Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator))}
active={Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator))} childrenDescription={<TypingBubbleItem />}
childrenDescription={<TypingBubbleItem />} />
/> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={() => {
onClickToggle={() => { void toggleLinkPreviews(isLinkPreviewsOn, forceUpdate);
void toggleLinkPreviews(isLinkPreviewsOn, forceUpdate); }}
}} title={window.i18n('linkPreviewsTitle')}
title={window.i18n('linkPreviewsTitle')} description={window.i18n('linkPreviewDescription')}
description={window.i18n('linkPreviewDescription')} active={isLinkPreviewsOn}
active={isLinkPreviewsOn} />
/> <SessionToggleWithDescription
<SessionToggleWithDescription onClickToggle={async () => {
onClickToggle={async () => { const toggledValue = !areBlindedRequestsEnabled;
const toggledValue = !areBlindedRequestsEnabled; await window.setSettingValue(SettingsKey.hasBlindedMsgRequestsEnabled, toggledValue);
await window.setSettingValue(SettingsKey.hasBlindedMsgRequestsEnabled, toggledValue); await SessionUtilUserProfile.insertUserProfileIntoWrapper(
await SessionUtilUserProfile.insertUserProfileIntoWrapper( UserUtils.getOurPubKeyStrFromCache()
UserUtils.getOurPubKeyStrFromCache() );
); await ConfigurationSync.queueNewJobIfNeeded();
await ConfigurationSync.queueNewJobIfNeeded(); forceUpdate();
forceUpdate(); }}
title={window.i18n('blindedMsgReqsSettingTitle')}
description={window.i18n('blindedMsgReqsSettingDesc')}
active={areBlindedRequestsEnabled}
/>
{!props.hasPassword ? (
<SessionSettingButtonItem
title={window.i18n('setAccountPasswordTitle')}
description={window.i18n('setAccountPasswordDescription')}
onClick={() => {
displayPasswordModal('set', props.onPasswordUpdated);
}} }}
title={window.i18n('blindedMsgReqsSettingTitle')} buttonText={window.i18n('setPassword')}
description={window.i18n('blindedMsgReqsSettingDesc')} dataTestId={'set-password-button'}
active={areBlindedRequestsEnabled}
/> />
) : (
{!props.hasPassword && ( <>
<SessionSettingButtonItem {/* We have a password, let's show the 'change' and 'remove' password buttons */}
title={window.i18n('setAccountPasswordTitle')}
description={window.i18n('setAccountPasswordDescription')}
onClick={() => {
displayPasswordModal('set', props.onPasswordUpdated);
}}
buttonText={window.i18n('setPassword')}
dataTestId={'set-password-button'}
/>
)}
{props.hasPassword && (
<SessionSettingButtonItem <SessionSettingButtonItem
title={window.i18n('changeAccountPasswordTitle')} title={window.i18n('changeAccountPasswordTitle')}
description={window.i18n('changeAccountPasswordDescription')} description={window.i18n('changeAccountPasswordDescription')}
@ -130,8 +130,6 @@ export const SettingsCategoryPrivacy = (props: {
buttonText={window.i18n('changePassword')} buttonText={window.i18n('changePassword')}
dataTestId="change-password-settings-button" dataTestId="change-password-settings-button"
/> />
)}
{props.hasPassword && (
<SessionSettingButtonItem <SessionSettingButtonItem
title={window.i18n('removeAccountPasswordTitle')} title={window.i18n('removeAccountPasswordTitle')}
description={window.i18n('removeAccountPasswordDescription')} description={window.i18n('removeAccountPasswordDescription')}
@ -142,9 +140,8 @@ export const SettingsCategoryPrivacy = (props: {
buttonText={window.i18n('removePassword')} buttonText={window.i18n('removePassword')}
dataTestId="remove-password-settings-button" dataTestId="remove-password-settings-button"
/> />
)} </>
</> )}
); </>
} );
return null;
}; };

Loading…
Cancel
Save