• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

benwbrum / fromthepage / 18174939649

01 Oct 2025 08:36PM UTC coverage: 65.028%. Remained the same
18174939649

Pull #4950

github

web-flow
Merge 7640db234 into 8f380a269
Pull Request #4950: Rubocop lint remove array whitespaces

1848 of 3359 branches covered (55.02%)

Branch coverage included in aggregate %.

154 of 201 new or added lines in 62 files covered. (76.62%)

8087 of 11919 relevant lines covered (67.85%)

109.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.99
/app/controllers/application_controller.rb
1
class ApplicationController < ActionController::Base
1✔
2
  DEFAULT_PER_PAGE = 200
1✔
3

4
  protect_from_forgery with: :exception, except: [:switch_locale, :saml]
1✔
5

6
  before_action do
1✔
7
    if current_user && current_user.admin
1,699✔
8
      Rack::MiniProfiler.authorize_request
124✔
9
    end
10
  end
11

12
  before_action :load_objects_from_params
1✔
13
  before_action :store_current_location, unless: :devise_controller?
1✔
14
  before_action :load_html_blocks
1✔
15
  before_action :authorize_collection
1✔
16
  before_action :configure_permitted_parameters, if: :devise_controller?
1✔
17
  skip_before_action :verify_authenticity_token, if: (:devise_controller? && :codespaces_environment?)
1✔
18
  before_action :set_current_user_in_model
1✔
19
  before_action :set_current_session_in_model
1✔
20
  before_action :masquerade_user!
1✔
21
  before_action :check_search_attempt
1✔
22
  after_action :track_action
1✔
23
  around_action :switch_locale
1✔
24

25
  layout :set_layout
1✔
26

27
  def switch_locale(&action)
1✔
28
    @dropdown_locales = I18n.available_locales.reject { |locale| locale.to_s.include? '-' }
13,200✔
29

30
    locale = nil
1,650✔
31

32
    # use user-record locale
33
    if user_signed_in? && !current_user.preferred_locale.blank?
1,650✔
34
      # the user has set their locale manually; use it.
×
35
      locale = current_user.preferred_locale
×
36
    end
37

38
    # if we can't find that, use session locale
39
    if locale.nil?
1,650!
40
      if session[:current_locale]
1,650!
41
        locale = session[:current_locale]
×
42
      end
43
    end
44

45
    # if we can't find that, use browser locale
46
    if locale.nil?
1,650!
47
      # the user might their locale set in the browser
1,650✔
48
      locale = http_accept_language.preferred_language_from(I18n.available_locales)
1,650✔
49
    end
50

51
    if locale.nil? || !I18n.available_locales.include?(locale.to_sym)
1,650✔
52
      # use the default if the above optiosn didn't work
1,251✔
53
      locale = I18n.default_locale
1,251✔
54
    end
55

56
    # append region to locale
57
    related_locales = http_accept_language.user_preferred_languages.select do |loc|
1,650✔
58
      loc.to_s.include?(locale.to_s) &&                              # is related to the chosen locale (is the locale, or is a regional version of it)
798✔
59
      I18n.available_locales.map { |e| e.to_s }.include?(loc.to_s) # is an available locale
5,586✔
60
    end
61

62
    unless related_locales.empty?
1,650✔
63
      # first preferred language from the related locales
399✔
64
      locale = http_accept_language.preferred_language_from(related_locales)
399✔
65
    end
66

67
    # execute the action with the locale
68
    I18n.with_locale(locale, &action)
1,650✔
69
  end
70

71
  # Set the current user in Current
72
  def set_current_user_in_model
1✔
73
    Current.user = current_user
1,694✔
74
  end
75

76
  # Set the current session in Current
77
  def set_current_session_in_model
1✔
78
    Current.session = session
1,694✔
79
  end
80

81
  def current_user
1✔
82
    super || guest_user
34,052✔
83
  end
84

85
  # find the guest user account if a guest user session is currently active
86
  def guest_user
1✔
87
    User.find_by(id: session[:guest_user_id])
1,855✔
88
  end
89

90
  # when the user chooses to transcribe as guest, find guest user id or create new guest user
91
  def guest_transcription
1✔
92
    return head(:forbidden) unless GUEST_TRANSCRIPTION_ENABLED
3✔
93

94
    if check_recaptcha(model: @page, attribute: :errors)
2✔
95
      User.find(session[:guest_user_id].nil? ? session[:guest_user_id] = create_guest_user.id : session[:guest_user_id])
2!
96
      redirect_to controller: 'transcribe', action: 'display_page', page_id: @page.id
