diff --git a/main.go b/main.go index b964889..c3bbdf1 100644 --- a/main.go +++ b/main.go @@ -23,6 +23,9 @@ func main() { router.POST("/auth/login", routes.Login) router.POST("/auth/register", routes.Register) + router.GET("/recipes", routes.GetUserRecipes) + // router.POST("/recipes", routes.CreateRecipe) + // Start server router.Run(":8080") } diff --git a/models/ingredient.go b/models/ingredient.go new file mode 100644 index 0000000..ae4bc55 --- /dev/null +++ b/models/ingredient.go @@ -0,0 +1,7 @@ +package models + +type Ingredient struct { + Name string `json:"name"` + Unit string `json:"unit"` + Quantity float64 `json:"quantity"` +} diff --git a/models/recipe.go b/models/recipe.go new file mode 100644 index 0000000..05b7998 --- /dev/null +++ b/models/recipe.go @@ -0,0 +1,85 @@ +package models + +import ( + "database/sql" + "encoding/json" + "strings" + + "github.com/google/uuid" +) + +type Recipe struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Ingredients []Ingredient `json:"ingredients"` +} + +func CreateRecipe(db *sql.DB, name string, description string, ingredients []Ingredient) (Recipe, error) { + recipe := Recipe{ + ID: uuid.New(), + Name: name, + Description: description, + Ingredients: ingredients, + } + + jsonIngredients, err := json.Marshal(recipe.Ingredients) + if err != nil { + return Recipe{}, err + } + + _, err = db.Exec("INSERT INTO recipes (id, name, description, ingredients) VALUES (?, ?, ?, ?)", + recipe.ID, recipe.Name, recipe.Description, jsonIngredients) + if err != nil { + return Recipe{}, err + } + + return recipe, nil +} + +func GetUserRecipes(db *sql.DB, token string) ([]Recipe, error) { + user, err := GetUser(db, uuid.MustParse(token)) + if err != nil { + return nil, err + } + + var recipeIds []string + + rows, err := db.Query("SELECT rid FROM user_recipe WHERE uid = ?", user.ID) + if err != nil { + return nil, err + } + + defer rows.Close() + + for rows.Next() { + var recipeId string + if err := rows.Scan(&recipeId); err != nil { + return nil, err + } + recipeIds = append(recipeIds, recipeId) + } + + rows, err = db.Query("SELECT id, name, description, ingredients FROM recipes WHERE id IN (" + strings.Join(recipeIds, ",") + ")") + if err != nil { + return nil, err + } + + defer rows.Close() + + var recipes []Recipe + for rows.Next() { + var recipe Recipe + var jsonIngredients string + if err := rows.Scan(&recipe.ID, &recipe.Name, &recipe.Description, &jsonIngredients); err != nil { + return nil, err + } + err := json.Unmarshal(([]byte)(jsonIngredients), &recipe.Ingredients) + if err != nil { + return nil, err + } + recipes = append(recipes, recipe) + } + + return recipes, nil +} diff --git a/models/user.go b/models/user.go index 548d21d..6fba848 100644 --- a/models/user.go +++ b/models/user.go @@ -21,12 +21,11 @@ type User struct { func LoginUser(db *sql.DB, email string, password string) (User, error) { var user User - var hashedPassword string var createdAt, updatedAt, tokenExpiration sql.NullTime var id, token sql.NullString err := db.QueryRow("SELECT id, email, username, password, created_at, updated_at, token, token_expiration FROM users WHERE email = ? AND password = ?", email, password). - Scan(&id, &user.Email, &user.Username, &hashedPassword, &createdAt, &updatedAt, &token, &tokenExpiration) + Scan(&id, &user.Email, &user.Username, &user.Password, &createdAt, &updatedAt, &token, &tokenExpiration) if err != nil { if err == sql.ErrNoRows { @@ -74,3 +73,38 @@ func RegisterUser(db *sql.DB, email string, username string, password string) (U return user, nil } + +func GetUser(db *sql.DB, token uuid.UUID) (User, error) { + var user User + var createdAt, updatedAt, tokenExpiration sql.NullTime + var id, tokenString sql.NullString + + err := db.QueryRow("SELECT id, email, username, created_at, updated_at, token, token_expiration FROM users WHERE token = ?", token). + Scan(&id, &user.Email, &user.Username, &createdAt, &updatedAt, &tokenString, &tokenExpiration) + + if err != nil { + if err == sql.ErrNoRows { + return User{}, errors.New("user not found") + } + return User{}, err + } + + // Parse UUID and time fields + if id.Valid { + user.ID, _ = uuid.Parse(id.String) + } + if createdAt.Valid { + user.CreatedAt = createdAt.Time + } + if updatedAt.Valid { + user.UpdatedAt = updatedAt.Time + } + if tokenString.Valid { + user.Token, _ = uuid.Parse(tokenString.String) + } + if tokenExpiration.Valid { + user.TokenExpiration = tokenExpiration.Time + } + + return user, nil +} diff --git a/routes/middleware.go b/routes/middleware.go index 7184af0..728e57d 100644 --- a/routes/middleware.go +++ b/routes/middleware.go @@ -21,11 +21,13 @@ func DBMiddleware(c *gin.Context) { func AuthMiddleware(c *gin.Context) { apiToken := os.Getenv("API_KEY") - token := c.GetHeader("Authorization") - if token != apiToken { + authToken := c.GetHeader("Authorization") + if authToken != apiToken { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) c.Abort() return } + token := c.GetHeader("Token") + c.Set("token", token) c.Next() } diff --git a/routes/recipe.go b/routes/recipe.go new file mode 100644 index 0000000..91e194c --- /dev/null +++ b/routes/recipe.go @@ -0,0 +1,43 @@ +package routes + +import ( + "CookingApp/models" + "database/sql" + "net/http" + + "github.com/gin-gonic/gin" +) + +type createRecipeBody struct { + Name string `json:"name"` + Description string `json:"description"` + Ingredients []models.Ingredient `json:"ingredients"` +} + +func CreateRecipe(c *gin.Context) { + db := c.MustGet("db").(*sql.DB) + + var body createRecipeBody + if err := c.BindJSON(&body); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + } + + recipe, err := models.CreateRecipe(db, body.Name, body.Description, body.Ingredients) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusCreated, recipe) +} + +func GetUserRecipes(c *gin.Context) { + db := c.MustGet("db").(*sql.DB) + token := c.MustGet("token").(string) + recipes, err := models.GetUserRecipes(db, token) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, recipes) +}