Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:finish task #5

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions wonder-world/1doc_look_ME/问答平台(后端).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
问答平台(后端)

1.概述

该后端程序实现注册登入,问题和回答的上传删除显示。

***

2.API

(1)“/v1/register”(注册)

name:用户名称

telephone:用户电话

password:密码

(2)“/v1/login”(登入)

telephone:用户电话

password:用户密码

(3)“/problem_hall/put”(输入问题)

title:问题标题

description:问题描述

name:提问者账号名

key:密匙(删除问题用密匙)

——问题名不可重复

(4)“/problem_hall/delete”(删除问题)

title:问题标题

key:密匙(密匙正确可删除)

(5)“/problem_hall/hall”(读取数据发送给前端)

first:开始跳过的数据

number:读取的数据数
(6)"/problem_hall/research"(给题目读问题)
title:问题题目

(6)“/answer/put”(提供回答)

description:回答内容

key:密匙(删除回答)

name:回答者账号名

title:回答对应的问题标题

(7)“/answer/delete”(删除问题)

text:问题内容

title:回答对应的问题标题

key;密匙

name:回答者的名字

(8)“/answer/hall”(显示回答数据)

title:问题标题

first:开始跳过的数据

number:读取的数据量
(9)检验登入状态
在操作问题和回答时会检验是否登入
(10)登出
name:在输入用户名

***
apifox链接:https://qsefuqgces.apifox.cn/
***



15 changes: 15 additions & 0 deletions wonder-world/account/import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package account

import "gorm.io/gorm"

type User struct { //用户
gorm.Model `json:"gorm_._model"`
Name string `json:"name,omitempty"`
Telephone string `json:"telephone,omitempty"`
Password string `json:"password,omitempty"`
ID int `json:"id,omitempty"`
}
type session struct {
Name string
Value string
}
56 changes: 56 additions & 0 deletions wonder-world/account/login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package account

import (
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"strconv"
"wonder-world/db"
"wonder-world/tool"
)

func Login(c *gin.Context) {
db := db.Dbfrom()
telephone := c.PostForm("telephone")
password := c.PostForm("password")
var user User
db.Where("telephone = ?", telephone).First(&user)
if user.ID == 0 {
c.JSON(422, gin.H{
"code": 422,
"message": "用户不存在",
})
return
}
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle potential bcrypt errors properly

When bcrypt.CompareHashAndPassword returns an error, it might not always be due to an incorrect password (e.g., hash corruption). Currently, all errors are treated as "密码错误" (incorrect password). Consider distinguishing between authentication errors and other possible errors to enhance error handling.

Suggested change:

if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
	if err == bcrypt.ErrMismatchedHashAndPassword {
		c.JSON(422, gin.H{
			"code":    422,
			"message": "密码错误",
		})
	} else {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "服务器错误",
		})
	}
	return
}

