Class: Protector::DSL::Meta::Box

Inherits:
Object
  • Object
show all
Defined in:
lib/protector/dsl.rb

Overview

Single DSL evaluation result

Instance Attribute Summary collapse

Protection DSL collapse

Instance Method Summary collapse

Constructor Details

#initialize(adapter, model, fields, subject, entry, blocks) ⇒ Box

Returns a new instance of Box.

Parameters:

  • model (Class)

    The class of protected entity

  • fields (Array<String>)

    All the fields the model has

  • subject (Object)

    Restriction subject

  • entry (Object)

    An instance of the model

  • blocks (Array<Proc>)

    An array of protect blocks



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/protector/dsl.rb', line 15

def initialize(adapter, model, fields, subject, entry, blocks)
  @adapter     = adapter
  @model       = model
  @fields      = fields
  @access      = {}
  @scope_procs = []
  @destroyable = false

  Protector.insecurely do
    blocks.each do |b|
      case b.arity
      when 2
        instance_exec(subject, entry, &b)
      when 1
        instance_exec(subject, &b)
      else
        instance_exec(&b)
      end
    end
  end
end

Instance Attribute Details

#accessObject

Returns the value of attribute access.



8
9
10
# File 'lib/protector/dsl.rb', line 8

def access
  @access
end

#adapterObject

Returns the value of attribute adapter.



8
9
10
# File 'lib/protector/dsl.rb', line 8

def adapter
  @adapter
end

#destroyableObject

Returns the value of attribute destroyable.



8
9
10
# File 'lib/protector/dsl.rb', line 8

def destroyable
  @destroyable
end

Instance Method Details

#can(action, *fields) ⇒ Object

Enables action for given fields.

Built-in possible actions are: :read, :update, :create. You can pass any other actions you want to use with #can? afterwards.

The method enables action for every field if fields splat is empty. Use #cannot to exclude some of them afterwards.

The list of fields can be given as a Hash. In this form you can pass Range or Proc as a value. First will make Protector check against value inclusion. The latter will make it evaluate given lambda (which is supposed to return true or false determining if the value should validate or not).

Examples:

protect do
  can :read               # Can read any field
  can :read, 'f1'         # Can read `f1` field
  can :read, %w(f2 f3)    # Can read `f2`, `f3` fields
  can :update, f1: 1..2   # Can update f1 field with values between 1 and 2

  # Can create f1 field with value equal to 'olo'
  can :create, f1: lambda{|x| x == 'olo'}
end

Parameters:

  • action (Symbol)

    Action to allow

  • fields (String, Hash, Array)

    Splat of fields to allow action with

See Also:



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/protector/dsl.rb', line 105

def can(action, *fields)
  action = deprecate_actions(action)

  return @destroyable = true if action == :destroy

  @access[action] = {} unless @access[action]

  if fields.length == 0
    @fields.each { |f| @access[action][f.to_s] = nil }
  else
    fields.each do |a|
      if a.is_a?(Array)
        a.each { |f| @access[action][f.to_s] = nil }
      elsif a.is_a?(Hash)
        @access[action].merge!(a.stringify_keys)
      else
        @access[action][a.to_s] = nil
      end
    end
  end
end

#can?(action, field = false) ⇒ Boolean

Check whether you can perform custom action for given fields (or generally if no field given)

Parameters:

  • action (Symbol)

    Action to check against

  • field (String) (defaults to: false)

    Field to check against

Returns:

  • (Boolean)


192
193
194
195
196
197
198
199
# File 'lib/protector/dsl.rb', line 192

def can?(action, field=false)
  return destroyable? if action == :destroy

  return false unless @access[action]
  return !@access[action].empty? unless field

  @access[action].key?(field.to_s)
end

#cannot(action, *fields) ⇒ Object

Disables action for given fields.

Works similar (but oppositely) to #can.

Parameters:

  • action (Symbol)

    Action to disallow

  • fields (String, Hash, Array)

    Splat of fields to disallow action with

See Also:



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/protector/dsl.rb', line 136

def cannot(action, *fields)
  action = deprecate_actions(action)

  return @destroyable = false if action == :destroy

  return unless @access[action]

  if fields.length == 0
    @access.delete(action)
  else
    fields.each do |a|
      if a.is_a?(Array)
        a.each { |f| @access[action].delete(f.to_s) }
      else
        @access[action].delete(a.to_s)
      end
    end

    @access.delete(action) if @access[action].empty?
  end
end

#cannot?(*args) ⇒ Boolean

Returns:

  • (Boolean)


201
202
203
# File 'lib/protector/dsl.rb', line 201

def cannot?(*args)
  !can?(*args)
end

#creatable?(fields = false) ⇒ Boolean

Checks whether you can create a model with given field in context of current subject

Returns:

  • (Boolean)


166
167
168
# File 'lib/protector/dsl.rb', line 166

def creatable?(fields=false)
  modifiable? :create, fields
end

#destroyable?Boolean

Checks whether you can destroy a model in context of current subject

Returns:

  • (Boolean)


184
185
186
# File 'lib/protector/dsl.rb', line 184

def destroyable?
  @destroyable
end

#eval_scope_procs(instance) ⇒ Object



71
72
73
74
75
# File 'lib/protector/dsl.rb', line 71

def eval_scope_procs(instance)
  scope_procs.reduce(instance) do |relation, scope_proc|
    relation.instance_eval(&scope_proc)
  end
end

#first_uncreatable_field(fields) ⇒ Object



170
171
172
# File 'lib/protector/dsl.rb', line 170

def first_uncreatable_field(fields)
  first_unmodifiable_field :create, fields
end

#first_unupdatable_field(fields) ⇒ Object



179
180
181
# File 'lib/protector/dsl.rb', line 179

def first_unupdatable_field(fields)
  first_unmodifiable_field :update, fields
end

#readable?(field) ⇒ Boolean

Checks whether given field of a model is readable in context of current subject

Returns:

  • (Boolean)


161
162
163
# File 'lib/protector/dsl.rb', line 161

def readable?(field)
  @access[:read] && @access[:read].key?(field.to_s)
end

#relationObject



65
66
67
68
69
# File 'lib/protector/dsl.rb', line 65

def relation
  return false unless scoped?

  @relation ||= eval_scope_procs @model
end

#scope { ... } ⇒ Object

Activates the scope that selections will be filtered with

Examples:

protect do
  # You can select nothing!
  scope { none }
end

Yields:

  • Calls given model methods before the selection



55
56
57
58
# File 'lib/protector/dsl.rb', line 55

def scope(&block)
  @scope_procs << block
  @relation = false
end

#scope_procsObject



60
61
62
63
# File 'lib/protector/dsl.rb', line 60

def scope_procs
  return [@adapter.null_proc] if @scope_procs.empty? && Protector.config.paranoid?
  @scope_procs
end

#scoped?Boolean

Checks whether protection with given subject has the selection scope defined

Returns:

  • (Boolean)


39
40
41
# File 'lib/protector/dsl.rb', line 39

def scoped?
  Protector.config.paranoid? || @scope_procs.length > 0
end

#updatable?(fields = false) ⇒ Boolean

Checks whether you can update a model with given field in context of current subject

Returns:

  • (Boolean)


175
176
177
# File 'lib/protector/dsl.rb', line 175

def updatable?(fields=false)
  modifiable? :update, fields
end