aboutsummaryrefslogtreecommitdiff
path: root/api/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'api/main.go')
-rw-r--r--api/main.go215
1 files changed, 121 insertions, 94 deletions
diff --git a/api/main.go b/api/main.go
index 57feb09..17a3c3a 100644
--- a/api/main.go
+++ b/api/main.go
@@ -1,18 +1,17 @@
1package main 1package main
2 2
3import ( 3import (
4 "net/http"
5 "crypto/rand" 4 "crypto/rand"
6 "encoding/base64"
7 "database/sql" 5 "database/sql"
8 "strings" 6 "encoding/base64"
9 "errors" 7 "errors"
10 "log" 8 "log"
9 "net/http"
10 "strings"
11 11
12 "github.com/gin-gonic/gin" 12 "github.com/gin-gonic/gin"
13 _ "github.com/mattn/go-sqlite3" 13 _ "github.com/mattn/go-sqlite3"
14 "golang.org/x/crypto/bcrypt" 14 "golang.org/x/crypto/bcrypt"
15 "water/api/lib"
16) 15)
17 16
18func CORSMiddleware() gin.HandlerFunc { 17func CORSMiddleware() gin.HandlerFunc {
@@ -22,15 +21,12 @@ func CORSMiddleware() gin.HandlerFunc {
22 c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 21 c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
23 c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT") 22 c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
24 23
25 log.Println("I am here")
26
27 if c.Request.Method == "OPTIONS" { 24 if c.Request.Method == "OPTIONS" {
28 log.Println(c.Request.Header) 25 log.Println(c.Request.Header)
29 c.AbortWithStatus(204) 26 c.AbortWithStatus(http.StatusNoContent)
30 return 27 return
31 } 28 }
32 29
33 log.Println(c.Request.Header)
34 c.Next() 30 c.Next()
35 } 31 }
36} 32}
@@ -38,7 +34,10 @@ func CORSMiddleware() gin.HandlerFunc {
38// generatToken will g 34// generatToken will g
39func generateToken() string { 35func generateToken() string {
40 token := make([]byte, 32) 36 token := make([]byte, 32)
41 rand.Read(token) 37 _, err := rand.Read(token)
38 if err != nil {
39 return ""
40 }
42 return base64.StdEncoding.EncodeToString(token) 41 return base64.StdEncoding.EncodeToString(token)
43} 42}
44 43
@@ -53,13 +52,13 @@ func establishDBConnection() *sql.DB {
53func checkForTokenInContext(c *gin.Context) (string, error) { 52func checkForTokenInContext(c *gin.Context) (string, error) {
54 authorizationHeader := c.GetHeader("Authorization") 53 authorizationHeader := c.GetHeader("Authorization")
55 if authorizationHeader == "" { 54 if authorizationHeader == "" {
56 return "", errors.New("Authorization header is missing") 55 return "", errors.New("authorization header is missing")
57 } 56 }
58 57
59 parts := strings.Split(authorizationHeader, " ") 58 parts := strings.Split(authorizationHeader, " ")
60 59
61 if len(parts) != 2 || parts[0] != "Bearer" { 60 if len(parts) != 2 || parts[0] != "Bearer" {
62 return "", errors.New("Invalid Authorization header format") 61 return "", errors.New("invalid Authorization header format")
63 } 62 }
64 63
65 return parts[1], nil 64 return parts[1], nil
@@ -98,15 +97,21 @@ func setupRouter() *gin.Engine {
98 } 97 }
99 98
100 db := establishDBConnection() 99 db := establishDBConnection()
101 defer db.Close() 100 defer func(db *sql.DB) {
101 err := db.Close()
102 if err != nil {
103 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
104 return
105 }
106 }(db)
102 107
103 var user models.User 108 var user User
104 var preference models.Preference 109 var preference Preference
105 var size models.Size 110 var size Size
106 111
107 row := db.QueryRow("SELECT name, uuid, password, color, size, unit FROM Users u INNER JOIN Preferences p ON p.user_id = u.id INNER JOIN Sizes s ON p.size_id = s.id WHERE u.name = ?", username) 112 row := db.QueryRow("SELECT name, uuid, password, color, size, unit FROM Users u INNER JOIN Preferences p ON p.user_id = u.id INNER JOIN Sizes s ON p.size_id = s.id WHERE u.name = ?", username)
108 if err := row.Scan(&user.Name, &user.UUID, &user.Password, &preference.Color, &size.Size, &size.Unit); err != nil { 113 if err := row.Scan(&user.Name, &user.UUID, &user.Password, &preference.Color, &size.Size, &size.Unit); err != nil {
109 if err == sql.ErrNoRows { 114 if errors.Is(err, sql.ErrNoRows) {
110 c.AbortWithStatus(http.StatusUnauthorized) 115 c.AbortWithStatus(http.StatusUnauthorized)
111 return 116 return
112 } 117 }
@@ -129,128 +134,147 @@ func setupRouter() *gin.Engine {
129 { 134 {
130 stats.GET("/", func(c *gin.Context) { 135 stats.GET("/", func(c *gin.Context) {
131 db := establishDBConnection() 136 db := establishDBConnection()
132 defer db.Close() 137 defer func(db *sql.DB) {
138 err := db.Close()
139 if err != nil {
140 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
141 return
142 }
143 }(db)
133 144
134 rows, err := db.Query("SELECT s.date, s.quantity, u.uuid, u.name FROM Statistics s INNER JOIN Users u ON u.id = s.user_id") 145 rows, err := db.Query("SELECT s.date, s.quantity, u.uuid, u.name FROM Statistics s INNER JOIN Users u ON u.id = s.user_id")
135 if err != nil { 146 if err != nil {
136 c.JSON(500, gin.H{"error": err.Error()}) 147 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
137 return 148 return
138 } 149 }
139 defer rows.Close() 150 defer func(rows *sql.Rows) {
151 err := rows.Close()
152 if err != nil {
153 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
154 return
155 }
156 }(rows)
140 157
141 var data []models.Statistic 158 var data []Statistic
142 159
143 for rows.Next() { 160 for rows.Next() {
144 var stat models.Statistic 161 var stat Statistic
145 var user models.User 162 var user User
146 if err := rows.Scan(&stat.Date, &stat.Quantity, &user.UUID, &user.Name); err != nil { 163 if err := rows.Scan(&stat.Date, &stat.Quantity, &user.UUID, &user.Name); err != nil {
147 c.JSON(500, gin.H{"error": err.Error()}) 164 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
148 return 165 return
149 } 166 }
150 stat.User = user 167 stat.User = user
151 data = append(data, stat) 168 data = append(data, stat)
152 } 169 }
153 170
171 c.JSON(http.StatusOK, data)
172 })
154 173
155 // TODO: return to this and figure out how to best collect the data you are looking for for each user (zach and parker) 174 stats.POST("/", func(c *gin.Context) {
156 rows, err = db.Query("SELECT date(s.date), SUM(s.quantity) as total FROM Statistics s WHERE s.date >= date('now', '-7 days') GROUP BY DATE(s.date)") 175 var stat StatisticPost
157 if err != nil { 176
158 c.JSON(500, gin.H{"error": err.Error()}) 177 if err := c.BindJSON(&stat); err != nil {
178 c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
159 return 179 return
160 } 180 }
161 defer rows.Close()
162 181
163 var dailySummaries []models.DailySummary 182 db := establishDBConnection()
164 for rows.Next() { 183 defer func(db *sql.DB) {
165 var summary models.DailySummary 184 err := db.Close()
166 if err := rows.Scan(&summary.Date, &summary.Total); err != nil { 185 if err != nil {
167 c.JSON(500, gin.H{"error": err.Error()}) 186 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
168 return 187 return
169 } 188 }
170 dailySummaries = append(dailySummaries, summary) 189 }(db)
171 }
172 190
173 c.JSON(http.StatusOK, gin.H{"stats": data, "totals": dailySummaries}) 191 result, err := db.Exec("INSERT INTO statistics (date, user_id, quantity) values (?, ?, ?)", stat.Date, stat.UserID, stat.Quantity)
174 rows, err = db.Query("SELECT s.date, SUM(s.quantity) as total, u.uuid, u.name FROM Statistics s INNER JOIN Users u ON u.id = s.user_id WHERE s.date >= date('now', '-7 days') GROUP BY s.date, s.user_id")
175 192
176 if err != nil { 193 if err != nil {
177 c.JSON(500, gin.H{"error": err.Error()}) 194 c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
178 return
179 } 195 }
180 defer rows.Close()
181 196
182 var totals []interface{} 197 id, err := result.LastInsertId()
183 for rows.Next() { 198 if err != nil {
184 var stat models.Statistic 199 c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
185 var user models.User
186 if err := rows.Scan(&stat.Date, &stat.Quantity, &user.UUID, &user.Name); err != nil {
187 c.JSON(500, gin.H{"error": err.Error()})
188 return
189 }
190 stat.User = user
191 totals = append(totals, stat)
192 } 200 }
193 201
194 c.JSON(http.StatusOK, gin.H{"stats": data, "totals": totals}) 202 c.JSON(http.StatusCreated, gin.H{"status": "created", "id": id})
195 }) 203 })
196 204
197 stats.POST("/", func(c *gin.Context) { 205 stats.GET("weekly/", func(c *gin.Context) {
198 var stat models.Statistic 206 db := establishDBConnection()
207 defer func(db *sql.DB) {
208 err := db.Close()
209 if err != nil {
210 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
211 return
212 }
213 }(db)
199 214
200 if err := c.BindJSON(&stat); err != nil { 215 rows, err := db.Query("SELECT date, total FROM `WeeklyStatisticsView`")
201 c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 216 if err != nil {
217 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
202 return 218 return
203 } 219 }
220 defer func(rows *sql.Rows) {
221 err := rows.Close()
222 if err != nil {
223 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
224 return
225 }
226 }(rows)
227
228 var data []WeeklyStatistic
229 for rows.Next() {
230 var weeklyStat WeeklyStatistic
231 if err := rows.Scan(&weeklyStat.Date, &weeklyStat.Total); err != nil {
232 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
233 }
234 data = append(data, weeklyStat)
235 }
236
237 c.JSON(http.StatusOK, data)
238 })
204 239
240 stats.GET("totals/", func(c *gin.Context) {
205 db := establishDBConnection() 241 db := establishDBConnection()
206 defer db.Close() 242 defer func(db *sql.DB) {
243 err := db.Close()
244 if err != nil {
245 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
246 return
247 }
248 }(db)
207 249
208 result, err := db.Exec("INSERT INTO statistics (date, user_id, quantity) values (?, ?, ?)", stat.Date, 1, stat.Quantity) 250 rows, err := db.Query("SELECT name, total FROM DailyUserStatistics")
209 251
210 if err != nil { 252 if err != nil {
211 c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 253 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
254 return
212 } 255 }
256 defer func(rows *sql.Rows) {
257 err := rows.Close()
258 if err != nil {
259 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
260 return
261 }
262 }(rows)
213 263
214 id, err := result.LastInsertId() 264 var data []DailyUserTotals
215 if err != nil { 265 for rows.Next() {
216 c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 266 var stat DailyUserTotals
267 if err := rows.Scan(&stat.Name, &stat.Total); err != nil {
268 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
269 return
270 }
271 data = append(data, stat)
217 } 272 }
218 273
219 c.JSON(http.StatusCreated, gin.H{"status": "created", "id": id}) 274 c.JSON(http.StatusOK, data)
220 })
221 275
222 stats.GET("/totals/", func(c *gin.Context) {
223 c.JSON(http.StatusOK, gin.H{"status": "ok"})
224 }) 276 })
225 277
226 // stats.GET("/totals/", func(c *gin.Context) {
227 // db := establishDBConnection()
228 // defer db.Close()
229 //
230 // rows, err := db.Query("SELECT s.date, SUM(s.quantity) as total, u.uuid, u.name FROM Statistics s INNER JOIN Users u ON u.id = s.user_id WHERE s.date >= date('now', '-7 days') GROUP BY s.date, s.user_id")
231 //
232 // if err != nil {
233 // c.JSON(500, gin.H{"error": err.Error()})
234 // return
235 // }
236 // defer rows.Close()
237 //
238 // var data []models.Statistic
239 // for rows.Next() {
240 // var stat models.Statistic
241 // var user models.User
242 // if err := rows.Scan(&stat.Date, &stat.Quantity, &user.UUID, &user.Name); err != nil {
243 // c.JSON(500, gin.H{"error": err.Error()})
244 // return
245 // }
246 // stat.User = user
247 // data = append(data, stat)
248 // }
249 //
250 // c.JSON(http.StatusOK, data)
251 //
252 // })
253
254 stats.GET("user/:uuid", func(c *gin.Context) { 278 stats.GET("user/:uuid", func(c *gin.Context) {
255 c.JSON(http.StatusOK, gin.H{"status": "ok", "uuid": c.Param("uuid")}) 279 c.JSON(http.StatusOK, gin.H{"status": "ok", "uuid": c.Param("uuid")})
256 }) 280 })
@@ -270,5 +294,8 @@ func setupRouter() *gin.Engine {
270func main() { 294func main() {
271 r := setupRouter() 295 r := setupRouter()
272 // Listen and Server in 0.0.0.0:8080 296 // Listen and Server in 0.0.0.0:8080
273 r.Run(":8080") 297 err := r.Run(":8080")
298 if err != nil {
299 return
300 }
274} 301}