c.JSON(422, gin.H{
"code": 422,
"message": "密码错误",
})
return
}
f := 1
for f == 1 {
name := tool.Randam()
value := tool.Randam()
_, err := c.Cookie(strconv.Itoa(name))
if err != nil {
f = -1
c.SetCookie(user.Name, strconv.Itoa(value), 3600, "/", "http://127.0.0.1:8080", false, false)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid using user.Name as the cookie name

Using user.Name as the cookie name can lead to security issues and potential conflicts, especially if multiple users share the same browser. It's better to use a constant cookie name like "session_token".


⚠️ Potential issue

Incorrect domain format in SetCookie

The domain parameter in c.SetCookie should not include the protocol (http://) or port number. It should be just the domain name.

Suggested change:

-	c.SetCookie(user.Name, strconv.Itoa(value), 3600, "/", "http://127.0.0.1:8080", false, false)
+	c.SetCookie("session_token", token, 3600, "/", "127.0.0.1", false, true)

Committable suggestion was skipped due to low confidence.

newsession := session{
Name: strconv.Itoa(name),
Value: strconv.Itoa(value),
}
Comment on lines +39 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure the Session struct is properly defined and exported

The session struct should be properly defined with exported fields (capitalized names) to be accessible by GORM for database operations.

Define the struct as:

type Session struct {
	ID     uint
	UserID uint
	Token  string
}

db.Create(&newsession)
c.JSON(200, gin.H{
"code": 200,
"message": "success",
})
return
}
}
Comment on lines +33 to +50
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Inefficient and insecure session management implementation

The current approach generates random cookie names and values in a loop until a unique one is found, which is inefficient and may introduce security vulnerabilities. Additionally, using random integers for cookie names and values without sufficient randomness or entropy can be insecure. It's recommended to use standardized session management practices.

Consider using a secure, standard method for session management:

  1. Generate a secure session token using cryptographic functions.
  2. Use a constant cookie name to simplify client-side handling.
  3. Set appropriate cookie attributes for security (e.g., HttpOnly).
  4. Store the session associated with the user ID in the database.

Suggested refactor:

import (
	// Add these imports
	"crypto/rand"
	"encoding/hex"
)

// Helper function to generate a secure random token
func generateSessionToken() (string, error) {
	byteToken := make([]byte, 32)
	if _, err := rand.Read(byteToken); err != nil {
		return "", err
	}
	return hex.EncodeToString(byteToken), nil
}

// Inside the Login function
token, err := generateSessionToken()
if err != nil {
	c.JSON(500, gin.H{
		"code":    500,
		"message": "服务器错误",
	})
	return
}

// Set the cookie with a constant name
c.SetCookie("session_token", token, 3600, "/", "127.0.0.1", false, true)

// Ensure that the Session struct is properly defined
newSession := Session{
	UserID: user.ID,
	Token:  token,
}
db.Create(&newSession)

c.JSON(200, gin.H{
	"code":    200,
	"message": "登录成功",
})
return

Make sure the Session struct is defined as:

type Session struct {
	ID     uint
	UserID uint
	Token  string
}


c.JSON(422, gin.H{
"code": 422,
"message": "cookie failure",
})
}
61 changes: 61 additions & 0 deletions wonder-world/account/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package account

import (
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"net/http"
"wonder-world/db"
)

func Register(c *gin.Context) {
db := db.Dbfrom()
var u User
u.Name = c.PostForm("name")
u.Password = c.PostForm("password")
u.Telephone = c.PostForm("telephone")
Comment on lines +10 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding input sanitization.

While the function correctly retrieves user input, it's advisable to sanitize the input to prevent potential security issues like SQL injection or XSS attacks.

Consider using a library like bluemonday for input sanitization. Here's an example of how you could implement it:

import "github.com/microcosm-cc/bluemonday"

// At the beginning of the Register function
p := bluemonday.UGCPolicy()
u.Name = p.Sanitize(c.PostForm("name"))
u.Password = p.Sanitize(c.PostForm("password"))
u.Telephone = p.Sanitize(c.PostForm("telephone"))

if len(u.Name) == 0 {
c.JSON(422, gin.H{
"code": 422,
"message": "用户名不能为空",
})
return
}
if len(u.Telephone) != 11 {
c.JSON(422, gin.H{
"code": 422,
"message": "手机号必须为11位",
})
return
}
if len(u.Password) <= 6 {
c.JSON(422, gin.H{
"code": 422,
"message": "密码不能少于6位",
})
return
}
Comment on lines +16 to +36
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance input validation and error handling.

While the current validations cover basic requirements, there are several areas for improvement:

  1. The telephone number validation only checks length, not format. Consider using a regex pattern to ensure it's a valid phone number.
  2. The password validation could be more robust, checking for complexity (e.g., requiring a mix of uppercase, lowercase, numbers, and special characters).
  3. Error responses use hard-coded status codes. Consider using constants for better maintainability.

Here's an example of how you could improve the validation:

import (
    "regexp"
    "net/http"
)

const (
    StatusUnprocessableEntity = 422
)

func isValidPhoneNumber(phone string) bool {
    pattern := `^1[3-9]\d{9}$`
    match, _ := regexp.MatchString(pattern, phone)
    return match
}

func isStrongPassword(password string) bool {
    return len(password) >= 8 &&
           regexp.MustCompile(`[A-Z]`).MatchString(password) &&
           regexp.MustCompile(`[a-z]`).MatchString(password) &&
           regexp.MustCompile(`[0-9]`).MatchString(password) &&
           regexp.MustCompile(`[!@#$%^&*]`).MatchString(password)
}

// In the Register function
if !isValidPhoneNumber(u.Telephone) {
    c.JSON(http.StatusUnprocessableEntity, gin.H{
        "code":    StatusUnprocessableEntity,
        "message": "Invalid phone number format",
    })
    return
}

if !isStrongPassword(u.Password) {
    c.JSON(http.StatusUnprocessableEntity, gin.H{
        "code":    StatusUnprocessableEntity,
        "message": "Password must be at least 8 characters long and include uppercase, lowercase, number, and special character",
    })
    return
}

var user User
db.Where("telephone = ?", u.Telephone).First(&user)
if user.ID != 0 {
c.JSON(422, gin.H{
"code": 422,
"message": "用户已存在",
})
return
}
Comment on lines +37 to +45
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider separating database operations from the handler.

While the existing user check is functional, it's generally a good practice to separate concerns by moving database operations to a separate layer (e.g., a repository pattern).

Consider creating a separate package for database operations. Here's an example of how you could refactor this:

// In a new file, e.g., repository/user_repository.go
package repository

import "gorm.io/gorm"

type UserRepository struct {
    DB *gorm.DB
}

func (r *UserRepository) FindByTelephone(telephone string) (*User, error) {
    var user User
    result := r.DB.Where("telephone = ?", telephone).First(&user)
    if result.Error != nil {
        if result.Error == gorm.ErrRecordNotFound {
            return nil, nil
        }
        return nil, result.Error
    }
    return &user, nil
}

// In the Register function
userRepo := repository.UserRepository{DB: db}
existingUser, err := userRepo.FindByTelephone(u.Telephone)
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{
        "code":    http.StatusInternalServerError,
        "message": "Error checking existing user",
    })
    return
}
if existingUser != nil {
    c.JSON(http.StatusUnprocessableEntity, gin.H{
        "code":    http.StatusUnprocessableEntity,
        "message": "User already exists",
    })
    return
}

