-
Notifications
You must be signed in to change notification settings - Fork 26
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
亻尔女子 #4
base: main
Are you sure you want to change the base?
亻尔女子 #4
Changes from 11 commits
e7da38b
f8cf8fb
df0bd3c
8f1f7e9
40cba04
298c7ad
7df0c62
6f478b9
9a75317
2fc97d8
5c25876
fead4d7
dfa39c8
c8baf54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
.idea | ||
.idea | ||
l1nk4i/config.toml | ||
.gitignore | ||
l1nk4i/test |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package admin | ||
|
||
import ( | ||
"github.com/gin-contrib/sessions" | ||
"github.com/gin-gonic/gin" | ||
"l1nk4i/db" | ||
"net/http" | ||
) | ||
|
||
func DeleteAnswer(c *gin.Context) { | ||
answerID := c.Param("answer-id") | ||
|
||
session := sessions.Default(c) | ||
role, exists := session.Get("role").(string) | ||
if !exists { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid session"}) | ||
return | ||
} | ||
|
||
if role != "admin" { | ||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) | ||
return | ||
} | ||
|
||
err := db.DeleteAnswer(answerID) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid answer-id"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, gin.H{"msg": "delete answer successful!"}) | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,32 @@ | ||||||||||||||||||||||||
package admin | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
import ( | ||||||||||||||||||||||||
"github.com/gin-contrib/sessions" | ||||||||||||||||||||||||
"github.com/gin-gonic/gin" | ||||||||||||||||||||||||
"l1nk4i/db" | ||||||||||||||||||||||||
"net/http" | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
func DeleteQuestion(c *gin.Context) { | ||||||||||||||||||||||||
questionID := c.Param("question-id") | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
session := sessions.Default(c) | ||||||||||||||||||||||||
role, exists := session.Get("role").(string) | ||||||||||||||||||||||||
if !exists { | ||||||||||||||||||||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid session"}) | ||||||||||||||||||||||||
return | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
if role != "admin" { | ||||||||||||||||||||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) | ||||||||||||||||||||||||
return | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
err := db.DeleteQuestion(questionID) | ||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid question-id"}) | ||||||||||||||||||||||||
return | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
Comment on lines
+25
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve error handling and add logging. While the deletion logic is correct, the error handling can be improved. Not all errors from Here's a suggested improvement: err := db.DeleteQuestion(questionID)
if err != nil {
- c.JSON(http.StatusBadRequest, gin.H{"error": "invalid question-id"})
+ log.Printf("Error deleting question %s: %v", questionID, err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete question"})
return
} Also, consider adding a package-level logger or using a logging middleware for consistent logging across the application. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
c.JSON(http.StatusOK, gin.H{"msg": "delete question successful!"}) | ||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package answer | ||
|
||
import ( | ||
"github.com/gin-contrib/sessions" | ||
"github.com/gin-gonic/gin" | ||
"github.com/google/uuid" | ||
"l1nk4i/db" | ||
"net/http" | ||
) | ||
|
||
func Create(c *gin.Context) { | ||
questionID := c.Param("question-id") | ||
|
||
var answerInfo struct { | ||
Content string `json:"content"` | ||
} | ||
|
||
if err := c.ShouldBind(&answerInfo); err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON"}) | ||
return | ||
} | ||
|
||
session := sessions.Default(c) | ||
userID, exists := session.Get("user_id").(string) | ||
if !exists { | ||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"}) | ||
return | ||
} | ||
|
||
// Verify that the question exists | ||
_, err := db.GetQuestionByQuestionID(questionID) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid question_id"}) | ||
return | ||
} | ||
|
||
answer := db.Answer{ | ||
AnswerID: uuid.New().String(), | ||
UserID: userID, | ||
QuestionID: questionID, | ||
Content: answerInfo.Content, | ||
} | ||
if err := db.CreateAnswer(&answer); err != nil { | ||
c.JSON(http.StatusInternalServerError, gin.H{"error": "create answer error"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, gin.H{"answer_id": answer.AnswerID}) | ||
return | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package answer | ||
|
||
import ( | ||
"github.com/gin-contrib/sessions" | ||
"github.com/gin-gonic/gin" | ||
"l1nk4i/db" | ||
"net/http" | ||
) | ||
|
||
func Delete(c *gin.Context) { | ||
answerID := c.Param("answer-id") | ||
|
||
// Verify user identity | ||
session := sessions.Default(c) | ||
userid, exists := session.Get("user_id").(string) | ||
if !exists { | ||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"}) | ||
return | ||
} | ||
|
||
answer, err := db.GetAnswerByAnswerID(answerID) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid answer_id"}) | ||
return | ||
} | ||
|
||
if answer.UserID != userid { | ||
c.JSON(http.StatusForbidden, gin.H{"error": "permission denied"}) | ||
return | ||
} | ||
|
||
// Delete answer | ||
err = db.DeleteAnswer(answerID) | ||
if err != nil { | ||
c.JSON(http.StatusInternalServerError, gin.H{"error": "delete answer error"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, gin.H{"msg": "delete answer successful!"}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package answer | ||
|
||
import ( | ||
"github.com/gin-gonic/gin" | ||
"l1nk4i/db" | ||
"net/http" | ||
) | ||
|
||
// Get gets answers to the question by question_id | ||
func Get(c *gin.Context) { | ||
questionID := c.Param("question-id") | ||
|
||
answers, err := db.GetAnswersByQuestionID(questionID) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid question_id"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, gin.H{"data": answers}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package answer | ||
|
||
import ( | ||
"github.com/gin-contrib/sessions" | ||
"github.com/gin-gonic/gin" | ||
"l1nk4i/db" | ||
"net/http" | ||
) | ||
|
||
func Update(c *gin.Context) { | ||
answerID := c.Param("answer-id") | ||
|
||
var answerInfo struct { | ||
Content string `json:"content"` | ||
} | ||
|
||
if err := c.ShouldBindJSON(&answerInfo); err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON"}) | ||
return | ||
} | ||
|
||
// Verify user identity | ||
session := sessions.Default(c) | ||
userid, exists := session.Get("user_id").(string) | ||
if !exists { | ||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"}) | ||
return | ||
} | ||
Comment on lines
+22
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance session handling and error messaging. The current implementation correctly checks for user authentication, but there are a couple of improvements that can be made:
Consider applying the following changes:
if !exists {
- c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"})
+ c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated", "details": "Valid session required"})
return
}
const UserIDKey = "user_id" Then use it in the code: -userid, exists := session.Get("user_id").(string)
+userid, exists := session.Get(UserIDKey).(string) |
||
|
||
answer, err := db.GetAnswerByAnswerID(answerID) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid answer_id"}) | ||
return | ||
} | ||
|
||
if answer.UserID != userid { | ||
c.JSON(http.StatusForbidden, gin.H{"error": "permission denied"}) | ||
return | ||
} | ||
|
||
// Update answer | ||
err = db.UpdateAnswer(answerID, answerInfo.Content) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid answer"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, gin.H{"msg": "update answer successful!"}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package question | ||
|
||
import ( | ||
"github.com/gin-contrib/sessions" | ||
"github.com/gin-gonic/gin" | ||
"l1nk4i/db" | ||
"net/http" | ||
) | ||
|
||
func Best(c *gin.Context) { | ||
answerID := c.Param("answer-id") | ||
questionID := c.Param("question-id") | ||
|
||
// Verify user identity | ||
session := sessions.Default(c) | ||
userid, exists := session.Get("user_id").(string) | ||
if !exists { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid session"}) | ||
return | ||
} | ||
|
||
question, err := db.GetQuestionByQuestionID(questionID) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid question_id"}) | ||
return | ||
} | ||
|
||
if question.UserID != userid { | ||
c.JSON(http.StatusForbidden, gin.H{"error": "permission denied"}) | ||
return | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a check to ensure the answer belongs to the question. While the current implementation correctly verifies question ownership, it doesn't confirm if the provided answer actually belongs to the question. This could potentially allow setting an unrelated answer as the best answer. Consider adding an additional check: if question.UserID != userid {
c.JSON(http.StatusForbidden, gin.H{"error": "permission denied"})
return
}
+
+ // Check if the answer belongs to the question
+ if !db.IsAnswerBelongsToQuestion(questionID, answerID) {
+ c.JSON(http.StatusBadRequest, gin.H{"error": "answer does not belong to the question"})
+ return
+ } Note: You'll need to implement the
|
||
|
||
// Set the best answer | ||
err = db.UpdateBestAnswer(questionID, answerID) | ||
if err != nil { | ||
c.JSON(http.StatusInternalServerError, gin.H{"error": "update best answer failed"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, gin.H{"msg": "update best answer successful!"}) | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,42 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
package question | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"github.com/gin-contrib/sessions" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"github.com/gin-gonic/gin" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"github.com/google/uuid" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"l1nk4i/db" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"net/http" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
func Create(c *gin.Context) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
var questionInfo struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Title string `json:"title"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Content string `json:"content"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err := c.ShouldBind(&questionInfo); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON"}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
session := sessions.Default(c) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
userID, exists := session.Get("user_id").(string) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !exists { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+22
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding validation for the user ID. While the function correctly retrieves and checks for the existence of a user ID in the session, it doesn't validate the format or content of the user ID. Consider adding a validation step for the user ID: userID, exists := session.Get("user_id").(string)
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"})
return
}
+ if !isValidUserID(userID) {
+ c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid user ID"})
+ return
+ }
// Add this helper function
+func isValidUserID(id string) bool {
+ // Implement your validation logic here
+ // For example, check if it's a valid UUID
+ _, err := uuid.Parse(id)
+ return err == nil
+}
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
question := db.Question{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
QuestionID: uuid.New().String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
UserID: userID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Title: questionInfo.Title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Content: questionInfo.Content, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err := db.CreateQuestion(&question); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "create question error"}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+29
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation and improve error handling for question creation. While the function correctly creates a new question and interacts with the database, there are a few areas for improvement:
Consider implementing these improvements:
+ if len(questionInfo.Title) == 0 || len(questionInfo.Content) == 0 {
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Title and content cannot be empty"})
+ return
+ }
+ // Add more validation as needed (e.g., max length)
if err := db.CreateQuestion(&question); err != nil {
- c.JSON(http.StatusInternalServerError, gin.H{"error": "create question error"})
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create question: " + err.Error()})
return
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusOK, gin.H{"question_id": question.QuestionID}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+40
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using HTTP 201 Created status for successful question creation. While the current implementation returns a 200 OK status, it's more RESTful to use 201 Created when a new resource is successfully created. Consider modifying the response as follows: - c.JSON(http.StatusOK, gin.H{"question_id": question.QuestionID})
+ c.JSON(http.StatusCreated, gin.H{"question_id": question.QuestionID}) 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,63 @@ | ||||||||||||||||||||||||||||||||||||||
package question | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
import ( | ||||||||||||||||||||||||||||||||||||||
"github.com/gin-contrib/sessions" | ||||||||||||||||||||||||||||||||||||||
"github.com/gin-gonic/gin" | ||||||||||||||||||||||||||||||||||||||
"l1nk4i/db" | ||||||||||||||||||||||||||||||||||||||
"net/http" | ||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
func Delete(c *gin.Context) { | ||||||||||||||||||||||||||||||||||||||
questionID := c.Param("question-id") | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
// Verify user identity | ||||||||||||||||||||||||||||||||||||||
session := sessions.Default(c) | ||||||||||||||||||||||||||||||||||||||
userid, exists := session.Get("user_id").(string) | ||||||||||||||||||||||||||||||||||||||
if !exists { | ||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"}) | ||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
Comment on lines
+15
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the session The current code uses a type assertion to retrieve To correctly check for the existence of -userid, exists := session.Get("user_id").(string)
-if !exists {
+userIDInterface := session.Get("user_id")
+if userIDInterface == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"})
return
}
+userid, ok := userIDInterface.(string)
+if !ok {
+ c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid session"})
+ return
+} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
question, err := db.GetQuestionByQuestionID(questionID) | ||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid question_id"}) | ||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
if question.UserID != userid { | ||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusForbidden, gin.H{"error": "permission denied"}) | ||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
// Delete question | ||||||||||||||||||||||||||||||||||||||
err = db.DeleteQuestion(questionID) | ||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "delete question error"}) | ||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
// Delete answers to the question | ||||||||||||||||||||||||||||||||||||||
err = deleteAnswers(questionID) | ||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "delete answers error"}) | ||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
c.JSON(http.StatusOK, gin.H{"msg": "delete question successful!"}) | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
func deleteAnswers(questionID string) error { | ||||||||||||||||||||||||||||||||||||||
answers, err := db.GetAnswersByQuestionID(questionID) | ||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||
return err | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
for _, answer := range *answers { | ||||||||||||||||||||||||||||||||||||||
err = db.DeleteAnswer(answer.AnswerID) | ||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||
return err | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Handle errors during answer deletion more comprehensively Currently, if an error occurs while deleting an individual answer, the function returns immediately, potentially leaving some answers undeleted. This could lead to inconsistent data states. Consider modifying the function to attempt deletion of all answers, collecting any errors, and handling them after all deletions have been attempted. You can refactor the code as follows: func deleteAnswers(questionID string) error {
answers, err := db.GetAnswersByQuestionID(questionID)
if err != nil {
return err
}
- for _, answer := range *answers {
- err = db.DeleteAnswer(answer.AnswerID)
- if err != nil {
- return err
- }
+ var deleteErrors []error
+ for _, answer := range *answers {
+ if err := db.DeleteAnswer(answer.AnswerID); err != nil {
+ deleteErrors = append(deleteErrors, err)
+ }
}
- return nil
+ if len(deleteErrors) > 0 {
+ // Aggregate errors or handle accordingly
+ return fmt.Errorf("errors occurred during answer deletion: %v", deleteErrors)
+ }
+ return nil
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation for the answer ID.
While the deletion logic is correctly delegated to the
db
package, there's no validation of theanswerID
format before using it. This could lead to unnecessary database calls or potential security issues if the ID is malformed.Consider adding validation for the
answerID
. For example:Also applies to: 25-29