Jelajahi Sumber

🛠️ fix: Align setup API errors to HTTP 200 with {success:false, message}

Unify the setup initialization endpoint’s error contract to match the rest
of the project and keep the frontend unchanged.

Changes
- controller/setup.go: Return HTTP 200 with {success:false, message} for all
  predictable errors in POST /api/setup, including:
  - already initialized
  - invalid payload
  - username too long
  - password mismatch
  - password too short
  - password hashing failure
  - root user creation failure
  - option persistence failures (SelfUseModeEnabled, DemoSiteEnabled)
  - setup record creation failure
- web/src/components/setup/SetupWizard.jsx: Restore catch handler to the
  previous generic toast (frontend logic unchanged).
- web/src/helpers/utils.jsx: Restore the original showError implementation
  (no Axios response.data parsing required).

Why
- Keep API behavior consistent across endpoints so the UI can rely on the
  success flag and message in the normal .then() flow instead of falling
  into Axios 4xx errors that only show a generic "400".

Impact
- UI now displays specific server messages during initialization without
  frontend adaptations.
- Note: clients relying solely on HTTP status codes for error handling
  should inspect the JSON body (success/message) instead.

No changes to the happy path; initialization success responses are unchanged.
t0ng7u 3 bulan lalu
induk
melakukan
4be61d00e4
1 mengubah file dengan 10 tambahan dan 10 penghapusan
  1. 10 10
      controller/setup.go

+ 10 - 10
controller/setup.go

@@ -53,7 +53,7 @@ func GetSetup(c *gin.Context) {
 func PostSetup(c *gin.Context) {
 	// Check if setup is already completed
 	if constant.Setup {
-		c.JSON(400, gin.H{
+		c.JSON(200, gin.H{
 			"success": false,
 			"message": "系统已经初始化完成",
 		})
@@ -66,7 +66,7 @@ func PostSetup(c *gin.Context) {
 	var req SetupRequest
 	err := c.ShouldBindJSON(&req)
 	if err != nil {
-		c.JSON(400, gin.H{
+		c.JSON(200, gin.H{
 			"success": false,
 			"message": "请求参数有误",
 		})
@@ -77,7 +77,7 @@ func PostSetup(c *gin.Context) {
 	if !rootExists {
 		// Validate username length: max 12 characters to align with model.User validation
 		if len(req.Username) > 12 {
-			c.JSON(400, gin.H{
+			c.JSON(200, gin.H{
 				"success": false,
 				"message": "用户名长度不能超过12个字符",
 			})
@@ -85,7 +85,7 @@ func PostSetup(c *gin.Context) {
 		}
 		// Validate password
 		if req.Password != req.ConfirmPassword {
-			c.JSON(400, gin.H{
+			c.JSON(200, gin.H{
 				"success": false,
 				"message": "两次输入的密码不一致",
 			})
@@ -93,7 +93,7 @@ func PostSetup(c *gin.Context) {
 		}
 
 		if len(req.Password) < 8 {
-			c.JSON(400, gin.H{
+			c.JSON(200, gin.H{
 				"success": false,
 				"message": "密码长度至少为8个字符",
 			})
@@ -103,7 +103,7 @@ func PostSetup(c *gin.Context) {
 		// Create root user
 		hashedPassword, err := common.Password2Hash(req.Password)
 		if err != nil {
-			c.JSON(500, gin.H{
+			c.JSON(200, gin.H{
 				"success": false,
 				"message": "系统错误: " + err.Error(),
 			})
@@ -120,7 +120,7 @@ func PostSetup(c *gin.Context) {
 		}
 		err = model.DB.Create(&rootUser).Error
 		if err != nil {
-			c.JSON(500, gin.H{
+			c.JSON(200, gin.H{
 				"success": false,
 				"message": "创建管理员账号失败: " + err.Error(),
 			})
@@ -135,7 +135,7 @@ func PostSetup(c *gin.Context) {
 	// Save operation modes to database for persistence
 	err = model.UpdateOption("SelfUseModeEnabled", boolToString(req.SelfUseModeEnabled))
 	if err != nil {
-		c.JSON(500, gin.H{
+		c.JSON(200, gin.H{
 			"success": false,
 			"message": "保存自用模式设置失败: " + err.Error(),
 		})
@@ -144,7 +144,7 @@ func PostSetup(c *gin.Context) {
 
 	err = model.UpdateOption("DemoSiteEnabled", boolToString(req.DemoSiteEnabled))
 	if err != nil {
-		c.JSON(500, gin.H{
+		c.JSON(200, gin.H{
 			"success": false,
 			"message": "保存演示站点模式设置失败: " + err.Error(),
 		})
@@ -160,7 +160,7 @@ func PostSetup(c *gin.Context) {
 	}
 	err = model.DB.Create(&setup).Error
 	if err != nil {
-		c.JSON(500, gin.H{
+		c.JSON(200, gin.H{
 			"success": false,
 			"message": "系统初始化失败: " + err.Error(),
 		})