2✔
97
    else
98
      # TODO: Get some kind of flash notification on failure
×
99
      flash[:error] = t('layouts.application.recaptcha_validation_failed')
×
100
      flash.keep
×
101
      redirect_to controller: 'transcribe', action: 'guest', page_id: @page.id
×
102
    end
103
  end
104

105
  def create_guest_user
1✔
106
    user = User.new { |user| user.guest = true }
4✔
107
    user.email = "guest_#{Time.now.to_i}#{rand(99)}@example.com"
2✔
108
    user.save(validate: false)
2✔
109
    user
2✔
110
  end
111

112
  def remove_col_id
1✔
113
    # if there's a col_id set, needs to be removed to prevent breadcrumb issues
114
    if session[:col_id]
269✔
115
      session[:col_id] = nil
9✔
116
    end
117
  end
118

119
  # See ActionController::RequestForgeryProtection for details
120
  # Uncomment the :secret if you're not using the cookie session store
121
  # protect_from_forgery :secret => 'I Hate InvalidAuthenticityToken'
122
  rescue_from ActiveRecord::RecordNotFound do |e|
1✔
123
    bad_record_id(e)
3✔
124
  end
125

126
  def load_objects_from_params
1✔
127
    # this needs to be ordered from the specific to the
128
    # general, so that parent_id will load the appropriate
129
    # object without being overridden by child_id.parent
130
    # whenever both are specified on the parameters
131

132
    if params[:article_id]
1,664✔
133
      @article = Article.find(params[:article_id])
58✔
134
      if session[:col_id] != nil
58✔
135
        @collection = set_friendly_collection(session[:col_id])
14✔
136
        session[:col_id] = nil
14✔
137
      else
44✔
138
        @collection = @article.collection
44✔
139
      end
140
    end
141
    if params[:page_id]
1,664✔
142
      @page = Page.find(params[:page_id])
387✔
143
      @work = @page.work
387✔
144
      if session[:col_id] != nil
387✔
145
        @collection = set_friendly_collection(session[:col_id])
132✔
146
        session[:col_id] = nil
132✔
147
      else
255✔
148
        @collection = @page.collection
255✔
149
      end
150
    end
151
    if params[:work_id]
1,664✔
152
      @work = Work.friendly.find(params[:work_id])
416✔
153
      @collection = @work.collection
415✔
154
    end
155
    if params[:document_set_id]
1,663✔
156
      @document_set = DocumentSet.friendly.find(params[:document_set_id])
13✔
157
      @collection = @document_set.collection
13✔
158
    end
159
    if params[:collection_id]
1,663✔
160
      @collection = set_friendly_collection(params[:collection_id])
804✔
161
    end
162

163
    if params[:user_id]
1,663✔
164
      @user = User.friendly.find(params[:user_id])
73✔
165
    end
166

167
    # category stuff may be orthogonal to collections and articles
168
    if params[:category_id]
1,661✔
169
      @category = Category.find(params[:category_id])
6✔
170
    end
171

172
    # consider loading work and collection from the versions
173
    if params[:page_version_id]
1,661!
174
      @page_version = PageVersion.find(params[:page_version_id])
×
175
      @page = @page_version.page
×
176
      @work = @page.work
×
177
      @collection = @work.collection
×
178
    end
179
    if params[:article_version_id]
1,661!
180
      @article_version = ArticleVersion.find(params[:article_version_id])
×
181
      @article = @article_version.article
×
182
      @collection = @article.collection
×
183
    end
184
    if params[:collection_ids]
1,661!
185
      @collection_ids = params[:collection_ids]
×
186
    end
187

188

189
    if self.class.module_parent == Thredded && @collection
1,661✔
190
      Thredded::Engine.routes.default_url_options = { user_slug: @collection.owner.slug, collection_id: @collection.slug }
1✔
191
    else
1,660✔
192
      Thredded::Engine.routes.default_url_options = { user_slug: 'nil', collection_id: 'nil' }
1,660✔
193
    end
194
  end
195

196
  def set_friendly_collection(id)
1✔
197
    if Collection.friendly.exists?(id)
950✔
198
      @collection = Collection.friendly.find(id)
831✔
199
    elsif DocumentSet.friendly.exists?(id)
119✔
200
      @collection = DocumentSet.friendly.find(id)
118✔
201
    elsif !DocumentSet.find_by(slug: id).nil?
1!
202
      @collection = DocumentSet.find_by(slug: id)
✔
203
    elsif !Collection.find_by(slug: id).nil?
1!
204
      @collection = Collection.find_by(slug: id)
