Skip to content

feat: finish task #9

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
50 changes: 50 additions & 0 deletions hkr0101/AI_answer/aianswer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package aianswer

import (
"context"
"github.com/gin-gonic/gin"
"github.com/sashabaranov/go-openai"
"log"
"net/http"
"os"
)

// ChatGPT处理函数
func ChatGPTHandler(c *gin.Context) {
var req struct {
Prompt string `json:"prompt"`
}
// 绑定JSON输入
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
return
}

// 从环境变量中获取API密钥
apiKey := os.Getenv("OPENAI_API_KEY")
if apiKey == "" {
log.Fatal("API Key not set")
}

// 初始化 OpenAI 客户端
client := openai.NewClient(apiKey)
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 for missing API key.

While retrieving the API key from environment variables is a good practice, using log.Fatal in a web handler can abruptly terminate the entire application. Consider a more graceful error handling approach.

Suggested improvement:

apiKey := os.Getenv("OPENAI_API_KEY")
if apiKey == "" {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "API Key not configured"})
    return
}

This change will return an error response to the client instead of terminating the application.


// 调用 OpenAI API
resp, err := client.CreateChatCompletion(context.Background(), openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo, // 或者其他模型
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: req.Prompt,
},
},
})

if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to communicate with ChatGPT"})
return
}
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 a timeout for the OpenAI API call.

The API call is correctly structured, but it lacks a timeout. This could potentially lead to long-running requests if the OpenAI service is slow to respond.

Consider adding a timeout to the context:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

resp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
    // ... rest of the code remains the same
})

This ensures that the request will be cancelled if it takes longer than 10 seconds (adjust the duration as needed).


// 返回 ChatGPT 的回复
c.JSON(http.StatusOK, gin.H{"response": resp.Choices[0].Message.Content})
}
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 additional error checking for the API response.

While the current implementation handles API call errors, it doesn't check for empty responses, which could lead to a panic if the Choices slice is empty.

Consider adding a check for empty responses:

if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to communicate with ChatGPT"})
    return
}

if len(resp.Choices) == 0 {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "No response from ChatGPT"})
    return
}

// Return ChatGPT's reply
c.JSON(http.StatusOK, gin.H{"response": resp.Choices[0].Message.Content})

This additional check ensures that the application handles cases where the API returns an empty response.

16 changes: 16 additions & 0 deletions hkr0101/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 简单的代码说明
实现了账户的注册、登录、登出,其中在储存密码时运用了简单的哈希函数。给予了admin
账号足够的权限。
实现了在登录情况下添加、删除、修改、查看自己的问题,以
及在所有的情况下查看所有/特定问题。在登录情况下添加、删除、修改、查看自
己的答案,以及在所有的情况下查看某一个问题的答案
一个小翻页,默认在显示一系列答案或者问题时每页20条内容
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Enhance security and clarity in the project overview

The project overview provides a good summary of the main features. However, there are a few points that could be improved:

  1. Security concern: The use of a "simple hash function" for password storage might not be secure enough. Consider using a strong, industry-standard password hashing algorithm like bcrypt, Argon2, or PBKDF2.

  2. Admin permissions: The description mentions that the admin account has "sufficient permissions," but it doesn't specify what these permissions are. Consider detailing the admin's capabilities for clarity.

  3. Pagination: While pagination is mentioned, it lacks details on how it's implemented or how users can navigate through pages. Consider adding more information about this feature.

Would you like assistance in drafting a more detailed and security-focused description for these sections?

在github上找到了一个关于调用chatgpt的项目用于生成ai答案,但是由于
我没有国外的手机号,无法获得chatgpt的key,这个内容仅仅停留在未测试可行性
* main.go是主程序
* routes中的是操作中涉及的函数
* mymodels中是三个实体Question、User、Answer
* myauth中是登录与登出的操作
* db中的是连接数据库以及在数据库中自动生成实体
* AI_answer中便是前文中提到的尚未完成的ai生成答案部分
api文档:https://apifox.com/apidoc/shared-86117e10-c314-4e57-a13f-494295b93689
30 changes: 30 additions & 0 deletions hkr0101/db/database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package db

import (
"Initial_Experience/myModels"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)

var DB *gorm.DB

