Skip to content

Commit

Permalink
Merge pull request #57 from DanglingDynamo/master
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr-Emerald-Wolf authored Mar 22, 2024
2 parents c5a1d0d + 513faf6 commit 043f0df
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Define variables
DOCKER_COMPOSE = docker compose
URI = "host= port= user= password= dbname=devsoc-24-backend"

URI = "host=139.59.71.66 port=5430 user=admin password=d352F68MX2Hdh2pRFWoB3R9yg dbname=devsoc-24-backend"

# Targets
Expand Down Expand Up @@ -27,7 +29,7 @@ migrate-up:
cd db/migrations && goose postgres $(URI) up && cd ../..

migrate-down:
cd db/migrations && goose postgres $(URI) down-to 0 && cd ../..
cd db/migrations && goose postgres $(URI) down && cd ../..

# Help target
help:
Expand Down
42 changes: 42 additions & 0 deletions internal/controllers/admin_user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,45 @@ func UnbanUser(ctx echo.Context) error {
"status": "success",
})
}

func CheckIn(ctx echo.Context) error {
var payload struct {
Email string `json:"email" validate:"required"`
}

if err := ctx.Bind(&payload); err != nil {
return ctx.JSON(http.StatusBadRequest, map[string]string{
"message": err.Error(),
"status": "fail",
})
}

user, err := services.FindUserByEmail(payload.Email)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return ctx.JSON(http.StatusNotFound, map[string]string{
"message": "User does not exist",
"status": "fail",
})
}
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"message": err.Error(),
"status": "error",
})
}

user.IsAdded = true

err = services.UpdateUser(&user.User)
if err != nil {
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"message": err.Error(),
"status": "fail",
})
}

return ctx.JSON(http.StatusOK, map[string]string{
"message": "checkin successful",
"status": "success",
})
}
137 changes: 137 additions & 0 deletions internal/controllers/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -730,3 +730,140 @@ func ResetPassword(ctx echo.Context) error {
"message": "password reset successfully",
})
}

func AdminLogin(ctx echo.Context) error {
var payload models.LoginRequest

if err := ctx.Bind(&payload); err != nil {
return ctx.JSON(http.StatusBadRequest, map[string]string{
"message": err.Error(),
"status": "fail",
})
}

if err := ctx.Validate(&payload); err != nil {
return ctx.JSON(http.StatusBadRequest, map[string]string{
"message": err.Error(),
"status": "fail",
})
}

payload.Email = strings.ToLower(payload.Email)

user, err := services.FindUserByEmail(payload.Email)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return ctx.JSON(http.StatusNotFound, map[string]string{
"message": "user does not exist",
"status": "fail",
})
}
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"messsage": err.Error(),
"status": "error",
})
}

if !user.IsVerified {
return ctx.JSON(http.StatusForbidden, map[string]string{
"message": "User is not verified",
"status": "fail",
})
}

if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(payload.Password)); err != nil {
if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
return ctx.JSON(http.StatusConflict, map[string]string{
"message": "Invalid password",
"status": "fail",
})
}
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"message": err.Error(),
"status": "error",
})
}

tokenVersionStr, err := database.RedisClient.Get(
fmt.Sprintf("token_version:%s", user.User.Email))
if err != nil && err != redis.Nil {
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"status": "error",
"message": err.Error(),
})
}

tokenVersion, _ := strconv.Atoi(tokenVersionStr)

accessToken, err := utils.CreateToken(utils.TokenPayload{
Exp: time.Hour * 24,
Email: user.User.Email,
Role: user.Role,
TokenVersion: tokenVersion + 1,
}, utils.ACCESS_TOKEN)
if err != nil {
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"message": err.Error(),
"status": "error",
})
}

refreshToken, err := utils.CreateToken(utils.TokenPayload{
Exp: time.Hour * 24,
Email: user.User.Email,
}, utils.REFRESH_TOKEN)
if err != nil {
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"message": err.Error(),
"status": "error",
})
}

if err := database.RedisClient.Set(fmt.Sprintf("token_version:%s", user.User.Email),
fmt.Sprint(tokenVersion+1), time.Hour*1); err != nil {
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"status": "error",
"message": err.Error(),
})
}

if err := database.RedisClient.Set(user.User.Email, refreshToken, time.Hour*1); err != nil {
return ctx.JSON(http.StatusInternalServerError, map[string]string{
"status": "error",
"message": err.Error(),
})
}

ctx.SetCookie(&http.Cookie{
Name: os.Getenv("ACCESS_COOKIE_NAME"),
Value: accessToken,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
MaxAge: 86400,
Secure: true,
})

ctx.SetCookie(&http.Cookie{
Name: os.Getenv("REFRESH_COOKIE_NAME"),
Value: refreshToken,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
MaxAge: 86400,
Secure: true,
})

if !user.IsProfileComplete {
return ctx.JSON(http.StatusLocked, map[string]interface{}{
"message": "profile not completed",
"status": "fail",
"data": map[string]interface{}{
"profile_complete": user.IsProfileComplete,
},
})
}

return ctx.JSON(http.StatusOK, map[string]interface{}{
"message": "login successful",
"status": "success",
})
}
1 change: 1 addition & 0 deletions internal/routes/admin_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func AdminRoutes(incomingRoutes *echo.Echo) {
admin.GET("/user/:email", controllers.GetUserByEmail)
admin.POST("/user/ban", controllers.BanUser, middleware.EditOnly)
admin.POST("/user/unban", controllers.UnbanUser, middleware.EditOnly)
admin.POST("/user/checkin", controllers.CheckIn, middleware.EditOnly)
admin.GET("/vitians", controllers.GetAllVitians)
admin.GET("/females", controllers.GetAllFemales)

Expand Down
1 change: 1 addition & 0 deletions internal/routes/user_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func UserRoutes(incomingRoutes *echo.Echo) {
incomingRoutes.POST("/resend", controllers.ResendOTP)
incomingRoutes.POST("/reset-password", controllers.RequestResetPassword)
incomingRoutes.PATCH("/reset-password", controllers.ResetPassword)
incomingRoutes.POST("/admin/login", controllers.AdminLogin)

user := incomingRoutes.Group("/user")
user.POST(
Expand Down

0 comments on commit 043f0df

Please sign in to comment.