Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/editing get user by #49

Merged
merged 5 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions backend/internal/handlers/profile/preferences.go

This file was deleted.

21 changes: 0 additions & 21 deletions backend/internal/handlers/profile/routes.go

This file was deleted.

11 changes: 0 additions & 11 deletions backend/internal/handlers/profile/service.go

This file was deleted.

74 changes: 65 additions & 9 deletions backend/internal/handlers/profiles/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,33 @@ import (
"net/http"

"github.com/GenerateNU/nightlife/internal/errs"
"github.com/GenerateNU/nightlife/internal/utils"

"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
func (s *Service) CreatePreferences(c *fiber.Ctx) error {
var p models.Preferences
if err := c.BodyParser(&p); err != nil {
return errs.BadRequest(err)
}

if verrs := p.Validate(); verrs != nil {
return errs.InvalidRequestData(verrs)
}

if err := s.store.CreatePreferences(c.Context(), p); err != nil {
return err
}

// close out with success status
return c.Status(fiber.StatusCreated).JSON(p)

}

func (s *Service) UpdateProfilePreferences(c *fiber.Ctx) error {

// Parse the request body
Expand Down Expand Up @@ -86,21 +107,56 @@ func (s *Service) RemoveFriend(c *fiber.Ctx) error {
return c.Status(http.StatusOK).JSON(fiber.Map{"message": "Friend removed successfully"})
}

/*
GetProfile retrieves a user's profile information by the user's username, email, or ID.
*/
func (s *Service) GetProfile(c *fiber.Ctx) error {

username := c.Params("username")
userIdentifier := c.Params("userIdentifier")

if username == "" {
c.Status(http.StatusBadRequest)
return errs.APIError{StatusCode: fiber.StatusBadRequest, Message: "username is required"}
}
var profile models.Profile
var err error

if utils.IsEmail(userIdentifier) {
// Query by email
profile, err = s.store.GetProfileByColumn(c.Context(), "email", userIdentifier)
} else if utils.IsUUID(userIdentifier) {
// Query by ID
profile, err = s.store.GetProfileByColumn(c.Context(), "user_id", userIdentifier)
} else {
// Query by username
profile, err = s.store.GetProfileByColumn(c.Context(), "username", userIdentifier)
}

if err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "profile not found"})
}

return c.Status(fiber.StatusOK).JSON(profile)
}

profile, err := s.store.GetProfileByUsername(c.Context(), username)

/*
Get All Users
*/
func (s *Service) GetAllUsers(c *fiber.Ctx) error {
// Fetch all users from the store
users, err := s.store.GetAllUsers(c.Context())
if err != nil {
c.Status(http.StatusInternalServerError)
return errs.APIError{StatusCode: fiber.StatusNotFound, Message: "profile not found"}

return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Failed to retrieve users",
"details": err.Error(),
})
}

// If no users are found, we can return a 404
if len(users) == 0 {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"message": "No users found",
})
}

return c.Status(http.StatusOK).JSON(profile)
// Return the list of users with a 200 OK status
return c.Status(fiber.StatusOK).JSON(users)
}
11 changes: 7 additions & 4 deletions backend/internal/handlers/profiles/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ func Routes(app *fiber.App, params types.Params) {
protected.Use(auth.Protected(&params.Supabase))

//Endpoints
protected.Get("/:username", service.GetProfile)
protected.Patch("/preferences", service.UpdateProfilePreferences)
protected.Delete("/:userId", service.DeleteUser)
protected.Delete("/friends/:username", service.RemoveFriend)
protected.Get("/", service.GetAllUsers)
protected.Get("/:userIdentifier", service.GetProfile)
protected.Post("/preferences", service.CreatePreferences)
protected.Patch("/preferences", service.UpdateProfilePreferences)
protected.Delete("/:userId", service.DeleteUser)
protected.Delete("/friends/:username", service.RemoveFriend)

}
13 changes: 12 additions & 1 deletion backend/internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,22 @@ func New(params types.Params) *fiber.App {

useMiddlewares(app)

health.Routes(app, params)
// Hellp route group
hello.Routes(app, params)

// Test route group
test.Routes(app, params)

// Health route group
health.Routes(app, params)

// Auth route group
auth.Routes(app, params)

// Venues route group
venues.Routes(app, params)

// Profile (User) route group
profiles.Routes(app, params)

//User Ratings route group
Expand Down
16 changes: 0 additions & 16 deletions backend/internal/storage/postgres/profile.go

This file was deleted.

76 changes: 59 additions & 17 deletions backend/internal/storage/postgres/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,24 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/GenerateNU/nightlife/internal/models"
"log"

"github.com/GenerateNU/nightlife/internal/models"

"github.com/google/uuid"
)

