diff options
Diffstat (limited to 'api/main.go')
-rw-r--r-- | api/main.go | 127 |
1 files changed, 108 insertions, 19 deletions
diff --git a/api/main.go b/api/main.go index ebae5d1..292a5f9 100644 --- a/api/main.go +++ b/api/main.go | |||
@@ -4,8 +4,13 @@ import ( | |||
4 | "net/http" | 4 | "net/http" |
5 | "crypto/rand" | 5 | "crypto/rand" |
6 | "encoding/base64" | 6 | "encoding/base64" |
7 | "database/sql" | ||
8 | "strings" | ||
9 | "errors" | ||
7 | 10 | ||
8 | "github.com/gin-gonic/gin" | 11 | "github.com/gin-gonic/gin" |
12 | _ "github.com/mattn/go-sqlite3" | ||
13 | "water/api/lib" | ||
9 | ) | 14 | ) |
10 | 15 | ||
11 | func CORSMiddleware() gin.HandlerFunc { | 16 | func CORSMiddleware() gin.HandlerFunc { |
@@ -30,6 +35,44 @@ func generateToken() string { | |||
30 | return base64.StdEncoding.EncodeToString(token) | 35 | return base64.StdEncoding.EncodeToString(token) |
31 | } | 36 | } |
32 | 37 | ||
38 | func establishDBConnection() *sql.DB { | ||
39 | db, err := sql.Open("sqlite3", "../db/water.sqlite3") | ||
40 | if err != nil { | ||
41 | panic(err) | ||
42 | } | ||
43 | return db | ||
44 | } | ||
45 | |||
46 | func checkForTokenInContext(c *gin.Context) (string, error) { | ||
47 | authorizationHeader := c.GetHeader("Authorization") | ||
48 | if authorizationHeader == "" { | ||
49 | return "", errors.New("Authorization header is missing") | ||
50 | } | ||
51 | |||
52 | parts := strings.Split(authorizationHeader, " ") | ||
53 | |||
54 | if len(parts) != 2 || parts[0] != "Bearer" { | ||
55 | return "", errors.New("Invalid Authorization header format") | ||
56 | } | ||
57 | |||
58 | return parts[1], nil | ||
59 | } | ||
60 | |||
61 | |||
62 | func TokenRequired() gin.HandlerFunc { | ||
63 | return func(c *gin.Context) { | ||
64 | _, err := checkForTokenInContext(c) | ||
65 | |||
66 | if err != nil { | ||
67 | c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) | ||
68 | c.Abort() | ||
69 | return | ||
70 | } | ||
71 | |||
72 | c.Next() | ||
73 | } | ||
74 | } | ||
75 | |||
33 | type User struct { | 76 | type User struct { |
34 | Username string | 77 | Username string |
35 | Password string | 78 | Password string |
@@ -44,6 +87,8 @@ func setupRouter() *gin.Engine { | |||
44 | // gin.DisableConsoleColor() | 87 | // gin.DisableConsoleColor() |
45 | r := gin.Default() | 88 | r := gin.Default() |
46 | r.Use(CORSMiddleware()) | 89 | r.Use(CORSMiddleware()) |
90 | r.Use(gin.Logger()) | ||
91 | r.Use(gin.Recovery()) | ||
47 | 92 | ||
48 | api := r.Group("api/v1") | 93 | api := r.Group("api/v1") |
49 | 94 | ||
@@ -68,26 +113,70 @@ func setupRouter() *gin.Engine { | |||
68 | }) | 113 | }) |
69 | 114 | ||
70 | stats := api.Group("stats") | 115 | stats := api.Group("stats") |
116 | stats.Use(TokenRequired()) | ||
117 | { | ||
118 | stats.GET("/", func(c *gin.Context) { | ||
119 | db := establishDBConnection() | ||
120 | defer db.Close() | ||
121 | |||
122 | rows, err := db.Query("SELECT * FROM statistics"); | ||
123 | if err != nil { | ||
124 | c.JSON(500, gin.H{"error": err.Error()}) | ||
125 | return | ||
126 | } | ||
127 | defer rows.Close() | ||
128 | |||
129 | var data []models.Statistic | ||
130 | for rows.Next() { | ||
131 | var stat models.Statistic | ||
132 | if err := rows.Scan(&stat.ID, &stat.Date, &stat.UserID, &stat.Quantity); err != nil { | ||
133 | c.JSON(500, gin.H{"error": err.Error()}) | ||
134 | return | ||
135 | } | ||
136 | data = append(data, stat) | ||
137 | } | ||
138 | |||
139 | c.JSON(http.StatusOK, data) | ||
140 | }) | ||
141 | |||
142 | stats.POST("/", func(c *gin.Context) { | ||
143 | var stat models.Statistic | ||
144 | |||
145 | if err := c.BindJSON(&stat); err != nil { | ||
146 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||
147 | return | ||
148 | } | ||
149 | |||
150 | db := establishDBConnection() | ||
151 | defer db.Close() | ||
152 | |||
153 | result, err := db.Exec("INSERT INTO statistics (date, user_id, quantity) values (?, ?, ?)", stat.Date, stat.UserID, stat.Quantity) | ||
154 | |||
155 | if err != nil { | ||
156 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||
157 | } | ||
158 | |||
159 | id, err := result.LastInsertId() | ||
160 | if err != nil { | ||
161 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||
162 | } | ||
163 | |||
164 | c.JSON(http.StatusCreated, gin.H{"status": "created", "id": id}) | ||
165 | }) | ||
166 | |||
167 | stats.GET("/:uuid", func(c *gin.Context) { | ||
168 | c.JSON(http.StatusOK, gin.H{"status": "ok", "uuid": c.Param("uuid")}) | ||
169 | }) | ||
170 | |||
171 | stats.PATCH("/:uuid", func(c *gin.Context) { | ||
172 | c.JSON(http.StatusNoContent, gin.H{"status": "No Content"}) | ||
173 | }) | ||
174 | |||
175 | stats.DELETE("/:uuid", func(c *gin.Context) { | ||
176 | c.JSON(http.StatusNoContent, gin.H{"status": "No Content"}) | ||
177 | }) | ||
178 | } | ||
71 | 179 | ||
72 | stats.GET("/", func(c *gin.Context) { | ||
73 | c.JSON(http.StatusOK, gin.H{"status": "ok"}) | ||
74 | }) | ||
75 | |||
76 | stats.POST("/", func(c *gin.Context) { | ||
77 | c.JSON(http.StatusCreated, gin.H{"status": "created"}) | ||
78 | }) | ||
79 | |||
80 | stats.GET("/:uuid", func(c *gin.Context) { | ||
81 | c.JSON(http.StatusOK, gin.H{"status": "ok", "uuid": c.Param("uuid")}) | ||
82 | }) | ||
83 | |||
84 | stats.PATCH("/:uuid", func(c *gin.Context) { | ||
85 | c.JSON(http.StatusNoContent, gin.H{"status": "No Content"}) | ||
86 | }) | ||
87 | |||
88 | stats.DELETE("/:uuid", func(c *gin.Context) { | ||
89 | c.JSON(http.StatusNoContent, gin.H{"status": "No Content"}) | ||
90 | }) | ||
91 | 180 | ||
92 | return r | 181 | return r |
93 | } | 182 | } |