This approach improves testability and maintainability of your code.

hasedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{
"code": 500,
"message": "密码加密错误",
})
return
}
u.Password = string(hasedPassword)
db.Create(&u)
c.JSON(200, gin.H{
"code": 200,
"message": "success",
})

Comment on lines +46 to +60
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error handling and success response for user creation.

The password hashing and user creation process is generally well-implemented, but there are a few areas for improvement:

  1. Error handling for the user creation process is missing.
  2. The success response could be more informative.

Consider the following improvements:

hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{
        "code":    http.StatusInternalServerError,
        "message": "Error hashing password",
    })
    return
}
u.Password = string(hashedPassword)

result := db.Create(&u)
if result.Error != nil {
    c.JSON(http.StatusInternalServerError, gin.H{
        "code":    http.StatusInternalServerError,
        "message": "Error creating user",
    })
    return
}

c.JSON(http.StatusCreated, gin.H{
    "code":    http.StatusCreated,
    "message": "User created successfully",
    "data": gin.H{
        "id":        u.ID,
        "name":      u.Name,
        "telephone": u.Telephone,
    },
})

This implementation adds error handling for the user creation process and provides more information in the success response, while still maintaining security by not returning sensitive information like the password.

}
58 changes: 58 additions & 0 deletions wonder-world/answer/andelet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package answer

import (
"fmt"
"github.com/gin-gonic/gin"
db2 "wonder-world/db"
"wonder-world/test"
)

