-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandler.go
159 lines (131 loc) · 4.49 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package main
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/golang-jwt/jwt/v4"
"github.com/labstack/echo/v4"
)
type Article struct {
ID int `json:"id"`
Title string `json:"title"`
}
const connStr = "user=user password=password dbname=articles_db host=localhost port=5432 sslmode=disable"
// Fetch all articles from the database
func getArticlesFromDB() ([]Article, error) {
db, err := sql.Open("postgres", connStr)
if err != nil {
return nil, err
}
defer db.Close()
rows, err := db.Query("SELECT id, title FROM articles")
if err != nil {
return nil, err
}
defer rows.Close()
var articles []Article
for rows.Next() {
var article Article
err := rows.Scan(&article.ID, &article.Title)
if err != nil {
return nil, err
}
articles = append(articles, article)
}
if err := rows.Err(); err != nil {
return nil, err
}
return articles, nil
}
func FindArticleByID(articleID string) (*Article, error) {
// Call queryArticleFromDB to fetch the article
article, err := queryArticleFromDB(articleID)
if err != nil {
return nil, err // Return the error if query fails
}
// Return the pointer to the article
return &article, nil
}
func DeleteArticleHandler(c echo.Context) error {
userToken := c.Get("user").(*jwt.Token)
// Extract the custom claims from the token
claims := userToken.Claims.(*jwtCustomClaims)
// Log the user performing the action
fmt.Printf("User %s is updating an article\n", claims.Name)
// Parse the article ID from the request parameter
id := c.Param("id")
// Check if the article exists in the database
article, err := FindArticleByID(id)
if err != nil {
return c.JSON(http.StatusNotFound, map[string]string{"error": fmt.Sprintf("Article with ID %s not found", id)})
}
// Connect to the database
db, err := sql.Open("postgres", connStr)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to connect to the database"})
}
defer db.Close()
// Delete the article from the database
_, err = db.Exec("DELETE FROM articles WHERE id = $1", article.ID)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to delete article with ID %s", id)})
}
// Delete the article from Redis cache
redisKey := fmt.Sprintf("article:%s", id)
err = rdb.Del(ctx, redisKey).Err()
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to delete article from Redis cache with ID %s", id)})
}
// Return success response
return c.JSON(http.StatusOK, map[string]string{"message": fmt.Sprintf("Article with ID %s successfully deleted", id)})
}
// UpdateArticleHandler
func UpdateArticleHandler(c echo.Context) error {
// Retrieve the token from the request context
userToken := c.Get("user").(*jwt.Token)
// Extract the custom claims from the token
claims := userToken.Claims.(*jwtCustomClaims)
// Log the user performing the action
fmt.Printf("User %s is updating an article\n", claims.Name)
// Parse the article ID from the request parameter
id := c.Param("id")
// Check if the article exists in the database
article, err := FindArticleByID(id)
if err != nil {
return c.JSON(http.StatusNotFound, map[string]string{"error": "Article not found"})
}
// Parse the JSON input to get the updated title
var updatedArticle struct {
Title string `json:"title"`
}
if err := c.Bind(&updatedArticle); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid JSON input"})
}
// Connect to the database
db, err := sql.Open("postgres", connStr)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Database connection error"})
}
defer db.Close()
// Update the article title in the database
_, err = db.Exec("UPDATE articles SET title = $1 WHERE id = $2", updatedArticle.Title, article.ID)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Error updating article"})
}
// Update the article title in Redis cache
article.Title = updatedArticle.Title
cacheData, err := json.Marshal(article)
if err == nil { // Don't fail the update if Redis serialization fails
redisKey := fmt.Sprintf("article:%s", id)
err = rdb.Set(ctx, redisKey, cacheData, 5*time.Minute).Err()
if err != nil {
fmt.Printf("Failed to update article in Redis: %v\n", err)
} else {
fmt.Printf("Updated article %s in Redis cache.\n", id)
}
}
// Return the updated article
return c.JSON(http.StatusOK, article)
}