veza/veza-backend-api/internal/repositories/room_repository.go
senke 2292ecd56b
Some checks failed
Backend API CI / test-unit (push) Failing after 2s
Frontend CI / test (push) Failing after 3s
Backend API CI / test-integration (push) Failing after 5s
Storybook Audit / Build & audit Storybook (push) Failing after 2s
feat(v0.10.7): Collaboration Temps Réel F481-F483
- F481: Co-listening sessions (WebSocket sync, ListenTogether page)
- F482: Stem sharing (upload/list/download wav,aiff,flac)
- F483: Collaborative rooms (type collaborative, max 10, invite-only)
- Roadmap: v0.10.7 → DONE
2026-03-10 13:34:16 +01:00

151 lines
5 KiB
Go

package repositories
import (
"context"
"errors"
"time"
"veza-backend-api/internal/models"
"github.com/google/uuid"
"gorm.io/gorm"
)
// RoomRepository gère les opérations de base de données pour les rooms
type RoomRepository struct {
db *gorm.DB
}
// NewRoomRepository crée une nouvelle instance de RoomRepository
func NewRoomRepository(db *gorm.DB) *RoomRepository {
return &RoomRepository{db: db}
}
// Create crée une nouvelle room
func (r *RoomRepository) Create(ctx context.Context, room *models.Room) error {
return r.db.WithContext(ctx).Create(room).Error
}
// GetByID récupère une room par son ID
func (r *RoomRepository) GetByID(ctx context.Context, id uuid.UUID) (*models.Room, error) {
var room models.Room
err := r.db.WithContext(ctx).
Preload("Members").
Preload("Messages").
First(&room, "id = ?", id).Error // Use explicit WHERE clause for UUID
if err != nil {
return nil, err
}
return &room, nil
}
// GetByUserID récupère toutes les rooms d'un utilisateur
// MIGRATION UUID: userID migré vers uuid.UUID
func (r *RoomRepository) GetByUserID(ctx context.Context, userID uuid.UUID) ([]*models.Room, error) {
var rooms []*models.Room
// Note: RoomMember model doesn't have DeletedAt field, so we don't check for deleted_at
// Also, Preload("Members") would try to add deleted_at IS NULL which doesn't exist for RoomMember
// So we load members separately or use Unscoped() to avoid the deleted_at check
err := r.db.WithContext(ctx).
Joins("JOIN room_members ON rooms.id = room_members.room_id").
Where("room_members.user_id = ?", userID).
Preload("Members", func(db *gorm.DB) *gorm.DB {
// Don't add deleted_at condition since RoomMember doesn't have DeletedAt
return db
}).
Find(&rooms).Error
if err != nil {
return nil, err
}
return rooms, nil
}
// Update met à jour une room
func (r *RoomRepository) Update(ctx context.Context, room *models.Room) error {
return r.db.WithContext(ctx).Save(room).Error
}
// Delete supprime une room (soft delete)
func (r *RoomRepository) Delete(ctx context.Context, id uuid.UUID) error {
return r.db.WithContext(ctx).Delete(&models.Room{}, "id = ?", id).Error // Use explicit WHERE clause for UUID
}
// AddMember ajoute un membre à une room
func (r *RoomRepository) AddMember(ctx context.Context, member *models.RoomMember) error {
return r.db.WithContext(ctx).Create(member).Error
}
// RemoveMember retire un membre d'une room
// MIGRATION UUID: userID migré vers uuid.UUID
func (r *RoomRepository) RemoveMember(ctx context.Context, roomID uuid.UUID, userID uuid.UUID) error {
return r.db.WithContext(ctx).
Where("room_id = ? AND user_id = ?", roomID, userID).
Delete(&models.RoomMember{}).Error
}
// GetMembersByRoomID récupère tous les membres d'une room
func (r *RoomRepository) GetMembersByRoomID(ctx context.Context, roomID uuid.UUID) ([]*models.RoomMember, error) {
var members []*models.RoomMember
err := r.db.WithContext(ctx).
Where("room_id = ?", roomID).
Preload("User").
Find(&members).Error
if err != nil {
return nil, err
}
return members, nil
}
// CountMembers returns the number of members in a room
func (r *RoomRepository) CountMembers(ctx context.Context, roomID uuid.UUID) (int64, error) {
var count int64
err := r.db.WithContext(ctx).Model(&models.RoomMember{}).
Where("room_id = ?", roomID).
Count(&count).Error
return count, err
}
// GetMemberRole returns the role of a user in a room, or empty if not a member
func (r *RoomRepository) GetMemberRole(ctx context.Context, roomID uuid.UUID, userID uuid.UUID) (string, error) {
var m models.RoomMember
err := r.db.WithContext(ctx).
Where("room_id = ? AND user_id = ?", roomID, userID).
First(&m).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return "", nil
}
return "", err
}
return m.Role, nil
}
// CreateRoomInvitation creates a room invitation
func (r *RoomRepository) CreateRoomInvitation(ctx context.Context, inv *models.RoomInvitation) error {
return r.db.WithContext(ctx).Create(inv).Error
}
// GetRoomInvitationByToken returns a pending invitation by token
func (r *RoomRepository) GetRoomInvitationByToken(ctx context.Context, token uuid.UUID) (*models.RoomInvitation, error) {
var inv models.RoomInvitation
err := r.db.WithContext(ctx).
Where("token = ? AND status = ? AND expires_at > ?", token, "pending", time.Now()).
First(&inv).Error
if err != nil {
return nil, err
}
return &inv, nil
}
// UpdateRoomInvitationStatus updates invitation status
func (r *RoomRepository) UpdateRoomInvitationStatus(ctx context.Context, id uuid.UUID, status string) error {
return r.db.WithContext(ctx).Model(&models.RoomInvitation{}).
Where("id = ?", id).Update("status", status).Error
}
// UpdateMemberRole updates the role of a room member (v0.9.7)
func (r *RoomRepository) UpdateMemberRole(ctx context.Context, roomID, userID uuid.UUID, role string) error {
return r.db.WithContext(ctx).Model(&models.RoomMember{}).
Where("room_id = ? AND user_id = ?", roomID, userID).
Update("role", role).Error
}