func Andelet(c *gin.Context) {
db := db2.Dbfrom()
f := 1
key := c.PostForm("key")
title := c.PostForm("title")
text := c.PostForm("text")
name := c.PostForm("name")
var user Ques
db.Where("title = ?", title).First(&user)
if user.ID == 0 {
c.JSON(422, gin.H{
"code": 422,
"message": "问题不存在",
})
return
}
Comment on lines +17 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve error handling and consider defining structs.

  1. The use of 422 status code for a non-existent question is unusual. Consider using 404 Not Found instead.
  2. The Ques struct is not defined in this file. Consider defining it at the top of the file or in a separate models package for better code organization.

Here's a suggested improvement:

+type Ques struct {
+	ID    uint
+	Title string
+	// Add other necessary fields
+}

 var user Ques
 db.Where("title = ?", title).First(&user)
 if user.ID == 0 {
-	c.JSON(422, gin.H{
-		"code":    422,
+	c.JSON(404, gin.H{
+		"code":    404,
 		"message": "问题不存在",
 	})
 	return
 }

Committable suggestion was skipped due to low confidence.

if !test.Getcookie(c, name) {
c.JSON(422, gin.H{
"code": 422,
"message": "重登",
})
return
}
var use []Anse
db.Where("name = ?", name).Find(&use)
fmt.Println(use)
if user.ID != 0 {
for _, answer := range use {
if answer.Text == text {
if answer.Key == key {
f = 0
db.Delete(&answer)
break
}
}
}
if f == 1 {
c.JSON(422, gin.H{
"code": 422,
"message": "错误",
})
return
}
c.JSON(200, gin.H{
"code": 200,
"message": "success",
})
}
}
Comment on lines +36 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor answer deletion logic for better readability and error handling.

  1. Replace the flag variable f with a more idiomatic approach.
  2. Simplify the nested if statements.
  3. Provide a more descriptive error message.
  4. Implement transaction management for the database operation.

Here's a suggested refactoring:

-	if user.ID != 0 {
-		for _, answer := range use {
-			if answer.Text == text {
-				if answer.Key == key {
-					f = 0
-					db.Delete(&answer)
-					break
-				}
-			}
-		}
-		if f == 1 {
-			c.JSON(422, gin.H{
-				"code":    422,
-				"message": "错误",
-			})
-			return
-		}
-		c.JSON(200, gin.H{
-			"code":    200,
-			"message": "success",
-		})
-	}
+	tx := db.Begin()
+	defer func() {
+		if r := recover(); r != nil {
+			tx.Rollback()
+		}
+	}()
+
+	var answerToDelete Anse
+	if err := tx.Where("name = ? AND text = ? AND key = ?", name, text, key).First(&answerToDelete).Error; err != nil {
+		tx.Rollback()
+		c.JSON(404, gin.H{
+			"code":    404,
+			"message": "Answer not found",
+		})
+		return
+	}
+
+	if err := tx.Delete(&answerToDelete).Error; err != nil {
+		tx.Rollback()
+		c.JSON(500, gin.H{
+			"code":    500,
+			"message": "Failed to delete answer",
+		})
+		return
+	}
+
+	tx.Commit()
+	c.JSON(200, gin.H{
+		"code":    200,
+		"message": "Answer deleted successfully",
+	})

This refactoring improves error handling, uses a database transaction, and provides more descriptive error messages.

Committable suggestion was skipped due to low confidence.

26 changes: 26 additions & 0 deletions wonder-world/answer/anhall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package answer

import (
"github.com/gin-gonic/gin"
"strconv"
db2 "wonder-world/db"
)

func Anhall(c *gin.Context) {
db := db2.Dbfrom()
Comment on lines +9 to +10
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for database connection.

The Dbfrom() function might return an error, which is currently not being handled. Consider adding error handling to ensure the application behaves correctly if the database connection fails.

Example implementation:

db, err := db2.Dbfrom()
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "Database connection failed"})
    return
}

number := c.PostForm("first")
number1 := c.PostForm("number")
title := c.PostForm("title")
var num, _ = strconv.Atoi(number)
num1, _ := strconv.Atoi(number1)
Comment on lines +11 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve error handling and add input validation.

  1. The error returned by strconv.Atoi is ignored, which could lead to unexpected behavior if the input is not a valid integer.
  2. There's no validation of the input data, which could lead to security vulnerabilities or unexpected behavior.

Consider implementing the following improvements:

  1. Handle errors from strconv.Atoi:
num, err := strconv.Atoi(number)
if err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 'first' parameter"})
    return
}
num1, err := strconv.Atoi(number1)
if err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 'number' parameter"})
    return
}
  1. Add input validation for all parameters:
if number == "" || number1 == "" || title == "" {
    c.JSON(http.StatusBadRequest, gin.H{"error": "Missing required parameters"})
    return
}

var user []Anse
db.Limit(num1).Offset(num).Find(&user)
for _, answer := range user {
if answer.Title == title {
}
c.JSON(200, gin.H{
"name": answer.Name,
"text": answer.Text,
})
}
Comment on lines +16 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix database query error handling and result processing logic.

There are several issues in this section:

  1. The database query doesn't handle potential errors.
  2. The if statement checking for title match is empty, which seems incorrect.
  3. The JSON response is sent for every item, not just matching ones.

Consider implementing the following improvements:

  1. Handle database query errors:
