fix(setup): align install validation and expose backend errors

Make setup password requirements consistent with backend rules and show API-provided error messages so install failures are actionable. Trim admin email before validation to avoid false invalid-email rejections from surrounding whitespace.
This commit is contained in:
laukkw
2026-03-17 15:38:18 +08:00
parent 045cba78b4
commit aa6047c460
4 changed files with 18 additions and 16 deletions

View File

@@ -247,6 +247,12 @@ func install(c *gin.Context) {
return return
} }
req.Admin.Email = strings.TrimSpace(req.Admin.Email)
req.Database.Host = strings.TrimSpace(req.Database.Host)
req.Database.User = strings.TrimSpace(req.Database.User)
req.Database.DBName = strings.TrimSpace(req.Database.DBName)
req.Redis.Host = strings.TrimSpace(req.Redis.Host)
// ========== COMPREHENSIVE INPUT VALIDATION ========== // ========== COMPREHENSIVE INPUT VALIDATION ==========
// Database validation // Database validation
if !validateHostname(req.Database.Host) { if !validateHostname(req.Database.Host) {
@@ -319,13 +325,6 @@ func install(c *gin.Context) {
return return
} }
// Trim whitespace from string inputs
req.Admin.Email = strings.TrimSpace(req.Admin.Email)
req.Database.Host = strings.TrimSpace(req.Database.Host)
req.Database.User = strings.TrimSpace(req.Database.User)
req.Database.DBName = strings.TrimSpace(req.Database.DBName)
req.Redis.Host = strings.TrimSpace(req.Redis.Host)
cfg := &SetupConfig{ cfg := &SetupConfig{
Database: req.Database, Database: req.Database,
Redis: req.Redis, Redis: req.Redis,

View File

@@ -218,7 +218,7 @@ export default {
email: 'Email', email: 'Email',
password: 'Password', password: 'Password',
confirmPassword: 'Confirm Password', confirmPassword: 'Confirm Password',
passwordPlaceholder: 'Min 6 characters', passwordPlaceholder: 'Min 8 characters',
confirmPasswordPlaceholder: 'Confirm password', confirmPasswordPlaceholder: 'Confirm password',
passwordMismatch: 'Passwords do not match' passwordMismatch: 'Passwords do not match'
}, },

View File

@@ -218,7 +218,7 @@ export default {
email: '邮箱', email: '邮箱',
password: '密码', password: '密码',
confirmPassword: '确认密码', confirmPassword: '确认密码',
passwordPlaceholder: '至少 6 个字符', passwordPlaceholder: '至少 8 个字符',
confirmPasswordPlaceholder: '确认密码', confirmPasswordPlaceholder: '确认密码',
passwordMismatch: '密码不匹配' passwordMismatch: '密码不匹配'
}, },

View File

@@ -565,7 +565,7 @@ const canProceed = computed(() => {
case 2: case 2:
return ( return (
formData.admin.email && formData.admin.email &&
formData.admin.password.length >= 6 && formData.admin.password.length >= 8 &&
formData.admin.password === confirmPassword.value formData.admin.password === confirmPassword.value
) )
default: default:
@@ -582,8 +582,9 @@ async function testDatabaseConnection() {
await testDatabase(formData.database) await testDatabase(formData.database)
dbConnected.value = true dbConnected.value = true
} catch (error: unknown) { } catch (error: unknown) {
const err = error as { response?: { data?: { detail?: string } }; message?: string } const err = error as { response?: { data?: { detail?: string; message?: string } }; message?: string }
errorMessage.value = err.response?.data?.detail || err.message || 'Connection failed' errorMessage.value =
err.response?.data?.detail || err.response?.data?.message || err.message || 'Connection failed'
} finally { } finally {
testingDb.value = false testingDb.value = false
} }
@@ -598,8 +599,9 @@ async function testRedisConnection() {
await testRedis(formData.redis) await testRedis(formData.redis)
redisConnected.value = true redisConnected.value = true
} catch (error: unknown) { } catch (error: unknown) {
const err = error as { response?: { data?: { detail?: string } }; message?: string } const err = error as { response?: { data?: { detail?: string; message?: string } }; message?: string }
errorMessage.value = err.response?.data?.detail || err.message || 'Connection failed' errorMessage.value =
err.response?.data?.detail || err.response?.data?.message || err.message || 'Connection failed'
} finally { } finally {
testingRedis.value = false testingRedis.value = false
} }
@@ -622,8 +624,9 @@ async function performInstall() {
// Start polling for service restart // Start polling for service restart
waitForServiceRestart() waitForServiceRestart()
} catch (error: unknown) { } catch (error: unknown) {
const err = error as { response?: { data?: { detail?: string } }; message?: string } const err = error as { response?: { data?: { detail?: string; message?: string } }; message?: string }
errorMessage.value = err.response?.data?.detail || err.message || 'Installation failed' errorMessage.value =
err.response?.data?.detail || err.response?.data?.message || err.message || 'Installation failed'
} finally { } finally {
installing.value = false installing.value = false
} }