Class: Screen

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
ActiveModel::ForbiddenAttributesProtection, PublicActivity::Common
Defined in:
app/models/screen.rb

Constant Summary

AUTH_NO_ACTION =

Define some actions for communication with the Screens form

0
AUTH_KEEP_TOKEN =
1
AUTH_LEGACY_SCREEN =
2
AUTH_NEW_TOKEN =
3
AUTH_NO_SECURITY =
4
TEMP_TOKEN_LENGTH =

Must be even.

6
ONLINE_THRESHOLD =

Scopes

5.minutes
OFFLINE_THRESHOLD =
5.minutes
SCREEN_OWNER_TYPES =

types of entities that may “own” a screen

["User", "Group"]

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) find_by_mac(mac_addr)



101
102
103
104
105
106
107
108
109
110
# File 'app/models/screen.rb', line 101

def self.find_by_mac(mac_addr)
  begin
    mac = MacAddr::condense(mac_addr)
    token = "mac:#{mac}"
    screen = Screen.where(:authentication_token => token).first
    return screen
  rescue ActiveRecord::ActiveRecordError
    return nil
  end
end

+ (Object) find_by_screen_token(token)



131
132
133
134
135
136
137
138
# File 'app/models/screen.rb', line 131

def self.find_by_screen_token(token)
  return nil if token.blank?
  begin
    Screen.where(:authentication_token=>'auth:'+token).first
  rescue ActiveRecord::ActiveRecordError
    nil
  end
end

+ (Object) find_by_temp_token(token)



177
178
179
180
181
182
183
184
# File 'app/models/screen.rb', line 177

def self.find_by_temp_token(token)
  return nil if token.blank?
  begin
    Screen.where(:authentication_token=>'temp:'+token).first
  rescue ActiveRecord::ActiveRecordError
    nil
  end
end

+ (Object) generate_temp_token

The token is first associated with a session, not a Screen, so it is generated independent of a particular instance



161
162
163
164
165
# File 'app/models/screen.rb', line 161

def self.generate_temp_token
  require 'securerandom'
  token = SecureRandom.hex(3) # Short token (length 3*2) since the user will enter this
  return token
end

Instance Method Details

- (Object) aspect_ratio

Determine the screen's aspect ratio. If it doesn't exist, calculate it



64
65
66
67
68
69
70
71
72
# File 'app/models/screen.rb', line 64

def aspect_ratio
  if width.nil? || height.nil?
    return { :width=> "", :height=> "" }
  end
  gcd = gcd(width,height)
  aspect_width = width/gcd
  aspect_height = height/gcd
  return {:width => aspect_width, :height => aspect_height }
end

- (Object) auth_action

Radio button default



199
200
201
202
203
204
205
# File 'app/models/screen.rb', line 199

def auth_action
  return AUTH_NEW_TOKEN if !self.new_temp_token.blank?
  return AUTH_NO_SECURITY if self.unsecured?
  return AUTH_KEEP_TOKEN if self.auth_in_progress? or self.auth_by_token?
  return AUTH_LEGACY_SCREEN if self.auth_by_mac?
  return 0
end

- (Object) auth_action=(action)

Store the value for this fake param until the callback is run.



189
190
191
192
193
194
195
196
# File 'app/models/screen.rb', line 189

def auth_action=(action)
  action = action.to_i
  if [AUTH_NEW_TOKEN, AUTH_NO_SECURITY].include? action
    @auth_action=action
  else
    @auth_action=AUTH_NO_ACTION
  end
end

- (Boolean) auth_by_mac?

Not really “authenticated”, but you get the point



242
243
244
245
# File 'app/models/screen.rb', line 242

def auth_by_mac? # Not really "authenticated", but you get the point
  !self.authentication_token.nil? and
     self.authentication_token.start_with? 'mac:'
end

- (Boolean) auth_by_token?



232
233
234
235
# File 'app/models/screen.rb', line 232

def auth_by_token?
  !self.authentication_token.nil? and
    self.authentication_token.start_with? 'auth:'
end

- (Boolean) auth_in_progress?



237
238
239
240
# File 'app/models/screen.rb', line 237

def auth_in_progress?
  !self.authentication_token.nil? and
    self.authentication_token.start_with? 'temp:'
end

- (Object) clear_screen_token



151
152
153
# File 'app/models/screen.rb', line 151

def clear_screen_token
  self.authentication_token = ''
end

- (Object) clear_screen_token!



147
148
149
# File 'app/models/screen.rb', line 147

def clear_screen_token!
  self.update_attribute(:authentication_token, '')
end

- (Object) clear_temp_token



155
156
157
# File 'app/models/screen.rb', line 155

def clear_temp_token
  self.new_temp_token = ''
end

- (String) frontend_cache_key(*args)

Compute a cache key suitable for use in the frontend. Combines the updated information for the screen, template, positions, and fields to make a single key.



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'app/models/screen.rb', line 254

