Class: ApplicationController

Inherits:
ActionController::Base
  • Object
show all
Defined in:
app/controllers/application_controller.rb

Direct Known Subclasses

ConcertoConfigController, ConcertoPluginsController, ContentsController, DashboardController, ErrorsController, FeedsController, FieldConfigsController, Frontend::ContentsController, Frontend::FieldsController, Frontend::ScreensController, Frontend::TemplatesController, GroupsController, KindsController, MediaController, MembershipsController, ScreensController, SubmissionsController, SubscriptionsController, TemplatesController, UsersController

Instance Method Summary (collapse)

Instance Method Details

- (Object) after_sign_in_path_for(resource)

Redirect the user to the dashboard after signing in.



335
336
337
# File 'app/controllers/application_controller.rb', line 335

def (resource)
  dashboard_path
end

- (Object) allow_cors

Cross-Origin Resource Sharing for JS interfaces Browsers are very selective about allowing CORS when Authentication headers are present. They require us to use an origin by name, not *, and to specifically allow authorization credentials (twice).



326
327
328
329
330
331
332
# File 'app/controllers/application_controller.rb', line 326

def allow_cors
  origin = request.headers['origin']
  headers['Access-Control-Allow-Origin'] = origin || '*'
  headers['Access-Control-Allow-Methods'] = '*'
  headers['Access-Control-Allow-Credentials'] = 'true'
  headers['Access-Control-Allow-Headers'] = 'Authorization'
end

- (Object) auth!(opts = {})

Authenticate using the current action and instance variables. If the instance variable is an Enumerable or ActiveRecord::Relation we remove anything that we cannot? from the array. If the instance variable is a single object, we raise CanCan::AccessDenied if we cannot? the object.

or raise if empty.

Parameters:

  • opts (Hash) (defaults to: {})

    The options to authenticate with.

Options Hash (opts):

  • action (Symbol)

    The CanCan action to test.

  • object (Object)

    The object we should be testing.

  • allow_empty (Boolean) — default: true

    If we should allow an empty array.

  • new_exception (Boolean) — default: true

    Allow the user to the page if they can create new objects, regardless of the empty status.



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'app/controllers/application_controller.rb', line 268

def auth!(opts = {})
  action_map = {
    'index' => :read,
    'show' => :read,
    'new' => :create,
    'edit' => :update,
    'create' => :create,
    'update' => :update,
    'destroy' => :delete,
  }

  test_action = (opts[:action] || action_map[action_name])
  allow_empty = true
  if !opts[:allow_empty].nil?
    allow_empty = opts[:allow_empty]
  end

  new_exception = true
  if !opts[:new_exception].nil?
    new_exception = opts[:new_exception]
  end

  var_name = controller_name
  if action_name != 'index'
    var_name = controller_name.singularize
  end
  object = (opts[:object] || instance_variable_get("@#{var_name}"))

  unless object.nil?
    if ((object.is_a? Enumerable) || (object.is_a? ActiveRecord::Relation))
      object.delete_if {|o| cannot?(test_action, o)}
      if new_exception && object.empty?
        # Parent will be Object for Concerto, or the module for Plugins.
        new_parent = self.class.parent
        class_name =  controller_name.singularize.classify
        new_class = new_parent.const_get(class_name) if new_parent.const_defined?(class_name)
        new_object = new_class.new if !new_class.nil?
        return true if can?(:create, new_object)
      end
      if !allow_empty && object.empty?
        fake_cancan = Class.new.extend(CanCan::Ability)
        message ||= fake_cancan.unauthorized_message(test_action, object.class)
        raise CanCan::AccessDenied.new(message, test_action, object.class)
      end
    else
      if cannot?(test_action, object)
        fake_cancan = Class.new.extend(CanCan::Ability)
        message ||= fake_cancan.unauthorized_message(test_action, object.class)
        raise CanCan::AccessDenied.new(message, test_action, object.class)
      end
    end
  end
end

- (Object) check_for_initial_install

If there are no users defined yet, redirect to create the first admin user



240
241
242
243
244
245
246
247
248
# File 'app/controllers/application_controller.rb', line 240

def check_for_initial_install
  #Don't do anything if a user is logged in
  unless user_signed_in?
    #if the flag set in the seeds file still isn't set to true and there are no users, let's do our thing
    if !User.exists? && !ConcertoConfig[:setup_complete]
      redirect_to new_user_registration_path
    end
  end
end

- (Object) compute_pending_moderation

Expose a instance variable counting the number of pending submissions a user can moderate. 0 indicates no pending submissions.



217
218
219
220
221
222
223
224
225
# File 'app/controllers/application_controller.rb', line 217

