mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-03 06:52:13 +08:00
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:
@@ -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,
|
||||||
|
|||||||
@@ -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'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ export default {
|
|||||||
email: '邮箱',
|
email: '邮箱',
|
||||||
password: '密码',
|
password: '密码',
|
||||||
confirmPassword: '确认密码',
|
confirmPassword: '确认密码',
|
||||||
passwordPlaceholder: '至少 6 个字符',
|
passwordPlaceholder: '至少 8 个字符',
|
||||||
confirmPasswordPlaceholder: '确认密码',
|
confirmPasswordPlaceholder: '确认密码',
|
||||||
passwordMismatch: '密码不匹配'
|
passwordMismatch: '密码不匹配'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user