×
205
    end
206

207
    # check to make sure URLs haven't gotten scrambled
208
    if @work
950✔
209
      if @work.collection != @collection
597✔
210
        # this could be a document set or a bad collection
65✔
211
        unless @collection.is_a? DocumentSet
65!
212
          @collection = @work.collection
×
213
        end
214
      end
215
    end
216
    @collection
950✔
217
  end
218

219
  def bad_record_id(e)
1✔
220
    logger.error("Bad record ID exception for params=#{params.inspect}")
3✔
221
    logger.error(e.backtrace[2])
3✔
222
    if @collection
3!
223
      redirect_to controller: 'collection', action: 'show', collection_id: @collection.id
×
224
    else
3✔
225
      redirect_to '/404'
3✔
226
    end
227

228
    nil
229
  end
230

231
  def load_html_blocks
1✔
232
    @html_blocks = {}
1,652✔
233
    page_blocks = PageBlock.where(controller: controller_name, view: action_name)
1,652✔
234
    page_blocks.each do |b|
1,652✔
235
      if b && b.html
814✔
236
        begin
82✔
237
          b.rendered_html = render_to_string(inline: b.html)
82✔
238
        rescue StandardError => _e
239
          b.rendered_html = ''
×
240
        end
241
      else
732✔
242
        b.rendered_html = ''
732✔
243
      end
244
      @html_blocks[b.tag] = b
814✔
245
    end
246
  end
247

248
  def authorize_collection
1✔
249
    return unless @collection
1,689✔
250
    if self.class.module_parent.name == 'Thredded'
924✔
251
      unless @collection.messageboards_enabled
1!
252
        flash[:error] = t('message_boards_are_disabled', project: @collection.title)
×
253
        redirect_to main_app.user_profile_path(@collection.owner)
×
254
      end
255
    end
256

257
    return unless @collection.restricted
924✔
258
    return if params[:controller] == 'iiif'
40!
259

260
    unless @collection.show_to?(current_user)
40✔
261
      # second chance?
2✔
262
      unless set_fallback_collection
2!
263
        flash[:error] = t('unauthorized_collection', project: @collection.title)
2✔
264
        redirect_to main_app.user_profile_path(@collection.owner)
2✔
265
      end
266
    end
267
  end
268

269
  def set_fallback_collection
1✔
270
    if @work && @work.collection.supports_document_sets
2✔
271
      alternative_set = @work.document_sets.unrestricted.first
2✔
272
      if alternative_set
2!
273
        @collection = alternative_set
×
274
        true
×
275
      else
2✔
276
        false
2✔
277
      end
278
    else
×
279
      false
×
280
    end
281
  end
282

283
  def configure_permitted_parameters
1✔
284
    devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:login, :email, :password, :password_confirmation, :display_name, :owner, :paid_date, :activity_email) }
73✔
285
    devise_parameter_sanitizer.permit(:sign_in) { |u| u.permit(:login_id, :login, :email, :password, :remember_me) }
95✔
286
    devise_parameter_sanitizer.permit(:account_update) { |u| u.permit(:login, :email, :password, :current_password, :password_confirmation, :real_name) }
73✔
287
  end
288

289
  # Redirect to admin or owner dashboard after sign in
290
  # Always send admins to admin dashboard
291
  # Everyone else should go back to where they came from if their previous page is set
292
  # Otherwise owners should go to their dashboards
293
  # And everyone else should go to user dashboard/watchlist
294
  def after_sign_in_path_for(resource)
1✔
295
    if current_user.admin
18✔
296
      admin_path
4✔
297
    elsif !session[:user_return_to].blank? && session[:user_return_to] != '/' && !session[:user_return_to].include?('/landing')
14✔
298
      session[:user_return_to]
2✔
299
    elsif current_user.owner
12✔
300
      if current_user.collections.any?
4✔
301
        dashboard_owner_path
2✔
302
      else
2✔
303
        dashboard_startproject_path
2✔
304
      end
8✔
305
    elsif current_user.deeds.any?
8✔
306
      dashboard_watchlist_path
3✔
307
    else
5✔
308
      landing_page_path
5✔
309
    end
310
  end
311

312
  # destroy guest user session if a user signs out, then redirect to root path
313
  def after_sign_out_path_for(resource)
1✔
314
    if session[:guest_user_id]
×
315
      session[:guest_user_id] = nil
×
316
    end
317
    root_path
×
318
  end
319

320
  # Wrapper around redirect_to for modal ajax forms
321
  def ajax_redirect_to(options = {}, response_status = {})