result := db.Limit(num1).Offset(num).Find(&user)
if result.Error != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "Database query failed"})
    return
}
  1. Fix the title matching logic:
for _, answer := range user {
    if answer.Title == title {
        c.JSON(200, gin.H{
            "name": answer.Name,
            "text": answer.Text,
        })
        return // Return after finding the first match
    }
}
// If no match is found
c.JSON(404, gin.H{"error": "No matching answer found"})

This will ensure that only matching answers are returned and that the function stops after finding the first match.

}
Comment on lines +9 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider refactoring for improved robustness and functionality.

The current implementation of Anhall has several areas that could be improved:

  1. Error handling is inconsistent and often missing.
  2. Input validation is not implemented.
  3. The logic for matching and returning answers is unclear.
  4. There's no pagination in the response, despite using offset and limit in the query.

To make this function more robust and suitable for a Q&A platform API, consider the following suggestions:

  1. Implement consistent error handling throughout the function.
  2. Add input validation for all parameters.
  3. Clarify the logic for matching answers and ensure it meets the requirements.
  4. Implement proper pagination in the response, including total count and next page information.

Would you like assistance in refactoring this function to address these issues? I can provide a more detailed implementation that incorporates these improvements.

52 changes: 52 additions & 0 deletions wonder-world/answer/anput.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package answer

import (
"github.com/gin-gonic/gin"
db2 "wonder-world/db"
"wonder-world/test"
)

func Anput(c *gin.Context) {
db := db2.Dbfrom()
description := c.PostForm("description")
name := c.PostForm("name")
key := c.PostForm("key")
title := c.PostForm("title")
Comment on lines +9 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using Gin's binding feature for form data.

Instead of retrieving form fields individually, consider using Gin's binding feature. This approach is less error-prone and provides automatic validation.

Here's an example of how you could refactor this:

type AnswerInput struct {
    Description string `form:"description" binding:"required"`
    Name        string `form:"name" binding:"required"`
    Key         string `form:"key" binding:"required"`
    Title       string `form:"title" binding:"required"`
}

func Anput(c *gin.Context) {
    var input AnswerInput
    if err := c.ShouldBind(&input); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    // Use input.Description, input.Name, etc.
    // ...
}

var user User
db.Where("name = ?", name).First(&user)
if user.ID == 0 {
c.JSON(422, gin.H{
"code": 422,
"message": "请输入正确的用户名",
})
return
}
if !test.Getcookie(c, name) {
c.JSON(422, gin.H{
"code": 422,
"message": "重登",
})
return
}
Comment on lines +15 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Optimize user validation and consider internationalizing error messages.

  1. The user existence check and cookie validation can be combined to reduce database queries:
if !test.Getcookie(c, name) {
    c.JSON(http.StatusUnauthorized, gin.H{
        "code":    http.StatusUnauthorized,
        "message": "Authentication required",
    })
    return
}

var user User
if err := db.Where("name = ?", name).First(&user).Error; err != nil {
    c.JSON(http.StatusUnprocessableEntity, gin.H{
        "code":    http.StatusUnprocessableEntity,
        "message": "Invalid username",
    })
    return
}
  1. Consider using internationalization for error messages to support multiple languages.

Would you like assistance in implementing these suggestions?

var use Ques
db.Where("title = ?", title).First(&use)
if use.ID == 0 {
c.JSON(422, gin.H{
"code": 422,
"message": "问题不存在",
})
return
}
newAnswer := Anse{
Name: name,
Text: description,
Key: key,
Title: title,
}
db.Create(&newAnswer)
Comment on lines +31 to +46
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve error handling and struct definition.

  1. Add error handling for database operations:
var question Ques
if err := db.Where("title = ?", title).First(&question).Error; err != nil {
    if errors.Is(err, gorm.ErrRecordNotFound) {
        c.JSON(http.StatusNotFound, gin.H{
            "code":    http.StatusNotFound,
            "message": "Question not found",
        })
    } else {
        c.JSON(http.StatusInternalServerError, gin.H{
            "code":    http.StatusInternalServerError,
            "message": "Database error",
        })
    }
    return
}
  1. The Anse struct is not defined in this file. Consider defining it here or importing it from the appropriate package.

Please provide the definition for the Anse struct or import it from the correct package.

c.JSON(200, gin.H{
"code": 200,
"message": "success",
})

Comment on lines +47 to +51
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance the response with more information and use HTTP status constants.

Consider providing more information in the success response and use HTTP status constants for better readability:

c.JSON(http.StatusOK, gin.H{
    "code":    http.StatusOK,
    "message": "Answer created successfully",
    "data": gin.H{
        "id":    newAnswer.ID,
        "title": newAnswer.Title,
    },
})

This provides more context about the created answer and uses the http.StatusOK constant for clarity.

}
25 changes: 25 additions & 0 deletions wonder-world/answer/import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package answer

