#8 add view and api to track activities

This commit is contained in:
Tim
2024-07-27 21:10:31 +02:00
parent 75f5ff2856
commit 8e4ef0c27a
12 changed files with 625 additions and 54 deletions

View File

@@ -3,22 +3,15 @@ package main
import (
"api/context"
"api/middleware"
"api/utils"
"api/workout"
"database/sql"
"log"
"net/http"
"firebase.google.com/go/auth"
_ "github.com/mattn/go-sqlite3"
)
type Person struct {
ID int
Name string
}
type Context context.Context
func main() {
context.InitializeDB()
@@ -29,16 +22,11 @@ func main() {
}
defer db.Close()
var context = Context{
DB: db,
}
var router = http.NewServeMux()
router.HandleFunc("GET /", context.HelloWorld)
var router = getRouter(db)
var server = http.Server{
Addr: ":8080",
Handler: middleware.Logging(middleware.EnsureAuth(router)),
Handler: middleware.Logging(middleware.EnableCors(middleware.EnsureAuth(router))),
}
log.Println("Starting server at", server.Addr)
@@ -48,28 +36,9 @@ func main() {
}
}
func (ctx *Context) HelloWorld(w http.ResponseWriter, r *http.Request) {
token := r.Context().Value(middleware.TOKEN_KEY).(*auth.Token)
log.Println(token.UID)
sqlStmt := `select COUNT(*) from person;`
result, err := ctx.DB.Query(sqlStmt)
if err != nil {
log.Fatal(err)
}
var count int
if result.Next() {
if result.Scan(&count) != nil {
log.Fatal(err)
}
} else {
log.Fatal("No rows found")
}
err = utils.WriteJSON(w, count)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
func getRouter(db *sql.DB) *http.ServeMux {
var router = http.NewServeMux()
router.HandleFunc("POST /workout", workout.NewWorkout(db))
router.HandleFunc("GET /workout", workout.GetWorkouts(db))
return router
}

View File

@@ -13,6 +13,11 @@ const TOKEN_KEY ContextKey = "token"
func EnsureAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tokenStr := r.Header.Get("Authorization")
if (tokenStr == "") || (len(tokenStr) < len("Bearer ")) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
tokenStr = tokenStr[len("Bearer "):]
token, err := utils.VerifyToken(tokenStr)

20
api/middleware/cors.go Normal file
View File

@@ -0,0 +1,20 @@
package middleware
import (
"net/http"
)
func EnableCors(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Authorization")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}

View File

@@ -1,5 +1,8 @@
create table person (id integer not null primary key, name text);
insert into person (id, name)
values (1, 'John');
CREATE TABLE workout (
user_id INTEGER NOT NULL,
date TEXT NOT NULL,
type TEXT NOT NULL,
sets INTEGER NOT NULL,
reps INTEGER NOT NULL
);

View File

@@ -1,4 +0,0 @@
insert into person (id, name)
values (2, 'John');

View File

@@ -1,4 +0,0 @@
insert into person (id, name)
values (3, 'Katja');

90
api/workout/workout.go Normal file
View File

@@ -0,0 +1,90 @@
package workout
import (
"api/middleware"
"api/utils"
"database/sql"
"net/http"
"strconv"
"time"
"firebase.google.com/go/auth"
)
func NewWorkout(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var dateStr = r.FormValue("date")
var typeStr = r.FormValue("type")
var setsStr = r.FormValue("sets")
var repsStr = r.FormValue("reps")
if dateStr == "" || typeStr == "" || setsStr == "" || repsStr == "" {
http.Error(w, "Missing required fields", http.StatusBadRequest)
return
}
date, err := time.Parse("2006-01-02", dateStr)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
sets, err := strconv.Atoi(setsStr)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
reps, err := strconv.Atoi(repsStr)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
token := r.Context().Value(middleware.TOKEN_KEY).(*auth.Token)
_, err = db.Exec("INSERT INTO workout (user_id, date, type, sets, reps) VALUES (?, ?, ?, ?, ?)", token.UID, date, typeStr, sets, reps)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}
func GetWorkouts(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Context().Value(middleware.TOKEN_KEY).(*auth.Token)
var userId = token.UID
rows, err := db.Query("SELECT date, type, sets, reps FROM workout WHERE user_id = ?", userId)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
var workouts = make([]map[string]interface{}, 0)
for rows.Next() {
var date string
var workoutType string
var sets int
var reps int
err = rows.Scan(&date, &workoutType, &sets, &reps)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
workout := map[string]interface{}{
"date": date,
"type": workoutType,
"sets": sets,
"reps": reps,
}
workouts = append(workouts, workout)
}
utils.WriteJSON(w, workouts)
}
}