Desktop self-hosted connection logging (#5410)

Also added in automotic protocol addition if missing. Defaults to
https://

---------

Co-authored-by: Anthony Stirling <[email protected]>
This commit is contained in:
ConnorYoh
2026-01-09 23:01:31 +00:00
committed by GitHub
co-authored by Anthony Stirling
parent a284dbfc15
commit 72389f5872
6 changed files with 334 additions and 34 deletions
@@ -20,36 +20,67 @@ export const ServerSelection: React.FC<ServerSelectionProps> = ({ onSelect, load
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Normalize URL: trim and remove trailing slashes
const url = customUrl.trim().replace(/\/+$/, '');
// Normalize and validate URL
let url = customUrl.trim().replace(/\/+$/, '');
if (!url) {
setTestError(t('setup.server.error.emptyUrl', 'Please enter a server URL'));
return;
}
// Auto-add https:// if no protocol specified
if (!url.startsWith('http://') && !url.startsWith('https://')) {
console.log('[ServerSelection] No protocol specified, adding https://');
url = `https://${url}`;
setCustomUrl(url); // Update the input field
}
// Validate URL format
try {
const urlObj = new URL(url);
console.log('[ServerSelection] Valid URL:', {
protocol: urlObj.protocol,
hostname: urlObj.hostname,
port: urlObj.port,
pathname: urlObj.pathname,
});
} catch (err) {
console.error('[ServerSelection] Invalid URL format:', err);
setTestError(t('setup.server.error.invalidUrl', 'Invalid URL format. Please enter a valid URL like https://your-server.com'));
return;
}
// Test connection before proceeding
setTesting(true);
setTestError(null);
setSecurityDisabled(false);
try {
const isReachable = await connectionModeService.testConnection(url);
console.log(`[ServerSelection] Testing connection to: ${url}`);
if (!isReachable) {
setTestError(t('setup.server.error.unreachable', 'Could not connect to server'));
try {
const testResult = await connectionModeService.testConnection(url);
if (!testResult.success) {
console.error('[ServerSelection] Connection test failed:', testResult);
setTestError(testResult.error || t('setup.server.error.unreachable', 'Could not connect to server'));
setTesting(false);
return;
}
console.log('[ServerSelection] ✅ Connection test successful');
// Fetch OAuth providers and check if login is enabled
const enabledProviders: SSOProviderConfig[] = [];
try {
console.log('[ServerSelection] Fetching login configuration...');
const response = await fetch(`${url}/api/v1/proprietary/ui-data/login`);
// Check if security is disabled (status 403 or error response)
if (!response.ok) {
console.warn(`[ServerSelection] Login config request failed with status ${response.status}`);
if (response.status === 403 || response.status === 401) {
console.log('[ServerSelection] Security is disabled on this server');
setSecurityDisabled(true);
setTesting(false);
return;
@@ -65,10 +96,11 @@ export const ServerSelection: React.FC<ServerSelectionProps> = ({ onSelect, load
}
const data = await response.json();
console.log('Login UI data:', data);
console.log('[ServerSelection] Login UI data:', data);
// Check if the response indicates security is disabled
if (data.enableLogin === false || data.securityEnabled === false) {
console.log('[ServerSelection] Security is explicitly disabled in config');
setSecurityDisabled(true);
setTesting(false);
return;
@@ -90,32 +122,39 @@ export const ServerSelection: React.FC<ServerSelectionProps> = ({ onSelect, load
});
});
console.log('[ServerSelection] Detected OAuth providers:', enabledProviders);
console.log('[ServerSelection] Detected OAuth providers:', enabledProviders);
} catch (err) {
console.error('[ServerSelection] Failed to fetch login configuration', err);
console.error('[ServerSelection] Failed to fetch login configuration:', err);
// Check if it's a security disabled error
if (err instanceof Error && (err.message.includes('403') || err.message.includes('401'))) {
console.log('[ServerSelection] Security is disabled (error-based detection)');
setSecurityDisabled(true);
setTesting(false);
return;
}
// For any other error (network, CORS, invalid JSON, etc.), show error and don't proceed
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
console.error('[ServerSelection] Configuration fetch error details:', errorMessage);
setTestError(
t('setup.server.error.configFetch', 'Failed to fetch server configuration. Please check the URL and try again.')
t('setup.server.error.configFetch', 'Failed to fetch server configuration: {{error}}', {
error: errorMessage
})
);
setTesting(false);
return;
}
// Connection successful - pass URL and OAuth providers
console.log('[ServerSelection] ✅ Server selection complete, proceeding to login');
onSelect({
url,
enabledOAuthProviders: enabledProviders.length > 0 ? enabledProviders : undefined,
});
} catch (error) {
console.error('Connection test failed:', error);
console.error('[ServerSelection] ❌ Unexpected error during connection test:', error);
setTestError(
error instanceof Error
? error.message
@@ -101,7 +101,12 @@ export const SetupWizard: React.FC<SetupWizardProps> = ({ onComplete }) => {
};
const handleSelfHostedLogin = async (username: string, password: string) => {
console.log('[SetupWizard] 🔐 Starting self-hosted login');
console.log(`[SetupWizard] Server: ${serverConfig?.url}`);
console.log(`[SetupWizard] Username: ${username}`);
if (!serverConfig) {
console.error('[SetupWizard] ❌ No server configured');
setError('No server configured');
return;
}
@@ -110,19 +115,35 @@ export const SetupWizard: React.FC<SetupWizardProps> = ({ onComplete }) => {
setLoading(true);
setError(null);
console.log('[SetupWizard] Step 1: Authenticating with server...');
await authService.login(serverConfig.url, username, password);
console.log('[SetupWizard] ✅ Authentication successful');
console.log('[SetupWizard] Step 2: Switching to self-hosted mode...');
await connectionModeService.switchToSelfHosted(serverConfig);
console.log('[SetupWizard] ✅ Switched to self-hosted mode');
console.log('[SetupWizard] Step 3: Initializing external backend...');
await tauriBackendService.initializeExternalBackend();
console.log('[SetupWizard] ✅ External backend initialized');
console.log('[SetupWizard] ✅ Setup complete, calling onComplete()');
onComplete();
} catch (err) {
console.error('Self-hosted login failed:', err);
setError(err instanceof Error ? err.message : 'Self-hosted login failed');
console.error('[SetupWizard] ❌ Self-hosted login failed:', err);
const errorMessage = err instanceof Error ? err.message : 'Self-hosted login failed';
console.error('[SetupWizard] Error message:', errorMessage);
setError(errorMessage);
setLoading(false);
}
};
const handleSelfHostedOAuthSuccess = async (_userInfo: UserInfo) => {
console.log('[SetupWizard] 🔐 OAuth login successful, completing setup');
console.log(`[SetupWizard] Server: ${serverConfig?.url}`);
if (!serverConfig) {
console.error('[SetupWizard] ❌ No server configured');
setError('No server configured');
return;
}
@@ -131,13 +152,22 @@ export const SetupWizard: React.FC<SetupWizardProps> = ({ onComplete }) => {
setLoading(true);
setError(null);
// OAuth already completed by authService.loginWithOAuth
console.log('[SetupWizard] Step 1: OAuth already completed');
console.log('[SetupWizard] Step 2: Switching to self-hosted mode...');
await connectionModeService.switchToSelfHosted(serverConfig);
console.log('[SetupWizard] ✅ Switched to self-hosted mode');
console.log('[SetupWizard] Step 3: Initializing external backend...');
await tauriBackendService.initializeExternalBackend();
console.log('[SetupWizard] ✅ External backend initialized');
console.log('[SetupWizard] ✅ Setup complete, calling onComplete()');
onComplete();
} catch (err) {
console.error('Self-hosted OAuth login completion failed:', err);
setError(err instanceof Error ? err.message : 'Failed to complete login');
console.error('[SetupWizard] ❌ Self-hosted OAuth login completion failed:', err);
const errorMessage = err instanceof Error ? err.message : 'Failed to complete login';
console.error('[SetupWizard] Error message:', errorMessage);
setError(errorMessage);
setLoading(false);
}
};