1✔
322
    if request.xhr?
51✔
323
      head :created, location: url_for(options)
8✔
324
    else
43✔
325
      redirect_to options, response_status
43✔
326
    end
327
  end
328

329
  private
1✔
330

331
  def set_layout
1✔
332
    request.xhr? ? false : nil
2,342✔
333
  end
334

335
  def per_page
1✔
336
    return @per_page if defined?(@per_page)
27✔
337

338
    @per_page = if params[:per_page].present?
14✔
339
                  params[:per_page].to_i
3✔
340
    else
11✔
341
                  default_per_page
11✔
342
    end
343

344
    @per_page
14✔
345
  end
346

347
  def default_per_page
1✔
348
    # Override in controller for custom defaults
349
    DEFAULT_PER_PAGE
11✔
350
  end
351
end
352

353
def page_params(page)
1✔
354
  if @collection
843✔
355
    collection = @collection
795✔
356
  else
48✔
357
    collection = page.work.access_object(current_user) || page.work.collection
48✔
358
  end
359

360
  if page.status_new?
843✔
361
    if user_signed_in?
468✔
362
      collection_transcribe_page_path(page.work.collection.owner, collection, page.work, page)
378✔
363
    else
90✔
364
      collection_guest_page_path(page.work.collection.owner, collection, page.work, page)
90✔
365
    end
366
  else
375✔
367
    collection_display_page_path(page.work.collection.owner, collection, page.work, page)
375✔
368
  end
369
end
370

371
def track_action
1✔
372
  extras = {}
1,653✔
373
  if @collection
1,653✔
374
    if @collection.is_a? DocumentSet
1,148✔
375
      extras[:document_set_id] = @collection.id
120✔
376
      extras[:document_set_title] = @collection.title
120✔
377
      extras[:collection_id] = @collection.collection.id
120✔
378
      extras[:collection_title] = @collection.collection.title
120✔
379
    else
1,028✔
380
      extras[:collection_id] = @collection.id
1,028✔
381
      extras[:collection_title] = @collection.title
1,028✔
382
    end
383
  end
384
  extras[:work_id] = @work.id if @work
1,653✔
385
  extras[:work_title] = @work.title if @work
1,653✔
386
  extras[:page_id] = @page.id if @page
1,653✔
387
  extras[:page_title] = @page.title if @page
1,653✔
388
  extras[:article_id] = @article.id if @article
1,653✔
389
  extras[:article_title] = @article.title if @article
1,653✔
390
  ahoy.track("#{controller_name}##{action_name}", extras) unless action_name == 'still_editing'
1,653✔
391
end
392

393
def check_api_access
1✔
394
  if (defined? @collection) && @collection
4✔
395
    if @collection.restricted && !@collection.api_access
2!
396
      if @api_user.nil? || !(@api_user.like_owner?(@collection))
×
397
        render status: 403, plain: 'This collection is private.  The collection owner must enable API access to it or make it public for it to appear.'
×
398
      end
399
    end
400
  end
401
end
402

403
def set_api_user
1✔
404
  authenticate_with_http_token do |token, options|
16✔
405
    @api_user = User.find_by(api_key: token)
12✔
406
  end
407
end
408

409
def check_search_attempt
1✔
410
  if session[:search_attempt_id]
1,694!
411
    your_profile = controller_name == 'user' && @user == current_user
×
NEW
412
    if ['dashboard', 'static'].include?(controller_name) || your_profile
×
413
      session[:search_attempt_id] = nil
×
414
    end
415
  end
416
end
417

418
def update_search_attempt_contributions
1✔
419
  if session[:search_attempt_id]
65!
420
    search_attempt = SearchAttempt.find(session[:search_attempt_id])
×
421
    search_attempt.increment!(:contributions)
×
422
  end
423
end
424

425
def update_search_attempt_user(user, session_var)
1✔
426
  if session_var[:search_attempt_id]
512!
427
    search_attempt = SearchAttempt.find(session_var[:search_attempt_id])
×
428
    search_attempt.user = user
×
429
    search_attempt.owner = user.owner
×
430
    search_attempt.save
×
431
  end
432
end
433

434
private
1✔
435

436
def store_current_location
1✔
437
  store_location_for(:user, request.url)
1,306✔
438
end
439

440
def check_recaptcha(options)
1✔
441
  return verify_recaptcha(options) if RECAPTCHA_ENABLED
2!
442

443
  true
2✔
444
end
445

446
def codespaces_environment?
1✔
447
  Rails.env.development? && ENV['CODESPACES'] == 'true'
531✔
448
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc