package storage import ( "context" "database/sql" "fmt" "time" ) func (s *Store) RevokeInvitationBatchAudited(ctx context.Context, batchID, actor string) (int, error) { const operation = "revoke invitation batch" var revoked int err := s.audited(ctx, operation, actor, func(tx *sql.Tx, at time.Time) error { var members int if err := tx.QueryRowContext(ctx, `SELECT count(*) FROM invitations WHERE batch_id = ?`, batchID).Scan(&members); err != nil { return classify(operation, err) } if members == 0 { return fmt.Errorf("%s: %w", operation, ErrNotFound) } ids, err := queryIDs(ctx, tx, operation, ` SELECT id FROM invitations WHERE batch_id = ? AND used_at IS NULL AND revoked_at IS NULL AND expires_at > ? ORDER BY id`, batchID, timeToInt(at)) if err != nil { return err } for _, id := range ids { if _, err := execCount(ctx, tx, operation, `UPDATE invitations SET revoked_at = ? WHERE id = ? AND used_at IS NULL AND revoked_at IS NULL`, timeToInt(at), id); err != nil { return err } if err := writeAudit(ctx, tx, operation, actor, "invitation.revoke", id, at, map[string]any{"batch": batchID}); err != nil { return err } } revoked = len(ids) return nil }) if err != nil { return 0, err } return revoked, nil }