diff --git a/cmd/api/auth.go b/cmd/api/auth.go index 2193819..3236eda 100644 --- a/cmd/api/auth.go +++ b/cmd/api/auth.go @@ -2,8 +2,10 @@ package main import ( "net/http" + "time" "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" "github.com/kunalkumar-1/Evently/internals/database" "golang.org/x/crypto/bcrypt" ) @@ -14,6 +16,15 @@ type registerRequest struct { Name string `json:"name" binding:"required,min=3,max=50"` } +type loginRequest struct { + Email string `json:"email" binding:"required,email"` + Password string `json:"password" binding:"required,min=8"` +} + +type loginResponse struct { + Token string `json:"token"` +} + func (app *application) registerUser(c *gin.Context) { var register registerRequest @@ -49,3 +60,51 @@ func (app *application) registerUser(c *gin.Context) { c.JSON(http.StatusCreated, user) } + +func (app *application) login(c *gin.Context) { + var auth loginRequest + if err := c.ShouldBindJSON(&auth); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + existingUser, err := app.models.Users.GetByEmail(auth.Email) + if existingUser == nil { + c.JSON(http.StatusUnauthorized, gin.H{ + "error": "Invlid Email or Password", + }) + return + } + if err != nil { + c.JSON(http.StatusUnauthorized, gin.H{ + "error": err.Error(), + }) + return + } + err = bcrypt.CompareHashAndPassword([]byte(existingUser.Password), []byte(auth.Password)) + if err != nil { + c.JSON(http.StatusUnauthorized, gin.H{ + "error": "Invalid Email or Password", + }) + return + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "UserId": existingUser.Id, + "expr": time.Now().Add(time.Hour * 72).Unix(), + }) + + tokenString, err := token.SignedString([]byte(app.jwtSecret)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Error Generating token", + }) + return + } + + c.JSON(http.StatusOK, loginResponse{ + Token: tokenString, + }) +} diff --git a/cmd/api/events.go b/cmd/api/events.go index ac8bff4..02b56af 100644 --- a/cmd/api/events.go +++ b/cmd/api/events.go @@ -228,14 +228,16 @@ func (app *application) getAttendeesForEvent(c *gin.Context) { }) return } - users, err := app.models.Attendees.GetAttendeeByEvent(id) + + events, err := app.models.Attendees.GetAttendeeByEvent(id) //get attendees for event if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "failed to retrieve Attendees for events", }) return } - c.JSON(http.StatusOK, users) + + c.JSON(http.StatusOK, events) } func (app *application) deleteAttendeeFromEvent(c *gin.Context) { diff --git a/cmd/api/routes.go b/cmd/api/routes.go index 7b9632b..f5cdbfb 100644 --- a/cmd/api/routes.go +++ b/cmd/api/routes.go @@ -16,12 +16,13 @@ func (app *application) routes() http.Handler { v1.GET("/events/:id", app.getEvent) // get event by id v1.PUT("/events/:id", app.updateEvent) // update event by id v1.DELETE("/events/:id", app.deleteEvent) //delete the event by id - v1.GET("/events/:id/attendees/:userId", app.getAttendeesForEvent) // get attendee to event - v1.POST("/events/:id/attendees/:userId", app.addAttendeeToEvent) // add attendee to event + v1.POST("/events/:id/attendees/:userId", app.addAttendeeToEvent) // get attendee to event + v1.GET("/events/:id/attendees/", app.getAttendeesForEvent) // add attendee to event v1.DELETE("/events/:id/attendees/:userId", app.deleteAttendeeFromEvent) //delete attendee from event - v1.GET("/events/:id/attendees", app.getEventsByAttendee) //get attendees for event + v1.GET("/attendees/:id/events", app.getEventsByAttendee) //get attendees for event + v1.POST("/auth/register", app.registerUser) // register user + v1.POST("/auth/login", app.login) - v1.POST("/auth/register", app.registerUser) // register user } return r diff --git a/go.mod b/go.mod index d0a74ee..a2ab52f 100644 --- a/go.mod +++ b/go.mod @@ -38,6 +38,7 @@ require ( require ( github.com/gin-gonic/gin v1.10.1 + github.com/golang-jwt/jwt/v4 v4.5.2 github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/joho/godotenv v1.5.1 diff --git a/go.sum b/go.sum index 6691cba..7d0a5b0 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs= github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= diff --git a/internals/database/users.go b/internals/database/users.go index d9dd21e..261215e 100644 --- a/internals/database/users.go +++ b/internals/database/users.go @@ -27,13 +27,12 @@ func (u *UserModel) Insert(user *User) error { } -func (u *UserModel) Get(id int) (*User, error) { +func (u *UserModel) getUser(query string, args ...interface{}) (*User, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - query := `SELECT * FROM users WHERE id = $1` var user User - err := u.Db.QueryRowContext(ctx, query, id).Scan(&user.Id, &user.Name, &user.Email, &user.Password) + err := u.Db.QueryRowContext(ctx, query, args...).Scan(&user.Id, &user.Name, &user.Email, &user.Password) if err != nil { if err == sql.ErrNoRows { return nil, nil @@ -42,3 +41,30 @@ func (u *UserModel) Get(id int) (*User, error) { } return &user, nil } + +func (u *UserModel) Get(id int) (*User, error) { + query := `SELECT * FROM users WHERE id = $1` + return u.getUser(query, id) +} + +func (u *UserModel) GetByEmail(email string) (*User, error) { + query := `SELECT * FROM users WHERE email = $1` + return u.getUser(query, email) +} + +// func (u *UserModel) GetByEmail(email string) (*User, error) { +// ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) +// defer cancel() + +// query := `SELECT * FROM users WHERE email = $1` + +// var user User +// err := u.Db.QueryRowContext(ctx, query, email).Scan(&user.Id, &user.Name, &user.Email, &user.Password) +// if err != nil { +// if err == sql.ErrNoRows { +// return nil, nil +// } +// return nil, err +// } +// return &user, nil +// }