init
This commit is contained in:
218
internal/handler/app_lock_handler.go
Normal file
218
internal/handler/app_lock_handler.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"accounting-app/pkg/api"
|
||||
"accounting-app/internal/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AppLockHandler handles HTTP requests for app lock
|
||||
type AppLockHandler struct {
|
||||
service *service.AppLockService
|
||||
}
|
||||
|
||||
// NewAppLockHandler creates a new app lock handler
|
||||
func NewAppLockHandler(service *service.AppLockService) *AppLockHandler {
|
||||
return &AppLockHandler{service: service}
|
||||
}
|
||||
|
||||
// SetPasswordRequest represents the request to set app lock password
|
||||
type SetPasswordRequest struct {
|
||||
Password string `json:"password" binding:"required,min=4"`
|
||||
}
|
||||
|
||||
// VerifyPasswordRequest represents the request to verify app lock password
|
||||
type VerifyPasswordRequest struct {
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
// ChangePasswordRequest represents the request to change app lock password
|
||||
type ChangePasswordRequest struct {
|
||||
OldPassword string `json:"old_password" binding:"required"`
|
||||
NewPassword string `json:"new_password" binding:"required,min=4"`
|
||||
}
|
||||
|
||||
// AppLockStatusResponse represents the app lock status response
|
||||
type AppLockStatusResponse struct {
|
||||
IsEnabled bool `json:"is_enabled"`
|
||||
IsLocked bool `json:"is_locked"`
|
||||
FailedAttempts int `json:"failed_attempts"`
|
||||
RemainingLockTime int `json:"remaining_lock_time"` // in seconds
|
||||
MaxAttempts int `json:"max_attempts"`
|
||||
}
|
||||
|
||||
// GetStatus returns the current app lock status
|
||||
// @Summary Get app lock status
|
||||
// @Tags AppLock
|
||||
// @Produce json
|
||||
// @Success 200 {object} AppLockStatusResponse
|
||||
// @Router /api/v1/app-lock/status [get]
|
||||
func (h *AppLockHandler) GetStatus(c *gin.Context) {
|
||||
userId, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
status, err := h.service.GetStatus(userId.(uint))
|
||||
if err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "GET_STATUS_FAILED", "Failed to get app lock status")
|
||||
return
|
||||
}
|
||||
|
||||
remainingTime, _ := h.service.GetRemainingLockTime(userId.(uint))
|
||||
|
||||
response := AppLockStatusResponse{
|
||||
IsEnabled: status.IsEnabled,
|
||||
IsLocked: status.IsLocked(),
|
||||
FailedAttempts: status.FailedAttempts,
|
||||
RemainingLockTime: remainingTime,
|
||||
MaxAttempts: service.MaxFailedAttempts,
|
||||
}
|
||||
|
||||
api.Success(c, response)
|
||||
}
|
||||
|
||||
// SetPassword sets or updates the app lock password
|
||||
// @Summary Set app lock password
|
||||
// @Tags AppLock
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body SetPasswordRequest true "Password"
|
||||
// @Success 200 {object} api.Response
|
||||
// @Router /api/v1/app-lock/password [post]
|
||||
func (h *AppLockHandler) SetPassword(c *gin.Context) {
|
||||
var req SetPasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request")
|
||||
return
|
||||
}
|
||||
|
||||
userId, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.SetPassword(userId.(uint), req.Password); err != nil {
|
||||
if err == service.ErrPasswordRequired {
|
||||
api.Error(c, http.StatusBadRequest, "PASSWORD_REQUIRED", "Password is required")
|
||||
return
|
||||
}
|
||||
api.Error(c, http.StatusInternalServerError, "SET_PASSWORD_FAILED", "Failed to set password")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"message": "Password set successfully"})
|
||||
}
|
||||
|
||||
// VerifyPassword verifies the app lock password
|
||||
// @Summary Verify app lock password
|
||||
// @Tags AppLock
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body VerifyPasswordRequest true "Password"
|
||||
// @Success 200 {object} api.Response
|
||||
// @Router /api/v1/app-lock/verify [post]
|
||||
func (h *AppLockHandler) VerifyPassword(c *gin.Context) {
|
||||
var req VerifyPasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request")
|
||||
return
|
||||
}
|
||||
|
||||
userId, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.VerifyPassword(userId.(uint), req.Password)
|
||||
if err != nil {
|
||||
if err == service.ErrAppLocked {
|
||||
remainingTime, _ := h.service.GetRemainingLockTime(userId.(uint))
|
||||
c.JSON(http.StatusLocked, gin.H{
|
||||
"success": false,
|
||||
"error": "App is locked",
|
||||
"remaining_lock_time": remainingTime,
|
||||
})
|
||||
return
|
||||
}
|
||||
if err == service.ErrAppLockInvalidPassword {
|
||||
status, _ := h.service.GetStatus(userId.(uint))
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"error": "Invalid password",
|
||||
"failed_attempts": status.FailedAttempts,
|
||||
"max_attempts": service.MaxFailedAttempts,
|
||||
"remaining_attempts": service.MaxFailedAttempts - status.FailedAttempts,
|
||||
})
|
||||
return
|
||||
}
|
||||
if err == service.ErrAppLockNotEnabled {
|
||||
api.Error(c, http.StatusBadRequest, "APP_LOCK_NOT_ENABLED", "App lock is not enabled")
|
||||
return
|
||||
}
|
||||
api.Error(c, http.StatusInternalServerError, "VERIFY_FAILED", "Failed to verify password")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"message": "Password verified successfully"})
|
||||
}
|
||||
|
||||
// DisableLock disables the app lock
|
||||
// @Summary Disable app lock
|
||||
// @Tags AppLock
|
||||
// @Produce json
|
||||
// @Success 200 {object} api.Response
|
||||
// @Router /api/v1/app-lock/disable [post]
|
||||
func (h *AppLockHandler) DisableLock(c *gin.Context) {
|
||||
userId, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.DisableLock(userId.(uint)); err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "DISABLE_FAILED", "Failed to disable app lock")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"message": "App lock disabled successfully"})
|
||||
}
|
||||
|
||||
// ChangePassword changes the app lock password
|
||||
// @Summary Change app lock password
|
||||
// @Tags AppLock
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body ChangePasswordRequest true "Old and new passwords"
|
||||
// @Success 200 {object} api.Response
|
||||
// @Router /api/v1/app-lock/password/change [post]
|
||||
func (h *AppLockHandler) ChangePassword(c *gin.Context) {
|
||||
var req ChangePasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request")
|
||||
return
|
||||
}
|
||||
|
||||
userId, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.ChangePassword(userId.(uint), req.OldPassword, req.NewPassword)
|
||||
if err != nil {
|
||||
if err == service.ErrAppLockInvalidPassword || err == service.ErrAppLocked {
|
||||
api.Error(c, http.StatusUnauthorized, "INVALID_OLD_PASSWORD", "Invalid old password")
|
||||
return
|
||||
}
|
||||
api.Error(c, http.StatusInternalServerError, "CHANGE_PASSWORD_FAILED", "Failed to change password")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"message": "Password changed successfully"})
|
||||
}
|
||||
Reference in New Issue
Block a user