- Implement full MessageHandler dispatch with all 18 incoming message types - Add handler_messages.go: SendMessage, EditMessage, DeleteMessage with ownership checks - Add handler_rooms.go: JoinConversation, LeaveConversation - Add handler_history.go: FetchHistory (cursor-based), SearchMessages (ILIKE), SyncMessages - Add handler_realtime.go: Typing, MarkAsRead, Delivered, AddReaction, RemoveReaction - Add handler_calls.go: WebRTC signaling relay (CallOffer/Answer/ICE/Hangup/Reject) - Add PermissionService: CanRead/CanSend/CanJoin/CanModerate based on room_members - Add RateLimiter: per-user per-action sliding window (in-memory) - Wire all dependencies in router.go setupChatWebSocket
68 lines
1.6 KiB
Go
68 lines
1.6 KiB
Go
package chat
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type PermissionService struct {
|
|
db *gorm.DB
|
|
logger *zap.Logger
|
|
}
|
|
|
|
func NewPermissionService(db *gorm.DB, logger *zap.Logger) *PermissionService {
|
|
if logger == nil {
|
|
logger = zap.NewNop()
|
|
}
|
|
return &PermissionService{
|
|
db: db,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
type roomMemberCheck struct {
|
|
Role string `gorm:"column:role"`
|
|
IsMuted bool `gorm:"column:is_muted"`
|
|
}
|
|
|
|
func (p *PermissionService) getMembership(ctx context.Context, userID, roomID uuid.UUID) (*roomMemberCheck, bool) {
|
|
var member roomMemberCheck
|
|
err := p.db.WithContext(ctx).
|
|
Table("room_members").
|
|
Select("role, is_muted").
|
|
Where("user_id = ? AND room_id = ?", userID, roomID).
|
|
First(&member).Error
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
return &member, true
|
|
}
|
|
|
|
func (p *PermissionService) CanRead(ctx context.Context, userID, roomID uuid.UUID) bool {
|
|
_, isMember := p.getMembership(ctx, userID, roomID)
|
|
return isMember
|
|
}
|
|
|
|
func (p *PermissionService) CanSend(ctx context.Context, userID, roomID uuid.UUID) bool {
|
|
member, isMember := p.getMembership(ctx, userID, roomID)
|
|
if !isMember {
|
|
return false
|
|
}
|
|
return !member.IsMuted
|
|
}
|
|
|
|
func (p *PermissionService) CanJoin(ctx context.Context, userID, roomID uuid.UUID) bool {
|
|
_, isMember := p.getMembership(ctx, userID, roomID)
|
|
return isMember
|
|
}
|
|
|
|
func (p *PermissionService) CanModerate(ctx context.Context, userID, roomID uuid.UUID) bool {
|
|
member, isMember := p.getMembership(ctx, userID, roomID)
|
|
if !isMember {
|
|
return false
|
|
}
|
|
return member.Role == "admin" || member.Role == "moderator" || member.Role == "owner"
|
|
}
|