Class: Dryml::PartContext

Inherits:
Object
  • Object
show all
Defined in:
lib/dryml/part_context.rb

Overview

Raised when the part context fails its integrity check.

Defined Under Namespace

Classes: TamperedWithPartContext, TypedId

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|_self| ... } ⇒ PartContext

Returns a new instance of PartContext.

Yields:

  • (_self)

Yield Parameters:



49
50
51
# File 'lib/dryml/part_context.rb', line 49

def initialize
  yield self
end

Class Attribute Details

.digestObject

Returns the value of attribute digest.



11
12
13
# File 'lib/dryml/part_context.rb', line 11

def digest
  @digest
end

.secretObject

Returns the value of attribute secret.



11
12
13
# File 'lib/dryml/part_context.rb', line 11

def secret
  @secret
end

Instance Attribute Details

#form_field_pathObject

Returns the value of attribute form_field_path.



53
54
55
# File 'lib/dryml/part_context.rb', line 53

def form_field_path
  @form_field_path
end

#localsObject

Returns the value of attribute locals.



53
54
55
# File 'lib/dryml/part_context.rb', line 53

def locals
  @locals
end

#part_nameObject

Returns the value of attribute part_name.



53
54
55
# File 'lib/dryml/part_context.rb', line 53

def part_name
  @part_name
end

#thisObject

Returns the value of attribute this.



53
54
55
# File 'lib/dryml/part_context.rb', line 53

def this
  @this
end

#this_fieldObject

Returns the value of attribute this_field.



53
54
55
# File 'lib/dryml/part_context.rb', line 53

def this_field
  @this_field
end

#this_idObject

Returns the value of attribute this_id.



53
54
55
# File 'lib/dryml/part_context.rb', line 53

def this_id
  @this_id
end

Class Method Details

.client_side_storage_uncoded(contexts, session) ⇒ Object



16
17
18
19
20
21
# File 'lib/dryml/part_context.rb', line 16

def self.client_side_storage_uncoded(contexts, session)
  contexts.inject({}) do |h, (dom_id, context)|
    h[dom_id] = context.marshal(session)
    h
  end
end

.for_call(part_name, environment, locals) ⇒ Object



32
33
34
35
36
37
38
39
# File 'lib/dryml/part_context.rb', line 32

def self.for_call(part_name, environment, locals)
  new do |c|
    c.part_name       = part_name
    c.locals          = locals.map { |l| pre_marshal(l) }
    c.this_id         = environment.typed_id
    c.form_field_path = environment.form_field_path
  end
end

.for_refresh(encoded_context, page_this, session) ⇒ Object



42
43
44
45
46
# File 'lib/dryml/part_context.rb', line 42

def self.for_refresh(encoded_context, page_this, session)
  new do |c|
    c.unmarshal(encoded_context, page_this, session)
  end
end

.pre_marshal(x) ⇒ Object



23
24
25
26
27
28
29
# File 'lib/dryml/part_context.rb', line 23

def self.pre_marshal(x)
  if x.is_a?(ActiveRecord::Base) && x.respond_to?(:typed_id)
    TypedId.new(x.typed_id)
  else
    x
  end
end

Instance Method Details

#generate_digest(data, session) ⇒ Object

Generate the HMAC keyed message digest. Uses SHA1 by default.



91
92
93
94
95
# File 'lib/dryml/part_context.rb', line 91

def generate_digest(data, session)
  secret = self.class.secret || Rails.application.secrets.secret_key_base || Rails.application.config.secret_key_base || Rails.application.config.secret_token
  key = secret.respond_to?(:call) ? secret.call(session) : secret
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new(self.class.digest), key, data)
end

#marshal(session) ⇒ Object



56
57
58
59
60
61
62
63
64
# File 'lib/dryml/part_context.rb', line 56

def marshal(session)
  context = [@part_name, @this_id, @locals]
  context << form_field_path if form_field_path
  # http://stackoverflow.com/questions/2620975/strange-n-in-base64-encoded-string-in-ruby
  # data = Base64.encode64(Marshal.dump(context)).strip
  data = Base64.strict_encode64(Marshal.dump(context)).strip
  digest = generate_digest(data, session)
  "#{data}--#{digest}"
end

#parse_this_id(page_this) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/dryml/part_context.rb', line 99

def parse_this_id(page_this)
  if this_id.nil? || this_id =="nil"
    nil
  elsif this_id == "this" || this_id == page_this._?.typed_id
    self.this = page_this
  elsif this_id =~ /^this:(.*)/ || (page_this._?.typed_id && this_id =~ /^#{page_this._?.typed_id}:(.*)/)
    self.this = page_this
    self.this_field = $1
  else
    parts = this_id.split(':')
    if parts.length == 3
      self.this       = Hobo::Model.find_by_typed_id("#{parts[0]}:#{parts[1]}")
      self.this_field = parts[2]
    else
      self.this = Hobo::Model.find_by_typed_id(this_id)
    end
  end
end

#restore_locals(locals) ⇒ Object



119
120
121
122
123
124
125
126
127
# File 'lib/dryml/part_context.rb', line 119

def restore_locals(locals)
  locals.map do |l|
    if l.is_a?(TypedId)
      Hobo::Model.find_by_typed_id(l)
    else
      l
    end
  end
end

#unmarshal(client_store, page_this, session) ⇒ Object

Unmarshal part context to a hash and verify its integrity.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/dryml/part_context.rb', line 68

def unmarshal(client_store, page_this, session)
  data, digest = CGI.unescape(client_store).strip.split('--')
  raise TamperedWithPartContext unless digest == generate_digest(data, session)

  context = Marshal.load(Base64.decode64(data))

  part_name, this_id, locals, form_field_path = context

  if Rails
    Rails.logger.info "Call part: #{part_name}. this-id = #{this_id}, locals = #{locals.inspect}"
    Rails.logger.info "         : form_field_path = #{form_field_path.inspect}" if form_field_path
  end

  self.part_name             = part_name
  self.this_id               = this_id
  self.locals                = restore_locals(locals)
  self.form_field_path       = form_field_path

  parse_this_id(page_this)
end