first commit
Made-with: Cursor
This commit is contained in:
132
internal/service/attendee.go
Normal file
132
internal/service/attendee.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/calendarapi/internal/models"
|
||||
"github.com/calendarapi/internal/repository"
|
||||
"github.com/calendarapi/internal/utils"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
type AttendeeService struct {
|
||||
queries *repository.Queries
|
||||
calendar *CalendarService
|
||||
}
|
||||
|
||||
func NewAttendeeService(queries *repository.Queries, calendar *CalendarService) *AttendeeService {
|
||||
return &AttendeeService{queries: queries, calendar: calendar}
|
||||
}
|
||||
|
||||
func (s *AttendeeService) AddAttendees(ctx context.Context, userID uuid.UUID, eventID uuid.UUID, attendees []AddAttendeeRequest) (*models.Event, error) {
|
||||
ev, err := s.queries.GetEventByID(ctx, utils.ToPgUUID(eventID))
|
||||
if err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, models.ErrNotFound
|
||||
}
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
calID := utils.FromPgUUID(ev.CalendarID)
|
||||
role, err := s.calendar.GetRole(ctx, calID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if role != "owner" && role != "editor" {
|
||||
return nil, models.ErrForbidden
|
||||
}
|
||||
|
||||
for _, a := range attendees {
|
||||
_, err := s.queries.CreateAttendee(ctx, repository.CreateAttendeeParams{
|
||||
ID: utils.ToPgUUID(uuid.New()),
|
||||
EventID: utils.ToPgUUID(eventID),
|
||||
UserID: optionalPgUUID(a.UserID),
|
||||
Email: utils.ToPgTextPtr(a.Email),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
}
|
||||
|
||||
reminders, _ := loadRemindersHelper(ctx, s.queries, eventID)
|
||||
atts, _ := loadAttendeesHelper(ctx, s.queries, eventID)
|
||||
attachments, _ := loadAttachmentsHelper(ctx, s.queries, eventID)
|
||||
return eventFromDB(ev, reminders, atts, attachments), nil
|
||||
}
|
||||
|
||||
func (s *AttendeeService) UpdateStatus(ctx context.Context, userID uuid.UUID, eventID uuid.UUID, attendeeID uuid.UUID, status string) (*models.Event, error) {
|
||||
ev, err := s.queries.GetEventByID(ctx, utils.ToPgUUID(eventID))
|
||||
if err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, models.ErrNotFound
|
||||
}
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
calID := utils.FromPgUUID(ev.CalendarID)
|
||||
role, err := s.calendar.GetRole(ctx, calID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
att, err := s.queries.GetAttendeeByID(ctx, utils.ToPgUUID(attendeeID))
|
||||
if err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, models.ErrNotFound
|
||||
}
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
isOrganizer := role == "owner" || role == "editor"
|
||||
isOwnAttendee := att.UserID.Valid && utils.FromPgUUID(att.UserID) == userID
|
||||
if !isOrganizer && !isOwnAttendee {
|
||||
return nil, models.ErrForbidden
|
||||
}
|
||||
|
||||
if status != "pending" && status != "accepted" && status != "declined" && status != "tentative" {
|
||||
return nil, models.NewValidationError("status must be pending, accepted, declined, or tentative")
|
||||
}
|
||||
|
||||
_, err = s.queries.UpdateAttendeeStatus(ctx, repository.UpdateAttendeeStatusParams{
|
||||
ID: utils.ToPgUUID(attendeeID),
|
||||
Status: status,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
reminders, _ := loadRemindersHelper(ctx, s.queries, eventID)
|
||||
atts, _ := loadAttendeesHelper(ctx, s.queries, eventID)
|
||||
attachments, _ := loadAttachmentsHelper(ctx, s.queries, eventID)
|
||||
return eventFromDB(ev, reminders, atts, attachments), nil
|
||||
}
|
||||
|
||||
func (s *AttendeeService) DeleteAttendee(ctx context.Context, userID uuid.UUID, eventID uuid.UUID, attendeeID uuid.UUID) error {
|
||||
ev, err := s.queries.GetEventByID(ctx, utils.ToPgUUID(eventID))
|
||||
if err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return models.ErrInternal
|
||||
}
|
||||
|
||||
calID := utils.FromPgUUID(ev.CalendarID)
|
||||
role, err := s.calendar.GetRole(ctx, calID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if role != "owner" && role != "editor" {
|
||||
return models.ErrForbidden
|
||||
}
|
||||
|
||||
return s.queries.DeleteAttendee(ctx, repository.DeleteAttendeeParams{
|
||||
ID: utils.ToPgUUID(attendeeID),
|
||||
EventID: utils.ToPgUUID(eventID),
|
||||
})
|
||||
}
|
||||
|
||||
type AddAttendeeRequest struct {
|
||||
UserID *uuid.UUID
|
||||
Email *string
|
||||
}
|
||||
Reference in New Issue
Block a user