import "gorm.io/gorm"

type User struct { //用户
gorm.Model `json:"gorm_._model"`
Name string `json:"name,omitempty"`
Telephone string `json:"telephone,omitempty"`
Password string `json:"password,omitempty"`
ID int `json:"id,omitempty"`
}
Comment on lines +5 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security and design improvements needed in User struct

  1. The ID field is redundant as gorm.Model already includes an ID field. Consider removing the explicit ID field.

  2. Storing passwords as plain text is a security risk. It's crucial to hash passwords before storage.

Consider applying these changes:

 type User struct { //用户
 	gorm.Model `json:"gorm_._model"`
 	Name       string `json:"name,omitempty"`
 	Telephone  string `json:"telephone,omitempty"`
-	Password   string `json:"password,omitempty"`
+	Password   string `json:"-"` // Never expose password in JSON
-	ID         int    `json:"id,omitempty"`
 }

Also, ensure that passwords are hashed before storage. Consider using a package like golang.org/x/crypto/bcrypt for secure password hashing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type User struct { //用户
gorm.Model `json:"gorm_._model"`
Name string `json:"name,omitempty"`
Telephone string `json:"telephone,omitempty"`
Password string `json:"password,omitempty"`
ID int `json:"id,omitempty"`
}
type User struct { //用户
gorm.Model `json:"gorm_._model"`
Name string `json:"name,omitempty"`
Telephone string `json:"telephone,omitempty"`
Password string `json:"-"` // Never expose password in JSON
}

type Ques struct { //问题
gorm.Model
Name string
Title string
Put string
Key string
}
Comment on lines +12 to +18
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve struct naming and field definitions

  1. The struct name Ques is not idiomatic Go. Consider using a full word like Question.
  2. The purpose of the Put field is unclear. Consider renaming or adding a comment to explain its use.
  3. JSON tags are missing, which may lead to unexpected behavior during serialization.

Consider applying these changes:

-type Ques struct { //问题
+type Question struct { //问题
 	gorm.Model
-	Name  string
-	Title string
-	Put   string
-	Key   string
+	Name  string `json:"name"`
+	Title string `json:"title"`
+	Put   string `json:"put"` // Consider renaming this field or adding a comment to explain its purpose
+	Key   string `json:"key"`
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type Ques struct { //问题
gorm.Model
Name string
Title string
Put string
Key string
}
type Question struct { //问题
gorm.Model
Name string `json:"name"`
Title string `json:"title"`
Put string `json:"put"` // Consider renaming this field or adding a comment to explain its purpose
Key string `json:"key"`
}

type Anse struct { //我、回答
Name string `json:"name"`
Text string `json:"text"`
Key string `json:"key"`
Title string `json:"title"`
gorm.Model
}
Comment on lines +19 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Clarify struct purpose and improve naming

  1. The struct name Anse is not idiomatic Go. Consider using a full word like Answer.
  2. The comment "我、回答" (me, answer) suggests ambiguous purpose. Consider splitting into separate structs if needed.
  3. The gorm.Model is placed at the end, which is inconsistent with other structs. Consider moving it to the top for consistency.

Consider applying these changes:

-type Anse struct { //我、回答
+type Answer struct { //回答
+	gorm.Model
 	Name  string `json:"name"`
 	Text  string `json:"text"`
 	Key   string `json:"key"`
 	Title string `json:"title"`
-	gorm.Model
 }

Also, consider if you need a separate struct for "me" (user) or if this information can be included in the existing User struct.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type Anse struct { //我、回答
Name string `json:"name"`
Text string `json:"text"`
Key string `json:"key"`
Title string `json:"title"`
gorm.Model
}
type Answer struct { //回答
gorm.Model
Name string `json:"name"`
Text string `json:"text"`
Key string `json:"key"`
Title string `json:"title"`
}

Loading