Support exporting legacy session

This commit is contained in:
Alexander Zinchuk 2021-06-12 04:24:40 +03:00
parent 19ef014068
commit f5086002bb
7 changed files with 80 additions and 38 deletions

View File

@ -105,10 +105,11 @@ export function onAuthError(err: Error) {
});
}
export function onAuthReady(sessionId: string) {
export function onAuthReady(sessionId: string, sessionJson: string) {
onUpdate({
...buildAuthStateUpdate('authorizationStateReady'),
sessionId,
sessionJson,
});
}

View File

@ -68,6 +68,7 @@ export async function init(sessionInfo: string, _onUpdate: OnApiUpdate) {
});
const newSessionId = await session.save();
const sessionJson = JSON.stringify(session.getSessionData(true));
if (DEBUG) {
// eslint-disable-next-line no-console
@ -76,7 +77,7 @@ export async function init(sessionInfo: string, _onUpdate: OnApiUpdate) {
console.log('[GramJs/client] CONNECTED as ', newSessionId);
}
onAuthReady(newSessionId);
onAuthReady(newSessionId, sessionJson);
onUpdate({ '@type': 'updateApiReady' });
void fetchCurrentUser();

View File

@ -36,6 +36,7 @@ export type ApiUpdateAuthorizationState = {
'@type': 'updateAuthorizationState';
authorizationState: ApiUpdateAuthorizationStateType;
sessionId?: string;
sessionJson?: string;
isCodeViaApp?: boolean;
hint?: string;
qrCode?: { token: string; expires: number };

View File

@ -15,7 +15,7 @@ export const DEBUG_ALERT_MSG = 'Shoot!\nSomething went wrong, please see the err
export const DEBUG_GRAMJS = false;
export const GRAMJS_SESSION_ID_KEY = 'GramJs:sessionId';
export const LEGACY_SESSION_KEY = 'dc';
export const LEGACY_SESSION_KEY = 'user_auth';
export const GLOBAL_STATE_CACHE_DISABLED = false;
export const GLOBAL_STATE_CACHE_KEY = 'tt-global-state';

View File

@ -12,7 +12,7 @@ class StorageSession extends MemorySession {
this._authKeys = {};
if (sessionInfo && sessionInfo.startsWith(SESSION_DATA_PREFIX)) {
this._sessionData = sessionInfo;
this._sessionString = sessionInfo;
} else if (sessionInfo) {
this._storageKey = sessionInfo;
}
@ -27,8 +27,8 @@ class StorageSession extends MemorySession {
}
async load() {
if (this._sessionData) {
await this._loadFromSessionData();
if (this._sessionString) {
await this._loadFromSessionString();
return;
}
@ -99,8 +99,26 @@ class StorageSession extends MemorySession {
void this._updateStorage();
}
async _loadFromSessionData() {
const [, mainDcIdStr, mainDcKey] = this._sessionData.split(':');
getSessionData(asHex) {
const sessionData = {
mainDcId: this._dcId,
keys: {},
hashes: {},
};
Object
.keys(this._authKeys)
.forEach((dcId) => {
const authKey = this._authKeys[dcId];
sessionData.keys[dcId] = asHex ? authKey._key.toString('hex') : authKey._key;
sessionData.hashes[dcId] = asHex ? authKey._hash.toString('hex') : authKey._hash;
});
return sessionData;
}
async _loadFromSessionString() {
const [, mainDcIdStr, mainDcKey] = this._sessionString.split(':');
const mainDcId = Number(mainDcIdStr);
const {
ipAddress,
@ -117,22 +135,8 @@ class StorageSession extends MemorySession {
return;
}
const sessionData = {
mainDcId: this._dcId,
keys: {},
hashes: {},
};
Object.keys(this._authKeys)
.map((dcId) => {
const authKey = this._authKeys[dcId];
sessionData.keys[dcId] = authKey._key;
sessionData.hashes[dcId] = authKey._hash;
return undefined;
});
try {
await this._saveToCache(JSON.stringify(sessionData));
await this._saveToCache(JSON.stringify(this.getSessionData()));
} catch (err) {
// eslint-disable-next-line no-console
console.warn('Failed to update session in storage');

View File

@ -22,12 +22,12 @@ addReducer('initApi', (global: GlobalState, actions) => {
let sessionInfo = localStorage.getItem(GRAMJS_SESSION_ID_KEY) || undefined;
if (!sessionInfo) {
const legacySessionMainDcRaw = localStorage.getItem(LEGACY_SESSION_KEY);
if (legacySessionMainDcRaw) {
const legacySessionMainDc = legacySessionMainDcRaw.replace(/"/g, '');
const legacySessionMainDcKeyRaw = localStorage.getItem(`dc${legacySessionMainDc}_auth_key`);
if (legacySessionMainDcKeyRaw) {
const legacySessionMainDcKey = legacySessionMainDcKeyRaw.replace(/"/g, '');
const legacySessionJson = localStorage.getItem(LEGACY_SESSION_KEY);
if (legacySessionJson) {
const { dcID: legacySessionMainDc } = JSON.parse(legacySessionJson);
const legacySessionMainKeyRaw = localStorage.getItem(`dc${legacySessionMainDc}_auth_key`);
if (legacySessionMainKeyRaw) {
const legacySessionMainDcKey = legacySessionMainKeyRaw.replace(/"/g, '');
sessionInfo = `session:${legacySessionMainDc}:${legacySessionMainDcKey}`;
}
}
@ -110,8 +110,10 @@ addReducer('gotToAuthQrCode', (global) => {
});
addReducer('saveSession', (global, actions, payload) => {
const { sessionId } = payload!;
const { sessionId, sessionJson } = payload!;
localStorage.setItem(GRAMJS_SESSION_ID_KEY, sessionId);
exportLegacySession(sessionJson, global.currentUserId!);
});
addReducer('signOut', () => {
@ -125,8 +127,7 @@ addReducer('signOut', () => {
addReducer('reset', () => {
localStorage.removeItem(GRAMJS_SESSION_ID_KEY);
localStorage.removeItem(LEGACY_SESSION_KEY);
updateAppBadge(0);
clearLegacySession();
cacheApi.clear(MEDIA_CACHE_NAME);
cacheApi.clear(MEDIA_CACHE_NAME_AVATARS);
@ -140,6 +141,8 @@ addReducer('reset', () => {
cacheApi.clear(`${langChachePrefix}${i === 0 ? '' : i}`);
}
updateAppBadge(0);
getDispatch().init();
});
@ -180,3 +183,23 @@ addReducer('deleteDeviceToken', (global) => {
delete newGlobal.push;
setGlobal(newGlobal);
});
function exportLegacySession(sessionJson: string, currentUserId: number) {
const { mainDcId, keys } = JSON.parse(sessionJson);
const legacySession = { dcID: mainDcId, id: currentUserId };
localStorage.setItem(LEGACY_SESSION_KEY, JSON.stringify(legacySession));
localStorage.setItem('dc', mainDcId);
Object.keys(keys).forEach((dcId) => {
localStorage.setItem(`dc${dcId}_auth_key`, `"${keys[dcId]}"`);
});
}
function clearLegacySession() {
localStorage.removeItem('dc5_auth_key');
localStorage.removeItem('dc4_auth_key');
localStorage.removeItem('dc3_auth_key');
localStorage.removeItem('dc2_auth_key');
localStorage.removeItem('dc1_auth_key');
localStorage.removeItem('dc');
localStorage.removeItem(LEGACY_SESSION_KEY);
}

View File

@ -11,7 +11,7 @@ import {
ApiUpdateConnectionState,
ApiUpdateCurrentUser,
} from '../../../api/types';
import { DEBUG } from '../../../config';
import { DEBUG, LEGACY_SESSION_KEY } from '../../../config';
import { subscribe } from '../../../util/notifications';
import { updateUser } from '../../reducers';
import { setLanguage } from '../../../util/langProvider';
@ -102,6 +102,11 @@ function onUpdateAuthorizationState(update: ApiUpdateAuthorizationState) {
});
break;
case 'authorizationStateReady': {
const { sessionId, sessionJson } = update;
if (sessionId && global.authRememberMe) {
getDispatch().saveSession({ sessionId, sessionJson });
}
if (wasAuthReady) {
break;
}
@ -112,11 +117,6 @@ function onUpdateAuthorizationState(update: ApiUpdateAuthorizationState) {
lastSyncTime: Date.now(),
});
const { sessionId } = update;
if (sessionId && global.authRememberMe) {
getDispatch().saveSession({ sessionId });
}
break;
}
}
@ -152,4 +152,16 @@ function onUpdateCurrentUser(update: ApiUpdateCurrentUser) {
...updateUser(getGlobal(), currentUser.id, currentUser),
currentUserId: currentUser.id,
});
updateLegacySessionUserId(currentUser.id);
}
function updateLegacySessionUserId(currentUserId: number) {
const legacySessionJson = localStorage.getItem(LEGACY_SESSION_KEY);
if (!legacySessionJson) return;
const legacySession = JSON.parse(legacySessionJson);
legacySession.id = currentUserId;
localStorage.setItem(LEGACY_SESSION_KEY, JSON.stringify(legacySession));
}