Passcode: Display error if passcode wasn't created (#3149)
This commit is contained in:
parent
c8d64dc929
commit
cc0e00ad2d
@ -31,6 +31,7 @@ import { formatDateToString } from '../../../util/dateFormat';
|
|||||||
import { setPermanentWebVersion } from '../../../util/permanentWebVersion';
|
import { setPermanentWebVersion } from '../../../util/permanentWebVersion';
|
||||||
import { clearWebsync } from '../../../util/websync';
|
import { clearWebsync } from '../../../util/websync';
|
||||||
import {
|
import {
|
||||||
|
selectCanSetPasscode,
|
||||||
selectCurrentMessageList, selectIsCurrentUserPremium, selectTabState, selectTheme,
|
selectCurrentMessageList, selectIsCurrentUserPremium, selectTabState, selectTheme,
|
||||||
} from '../../../global/selectors';
|
} from '../../../global/selectors';
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
@ -82,7 +83,7 @@ type StateProps =
|
|||||||
isConnectionStatusMinimized: ISettings['isConnectionStatusMinimized'];
|
isConnectionStatusMinimized: ISettings['isConnectionStatusMinimized'];
|
||||||
areChatsLoaded?: boolean;
|
areChatsLoaded?: boolean;
|
||||||
hasPasscode?: boolean;
|
hasPasscode?: boolean;
|
||||||
isAuthRememberMe?: boolean;
|
canSetPasscode?: boolean;
|
||||||
}
|
}
|
||||||
& Pick<GlobalState, 'connectionState' | 'isSyncing' | 'archiveSettings'>
|
& Pick<GlobalState, 'connectionState' | 'isSyncing' | 'archiveSettings'>
|
||||||
& Pick<TabState, 'canInstall'>;
|
& Pick<TabState, 'canInstall'>;
|
||||||
@ -114,7 +115,7 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
|
|||||||
isConnectionStatusMinimized,
|
isConnectionStatusMinimized,
|
||||||
areChatsLoaded,
|
areChatsLoaded,
|
||||||
hasPasscode,
|
hasPasscode,
|
||||||
isAuthRememberMe,
|
canSetPasscode,
|
||||||
canInstall,
|
canInstall,
|
||||||
archiveSettings,
|
archiveSettings,
|
||||||
}) => {
|
}) => {
|
||||||
@ -158,7 +159,7 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
}, [hasPasscode]);
|
}, [hasPasscode]);
|
||||||
|
|
||||||
useHotkeys(isAuthRememberMe ? {
|
useHotkeys(canSetPasscode ? {
|
||||||
'Ctrl+Shift+L': handleLockScreenHotkey,
|
'Ctrl+Shift+L': handleLockScreenHotkey,
|
||||||
'Alt+Shift+L': handleLockScreenHotkey,
|
'Alt+Shift+L': handleLockScreenHotkey,
|
||||||
'Meta+Shift+L': handleLockScreenHotkey,
|
'Meta+Shift+L': handleLockScreenHotkey,
|
||||||
@ -481,7 +482,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
hasPasscode: Boolean(global.passcode.hasPasscode),
|
hasPasscode: Boolean(global.passcode.hasPasscode),
|
||||||
canInstall: Boolean(tabState.canInstall),
|
canInstall: Boolean(tabState.canInstall),
|
||||||
archiveSettings,
|
archiveSettings,
|
||||||
isAuthRememberMe: global.authRememberMe,
|
canSetPasscode: selectCanSetPasscode(global),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(LeftMainHeader));
|
)(LeftMainHeader));
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { getActions, withGlobal } from '../../../global';
|
|||||||
import type { ApiPrivacySettings } from '../../../types';
|
import type { ApiPrivacySettings } from '../../../types';
|
||||||
import { SettingsScreens } from '../../../types';
|
import { SettingsScreens } from '../../../types';
|
||||||
|
|
||||||
import { selectIsCurrentUserPremium } from '../../../global/selectors';
|
import { selectCanSetPasscode, selectIsCurrentUserPremium } from '../../../global/selectors';
|
||||||
|
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||||
@ -23,7 +23,7 @@ type StateProps = {
|
|||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
hasPassword?: boolean;
|
hasPassword?: boolean;
|
||||||
hasPasscode?: boolean;
|
hasPasscode?: boolean;
|
||||||
isAuthRememberMe?: boolean;
|
canSetPasscode?: boolean;
|
||||||
blockedCount: number;
|
blockedCount: number;
|
||||||
webAuthCount: number;
|
webAuthCount: number;
|
||||||
isSensitiveEnabled?: boolean;
|
isSensitiveEnabled?: boolean;
|
||||||
@ -63,7 +63,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
privacyPhoneP2P,
|
privacyPhoneP2P,
|
||||||
onScreenSelect,
|
onScreenSelect,
|
||||||
onReset,
|
onReset,
|
||||||
isAuthRememberMe,
|
canSetPasscode,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
loadPrivacySettings,
|
loadPrivacySettings,
|
||||||
@ -160,7 +160,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
{lang('BlockedUsers')}
|
{lang('BlockedUsers')}
|
||||||
<span className="settings-item__current-value">{blockedCount || ''}</span>
|
<span className="settings-item__current-value">{blockedCount || ''}</span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
{isAuthRememberMe && (
|
{canSetPasscode && (
|
||||||
<ListItem
|
<ListItem
|
||||||
icon="key"
|
icon="key"
|
||||||
narrow
|
narrow
|
||||||
@ -394,7 +394,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
privacyPhoneCall: privacy.phoneCall,
|
privacyPhoneCall: privacy.phoneCall,
|
||||||
privacyPhoneP2P: privacy.phoneP2P,
|
privacyPhoneP2P: privacy.phoneP2P,
|
||||||
canDisplayChatInTitle,
|
canDisplayChatInTitle,
|
||||||
isAuthRememberMe: global.authRememberMe,
|
canSetPasscode: selectCanSetPasscode(global),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(SettingsPrivacy));
|
)(SettingsPrivacy));
|
||||||
|
|||||||
@ -3,14 +3,15 @@ import { addActionHandler, setGlobal, getGlobal } from '../../index';
|
|||||||
import { clearPasscodeSettings, updatePasscodeSettings } from '../../reducers';
|
import { clearPasscodeSettings, updatePasscodeSettings } from '../../reducers';
|
||||||
import { clearStoredSession, loadStoredSession, storeSession } from '../../../util/sessions';
|
import { clearStoredSession, loadStoredSession, storeSession } from '../../../util/sessions';
|
||||||
import {
|
import {
|
||||||
clearEncryptedSession, decryptSession, encryptSession, setupPasscode,
|
clearEncryptedSession, decryptSession, encryptSession, forgetPasscode, setupPasscode,
|
||||||
} from '../../../util/passcode';
|
} from '../../../util/passcode';
|
||||||
import { forceUpdateCache, migrateCache, serializeGlobal } from '../../cache';
|
import { forceUpdateCache, migrateCache, serializeGlobal } from '../../cache';
|
||||||
import { onBeforeUnload } from '../../../util/schedulers';
|
import { onBeforeUnload } from '../../../util/schedulers';
|
||||||
import { cloneDeep } from '../../../util/iteratees';
|
import { cloneDeep } from '../../../util/iteratees';
|
||||||
import { INITIAL_GLOBAL_STATE } from '../../initialState';
|
import { INITIAL_GLOBAL_STATE } from '../../initialState';
|
||||||
import type { ActionReturnType } from '../../types';
|
import type { ActionReturnType } from '../../types';
|
||||||
import { signalPasscodeHash } from '../../../util/establishMultitabRole';
|
import { getCurrentTabId, signalPasscodeHash } from '../../../util/establishMultitabRole';
|
||||||
|
import { SettingsScreens } from '../../../types';
|
||||||
|
|
||||||
let noLockOnUnload = false;
|
let noLockOnUnload = false;
|
||||||
onBeforeUnload(() => {
|
onBeforeUnload(() => {
|
||||||
@ -21,7 +22,7 @@ onBeforeUnload(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('setPasscode', async (global, actions, payload): Promise<void> => {
|
addActionHandler('setPasscode', async (global, actions, payload): Promise<void> => {
|
||||||
const { passcode } = payload;
|
const { passcode, tabId = getCurrentTabId() } = payload;
|
||||||
global = updatePasscodeSettings(global, {
|
global = updatePasscodeSettings(global, {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
});
|
});
|
||||||
@ -36,18 +37,34 @@ addActionHandler('setPasscode', async (global, actions, payload): Promise<void>
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await encryptSession(sessionJson, globalJson);
|
try {
|
||||||
|
await encryptSession(sessionJson, globalJson);
|
||||||
|
|
||||||
signalPasscodeHash();
|
signalPasscodeHash();
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
global = updatePasscodeSettings(global, {
|
global = updatePasscodeSettings(global, {
|
||||||
hasPasscode: true,
|
hasPasscode: true,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
});
|
});
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
|
|
||||||
forceUpdateCache(true);
|
forceUpdateCache(true);
|
||||||
|
} catch (err: any) {
|
||||||
|
forgetPasscode();
|
||||||
|
|
||||||
|
global = getGlobal();
|
||||||
|
global = updatePasscodeSettings(global, {
|
||||||
|
isLoading: false,
|
||||||
|
});
|
||||||
|
setGlobal(global);
|
||||||
|
|
||||||
|
actions.showNotification({
|
||||||
|
message: 'Failed to set passcode',
|
||||||
|
tabId,
|
||||||
|
});
|
||||||
|
actions.requestNextSettingsScreen({ screen: SettingsScreens.PasscodeDisabled, tabId });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('clearPasscode', (global): ActionReturnType => {
|
addActionHandler('clearPasscode', (global): ActionReturnType => {
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import { getCurrentTabId, reestablishMasterToSelf } from '../util/establishMulti
|
|||||||
import { updateTabState } from './reducers/tabs';
|
import { updateTabState } from './reducers/tabs';
|
||||||
import type { ActionReturnType, GlobalState } from './types';
|
import type { ActionReturnType, GlobalState } from './types';
|
||||||
import { isLocalMessageId } from './helpers';
|
import { isLocalMessageId } from './helpers';
|
||||||
|
import { isCacheApiSupported } from '../util/cacheApi';
|
||||||
|
|
||||||
initCache();
|
initCache();
|
||||||
|
|
||||||
@ -129,6 +130,12 @@ addActionHandler('init', (global, actions, payload): ActionReturnType => {
|
|||||||
actions.initApi();
|
actions.initApi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isCacheApiSupported().then((isSupported) => {
|
||||||
|
global = getGlobal();
|
||||||
|
global.isCacheApiSupported = isSupported;
|
||||||
|
setGlobal(global);
|
||||||
|
});
|
||||||
|
|
||||||
return updateTabState(global, {
|
return updateTabState(global, {
|
||||||
messageLists: parsedMessageList ? [parsedMessageList] : initialTabState.messageLists,
|
messageLists: parsedMessageList ? [parsedMessageList] : initialTabState.messageLists,
|
||||||
}, tabId);
|
}, tabId);
|
||||||
|
|||||||
@ -11,3 +11,7 @@ export function selectNotifyExceptions<T extends GlobalState>(global: T) {
|
|||||||
export function selectLanguageCode<T extends GlobalState>(global: T) {
|
export function selectLanguageCode<T extends GlobalState>(global: T) {
|
||||||
return global.settings.byKey.language.replace('-raw', '');
|
return global.settings.byKey.language.replace('-raw', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectCanSetPasscode<T extends GlobalState>(global: T) {
|
||||||
|
return global.authRememberMe && global.isCacheApiSupported;
|
||||||
|
}
|
||||||
|
|||||||
@ -579,6 +579,7 @@ export type GlobalState = {
|
|||||||
appConfig?: ApiAppConfig;
|
appConfig?: ApiAppConfig;
|
||||||
hasWebAuthTokenFailed?: boolean;
|
hasWebAuthTokenFailed?: boolean;
|
||||||
hasWebAuthTokenPasswordRequired?: true;
|
hasWebAuthTokenPasswordRequired?: true;
|
||||||
|
isCacheApiSupported?: boolean;
|
||||||
connectionState?: ApiUpdateConnectionStateType;
|
connectionState?: ApiUpdateConnectionStateType;
|
||||||
currentUserId?: string;
|
currentUserId?: string;
|
||||||
isSyncing?: boolean;
|
isSyncing?: boolean;
|
||||||
@ -2334,7 +2335,7 @@ export interface ActionPayloads {
|
|||||||
connectToActivePhoneCall: undefined;
|
connectToActivePhoneCall: undefined;
|
||||||
|
|
||||||
// Passcode
|
// Passcode
|
||||||
setPasscode: { passcode: string };
|
setPasscode: { passcode: string } & WithTabId;
|
||||||
clearPasscode: undefined;
|
clearPasscode: undefined;
|
||||||
lockScreen: undefined;
|
lockScreen: undefined;
|
||||||
decryptSession: { passcode: string };
|
decryptSession: { passcode: string };
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
// eslint-disable-next-line no-restricted-globals
|
// eslint-disable-next-line no-restricted-globals
|
||||||
const cacheApi = self.caches;
|
const cacheApi = self.caches;
|
||||||
|
|
||||||
|
let isSupported: boolean | undefined;
|
||||||
|
|
||||||
|
export async function isCacheApiSupported() {
|
||||||
|
isSupported = isSupported ?? await cacheApi.has('test').then(() => true).catch(() => false);
|
||||||
|
return isSupported;
|
||||||
|
}
|
||||||
|
|
||||||
export enum Type {
|
export enum Type {
|
||||||
Text,
|
Text,
|
||||||
Blob,
|
Blob,
|
||||||
@ -67,7 +74,7 @@ export async function fetch(
|
|||||||
|
|
||||||
export async function save(cacheName: string, key: string, data: AnyLiteral | Blob | ArrayBuffer | string) {
|
export async function save(cacheName: string, key: string, data: AnyLiteral | Blob | ArrayBuffer | string) {
|
||||||
if (!cacheApi) {
|
if (!cacheApi) {
|
||||||
return undefined;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -78,11 +85,12 @@ export async function save(cacheName: string, key: string, data: AnyLiteral | Bl
|
|||||||
const request = new Request(key.replace(/:/g, '_'));
|
const request = new Request(key.replace(/:/g, '_'));
|
||||||
const response = new Response(cacheData);
|
const response = new Response(cacheData);
|
||||||
const cache = await cacheApi.open(cacheName);
|
const cache = await cacheApi.open(cacheName);
|
||||||
return await cache.put(request, response);
|
await cache.put(request, response);
|
||||||
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.warn(err);
|
console.warn(err);
|
||||||
return undefined;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -117,7 +117,12 @@ function sha256(plaintext: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function store(key: string, value: ArrayBuffer) {
|
async function store(key: string, value: ArrayBuffer) {
|
||||||
await cacheApi.save(PASSCODE_CACHE_NAME, key, value);
|
const isSuccessful = await cacheApi.save(PASSCODE_CACHE_NAME, key, value);
|
||||||
|
if (isSuccessful) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Failed to save to cache');
|
||||||
}
|
}
|
||||||
|
|
||||||
function load(key: string) {
|
function load(key: string) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user