Enhance member transfer service and dialog for improved credential handling

Updated the MemberTransferService to better manage login credentials, ensuring that saved credentials are utilized when none are provided. Improved error handling during login attempts by extracting detailed error messages and adjusting status codes to prevent user logout. Refined the MemberTransferDialog to clear login credentials when no club is selected and to only include non-empty values in the login credentials object, enhancing user experience and validation logic.
This commit is contained in:
Torsten Schulz (local)
2025-11-05 16:22:40 +01:00
parent c05cfbbe38
commit ad99787f75
2 changed files with 124 additions and 30 deletions

View File

@@ -72,14 +72,44 @@ class MemberTransferService {
loginEndpointUrl = savedConfig.server.replace(/\/$/, '') + '/' + config.loginEndpoint.replace(/^\//, '');
// Login-Credentials aus gespeicherter Konfiguration laden, falls vorhanden
if (!loginCredentials && savedConfig.loginEndpoint === config.loginEndpoint) {
loginCredentials = savedConfig.getLoginCredentials();
// WICHTIG: Nur wenn keine Credentials übergeben wurden ODER wenn übergebene Credentials leer sind
if (!loginCredentials || Object.keys(loginCredentials).length === 0) {
if (savedConfig.loginEndpoint === config.loginEndpoint) {
const savedCredentials = savedConfig.getLoginCredentials();
if (savedCredentials && Object.keys(savedCredentials).length > 0) {
loginCredentials = savedCredentials;
}
}
}
}
}
if (config.transferEndpoint && !config.transferEndpoint.startsWith('http') && savedConfig) {
if (savedConfig.server) {
// Auch wenn vollständige URLs verwendet werden, gespeicherte Credentials verwenden falls keine übergeben
if (config.loginEndpoint && config.loginEndpoint.startsWith('http')) {
if (!loginCredentials || Object.keys(loginCredentials).length === 0) {
// Versuche gespeicherte Konfiguration zu finden (falls noch nicht geladen)
if (!savedConfig) {
savedConfig = await MemberTransferConfig.findOne({
where: { clubId }
});
}
if (savedConfig && savedConfig.loginEndpoint === config.loginEndpoint) {
const savedCredentials = savedConfig.getLoginCredentials();
if (savedCredentials && Object.keys(savedCredentials).length > 0) {
loginCredentials = savedCredentials;
}
}
}
}
if (config.transferEndpoint && !config.transferEndpoint.startsWith('http')) {
// Versuche gespeicherte Konfiguration zu finden (falls noch nicht geladen)
if (!savedConfig) {
savedConfig = await MemberTransferConfig.findOne({
where: { clubId }
});
}
if (savedConfig && savedConfig.server) {
// Server + relativen Pfad kombinieren
transferEndpointUrl = savedConfig.server.replace(/\/$/, '') + '/' + config.transferEndpoint.replace(/^\//, '');
}
@@ -90,7 +120,21 @@ class MemberTransferService {
config.bulkWrapperTemplate = savedConfig.bulkWrapperTemplate;
}
if (loginEndpointUrl && loginCredentials) {
// Prüfe ob Login-Credentials vorhanden sind und nicht leer
// Filtere leere Strings/Leerzeichen heraus
if (loginCredentials && Object.keys(loginCredentials).length > 0) {
// Prüfe ob alle Werte nicht-leer sind (nach Trimmen)
const hasValidCredentials = Object.values(loginCredentials).some(
value => value && typeof value === 'string' && value.trim().length > 0
);
if (!hasValidCredentials) {
devLog('[transferMembers] Login-Credentials enthalten nur leere Werte');
loginCredentials = null;
}
}
if (loginEndpointUrl && loginCredentials && Object.keys(loginCredentials).length > 0) {
try {
const loginResult = await this.performLogin(
loginEndpointUrl,
@@ -99,11 +143,13 @@ class MemberTransferService {
);
if (!loginResult.success) {
// WICHTIG: Verwende 400 statt 401, damit der Benutzer nicht ausgeloggt wird
// 401 wird vom Frontend als "nicht autorisiert" interpretiert und führt zu automatischem Logout
return {
status: 401,
status: 400,
response: {
success: false,
message: 'Login fehlgeschlagen',
message: 'Login am externen System fehlgeschlagen',
error: loginResult.error,
transferred: 0,
errors: []
@@ -115,11 +161,12 @@ class MemberTransferService {
sessionCookie = loginResult.cookie;
} catch (loginError) {
devLog('[transferMembers] Login error:', loginError);
// WICHTIG: Verwende 400 statt 401, damit der Benutzer nicht ausgeloggt wird
return {
status: 401,
status: 400,
response: {
success: false,
message: 'Login fehlgeschlagen: ' + loginError.message,
message: 'Login am externen System fehlgeschlagen: ' + loginError.message,
transferred: 0,
errors: []
}
@@ -394,9 +441,30 @@ class MemberTransferService {
};
} catch (error) {
devLog('[performLogin] Error:', error);
// Extrahiere detaillierte Fehlerinformationen
let errorMessage = 'Login fehlgeschlagen';
let statusCode = error.response?.status;
if (error.response?.data) {
// Versuche verschiedene Felder für die Fehlermeldung
errorMessage = error.response.data.message ||
error.response.data.error ||
error.response.data.errorMessage ||
(typeof error.response.data === 'string' ? error.response.data : errorMessage);
} else if (error.message) {
errorMessage = error.message;
}
// Logge den Status-Code für Debugging
if (statusCode) {
devLog(`[performLogin] Externer Endpoint Status: ${statusCode}`);
}
return {
success: false,
error: error.response?.data?.message || error.message || 'Login fehlgeschlagen'
error: errorMessage,
statusCode: statusCode
};
}
}

View File

@@ -179,9 +179,24 @@ export default {
methods: {
async loadSavedConfig() {
if (!this.currentClub) {
// Login-Credentials leeren, auch wenn kein Club vorhanden
this.loginCredentials = {
username: '',
password: '',
additionalField1: '',
additionalField2: ''
};
return;
}
// WICHTIG: Login-Credentials sofort leeren, damit sie nicht vorausgefüllt werden
this.loginCredentials = {
username: '',
password: '',
additionalField1: '',
additionalField2: ''
};
this.loadingConfig = true;
try {
const response = await apiClient.get(`/member-transfer-config/${this.currentClub}`);
@@ -200,13 +215,8 @@ export default {
this.config.useBulkMode = savedConfig.useBulkMode || false;
this.config.bulkWrapperTemplate = savedConfig.bulkWrapperTemplate || '';
// Login-Credentials zurücksetzen (werden nur verwendet, wenn im Dialog eingegeben)
this.loginCredentials = {
username: '',
password: '',
additionalField1: '',
additionalField2: ''
};
// Login-Credentials bleiben leer (werden nur verwendet, wenn im Dialog eingegeben)
// Gespeicherte Credentials werden vom Backend verwendet, wenn keine eingegeben werden
}
} catch (error) {
// Keine Konfiguration vorhanden - das ist OK, Dialog bleibt leer
@@ -214,6 +224,13 @@ export default {
console.error('Fehler beim Laden der gespeicherten Konfiguration:', error);
}
} finally {
// Sicherstellen, dass Login-Credentials leer sind
this.loginCredentials = {
username: '',
password: '',
additionalField1: '',
additionalField2: ''
};
this.loadingConfig = false;
}
},
@@ -252,28 +269,37 @@ export default {
try {
// Login-Credentials zusammenstellen
// WICHTIG: Nur nicht-leere Werte hinzufügen (nach Trimmen)
// Leere Strings würden die gespeicherten Credentials überschreiben
const loginCredentials = {};
if (this.loginCredentials.username) {
loginCredentials.username = this.loginCredentials.username;
const trimmedUsername = this.loginCredentials.username?.trim();
const trimmedPassword = this.loginCredentials.password?.trim();
if (trimmedUsername) {
loginCredentials.username = trimmedUsername;
}
if (this.loginCredentials.password) {
loginCredentials.password = this.loginCredentials.password;
if (trimmedPassword) {
loginCredentials.password = trimmedPassword;
}
// Zusätzliche Felder verarbeiten
if (this.loginCredentials.additionalField1) {
const parts1 = this.loginCredentials.additionalField1.split(':').map(s => s.trim());
if (parts1.length === 2) {
// Zusätzliche Felder verarbeiten (nur wenn nicht leer)
const trimmedAdditional1 = this.loginCredentials.additionalField1?.trim();
if (trimmedAdditional1) {
const parts1 = trimmedAdditional1.split(':').map(s => s.trim());
if (parts1.length === 2 && parts1[0] && parts1[1]) {
loginCredentials[parts1[0]] = parts1[1];
} else {
} else if (parts1.length === 1 && parts1[0]) {
// Falls kein Doppelpunkt, verwende den gesamten Wert als Feldname
loginCredentials[parts1[0]] = parts1[0];
}
}
if (this.loginCredentials.additionalField2) {
const parts2 = this.loginCredentials.additionalField2.split(':').map(s => s.trim());
if (parts2.length === 2) {
const trimmedAdditional2 = this.loginCredentials.additionalField2?.trim();
if (trimmedAdditional2) {
const parts2 = trimmedAdditional2.split(':').map(s => s.trim());
if (parts2.length === 2 && parts2[0] && parts2[1]) {
loginCredentials[parts2[0]] = parts2[1];
} else {
} else if (parts2.length === 1 && parts2[0]) {
loginCredentials[parts2[0]] = parts2[0];
}
}