refactor(myTischtennis): streamline session management and enhance login flow
- Updated AutoFetchMatchResultsService to utilize verifyLogin for session re-establishment, improving reliability and handling of CAPTCHA challenges. - Refactored MyTischtennisService to save Playwright storage state separately, ensuring robustness in session persistence and preventing failures due to missing DB columns. - Minor adjustments in TeamManagementView to enhance async data fetching logic.
This commit is contained in:
@@ -23,10 +23,10 @@ class AutoFetchMatchResultsService {
|
||||
// Find all users with auto-updates enabled
|
||||
const accounts = await MyTischtennis.findAll({
|
||||
where: {
|
||||
autoUpdateRatings: true, // Nutze das gleiche Flag
|
||||
savePassword: true // Must have saved password
|
||||
},
|
||||
attributes: ['id', 'userId', 'email', 'savePassword', 'encryptedPassword', 'accessToken', 'expiresAt', 'cookie']
|
||||
autoUpdateRatings: true,
|
||||
savePassword: true
|
||||
}
|
||||
// No attributes restriction — all fields needed for session handling and re-login
|
||||
});
|
||||
|
||||
devLog(`Found ${accounts.length} accounts with auto-updates enabled for match results`);
|
||||
@@ -68,30 +68,18 @@ class AutoFetchMatchResultsService {
|
||||
|
||||
// Check if session is still valid
|
||||
if (!account.accessToken || !account.expiresAt || account.expiresAt < Date.now() / 1000) {
|
||||
devLog(`Session expired for ${account.email}, attempting re-login`);
|
||||
|
||||
// Try to re-login with stored password
|
||||
const password = account.getPassword();
|
||||
if (!password) {
|
||||
throw new Error('No stored password available for re-login');
|
||||
devLog(`Session expired for ${account.email}, attempting re-login via verifyLogin (incl. Playwright fallback)`);
|
||||
// verifyLogin handles CAPTCHA via Playwright and persists the session to DB.
|
||||
await myTischtennisService.verifyLogin(account.userId);
|
||||
// Reload the account to get the fresh session data written by verifyLogin.
|
||||
const refreshed = await MyTischtennis.findOne({ where: { userId: account.userId } });
|
||||
if (!refreshed?.cookie) {
|
||||
throw new Error('Re-login via verifyLogin did not produce a valid session');
|
||||
}
|
||||
|
||||
const loginResult = await myTischtennisClient.login(account.email, password);
|
||||
if (!loginResult.success) {
|
||||
if (loginResult.requiresCaptcha) {
|
||||
throw new Error(`Re-login failed: CAPTCHA erforderlich. Bitte loggen Sie sich einmal direkt auf mytischtennis.de ein, um das CAPTCHA zu lösen.`);
|
||||
}
|
||||
throw new Error(`Re-login failed: ${loginResult.error}`);
|
||||
}
|
||||
|
||||
// Update session data
|
||||
account.accessToken = loginResult.accessToken;
|
||||
account.refreshToken = loginResult.refreshToken;
|
||||
account.expiresAt = loginResult.expiresAt;
|
||||
account.cookie = loginResult.cookie;
|
||||
account.savePassword = true; // ensure flag persists when saving
|
||||
await account.save();
|
||||
|
||||
account.accessToken = refreshed.accessToken;
|
||||
account.refreshToken = refreshed.refreshToken;
|
||||
account.expiresAt = refreshed.expiresAt;
|
||||
account.cookie = refreshed.cookie;
|
||||
devLog(`Successfully re-logged in for ${account.email}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,9 +111,6 @@ class MyTischtennisService {
|
||||
account.expiresAt = loginResult.expiresAt;
|
||||
account.cookie = loginResult.cookie;
|
||||
account.userData = loginResult.user;
|
||||
if (loginResult.storageState) {
|
||||
account.playwrightStorageState = loginResult.storageState;
|
||||
}
|
||||
|
||||
// Hole Club-ID und Federation
|
||||
const profileResult = await myTischtennisClient.getUserProfile(loginResult.cookie);
|
||||
@@ -130,6 +127,11 @@ class MyTischtennisService {
|
||||
}
|
||||
|
||||
await account.save();
|
||||
|
||||
// Save Playwright storage state separately so a missing DB column never breaks the main save.
|
||||
if (loginResult?.success && loginResult.storageState) {
|
||||
await this._savePlaywrightStorageState(account, loginResult.storageState);
|
||||
}
|
||||
} else {
|
||||
// Create new
|
||||
const accountData = {
|
||||
@@ -147,9 +149,6 @@ class MyTischtennisService {
|
||||
accountData.expiresAt = loginResult.expiresAt;
|
||||
accountData.cookie = loginResult.cookie;
|
||||
accountData.userData = loginResult.user;
|
||||
if (loginResult.storageState) {
|
||||
accountData.playwrightStorageState = loginResult.storageState;
|
||||
}
|
||||
|
||||
// Hole Club-ID
|
||||
const profileResult = await myTischtennisClient.getUserProfile(loginResult.cookie);
|
||||
@@ -166,6 +165,10 @@ class MyTischtennisService {
|
||||
account.setPassword(password);
|
||||
await account.save();
|
||||
}
|
||||
|
||||
if (loginResult?.success && loginResult.storageState) {
|
||||
await this._savePlaywrightStorageState(account, loginResult.storageState);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -296,9 +299,6 @@ class MyTischtennisService {
|
||||
account.expiresAt = effectiveLoginResult.expiresAt;
|
||||
account.cookie = effectiveLoginResult.cookie;
|
||||
account.userData = effectiveLoginResult.user;
|
||||
if (effectiveLoginResult.storageState) {
|
||||
account.playwrightStorageState = effectiveLoginResult.storageState;
|
||||
}
|
||||
|
||||
// Hole Club-ID und Federation
|
||||
const profileResult = await myTischtennisClient.getUserProfile(effectiveLoginResult.cookie);
|
||||
@@ -312,6 +312,11 @@ class MyTischtennisService {
|
||||
}
|
||||
|
||||
await account.save();
|
||||
|
||||
// Save Playwright storage state separately so a missing DB column never breaks the main save.
|
||||
if (effectiveLoginResult.storageState) {
|
||||
await this._savePlaywrightStorageState(account, effectiveLoginResult.storageState);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@@ -432,6 +437,22 @@ class MyTischtennisService {
|
||||
console.error('Error logging update attempt:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the Playwright browser storage state to the account.
|
||||
* Runs in its own try-catch so a missing DB column never blocks the main session save.
|
||||
*/
|
||||
async _savePlaywrightStorageState(account, storageState) {
|
||||
try {
|
||||
account.playwrightStorageState = storageState;
|
||||
await account.save({ fields: ['playwrightStorageState'] });
|
||||
console.log('[myTischtennisService] Playwright storage state saved (session cached for future logins)');
|
||||
} catch (err) {
|
||||
// Column likely missing on this server — run:
|
||||
// ALTER TABLE my_tischtennis ADD COLUMN playwright_storage_state LONGTEXT NULL;
|
||||
console.warn('[myTischtennisService] Could not save playwright_storage_state (DB column missing?):', err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new MyTischtennisService();
|
||||
|
||||
Reference in New Issue
Block a user