// 数据库的连接
func Connect() {
var err error
dsn := "root:123456@tcp(localhost:3306)/initial_experience"
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal("Failed to connect to the database:", err)
} else {
log.Println("Successfully connected to the database")
}
}
Comment on lines +13 to +22
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 database connection handling and configuration.

The Connect function has several areas for improvement:

  1. The Data Source Name (DSN) is hardcoded, which is not secure or flexible.
  2. Using log.Fatal will terminate the program, which might not be the desired behavior in all cases.
  3. The else block is unnecessary.

Consider the following improvements:

  1. Use environment variables or a configuration file for the DSN:

    dsn := os.Getenv("DATABASE_DSN")
  2. Return an error instead of using log.Fatal:

    func Connect() error {
        var err error
        dsn := os.Getenv("DATABASE_DSN")
        DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
        if err != nil {
            return fmt.Errorf("failed to connect to the database: %w", err)
        }
        log.Println("Successfully connected to the database")
        return nil
    }
  3. Remove the else block as it's not needed after the if statement returns.

These changes will make the function more flexible, secure, and easier to use in different contexts.


// 自动迁移模型
func Migrate() {
err := DB.AutoMigrate(&mymodels.User{}, &mymodels.Question{}, &mymodels.Answer{})
if err != nil {
log.Fatal("Migration failed:", err)
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Reconsider the use of AutoMigrate and improve error handling.

The Migrate function uses AutoMigrate, which can be risky in production environments. It also uses log.Fatal for error handling, which terminates the program.

Consider the following improvements:

  1. For production, consider using a dedicated migration tool or manually managing migrations for better control and safety.

  2. If you decide to keep AutoMigrate, return an error instead of using log.Fatal:

    func Migrate() error {
        err := DB.AutoMigrate(&mymodels.User{}, &mymodels.Question{}, &mymodels.Answer{})
        if err != nil {
            return fmt.Errorf("migration failed: %w", err)
        }
        log.Println("Migration completed successfully")
        return nil
    }
  3. Add a warning log before running migrations:

    log.Println("Warning: Running AutoMigrate. This may make schema changes.")

These changes will give the caller more control over error handling and make the migration process safer and more transparent.

40 changes: 40 additions & 0 deletions hkr0101/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Initial_Experience
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 module name to follow Go conventions

The current module name "Initial_Experience" doesn't follow Go naming conventions. In Go, it's recommended to use lowercase letters and hyphens for module names.

Consider changing the module name to something like:

-module Initial_Experience
+module github.com/hduhelp/backend_2024_freshman_task

This assumes the repository is hosted on GitHub under the "hduhelp" organization. Adjust the path accordingly if it's different.

📝 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
module Initial_Experience
module github.com/hduhelp/backend_2024_freshman_task


go 1.23.1
Comment on lines +1 to +3
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Update Go version to a valid release

The specified Go version 1.23.1 is not a valid released version. As of October 2024, the latest stable version is in the 1.21.x series.

Please update the Go version to a valid, stable release. For example:

-go 1.23.1
+go 1.21.5

Make sure to test your code with the updated version to ensure compatibility.

📝 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
module Initial_Experience
go 1.23.1
module Initial_Experience
go 1.21.5


require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/bytedance/sonic v1.12.3 // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.10.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.22.1 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/sashabaranov/go-openai v1.31.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.10.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.7 // indirect
gorm.io/gorm v1.25.12 // indirect
)
93 changes: 93 additions & 0 deletions hkr0101/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU=
github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sashabaranov/go-openai v1.31.0 h1:rGe77x7zUeCjtS2IS7NCY6Tp4bQviXNMhkQM6hz/UC4=
github.com/sashabaranov/go-openai v1.31.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8=
golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
57 changes: 57 additions & 0 deletions hkr0101/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package main

import (
"Initial_Experience/AI_answer"
"Initial_Experience/db"
"Initial_Experience/myauth"
"Initial_Experience/routes"
"github.com/gin-gonic/gin"
)
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 absolute import paths and consistent package naming.

  1. The use of relative import paths (e.g., "Initial_Experience/AI_answer") might cause issues if the project structure changes. Consider using absolute import paths to improve maintainability.

  2. There's an inconsistency in the naming of the AI_answer package (using underscore) compared to other packages (using camelCase). For consistency, consider renaming it to aianswer to match the naming convention of other packages.

Here's a suggested improvement for the import section:

import (
-	"Initial_Experience/AI_answer"
-	"Initial_Experience/db"
-	"Initial_Experience/myauth"
-	"Initial_Experience/routes"
+	"github.com/yourusername/projectname/aianswer"
+	"github.com/yourusername/projectname/db"
+	"github.com/yourusername/projectname/myauth"
+	"github.com/yourusername/projectname/routes"
	"github.com/gin-gonic/gin"
)

Replace yourusername and projectname with the appropriate values for your project.

Committable suggestion was skipped due to low confidence.


func main() {
r := gin.Default()
db.Connect()
db.Migrate()
Comment on lines +10 to +13
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 error handling and configuration in the main function.

  1. Add error handling for database operations to ensure the application fails gracefully if there are connection issues.
  2. Consider making the server port configurable through environment variables for better flexibility across different environments.

Here's a suggested improvement for the main function:

func main() {
	r := gin.Default()
-	db.Connect()
-	db.Migrate()
+	if err := db.Connect(); err != nil {
+		log.Fatalf("Failed to connect to database: %v", err)
+	}
+	if err := db.Migrate(); err != nil {
+		log.Fatalf("Failed to run database migrations: %v", err)
+	}

	// ... (rest of the code)

-	r.Run(":8080")
+	port := os.Getenv("PORT")
+	if port == "" {
+		port = "8080"
+	}
+	if err := r.Run(":" + port); err != nil {
+		log.Fatalf("Failed to start server: %v", err)
+	}
}

Don't forget to import the log and os packages if you implement these changes.

Also applies to: 56-57

//用户注册
r.POST("/register", myauth.RegisterHandler)
// 用户登录
r.POST("/login", myauth.LoginHandler)
// 用户登出
r.POST("/logout", myauth.LogoutHandler)
// 问题管理

//查看所有问题
r.GET("/questions", routes.GetQuestions)
//查看某个问题
r.GET("/questions/:question_id", routes.GetQuestionByID)
//查看某个问题的所有答案
r.GET("/questions/:question_id/answer", routes.GetAnswerListByQuestion)
//查看某个问题的某个答案
r.GET("/questions/answer/:answer_id", routes.GetAnswerByID)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Review public routes for security and remove redundant logout route.

  1. The /questions and /questions/:question_id/answer endpoints are public. Consider if this aligns with your security requirements or if these should be behind authentication.

  2. The logout route is defined twice: once as a public route and once in the authenticated group. This is redundant and might lead to confusion.

Remove the redundant logout route and consider moving some routes behind authentication:

// Public routes
r.POST("/register", myauth.RegisterHandler)
r.POST("/login", myauth.LoginHandler)
r.POST("/logout", myauth.LogoutHandler)

- r.GET("/questions", routes.GetQuestions)
- r.GET("/questions/:question_id", routes.GetQuestionByID)
- r.GET("/questions/:question_id/answer", routes.GetAnswerListByQuestion)
- r.GET("/questions/answer/:answer_id", routes.GetAnswerByID)

// In the authenticated group
auth := r.Group("/my")
auth.Use(myauth.AuthMiddleware())
{
+	auth.GET("/questions", routes.GetQuestions)
+	auth.GET("/questions/:question_id", routes.GetQuestionByID)
+	auth.GET("/questions/:question_id/answer", routes.GetAnswerListByQuestion)
+	auth.GET("/questions/answer/:answer_id", routes.GetAnswerByID)
	
	// ... (other authenticated routes)

-	auth.POST("/logout", myauth.LogoutHandler) // Remove this line
}

This change ensures that question and answer data is only accessible to authenticated users and removes the redundant logout route.

Also applies to: 52-52


auth := r.Group("/my")
auth.Use(myauth.AuthMiddleware()) // 使用身份验证中间件
{
//创建问题
auth.POST("/questions", routes.CreateQuestion)
//创建答案
auth.POST("/questions/:question_id/answer", routes.CreateAnswer)
//删除问题
auth.DELETE("/questions/:question_id", routes.DeleteQuestion)
//删除答案
auth.DELETE("/questions/answer/:answer_id", routes.DeleteAnswer)
//更新问题
auth.PUT("/questions/:question_id", routes.UpdateQuestion)
//更新答案
auth.PUT("/:answer_id", routes.UpdateAnswer)
//给出当前用户的所有答案
auth.GET("/answer", routes.GetAnswerListByUser)
//给出当前用户的所有问题
auth.GET("/questions", routes.GetQuestionByUser)
//登出
auth.POST("/logout", myauth.LogoutHandler)
//调用ai,未完成
auth.POST("/chat", aianswer.ChatGPTHandler)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Address incomplete AI chat functionality and improve route paths.

  1. The AI chat functionality is marked as incomplete. It's important to complete this feature or remove it if it's not intended for the current version.

  2. Some route paths could be more RESTful. For example, the update answer route uses a non-standard path.

Here are some suggestions:

  1. For the AI chat functionality:

    • If it's not ready for this version, consider removing it or adding a TODO comment with more details.
    • If it's meant to be included, complete the implementation and remove the "未完成" (incomplete) comment.
  2. Improve RESTful route paths:

auth.Group("/my")
{
	// ... (other routes)

-	auth.PUT("/:answer_id", routes.UpdateAnswer)
+	auth.PUT("/questions/answer/:answer_id", routes.UpdateAnswer)

	// ... (other routes)

-	auth.POST("/chat", aianswer.ChatGPTHandler)
+	// TODO: Implement AI chat functionality
+	// auth.POST("/chat", aianswer.ChatGPTHandler)
}

These changes make the update answer route more consistent with other answer-related routes and comment out the incomplete AI chat functionality until it's ready to be implemented.

📝 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
auth := r.Group("/my")
auth.Use(myauth.AuthMiddleware()) // 使用身份验证中间件
{
//创建问题
auth.POST("/questions", routes.CreateQuestion)
//创建答案
auth.POST("/questions/:question_id/answer", routes.CreateAnswer)
//删除问题
auth.DELETE("/questions/:question_id", routes.DeleteQuestion)
//删除答案
auth.DELETE("/questions/answer/:answer_id", routes.DeleteAnswer)
//更新问题
auth.PUT("/questions/:question_id", routes.UpdateQuestion)
//更新答案
auth.PUT("/:answer_id", routes.UpdateAnswer)
//给出当前用户的所有答案
auth.GET("/answer", routes.GetAnswerListByUser)
//给出当前用户的所有问题
auth.GET("/questions", routes.GetQuestionByUser)
//登出
auth.POST("/logout", myauth.LogoutHandler)
//调用ai,未完成
auth.POST("/chat", aianswer.ChatGPTHandler)
}
auth := r.Group("/my")
auth.Use(myauth.AuthMiddleware()) // 使用身份验证中间件
{
//创建问题
auth.POST("/questions", routes.CreateQuestion)
//创建答案
auth.POST("/questions/:question_id/answer", routes.CreateAnswer)
//删除问题
auth.DELETE("/questions/:question_id", routes.DeleteQuestion)
//删除答案
auth.DELETE("/questions/answer/:answer_id", routes.DeleteAnswer)
//更新问题
auth.PUT("/questions/:question_id", routes.UpdateQuestion)
//更新答案
auth.PUT("/questions/answer/:answer_id", routes.UpdateAnswer)
//给出当前用户的所有答案
auth.GET("/answer", routes.GetAnswerListByUser)
//给出当前用户的所有问题
auth.GET("/questions", routes.GetQuestionByUser)
//登出
auth.POST("/logout", myauth.LogoutHandler)
//调用ai,未完成
// TODO: Implement AI chat functionality
// auth.POST("/chat", aianswer.ChatGPTHandler)
}

r.Run(":8080")
}
24 changes: 24 additions & 0 deletions hkr0101/myModels/mymodels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package mymodels

// Question 结构体
type Question struct {
QuestionID int `json:"question_id" gorm:"primaryKey;autoIncrement"`
Content string `json:"content" binding:"required"`
Status string `json:"status" binding:"required"`
Name string `json:"name" binding:"required"`
UserID int `json:"user_id"` // 外键,关联用户
}
Comment on lines +4 to +10
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 Question struct definition for improved database interactions.

The Question struct can be improved to better leverage GORM's features:

  1. Add a GORM tag for the foreign key relationship on the UserID field.
  2. Consider using an enum or constants for the Status field to ensure consistency.
  3. Add GORM tags for indexing frequently queried fields.

Here's a suggested improvement:

 type Question struct {
 	QuestionID int    `json:"question_id" gorm:"primaryKey;autoIncrement"`
 	Content    string `json:"content" binding:"required"`
-	Status     string `json:"status" binding:"required"`
+	Status     string `json:"status" binding:"required" gorm:"type:ENUM('open', 'closed', 'in_progress');index"`
 	Name       string `json:"name" binding:"required"`
-	UserID     int    `json:"user_id"` // 外键,关联用户
+	UserID     int    `json:"user_id" gorm:"index;foreignKey:UserID"`
 }

Also, consider defining constants for the Status field:

const (
    StatusOpen       = "open"
    StatusClosed     = "closed"
    StatusInProgress = "in_progress"
)

These changes will improve database interactions and maintain data consistency.


// User 结构体
type User struct {
UserID int `json:"user_id" gorm:"primaryKey;autoIncrement"`
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
Comment on lines +13 to +17
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 the User struct for better performance and security.

Consider the following enhancements to the User struct:

  1. Add an index to the Username field for faster lookups.
  2. Add a unique constraint to the Username field to prevent duplicate usernames.
  3. Exclude the Password field from JSON responses for security reasons.

Here's a suggested improvement:

 type User struct {
 	UserID   int    `json:"user_id" gorm:"primaryKey;autoIncrement"`
-	Username string `json:"username" binding:"required"`
-	Password string `json:"password" binding:"required"`
+	Username string `json:"username" binding:"required" gorm:"uniqueIndex"`
+	Password string `json:"-" binding:"required"`
 }

These changes will improve query performance, ensure username uniqueness, and enhance security by not exposing the password in JSON responses.

📝 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 {
UserID int `json:"user_id" gorm:"primaryKey;autoIncrement"`
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
type User struct {
UserID int `json:"user_id" gorm:"primaryKey;autoIncrement"`
Username string `json:"username" binding:"required" gorm:"uniqueIndex"`
Password string `json:"-" binding:"required"`
}


type Answer struct {
AnswerID int `json:"answer_id" gorm:"primaryKey;autoIncrement"`
Content string `json:"content" binding:"required"`
QuestionID int `json:"question_id"` // 外键,关联问题
UserID int `json:"user_id"` // 外键,关联用户
}
Comment on lines +19 to +24
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 Answer struct with proper relationships and timestamps.

The Answer struct can be improved to better leverage GORM's features and improve data tracking:

  1. Add GORM tags for the foreign key relationships on the QuestionID and UserID fields.
  2. Include timestamp fields (created_at, updated_at) for better data tracking.
  3. Add an index to the QuestionID field for faster querying.

Here's a suggested improvement:

 type Answer struct {
 	AnswerID   int    `json:"answer_id" gorm:"primaryKey;autoIncrement"`
 	Content    string `json:"content" binding:"required"`
-	QuestionID int    `json:"question_id"` // 外键,关联问题
-	UserID     int    `json:"user_id"`     // 外键,关联用户
+	QuestionID int    `json:"question_id" gorm:"index;foreignKey:QuestionID"`
+	UserID     int    `json:"user_id" gorm:"foreignKey:UserID"`
+	CreatedAt  time.Time `json:"created_at" gorm:"autoCreateTime"`
+	UpdatedAt  time.Time `json:"updated_at" gorm:"autoUpdateTime"`
 }

These changes will properly define the relationships in the database, add timestamps for better data tracking, and improve query performance for finding answers to a specific question.

Don't forget to import the time package if it's not already imported.

📝 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 Answer struct {
AnswerID int `json:"answer_id" gorm:"primaryKey;autoIncrement"`
Content string `json:"content" binding:"required"`
QuestionID int `json:"question_id"` // 外键,关联问题
UserID int `json:"user_id"` // 外键,关联用户
}
type Answer struct {
AnswerID int `json:"answer_id" gorm:"primaryKey;autoIncrement"`
Content string `json:"content" binding:"required"`
QuestionID int `json:"question_id" gorm:"index;foreignKey:QuestionID"`
UserID int `json:"user_id" gorm:"foreignKey:UserID"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
}

Loading