diff --git a/internal/api/handler/avatar_handler.go b/internal/api/handler/avatar_handler.go index b3a999d..deb053f 100644 --- a/internal/api/handler/avatar_handler.go +++ b/internal/api/handler/avatar_handler.go @@ -32,6 +32,14 @@ func NewAvatarHandler(userRepo avatarUserRepository) *AvatarHandler { return &AvatarHandler{userRepo: userRepo} } +const ( + maxAvatarSize = 5 * 1024 * 1024 // 5MB + magicBytesBufSize = 512 + avatarTokenLen = 8 + dirPerm = 0o755 + filePerm = 0o644 +) + // generateSecureToken generates a secure random token func generateSecureToken(length int) string { bytes := make([]byte, length) @@ -93,7 +101,7 @@ func (h *AvatarHandler) UploadAvatar(c *gin.Context) { } // Validate file size (max 5MB) - if file.Size > 5*1024*1024 { + if file.Size > maxAvatarSize { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "file size exceeds 5MB limit"}) return } @@ -115,7 +123,7 @@ func (h *AvatarHandler) UploadAvatar(c *gin.Context) { defer src.Close() // Validate Magic Bytes to detect actual file type (prevents file extension spoofing) - buf := make([]byte, 512) + buf := make([]byte, magicBytesBufSize) n, err := src.Read(buf) if err != nil && err != io.EOF { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "failed to read file"}) @@ -140,11 +148,11 @@ func (h *AvatarHandler) UploadAvatar(c *gin.Context) { } // Generate unique filename - avatarFilename := fmt.Sprintf("avatar_%d_%s%s", userID, generateSecureToken(8), ext) + avatarFilename := fmt.Sprintf("avatar_%d_%s%s", userID, generateSecureToken(avatarTokenLen), ext) uploadDir := "./uploads/avatars" // Create upload directory if not exists - if err := os.MkdirAll(uploadDir, 0o755); err != nil { + if err := os.MkdirAll(uploadDir, dirPerm); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to create upload directory"}) return } @@ -156,7 +164,7 @@ func (h *AvatarHandler) UploadAvatar(c *gin.Context) { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to read uploaded file"}) return } - if err := os.WriteFile(dstPath, data, 0o644); err != nil { + if err := os.WriteFile(dstPath, data, filePerm); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to save avatar file"}) return }