def frontend_cache_key(*args)
  max_updated_at = self.updated_at.try(:utc).try(:to_i)
  max_updated_at = [self.template.updated_at.try(:utc).try(:to_i), max_updated_at].max
  self.template.positions.each do |p|
    max_updated_at = [p.updated_at.try(:utc).try(:to_i), p.field.updated_at.try(:utc).try(:to_i), max_updated_at].max
    p.field.field_configs.each do |field_config|
      if !field_config.updated_at.nil?
        max_updated_at = [field_config.updated_at.try(:utc).try(:to_i),max_updated_at].max
      end
    end
end
  args.each do |ao|
    if ao.methods.include? 'updated_at'
      max_updated_at = [ao.updated_at.try(:utc).try(:to_i), max_updated_at].max
    end
  end
  return "frontend-screen/#{self.id}-#{self.template.id}-#{max_updated_at}"
end

- (Object) gcd(a, b)

Run Euclidean algorithm to find GCD



75
76
77
78
79
80
# File 'app/models/screen.rb', line 75

def gcd (a,b)
  if b == 0
    return a
  end
  return gcd(b, a.modulo(b))
end

- (Object) generate_screen_token!



140
141
142
143
144
145
# File 'app/models/screen.rb', line 140

def generate_screen_token!
  require 'securerandom'
  token = SecureRandom.hex
  self.update_attribute(:authentication_token, 'auth:'+token)
  return token
end

- (Boolean) is_offline?



97
98
99
# File 'app/models/screen.rb', line 97

def is_offline?
  frontend_updated_at.nil? || frontend_updated_at < (Clock.time - Screen::OFFLINE_THRESHOLD)
end

- (Boolean) is_online?



93
94
95
# File 'app/models/screen.rb', line 93

def is_online?
  !frontend_updated_at.nil? && frontend_updated_at >= (Clock.time - Screen::ONLINE_THRESHOLD)
end

- (Object) mac_address



121
122
123
124
125
# File 'app/models/screen.rb', line 121

def mac_address
  mac = token_by_type('mac')
  mac = MacAddr::expand(mac) unless mac.nil?
  return mac
end

- (Object) mac_address=(mac_addr)



112
113
114
115
116
117
118
119
# File 'app/models/screen.rb', line 112

def mac_address=(mac_addr)
  mac = MacAddr::condense(mac_addr)
  if !mac.empty?
    self.authentication_token = "mac:#{mac}"
  else
    self.authentication_token = nil
  end
end

- (Object) mark_updated



82
83
84
# File 'app/models/screen.rb', line 82

def mark_updated
  update_column(:frontend_updated_at, Clock.time)
end

- (Object) new_temp_token



212
213
214
# File 'app/models/screen.rb', line 212

def new_temp_token
  @new_temp_token || ""
end

- (Object) new_temp_token=(token)

Store the value for this fake param until the callback is run.



208
209
210
# File 'app/models/screen.rb', line 208

def new_temp_token=(token)
  @new_temp_token=token
end

- (Object) screen_token



127
128
129
# File 'app/models/screen.rb', line 127

def screen_token
  token_by_type('auth')
end

- (Object) sometimes_mark_updated(pct = 0.1)

Mark the screen as updated some percentage of the time. Doesn't always mark the screen as updated to avoid flooding the database but does it frequently enought for online / offline detection.



89
90
91
# File 'app/models/screen.rb', line 89

def sometimes_mark_updated(pct=0.1)
  mark_updated if rand() <= pct
end

- (Object) temp_token



173
174
175
# File 'app/models/screen.rb', line 173

def temp_token
  token_by_type('temp')
end

- (Object) temp_token=(token)



167
168
169
170
171
# File 'app/models/screen.rb', line 167

def temp_token=(token)
  if !token.nil? and !token.empty? #TODO: Validate
    self.authentication_token = "temp:#{token}"
  end
end

- (Boolean) unsecured?



227
228
229
230
# File 'app/models/screen.rb', line 227

def unsecured?
  self.authentication_token.nil? or
    !self.authentication_token.start_with? 'auth:', 'temp:', 'mac:'
end

- (Object) unsecured_screens_must_be_public



45
46
47
48
49
# File 'app/models/screen.rb', line 45

def unsecured_screens_must_be_public
  if !is_public? and (unsecured? or auth_by_mac?)
    errors.add(:base, 'Screens must be publicly viewable if they are not secured by a token.')
  end
end

- (Object) update_authentication

Callback to execute the action requested by the form, based on the provided data.



218
219
220
221
222
223
224
225
# File 'app/models/screen.rb', line 218

def update_authentication
  if @auth_action == AUTH_NO_SECURITY
    self.clear_screen_token
    self.clear_temp_token
  elsif @auth_action == AUTH_NEW_TOKEN
    self.temp_token=@new_temp_token
  end
end