def compute_pending_moderation
  @pending_submissions_count = 0
  if user_signed_in?
    feeds = current_user.owned_feeds
    feeds.each do |f|
      @pending_submissions_count += f.submissions_to_moderate.count
    end
  end
end

- (Object) current_ability

Current Ability for CanCan authorization This matches CanCan's code but is here to be explicit, since we modify @current_ability below for plugins.



18
19
20
# File 'app/controllers/application_controller.rb', line 18

def current_ability
  @current_ability ||= ::Ability.new(current_accessor)
end

- (Object) current_accessor

Determine the current logged-in screen or user to be used for auth on the current action. Used by current_ability and use_plugin_ability



25
26
27
28
29
30
# File 'app/controllers/application_controller.rb', line 25

def current_accessor
  if @screen_api
    @current_accessor ||= current_screen
  end
  @current_accessor ||= current_user
end

- (Object) current_screen

current_screen finds the currently authenticated screen based on a cookie or HTTP basic auth sent with the request. Remember, this is only used on actions with the screen_api filter. On all other actions, screen auth is ignored and the current_accessor is the logged in user or anonymous.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/controllers/application_controller.rb', line 37

def current_screen
  if @current_screen.nil?
    unless request.authorization.blank?
      (user,pass) = http_basic_user_name_and_password
      if user=="screen" and !pass.nil?
        @current_screen = Screen.find_by_screen_token(pass)
        if params.has_key? :request_cookie
          cookies.permanent[:concerto_screen_token] = pass
        end
      end
    end
    if @current_screen.nil? and cookies.has_key? :concerto_screen_token
      token = cookies[:concerto_screen_token]
      @current_screen = Screen.find_by_screen_token(token)
    end
  end
  @current_screen
end

- (Object) http_basic_user_name_and_password



56
57
58
# File 'app/controllers/application_controller.rb', line 56

def http_basic_user_name_and_password
  ActionController::HttpAuthentication::Basic.user_name_and_password(request)
end

- (Object) precompile_error_catch



120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'app/controllers/application_controller.rb', line 120

def precompile_error_catch
  require 'yaml'
  concerto_base_config = YAML.load_file("./config/concerto.yml")
  if concerto_base_config['compile_production_assets'] == true  
    if File.exist?('public/assets/manifest.yml') == false && Rails.env.production?
      precompile_status = system("env RAILS_ENV=production bundle exec rake assets:precompile")
      if precompile_status == true
        restart_webserver()
      else
        raise "Asset precompilation failed. Please make sure the command rake assets:precompile works."
      end
    end
  end
end

- (Model?) process_notification(ar_instance, pa_params, options = {})

Record and send notification of an activity.

Parameters:

  • ar_instance (ActiveRecord<#create_activity>)

    Instance of the model on which activity is being tracked; for this to work, its class needs to include PublicActivity::Common.

  • pa_params (Hash)

    Any information you want to send to PublicActivity to be stored in the params column. This is redundant since you can also include them in the options.

  • options (Hash) (defaults to: {})

    Options to send to PublicActivity like :key, :action, :owner, and :recipient (see rubydoc.info/gems/public_activity/PublicActivity/Common:create_activity).

Returns:

  • (Model, nil)

    New activity if created successfully, otherwise nil.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'app/controllers/application_controller.rb', line 188

def process_notification(ar_instance, pa_params, options = {})
  return nil if ar_instance.nil? || !ar_instance.respond_to?('create_activity')

  options[:params] ||= {}
  options[:params].merge!(pa_params) unless pa_params.nil?
  activity = ar_instance.create_activity(options)
  # form the actionmailer method name by combining the class name with the action being performed (e.g. "submission_update")
  am_string = "#{ar_instance.class.name.downcase}_#{options[:action]}"
  # If ActivityMailer can find a method by the formulated name, pass in the activity (everything we know about what was done)
  if ActivityMailer.respond_to?(am_string) && (options[:recipient].nil? || options[:owner].nil? || options[:recipient] != options[:owner])
    #fulfilling bamnet's expansive notification ambitions via metaprogramming since 2013
    begin
      ActivityMailer.send(am_string, activity).deliver
    #make an effort to catch all mail-related exceptions after sending the mail - IOError will catch anything for sendmail, SMTP for the rest
    rescue IOError, Net::SMTPAuthenticationError, Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError => e
      Rails.logger.debug "Mail delivery failed at #{Time.now.to_s} for #{options[:recipient]}: #{e.message}"
      ConcertoConfig.first.create_activity :action => :system_notification, :params => {:message => t(:smtp_send_error)}
    rescue OpenSSL::SSL::SSLError => e
      Rails.logger.debug "Mail delivery failed at #{Time.now.to_s} for #{options[:recipient]}: #{e.message} -- might need to disable SSL Verification in settings"
      ConcertoConfig.first.create_activity :action => :system_notification, :params => {:message => t(:smtp_send_error_ssl)}
    end
  end

  activity
end

- (Object) restart_webserver



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'app/controllers/application_controller.rb', line 82

def restart_webserver
  unless webserver_supports_restart?
    flash[:notice] = t(:wont_write_restart_txt)
    return false      
  end    
  begin
    File.open("tmp/restart.txt", "w") {}
    return true
  rescue
    #generally a write permission error
    flash[:notice] = t(:cant_write_restart_txt)
    return false
  end
end

- (Object) screen_api

Call this with a before filter to indicate that the current action should be treated as a Screen API page. On Screen API pages, the current logged-in screen (if there is one) is used instead of the current user. For non-screen API pages, it is impossible for a screen to view the page (though that may change).



78
79
80
# File 'app/controllers/application_controller.rb', line 78

def screen_api
  @screen_api=true
end

- (Object) set_locale



231
232
233
234
235
236
237
# File 'app/controllers/application_controller.rb', line 231

def set_locale
  if user_signed_in? && current_user.locale != ""
    session[:locale] = current_user.locale
  end

  I18n.locale = session[:locale] || I18n.default_locale
end

- (Object) set_time_zone(&block)



97
98
99
100
101
102
103
# File 'app/controllers/application_controller.rb', line 97

def set_time_zone(&block)
  if user_signed_in? && !current_user.time_zone.nil?
    Time.use_zone(current_user.time_zone, &block)
  else 
    Time.use_zone(ConcertoConfig[:system_time_zone], &block)
  end
end

- (Object) set_version



227
228
229
# File 'app/controllers/application_controller.rb', line 227

def set_version
  require 'concerto/version'
end

- (Object) sign_in_screen(screen)



60
61
62
63
# File 'app/controllers/application_controller.rb', line 60

def (screen)
  token = screen.generate_screen_token!
  cookies.permanent[:concerto_screen_token]=token
end

- (Object) sign_out_screen



65
66
67
68
69
70
71
# File 'app/controllers/application_controller.rb', line 65

def sign_out_screen
  if !current_screen.nil?
    current_screen.clear_screen_token!
    @current_screen = nil
  end
  cookies.permanent[:concerto_screen_token]=""
end

- (Object) switch_to_main_app_ability

Revert to the main app ability after using a plugin ability (if it was defined). Used by ConcertoPlugin for rendering hooks, and by use_plugin_ability block above.



175
176
177
# File 'app/controllers/application_controller.rb', line 175

def switch_to_main_app_ability
  @current_ability = @main_app_ability # it is okay if this is nil
end

- (Object) switch_to_plugin_ability(mod)

Store the current ability (if defined) and switch to the ability class for the specified plugin, if it has one. Always call switch_to_main_app_ability when done. Used by ConcertoPlugin for rendering hooks, and by use_plugin_ability block above.



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'app/controllers/application_controller.rb', line 148

def switch_to_plugin_ability(mod)
  @main_app_ability = @current_ability
  @plugin_abilities = @plugin_abilities || {}
  mod_sym = mod.name.to_sym
  if @plugin_abilities[mod_sym].nil?
    begin
      ability = (mod.name+"::Ability").constantize
    rescue
      ability = nil
    end
    if ability.nil?
      # Presumably this plugin doesn't define its own rules, no biggie
      logger.warn "ConcertoPlugin: use_plugin_ability: "+
        "No Ability found for "+mod.name
    else
      @plugin_abilities[mod_sym] ||= ability.new(current_accessor)
      @current_ability = @plugin_abilities[mod_sym]
    end
  else
    @current_ability = @plugin_abilities[mod_sym]
  end
end

- (Object) use_plugin_ability(mod, &block)

Allow views in the main application to do authorization checks for plugins.



137
138
139
140
141
# File 'app/controllers/application_controller.rb', line 137

def use_plugin_ability(mod, &block)
  switch_to_plugin_ability(mod)
  yield
  switch_to_main_app_ability
end

- (Boolean) webserver_supports_restart?

Returns:

  • (Boolean)


105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'app/controllers/application_controller.rb', line 105

def webserver_supports_restart?
  #add any webservers that don't support tmp/restart.txt to this array
  no_restart_txt = ["webrick"]  
  no_restart_txt.each do |w|    
    #check if the server environment contains a webserver that doesn't support restart.txt
    #This is NOT foolproof - a webserver may elect not to send this
    server_match = /\S*#{w}/.match(env['SERVER_SOFTWARE'].to_s.downcase)
    if server_match.nil?
      return true
    else
      return false
    end
  end
end