init
This commit is contained in:
138
internal/handler/backup_handler.go
Normal file
138
internal/handler/backup_handler.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"accounting-app/pkg/api"
|
||||
"accounting-app/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// BackupHandler handles HTTP requests for backup operations
|
||||
type BackupHandler struct {
|
||||
service *service.BackupService
|
||||
}
|
||||
|
||||
// NewBackupHandler creates a new BackupHandler instance
|
||||
func NewBackupHandler(service *service.BackupService) *BackupHandler {
|
||||
return &BackupHandler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// ExportBackup handles POST /api/v1/backup/export
|
||||
// @Summary Export encrypted database backup
|
||||
// @Description Creates an encrypted backup of the database with SHA256 integrity checking
|
||||
// @Tags backup
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body service.BackupRequest true "Backup request"
|
||||
// @Success 200 {object} service.BackupResponse
|
||||
// @Failure 400 {object} api.ErrorResponse
|
||||
// @Failure 500 {object} api.ErrorResponse
|
||||
// @Router /api/v1/backup/export [post]
|
||||
func (h *BackupHandler) ExportBackup(c *gin.Context) {
|
||||
var req service.BackupRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response, err := h.service.ExportBackup(req)
|
||||
if err != nil {
|
||||
if err == service.ErrInvalidPassword {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_PASSWORD", err.Error())
|
||||
return
|
||||
}
|
||||
api.Error(c, http.StatusInternalServerError, "BACKUP_FAILED", "Failed to create backup: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, response)
|
||||
}
|
||||
|
||||
// ImportBackup handles POST /api/v1/backup/import
|
||||
// @Summary Import and restore from encrypted backup
|
||||
// @Description Restores the database from an encrypted backup file with integrity verification
|
||||
// @Tags backup
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body service.RestoreRequest true "Restore request"
|
||||
// @Success 200 {object} api.SuccessResponse
|
||||
// @Failure 400 {object} api.ErrorResponse
|
||||
// @Failure 500 {object} api.ErrorResponse
|
||||
// @Router /api/v1/backup/import [post]
|
||||
func (h *BackupHandler) ImportBackup(c *gin.Context) {
|
||||
var req service.RestoreRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.ImportBackup(req)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case service.ErrInvalidBackupFile:
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_BACKUP_FILE", "Invalid backup file format")
|
||||
return
|
||||
case service.ErrChecksumMismatch:
|
||||
api.Error(c, http.StatusBadRequest, "CHECKSUM_MISMATCH", "Backup file integrity check failed")
|
||||
return
|
||||
case service.ErrDecryptionFailed:
|
||||
api.Error(c, http.StatusBadRequest, "DECRYPTION_FAILED", "Failed to decrypt backup - incorrect password")
|
||||
return
|
||||
default:
|
||||
api.Error(c, http.StatusInternalServerError, "RESTORE_FAILED", "Failed to restore backup: "+err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{
|
||||
"message": "Database restored successfully from backup",
|
||||
})
|
||||
}
|
||||
|
||||
// VerifyBackup handles POST /api/v1/backup/verify
|
||||
// @Summary Verify backup file integrity
|
||||
// @Description Verifies the integrity of a backup file without restoring it
|
||||
// @Tags backup
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body map[string]string true "Verify request with file_path"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} api.ErrorResponse
|
||||
// @Failure 500 {object} api.ErrorResponse
|
||||
// @Router /api/v1/backup/verify [post]
|
||||
func (h *BackupHandler) VerifyBackup(c *gin.Context) {
|
||||
var req struct {
|
||||
FilePath string `json:"file_path" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
isValid, checksum, err := h.service.VerifyBackup(req.FilePath)
|
||||
if err != nil {
|
||||
if err == service.ErrInvalidBackupFile {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_BACKUP_FILE", "Invalid backup file format")
|
||||
return
|
||||
}
|
||||
api.Error(c, http.StatusInternalServerError, "VERIFY_FAILED", "Failed to verify backup: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{
|
||||
"valid": isValid,
|
||||
"checksum": checksum,
|
||||
"message": getVerificationMessage(isValid),
|
||||
})
|
||||
}
|
||||
|
||||
func getVerificationMessage(isValid bool) string {
|
||||
if isValid {
|
||||
return "Backup file integrity verified successfully"
|
||||
}
|
||||
return "Backup file integrity check failed - file may be corrupted"
|
||||
}
|
||||
Reference in New Issue
Block a user