first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:37:58 +03:00
commit 8b1fbdee99
104 changed files with 23398 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
package handlers
import (
"net/http"
"os"
"strings"
"gauth-central/internal/database"
"gauth-central/internal/models"
"gauth-central/pkg/utils"
"github.com/gin-gonic/gin"
)
type AvatarHandler struct{}
func NewAvatarHandler() *AvatarHandler {
return &AvatarHandler{}
}
// UploadAvatar godoc
// @Summary Upload user avatar
// @Tags User
// @Security ApiKeyAuth
// @Accept multipart/form-data
// @Produce json
// @Param avatar formData file true "Avatar image file"
// @Success 200 {object} map[string]interface{}
// @Router /user/avatar [post]
func (h *AvatarHandler) UploadAvatar(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
// Parse multipart form
file, err := c.FormFile("avatar")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "No file uploaded"})
return
}
// Validate file size (max 5MB)
if file.Size > 5*1024*1024 {
c.JSON(http.StatusBadRequest, gin.H{"error": "File size exceeds 5MB limit"})
return
}
// Get user to check for old avatar
var user models.User
if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}
// Delete old avatar file if exists and is not from OAuth
if user.Avatar != "" && strings.HasPrefix(user.Avatar, "/uploads/") {
oldPath := "." + user.Avatar
os.Remove(oldPath) // Ignore error if file doesn't exist
}
// Use utils.SaveOptimizedImage
avatarURL, err := utils.SaveOptimizedImage(file, "./uploads/avatars", userID, nil)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save avatar: " + err.Error()})
return
}
// Update avatar URL
if err := database.DB.Model(&user).Update("avatar", avatarURL).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update avatar"})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Avatar uploaded successfully",
"avatar_url": avatarURL,
"user": gin.H{
"id": user.ID,
"username": user.UserName,
"email": user.Email,
"avatar": avatarURL,
},
})
}
// DeleteAvatar godoc
// @Summary Delete user avatar
// @Tags User
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Router /user/avatar [delete]
func (h *AvatarHandler) DeleteAvatar(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
var user models.User
if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}
// Delete avatar file if it's a local upload
if user.Avatar != "" && strings.HasPrefix(user.Avatar, "/uploads/") {
filepath := "." + user.Avatar
os.Remove(filepath) // Ignore error if file doesn't exist
}
// Set avatar to empty string
if err := database.DB.Model(&user).Update("avatar", "").Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete avatar"})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Avatar deleted successfully",
"user": gin.H{
"id": user.ID,
"username": user.UserName,
"email": user.Email,
"avatar": "",
},
})
}
// AdminUploadAvatar godoc
// @Summary Upload avatar for any user (Admin only)
// @Tags Admin - User Management
// @Security ApiKeyAuth
// @Accept multipart/form-data
// @Produce json
// @Param id path string true "User ID"
// @Param avatar formData file true "Avatar image file"
// @Success 200 {object} map[string]interface{}
// @Router /admin/users/{id}/avatar [post]
func (h *AvatarHandler) AdminUploadAvatar(c *gin.Context) {
userID := c.Param("id")
// Parse multipart form
file, err := c.FormFile("avatar")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "No file uploaded"})
return
}
// Validate file size (max 5MB)
if file.Size > 5*1024*1024 {
c.JSON(http.StatusBadRequest, gin.H{"error": "File size exceeds 5MB limit"})
return
}
// Get user to check for old avatar
var user models.User
if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}
// Delete old avatar file if exists and is not from OAuth
if user.Avatar != "" && strings.HasPrefix(user.Avatar, "/uploads/") {
oldPath := "." + user.Avatar
os.Remove(oldPath) // Ignore error if file doesn't exist
}
// Use utils.SaveOptimizedImage
avatarURL, err := utils.SaveOptimizedImage(file, "./uploads/avatars", userID, nil)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save avatar: " + err.Error()})
return
}
// Update avatar URL
if err := database.DB.Model(&user).Update("avatar", avatarURL).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update avatar"})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Avatar uploaded successfully",
"avatar_url": avatarURL,
"user": gin.H{
"id": user.ID,
"username": user.UserName,
"email": user.Email,
"avatar": avatarURL,
},
})
}