package store import "gorm.io/gorm" func (s *Store) ListVisitors() ([]User, error) { var users []User err := s.db.Where("role = ?", "visitor").Order("id asc").Find(&users).Error return users, err } func (s *Store) ListResourceVisitorIDs(resourceType string, resourceID uint) ([]uint, error) { var bindings []ResourceVisitor err := s.db.Where("resource_type = ? AND resource_id = ?", resourceType, resourceID). Order("user_id asc").Find(&bindings).Error if err != nil { return nil, err } ids := make([]uint, len(bindings)) for i, b := range bindings { ids[i] = b.UserID } return ids, nil } func (s *Store) SetResourceVisitors(resourceType string, resourceID uint, userIDs []uint) error { return s.db.Transaction(func(tx *gorm.DB) error { if err := tx.Where("resource_type = ? AND resource_id = ?", resourceType, resourceID). Delete(&ResourceVisitor{}).Error; err != nil { return err } for _, uid := range userIDs { rv := ResourceVisitor{ ResourceType: resourceType, ResourceID: resourceID, UserID: uid, } if err := tx.Create(&rv).Error; err != nil { return err } } return nil }) } func (s *Store) DeleteResourceVisitors(resourceType string, resourceID uint) error { return s.db.Where("resource_type = ? AND resource_id = ?", resourceType, resourceID). Delete(&ResourceVisitor{}).Error } func (s *Store) ListAllResourceVisitors() ([]ResourceVisitor, error) { var items []ResourceVisitor err := s.db.Order("resource_type, resource_id, user_id").Find(&items).Error return items, err } const MaxVisitorAccessLogsPerUser = 200 func (s *Store) AppendVisitorAccessLog(entry *VisitorAccessLog) error { return s.db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(entry).Error; err != nil { return err } var keepIDs []uint if err := tx.Model(&VisitorAccessLog{}).Where("user_id = ?", entry.UserID). Order("id desc").Limit(MaxVisitorAccessLogsPerUser).Pluck("id", &keepIDs).Error; err != nil { return err } if len(keepIDs) == 0 { return nil } return tx.Where("user_id = ? AND id NOT IN ?", entry.UserID, keepIDs). Delete(&VisitorAccessLog{}).Error }) } func (s *Store) ListVisitorAccessLogs(userID uint, limit int) ([]VisitorAccessLog, error) { if limit <= 0 || limit > MaxVisitorAccessLogsPerUser { limit = MaxVisitorAccessLogsPerUser } var items []VisitorAccessLog err := s.db.Where("user_id = ?", userID). Order("id desc").Limit(limit).Find(&items).Error return items, err } func (s *Store) DeleteVisitorAccessLogs(userID uint) error { return s.db.Where("user_id = ?", userID).Delete(&VisitorAccessLog{}).Error }