Module: Sequel::Plugins::Privacy::DatasetMethods

Extended by:
T::Generic, T::Helpers, T::Sig
Defined in:
lib/sequel/plugins/privacy.rb

Constant Summary collapse

EAGER_VC_KEY =

Thread-local key for propagating the current VC to eager-load datasets via the :eager_block injected in ClassMethods#associate.

:sequel_privacy_eager_vc

Instance Method Summary collapse

Instance Method Details

#allObject



732
733
734
735
# File 'lib/sequel/plugins/privacy.rb', line 732

def all
  results = super
  opts[:viewer_context] ? results.compact : results
end

#create(values = {}) ⇒ Object



769
770
771
# File 'lib/sequel/plugins/privacy.rb', line 769

def create(values = {})
  T.cast(new(values), Sequel::Model).save
end

#for_vc(vc) ⇒ Object



690
691
692
# File 'lib/sequel/plugins/privacy.rb', line 690

def for_vc(vc)
  clone(viewer_context: vc)
end

#new(values = {}) ⇒ Object



760
761
762
763
764
765
766
# File 'lib/sequel/plugins/privacy.rb', line 760

def new(values = {})
  instance = T.unsafe(model).new(values)
  if (vc = opts[:viewer_context])
    instance.instance_variable_set(:@viewer_context, vc)
  end
  instance
end

#post_load(all_records) ⇒ Object



744
745
746
747
748
749
750
751
752
753
754
755
756
757
# File 'lib/sequel/plugins/privacy.rb', line 744

def post_load(all_records)
  vc = opts[:viewer_context]
  return super unless vc && opts[:eager]

  all_records.compact!

  old = Thread.current[EAGER_VC_KEY]
  Thread.current[EAGER_VC_KEY] = vc
  begin
    super
  ensure
    Thread.current[EAGER_VC_KEY] = old
  end
end

#row_procObject



701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
# File 'lib/sequel/plugins/privacy.rb', line 701

def row_proc
  vc = opts[:viewer_context]
  return super unless vc

  model_class = T.cast(model, ClassMethods)
  vc_key = model_class.privacy_vc_key
  proc do |values|
    old_vc = Thread.current[vc_key]
    Thread.current[vc_key] = vc
    begin
      instance = model_class.(values)
    ensure
      Thread.current[vc_key] = old_vc
    end

    next nil if instance.nil?

    instance.instance_variable_set(:@viewer_context, vc)
    next instance if Sequel::Privacy::Enforcer.in_policy_eval?
    next instance if Thread.current[EAGER_VC_KEY]

    if T.cast(instance, InstanceMethods).allow?(vc, :view)
      instance
    else
      Sequel::Privacy.logger&.debug { "Privacy denied :view on #{model_class}[#{instance.pk}]" }
      nil
    end
  end
end