func (db *DB) GetProfileByUsername(ctx context.Context, username string) (models.Profile, error) {
/*
Gets a user profile by a column, (username, id, or email).
*/
func (db *DB) GetProfileByColumn(ctx context.Context, column string, value string) (models.Profile, error) {
var profile models.Profile
var query = fmt.Sprintf(`
SELECT user_id, first_name, username, email, age, location, profile_picture_url, created_at
FROM users
WHERE %s = $1`, column)

var query = `
SELECT user_id,
first_name,
username,
email,
age,
location,
profile_picture_url,
created_at
FROM users
WHERE username = $1
`

row := db.conn.QueryRow(ctx, query, username)
row := db.conn.QueryRow(ctx, query, value)

err := row.Scan(
&profile.UserID,
Expand All @@ -42,14 +37,23 @@ func (db *DB) GetProfileByUsername(ctx context.Context, username string) (models

if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return models.Profile{}, fmt.Errorf("no profile found for username: %s", username)
return models.Profile{}, fmt.Errorf("no profile found for %s: %s", column, value)
}
return models.Profile{}, err
}

return profile, nil
}

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)
VALUES ($1, $2, $3, $4, $5, $6)`

_, err := db.conn.Query(ctx, query, p.UserID, p.Location, p.Age, p.Music, p.Ambiance, p.Notifs)
return err
}

func (db *DB) UpdateProfilePreferences(ctx context.Context, userID uuid.UUID, preferencetypeto string, preferencevalueto string, preferenceType string, preferenceValue string) error {

// SQL query execution
Expand Down Expand Up @@ -100,3 +104,41 @@ func (db *DB) RemoveFriend(ctx context.Context, userID uuid.UUID, friendUsername
}
return nil
}

/*
Get All Users
*/
func (db *DB) GetAllUsers(ctx context.Context) ([]models.Profile, error) {

rows, err := db.conn.Query(ctx, `SELECT user_id, first_name, username, email, age, location, profile_picture_url, created_at FROM users`)
if err != nil {
return nil, err
}
defer rows.Close()

var profiles []models.Profile

// Iterate through the result rows
for rows.Next() {
var profile models.Profile
if err := rows.Scan(
&profile.UserID,
&profile.FirstName,
&profile.Username,
&profile.Email,
&profile.Age,
&profile.Location,
&profile.ProfilePictureURL,
&profile.CreatedAt,
); err != nil {
return nil, err
}
profiles = append(profiles, profile)
}

if err := rows.Err(); err != nil {
return nil, err
}

return profiles, nil
}
11 changes: 6 additions & 5 deletions backend/internal/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ type Test interface {
}

type Profile interface {
CreatePreferences(context.Context, models.Preferences) error
UpdateProfilePreferences(context.Context, uuid.UUID, string, string, string, string) error
DeleteAccount(context.Context, uuid.UUID) error
RemoveFriend(context.Context, uuid.UUID, string) error
GetProfileByUsername(context.Context, string) (models.Profile, error)
CreatePreferences(context.Context, models.Preferences) error
UpdateProfilePreferences(context.Context, uuid.UUID, string, string, string, string) error
DeleteAccount(context.Context, uuid.UUID) error
RemoveFriend(context.Context, uuid.UUID, string) error
GetProfileByColumn(context.Context, string, string) (models.Profile, error)
GetAllUsers(context.Context) ([]models.Profile, error)
}

type UserRating interface {
Expand Down
19 changes: 19 additions & 0 deletions backend/internal/utils/validators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// internal/utils/validators.go
package utils

import (
"regexp"
)

// Check if the string is a valid email address
func IsEmail(input string) bool {
// Define the regular expression for validating an email address
var emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
return emailRegex.MatchString(input)
}

// Check if the string is a valid UUID
func IsUUID(input string) bool {
uuidRegex := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)
return uuidRegex.MatchString(input)
}
Loading