diff --git a/backend/internal/handlers/profile/preferences.go b/backend/internal/handlers/profile/preferences.go index 2619ba5..1b0a2ff 100644 --- a/backend/internal/handlers/profile/preferences.go +++ b/backend/internal/handlers/profile/preferences.go @@ -1,9 +1,14 @@ package profile import ( + "log" + "net/http" + "github.com/GenerateNU/nightlife/internal/errs" "github.com/GenerateNU/nightlife/internal/models" "github.com/gofiber/fiber/v2" + + "github.com/google/uuid" ) // POST Endpoint -> allows users to add their preferences to the db @@ -25,3 +30,79 @@ func (s *Service) CreatePreferences(c *fiber.Ctx) error { return c.Status(fiber.StatusCreated).JSON(p) } + + +func (s *Service) UpdateProfilePrefences(c *fiber.Ctx) error { + + // Parse the request body + var req models.UpdateProfilePrefencesRequest + if err := c.BodyParser(&req); err != nil { // Declare a new instance of `err` in the scope of this if statement + log.Printf("Error parsing JSON: %v, Request: %+v", err, req) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Cannot parse JSON", + }) + } + + err := s.store.UpdateProfilePrefences(c.Context(), req.UserID, req.PreferenceTypeTo, req.PreferenceValueTo, req.PreferenceType, req.PreferenceValue) + if err != nil { + return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to update review", + }) + } + + return c.Status(http.StatusOK).JSON(fiber.Map{ + "message": "Review updated successfully", + }) + +} + +/* +Deletes a user account. +*/ +func (s *Service) DeleteUser(c *fiber.Ctx) error { + // Extract user ID from the URL parameter + userID := c.Params("userId") + if userID == "" { + return fiber.NewError(fiber.StatusBadRequest, "User ID is required") + } + + // Convert user ID to UUID + userUUID, err := uuid.Parse(userID) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid User ID format") + } + + // Call DeleteAccount function to delete the user from the database + err = s.store.DeleteAccount(c.Context(), userUUID) + if err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete user") + } + + // Return success response + return c.Status(http.StatusOK).JSON(fiber.Map{"message": "User deleted successfully"}) +} + +// RemoveFriend removes a friend from the authenticated user's friend list +func (s *Service) RemoveFriend(c *fiber.Ctx) error { + + // username of the friend to be removed + friendUsername := c.Params("username") + if friendUsername == "" { + return fiber.NewError(fiber.StatusBadRequest, "Friend's username is required") + } + + // Get the user's ID from the context (assuming it's set during authentication) + userID, ok := c.Locals("userId").(uuid.UUID) + if !ok { + return fiber.NewError(fiber.StatusUnauthorized, "User not authenticated") + } + + // call function to remove the friend by username + err := s.store.RemoveFriend(c.Context(), userID, friendUsername) + if err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Failed to remove friend") + } + + // Return success message + return c.Status(http.StatusOK).JSON(fiber.Map{"message": "Friend removed successfully"}) +} diff --git a/backend/internal/handlers/profile/routes.go b/backend/internal/handlers/profile/routes.go index 16ebc1e..1d15198 100644 --- a/backend/internal/handlers/profile/routes.go +++ b/backend/internal/handlers/profile/routes.go @@ -18,4 +18,7 @@ func Routes(app *fiber.App, params types.Params) { //Endpoints protected.Post("/preferences", service.CreatePreferences) + protected.Patch("/preferences", service.UpdateProfilePrefences) + protected.Delete("/:userId", service.DeleteUser) + protected.Delete("/friends/:username", service.RemoveFriend) } diff --git a/backend/internal/handlers/profiles/profiles.go b/backend/internal/handlers/profiles/profiles.go deleted file mode 100644 index 0c5a80f..0000000 --- a/backend/internal/handlers/profiles/profiles.go +++ /dev/null @@ -1,85 +0,0 @@ -package profiles - -import ( - "log" - "net/http" - - "github.com/GenerateNU/nightlife/internal/models" - "github.com/gofiber/fiber/v2" - "github.com/google/uuid" -) - -func (s *Service) UpdateProfilePrefences(c *fiber.Ctx) error { - - // Parse the request body - var req models.UpdateProfilePrefencesRequest - if err := c.BodyParser(&req); err != nil { // Declare a new instance of `err` in the scope of this if statement - log.Printf("Error parsing JSON: %v, Request: %+v", err, req) - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "error": "Cannot parse JSON", - }) - } - - err := s.store.UpdateProfilePrefences(c.Context(), req.UserID, req.PreferenceTypeTo, req.PreferenceValueTo, req.PreferenceType, req.PreferenceValue) - if err != nil { - return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ - "error": "Failed to update review", - }) - } - - return c.Status(http.StatusOK).JSON(fiber.Map{ - "message": "Review updated successfully", - }) - -} - -/* -Deletes a user account. -*/ -func (s *Service) DeleteUser(c *fiber.Ctx) error { - // Extract user ID from the URL parameter - userID := c.Params("userId") - if userID == "" { - return fiber.NewError(fiber.StatusBadRequest, "User ID is required") - } - - // Convert user ID to UUID - userUUID, err := uuid.Parse(userID) - if err != nil { - return fiber.NewError(fiber.StatusBadRequest, "Invalid User ID format") - } - - // Call DeleteAccount function to delete the user from the database - err = s.store.DeleteAccount(c.Context(), userUUID) - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete user") - } - - // Return success response - return c.Status(http.StatusOK).JSON(fiber.Map{"message": "User deleted successfully"}) -} - -// RemoveFriend removes a friend from the authenticated user's friend list -func (s *Service) RemoveFriend(c *fiber.Ctx) error { - - // username of the friend to be removed - friendUsername := c.Params("username") - if friendUsername == "" { - return fiber.NewError(fiber.StatusBadRequest, "Friend's username is required") - } - - // Get the user's ID from the context (assuming it's set during authentication) - userID, ok := c.Locals("userId").(uuid.UUID) - if !ok { - return fiber.NewError(fiber.StatusUnauthorized, "User not authenticated") - } - - // call function to remove the friend by username - err := s.store.RemoveFriend(c.Context(), userID, friendUsername) - if err != nil { - return fiber.NewError(fiber.StatusInternalServerError, "Failed to remove friend") - } - - // Return success message - return c.Status(http.StatusOK).JSON(fiber.Map{"message": "Friend removed successfully"}) -} diff --git a/backend/internal/handlers/profiles/routes.go b/backend/internal/handlers/profiles/routes.go deleted file mode 100644 index 8179a40..0000000 --- a/backend/internal/handlers/profiles/routes.go +++ /dev/null @@ -1,26 +0,0 @@ -package profiles - -//NOTE: This is an example usage for auth demonstration purposes. In real configurations (beyond login) all route groups should be protected - -import ( - "github.com/GenerateNU/nightlife/internal/auth" - "github.com/GenerateNU/nightlife/internal/types" - "github.com/gofiber/fiber/v2" -) - -// Create HelloGroup fiber route group -func Routes(app *fiber.App, params types.Params) { - service := newService(params.Store) - - // Create Protected Grouping - protected := app.Group("/profiles") - - // Register Middleware - protected.Use(auth.Protected(¶ms.Supabase)) - - //Endpoints - protected.Patch("/preferences", service.UpdateProfilePrefences) - protected.Delete("/:userId", service.DeleteUser) - protected.Delete("/friends/:username", service.RemoveFriend) - -} diff --git a/backend/internal/handlers/profiles/service.go b/backend/internal/handlers/profiles/service.go deleted file mode 100644 index f0a2a5c..0000000 --- a/backend/internal/handlers/profiles/service.go +++ /dev/null @@ -1,11 +0,0 @@ -package profiles - -import "github.com/GenerateNU/nightlife/internal/storage" - -type Service struct { - store storage.Storage -} - -func newService(store storage.Storage) *Service { - return &Service{store: store} -} diff --git a/backend/internal/server/server.go b/backend/internal/server/server.go index 57984f6..2248916 100644 --- a/backend/internal/server/server.go +++ b/backend/internal/server/server.go @@ -5,7 +5,7 @@ import ( "github.com/GenerateNU/nightlife/internal/handlers/auth" "github.com/GenerateNU/nightlife/internal/handlers/health" "github.com/GenerateNU/nightlife/internal/handlers/hello" - "github.com/GenerateNU/nightlife/internal/handlers/profiles" + "github.com/GenerateNU/nightlife/internal/handlers/profile" "github.com/GenerateNU/nightlife/internal/handlers/test" userrating "github.com/GenerateNU/nightlife/internal/handlers/user_ratings" venueratings "github.com/GenerateNU/nightlife/internal/handlers/venue_ratings" @@ -28,7 +28,7 @@ func New(params types.Params) *fiber.App { hello.Routes(app, params) test.Routes(app, params) auth.Routes(app, params) - profiles.Routes(app, params) + profile.Routes(app, params) //User Ratings route group userrating.Routes(app, params) diff --git a/backend/internal/storage/postgres/profile.go b/backend/internal/storage/postgres/profile.go index 462fd42..9bbb995 100644 --- a/backend/internal/storage/postgres/profile.go +++ b/backend/internal/storage/postgres/profile.go @@ -3,9 +3,13 @@ package postgres import ( "context" + "log" + + "github.com/google/uuid" "github.com/GenerateNU/nightlife/internal/models" ) + func (db *DB) CreatePreferences(ctx context.Context, p models.Preferences) error { // query to save user data to db query := `INSERT INTO preferences (userID, location, age, music, ambiance, notifs) @@ -14,3 +18,58 @@ func (db *DB) CreatePreferences(ctx context.Context, p models.Preferences) error _, err := db.conn.Query(ctx, query, p.UserID, p.Location, p.Age, p.Music, p.Ambiance, p.Notifs) return err } + + +func (db *DB) UpdateProfilePrefences(ctx context.Context, userID uuid.UUID, preferencetypeto string, preferencevalueto string, preferenceType string, preferenceValue string) error { + + // SQL query execution + _, err := db.conn.Exec(ctx, ` + UPDATE "UserPreference" up + SET + user_id = $1, + preference_type = $2, + preference_value = $3 + WHERE user_id = $1 AND preference_type = $4 AND preference_value = $5; + `, userID, preferencetypeto, preferencevalueto, preferenceType, preferenceValue) + + if err != nil { + log.Printf("Failed to update preferences for userId %s: %v", userID, err) + return err + } + + log.Printf("Successfully updated preferences for userId: %s", userID) + return nil + +} + + +/* +Delete an account +*/ +func (db *DB) DeleteAccount(ctx context.Context, userID uuid.UUID) error { + _, err := db.conn.Exec(ctx, `DELETE FROM "User" WHERE user_id = $1`, userID) + + if err != nil { + return err + } + + return nil +} + +/* +RemoveFriend removes a friend from the user's friend list based on the friend's username +*/ +func (db *DB) RemoveFriend(ctx context.Context, userID uuid.UUID, friendUsername string) error { + _, err := db.conn.Exec(ctx, ` + DELETE FROM "Friendship" + WHERE user_id1 = $1 AND user_id2 = (SELECT user_id FROM "User" WHERE username = $2) + OR user_id2 = $1 AND user_id1 = (SELECT user_id FROM "User" WHERE username = $2) + `, userID, friendUsername) + + if err != nil { + return err + } + return nil +} + + diff --git a/backend/internal/storage/postgres/profiles.go b/backend/internal/storage/postgres/profiles.go deleted file mode 100644 index 014c8ab..0000000 --- a/backend/internal/storage/postgres/profiles.go +++ /dev/null @@ -1,62 +0,0 @@ -package postgres - -import ( - "context" - - "log" - - "github.com/google/uuid" -) - -func (db *DB) UpdateProfilePrefences(ctx context.Context, userID uuid.UUID, preferencetypeto string, preferencevalueto string, preferenceType string, preferenceValue string) error { - - // SQL query execution - _, err := db.conn.Exec(ctx, ` - UPDATE "UserPreference" up - SET - user_id = $1, - preference_type = $2, - preference_value = $3 - WHERE user_id = $1 AND preference_type = $4 AND preference_value = $5; - `, userID, preferencetypeto, preferencevalueto, preferenceType, preferenceValue) - - if err != nil { - log.Printf("Failed to update preferences for userId %s: %v", userID, err) - return err - } - - log.Printf("Successfully updated preferences for userId: %s", userID) - return nil - -} - - -/* -Delete an account -*/ -func (db *DB) DeleteAccount(ctx context.Context, userID uuid.UUID) error { - _, err := db.conn.Exec(ctx, `DELETE FROM "User" WHERE user_id = $1`, userID) - - if err != nil { - return err - } - - return nil -} - -/* -RemoveFriend removes a friend from the user's friend list based on the friend's username -*/ -func (db *DB) RemoveFriend(ctx context.Context, userID uuid.UUID, friendUsername string) error { - _, err := db.conn.Exec(ctx, ` - DELETE FROM "Friendship" - WHERE user_id1 = $1 AND user_id2 = (SELECT user_id FROM "User" WHERE username = $2) - OR user_id2 = $1 AND user_id1 = (SELECT user_id FROM "User" WHERE username = $2) - `, userID, friendUsername) - - if err != nil { - return err - } - return nil -} - diff --git a/backend/internal/storage/storage.go b/backend/internal/storage/storage.go index ffb9e3a..eab2e72 100644 --- a/backend/internal/storage/storage.go +++ b/backend/internal/storage/storage.go @@ -25,6 +25,7 @@ type Profile interface { UpdateProfilePrefences(context.Context, uuid.UUID, string, string, string, string) error DeleteAccount(context.Context, uuid.UUID) error RemoveFriend(context.Context, uuid.UUID, string) error + } type UserRating interface {