mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
244 lines
8.5 KiB
Go
244 lines
8.5 KiB
Go
package controllers
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
"fotbal-club/internal/models"
|
|
"fotbal-club/internal/services"
|
|
)
|
|
|
|
type EventController struct{ DB *gorm.DB }
|
|
|
|
// GetEventByID returns a single event by its ID (public; returns only public events unless owner)
|
|
func (ctrl *EventController) GetEventByID(c *gin.Context) {
|
|
id := c.Param("id")
|
|
var ev models.Event
|
|
if err := ctrl.DB.Preload("Attachments").First(&ev, id).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "Event not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"})
|
|
return
|
|
}
|
|
// If not public, allow only owner (when identified upstream)
|
|
if !ev.IsPublic {
|
|
if roleVal, hasRole := c.Get("userRole"); hasRole {
|
|
if role, _ := roleVal.(string); role == "admin" {
|
|
c.JSON(http.StatusOK, ev)
|
|
return
|
|
}
|
|
}
|
|
if userID, exists := c.Get("userID"); !exists || ev.CreatedByID != userID {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "Not allowed"})
|
|
return
|
|
}
|
|
}
|
|
c.JSON(http.StatusOK, ev)
|
|
}
|
|
|
|
type EventInput struct {
|
|
Title string `json:"title" binding:"required"`
|
|
Description string `json:"description"`
|
|
StartTime time.Time `json:"start_time" binding:"required"`
|
|
EndTime *time.Time `json:"end_time"`
|
|
Location string `json:"location"`
|
|
Type string `json:"type" binding:"required,oneof=match training meeting other"`
|
|
IsPublic bool `json:"is_public"`
|
|
CategoryName string `json:"category_name"`
|
|
ImageURL string `json:"image_url"`
|
|
FileURL string `json:"file_url"`
|
|
YoutubeURL string `json:"youtube_url"`
|
|
Latitude *float64 `json:"latitude"`
|
|
Longitude *float64 `json:"longitude"`
|
|
Attachments []struct {
|
|
Name string `json:"name"`
|
|
URL string `json:"url"`
|
|
MimeType string `json:"mime_type"`
|
|
Size int64 `json:"size"`
|
|
} `json:"attachments"`
|
|
}
|
|
|
|
func (ctrl *EventController) CreateEvent(c *gin.Context) {
|
|
// Ensure latest schema (adds columns if missing)
|
|
_ = ctrl.DB.AutoMigrate(&models.Event{}, &models.EventAttachment{})
|
|
var input EventInput
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
userID, _ := c.Get("userID")
|
|
event := models.Event{
|
|
Title: input.Title,
|
|
Description: input.Description,
|
|
StartTime: input.StartTime,
|
|
EndTime: input.EndTime,
|
|
Location: input.Location,
|
|
Type: models.EventType(input.Type),
|
|
IsPublic: input.IsPublic,
|
|
CreatedByID: userID.(uint),
|
|
CategoryName: input.CategoryName,
|
|
ImageURL: input.ImageURL,
|
|
FileURL: input.FileURL,
|
|
YoutubeURL: input.YoutubeURL,
|
|
Latitude: input.Latitude,
|
|
Longitude: input.Longitude,
|
|
}
|
|
|
|
if err := ctrl.DB.Create(&event).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create event"})
|
|
return
|
|
}
|
|
// Create attachments if any
|
|
if len(input.Attachments) > 0 {
|
|
var atts []models.EventAttachment
|
|
for _, a := range input.Attachments {
|
|
if a.URL == "" { continue }
|
|
atts = append(atts, models.EventAttachment{ EventID: event.ID, Name: a.Name, URL: a.URL, MimeType: a.MimeType, Size: a.Size })
|
|
}
|
|
if len(atts) > 0 {
|
|
if err := ctrl.DB.Create(&atts).Error; err != nil {
|
|
// non-fatal
|
|
}
|
|
}
|
|
}
|
|
|
|
// Reload with attachments
|
|
var out models.Event
|
|
_ = ctrl.DB.Preload("Attachments").First(&out, event.ID).Error
|
|
|
|
// Track file usage
|
|
fileTracker := services.NewFileTracker(ctrl.DB)
|
|
go fileTracker.TrackEventFiles(&out)
|
|
|
|
c.JSON(http.StatusCreated, out)
|
|
}
|
|
|
|
func (ctrl *EventController) GetEvents(c *gin.Context) {
|
|
var events []models.Event
|
|
query := ctrl.DB.Preload("Attachments")
|
|
// Admin sees all events
|
|
if roleVal, hasRole := c.Get("userRole"); hasRole {
|
|
if role, _ := roleVal.(string); role == "admin" {
|
|
if err := query.Find(&events).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch events"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, events)
|
|
return
|
|
}
|
|
}
|
|
if userID, exists := c.Get("userID"); !exists {
|
|
query = query.Where("is_public = ?", true)
|
|
} else {
|
|
query = query.Where("created_by_id = ? OR is_public = ?", userID, true)
|
|
}
|
|
|
|
if err := query.Find(&events).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch events"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, events)
|
|
}
|
|
|
|
func (ctrl *EventController) GetUpcomingEvents(c *gin.Context) {
|
|
var events []models.Event
|
|
query := ctrl.DB.Preload("Attachments").Where("start_time >= ?", time.Now()).Order("start_time ASC").Limit(5)
|
|
// Admin sees all upcoming events
|
|
if roleVal, hasRole := c.Get("userRole"); hasRole {
|
|
if role, _ := roleVal.(string); role == "admin" {
|
|
if err := query.Find(&events).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch events"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, events)
|
|
return
|
|
}
|
|
}
|
|
if userID, exists := c.Get("userID"); !exists {
|
|
query = query.Where("is_public = ?", true)
|
|
} else {
|
|
query = query.Where("created_by_id = ? OR is_public = ?", userID, true)
|
|
}
|
|
|
|
if err := query.Find(&events).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch events"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, events)
|
|
}
|
|
|
|
// UpdateEvent updates an existing event (protected)
|
|
func (ctrl *EventController) UpdateEvent(c *gin.Context) {
|
|
// Ensure latest schema (adds columns if missing)
|
|
_ = ctrl.DB.AutoMigrate(&models.Event{}, &models.EventAttachment{})
|
|
id := c.Param("id")
|
|
var ev models.Event
|
|
if err := ctrl.DB.First(&ev, id).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "Event not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"})
|
|
return
|
|
}
|
|
var input EventInput
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
ev.Title = input.Title
|
|
ev.Description = input.Description
|
|
ev.StartTime = input.StartTime
|
|
ev.EndTime = input.EndTime
|
|
ev.Location = input.Location
|
|
ev.Type = models.EventType(input.Type)
|
|
ev.IsPublic = input.IsPublic
|
|
ev.CategoryName = input.CategoryName
|
|
ev.ImageURL = input.ImageURL
|
|
ev.FileURL = input.FileURL
|
|
ev.YoutubeURL = input.YoutubeURL
|
|
ev.Latitude = input.Latitude
|
|
ev.Longitude = input.Longitude
|
|
if err := ctrl.DB.Save(&ev).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update event"})
|
|
return
|
|
}
|
|
// Replace attachments (simple strategy)
|
|
if err := ctrl.DB.Where("event_id = ?", ev.ID).Delete(&models.EventAttachment{}).Error; err == nil {
|
|
if len(input.Attachments) > 0 {
|
|
var atts []models.EventAttachment
|
|
for _, a := range input.Attachments {
|
|
if a.URL == "" { continue }
|
|
atts = append(atts, models.EventAttachment{ EventID: ev.ID, Name: a.Name, URL: a.URL, MimeType: a.MimeType, Size: a.Size })
|
|
}
|
|
if len(atts) > 0 {
|
|
_ = ctrl.DB.Create(&atts).Error
|
|
}
|
|
}
|
|
}
|
|
var out models.Event
|
|
_ = ctrl.DB.Preload("Attachments").First(&out, ev.ID).Error
|
|
|
|
// Track file usage
|
|
fileTracker := services.NewFileTracker(ctrl.DB)
|
|
go fileTracker.TrackEventFiles(&out)
|
|
|
|
c.JSON(http.StatusOK, out)
|
|
}
|
|
|
|
// DeleteEvent removes an event (protected)
|
|
func (ctrl *EventController) DeleteEvent(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if err := ctrl.DB.Delete(&models.Event{}, id).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete event"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"ok": true})
|
|
}
|