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)



94
95
96
97
98
99
100
101
102
103
# File 'app/models/screen.rb', line 94

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)



124
125
126
127
128
129
130
131
# File 'app/models/screen.rb', line 124

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)



170
171
172
173
174
175
176
177
# File 'app/models/screen.rb', line 170

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



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

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



57
58
59
60
61
62
63
64
65
# File 'app/models/screen.rb', line 57

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



192
193
194
195
196
197
198
# File 'app/models/screen.rb', line 192

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.



182
183
184
185
186
187
188
189
# File 'app/models/screen.rb', line 182

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

Returns:

  • (Boolean)


235
236
237
238
# File 'app/models/screen.rb', line 235

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?

Returns:

  • (Boolean)


225
226
227
228
# File 'app/models/screen.rb', line 225

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

- (Boolean) auth_in_progress?

Returns:

  • (Boolean)


230
231
232
233
# File 'app/models/screen.rb', line 230

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

- (Object) clear_screen_token



144
145
146
# File 'app/models/screen.rb', line 144

def clear_screen_token
  self.authentication_token = ''
end

- (Object) clear_screen_token!



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

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

- (Object) clear_temp_token



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

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.

Parameters:

  • args (Array<#updated_at>)

    A list of object to factor in. These objects should respond to the `updated_at` method and are skipped if they do not.

Returns:

  • (String)

    The cache key for this frontend string.



247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'app/models/screen.rb', line 247

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
  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



68
69
70
71
72
73
# File 'app/models/screen.rb', line 68

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

- (Object) generate_screen_token!



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

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

- (Boolean) is_offline?

Returns:

  • (Boolean)


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

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

- (Boolean) is_online?

Returns:

  • (Boolean)


86
87
88
# File 'app/models/screen.rb', line 86

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

- (Object) mac_address



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

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

- (Object) mac_address=(mac_addr)



105
106
107
108
109
110
111
112
# File 'app/models/screen.rb', line 105

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



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

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

- (Object) new_temp_token



205
206
207
# File 'app/models/screen.rb', line 205

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.



201
202
203
# File 'app/models/screen.rb', line 201

def new_temp_token=(token)
  @new_temp_token=token
end

- (Object) screen_token



120
121
122
# File 'app/models/screen.rb', line 120

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.



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

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

- (Object) temp_token



166
167
168
# File 'app/models/screen.rb', line 166

def temp_token
  token_by_type('temp')
end

- (Object) temp_token=(token)



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

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

- (Boolean) unsecured?

Returns:

  • (Boolean)


220
221
222
223
# File 'app/models/screen.rb', line 220

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

- (Object) update_authentication

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



211
212
213
214
215
216
217
218
# File 'app/models/screen.rb', line 211

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