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

benwbrum / fromthepage / 17387282326

01 Sep 2025 09:13PM UTC coverage: 64.405%. Remained the same
17387282326

push

github

web-flow
4857 - Require rubocop step in CI (#4858)

* 4857 - Require rubocop step in CI

* 4865 - Organize gemfiles

1790 of 3303 branches covered (54.19%)

Branch coverage included in aggregate %.

839 of 1497 new or added lines in 133 files covered. (56.05%)

43 existing lines in 29 files now uncovered.

7928 of 11786 relevant lines covered (67.27%)

103.82 hits per line

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

54.44
/app/controllers/admin_controller.rb
1
class AdminController < ApplicationController
1✔
2
  include ErrorHelper
1✔
3

4
  before_action :authorized?
1✔
5

6
  PAGES_PER_SCREEN = 20
1✔
7

8
  def authorized?
1✔
9
    unless user_signed_in? && current_user.admin
51✔
10
      redirect_to dashboard_path
2✔
11
    end
12
  end
13

14
  def index
1✔
15
    @users = User.all
17✔
16
    @owners = User.where(owner: true)
17✔
17

18
    transcription_deeds = Deed.where(deed_type: DeedType.transcriptions_or_corrections_no_edits)
17✔
19
    contributor_deeds = Deed.where(deed_type: DeedType.contributor_types)
17✔
20

21
    # Count stats for dashboard
22
    @pages_per_hour         = transcription_deeds.where('created_at between ? and ?', Time.now - 1.hour, Time.now).count
17✔
23
    @contributions_per_hour = contributor_deeds.where('created_at between ? and ?', Time.now - 1.hour, Time.now).count
17✔
24
    @collections_count      = Collection.all.count
17✔
25
    @articles_count         = Article.all.count
17✔
26
    @works_count            = Work.all.count
17✔
27
    @ia_works_count         = IaWork.all.count
17✔
28
    @pages_count            = Page.all.count
17✔
29
    @transcribed_count      = Page.where.not(status: :new).count
17✔
30
    @notes_count            = Note.all.count
17✔
31
    @users_count            = User.all.count
17✔
32
    @owners_count           = User.where(owner: true).count
17✔
33

34
    @transcription_counts = {}
17✔
35
    @contribution_counts = {}
17✔
36
    @activity_project_counts = {}
17✔
37
    @unique_contributor_counts = {}
17✔
38
    @week_intervals=[ 1, 2, 4, 12, 26, 52, 104, 156, 208 ]
17✔
39
    @week_intervals.each do |weeks_ago|
17✔
40
      start_date = Date.yesterday - weeks_ago.weeks
153✔
41
      end_date = start_date + 1.week
153✔
42
      @transcription_counts[weeks_ago] = transcription_deeds.where('created_at between ? and ?', start_date, end_date).count
153✔
43
      @contribution_counts[weeks_ago] = contributor_deeds.where('created_at between ? and ?', start_date, end_date).count
153✔
44
      @activity_project_counts[weeks_ago] = contributor_deeds.where('created_at between ? and ?', start_date, end_date).distinct.count(:collection_id)
153✔
45
      @unique_contributor_counts[weeks_ago] = contributor_deeds.where('created_at between ? and ?', start_date, end_date).distinct.count(:user_id)
153✔
46
    end
47

48
    @version = ActiveRecord::Migrator.current_version
17✔
49

50

51
=begin
52
    sql_online =
53
      'SELECT count(DISTINCT user_id) count '+
54
      'FROM interactions '+
55
      'WHERE created_on > date_sub(UTC_TIMESTAMP(), INTERVAL 20 MINUTE) '+
56
      'AND user_id IS NOT NULL'
57

58
    @users_count = Interaction.connection.select_value(sql_online)
59
=end
60
  end
61

62
  def user_list
1✔
63
    if params[:search]
10✔
64
      @users = User.search(params[:search]).order(created_at: :desc).paginate page: params[:page], per_page: PAGES_PER_SCREEN
3✔
65
    else
7✔
66
      @users = User.order(created_at: :desc).paginate page: params[:page], per_page: PAGES_PER_SCREEN
7✔
67
    end
68
  end
69

70
  def edit_user
1✔
71
  end
72

73
  def user_visits
1✔
NEW
74
    @visits = @user.visits.order(started_at: :desc).paginate page: params[:page], per_page: PAGES_PER_SCREEN
×
75
  end
76

77
  def visit_actions
1✔
78
    @visit = Visit.find(params[:visit_id])
×
NEW
79
    @actions = @visit.ahoy_events.order(time: :asc).paginate page: params[:page], per_page: 500
×
80
  end
81

82
  def visit_deeds
1✔
83
    @visit = Visit.find(params[:visit_id])
×
84
  end
85

86
  def update_user
1✔
87
    owner = @user.owner
1✔
88
    if @user.update(user_params)
1✔
89
      if owner == false && @user.owner == true
1!
90
        if SMTP_ENABLED
1!
91
          begin
1✔
92
            text = PageBlock.find_by(view: 'new_owner').html
1✔
93
            UserMailer.new_owner(@user, text).deliver!
1✔
94
          rescue StandardError => e
95
            log_smtp_error(e, current_user)
×
96
          end
97
        end
98
      end
99

100
      flash[:notice] = t('.user_profile_updated')
1✔
101
      if owner
1!
NEW
102
        ajax_redirect_to action: 'owner_list'
×
103
      else
1✔
104
        ajax_redirect_to action: 'user_list'
1✔
105
      end
106

107
    else
×
NEW
108
      render action: 'edit_user'
×
109
    end
110
  end
111

112
  def delete_user
1✔
113
    @user.soft_delete
1✔
114
    # @user.destroy
115
    flash[:notice] = t('.user_profile_deleted')
1✔
116
    redirect_to action: 'user_list'
1✔
117
  end
118

119
  def expunge_confirmation
1✔
120
  end
121

122
  def expunge_user
1✔
123
    @user.expunge
×
124
    flash[:notice] = t('.user_expunged', user: @user.display_name)
×
125
    if params[:flag_id]
×
NEW
126
      ajax_redirect_to action: 'revert_flag', flag_id: params[:flag_id]
×
127
    else
×
NEW
128
      ajax_redirect_to action: 'user_list'  # what if we came from the flag list?  TODO
×
129
    end
130
  end
131

132

133
  def flag_list
1✔
134
    @flags = Flag.where(status: Flag::Status::UNCONFIRMED).order(content_at: :desc).paginate page: params[:page], per_page: PAGES_PER_SCREEN
2✔
135
  end
136

137
  def revert_flag
1✔
138
    # find the flag
139
    flag = Flag.find(params[:flag_id])
×
140
    # revert the content
141
    flag.revert_content!
×
142
    # redirect to flag list at the appropriate page
NEW
143
    redirect_to action: 'flag_list', page: params[:page]
×
144
  end
145

146
  def ok_flag
1✔
147
    # find the flag
148
    flag = Flag.find(params[:flag_id])
×
149
    # revert the content
150
    flag.mark_ok!
×
151
    # redirect to flag list at the appropriate page
NEW
152
    redirect_to action: 'flag_list', page: params[:page]
×
153
  end
154

155
  def ok_user
1✔
156
    flag = Flag.find(params[:flag_id])
×
157
    flag.ok_user
×
NEW
158
    redirect_to action: 'flag_list', page: params[:page]
×
159
  end
160

161
  def tail_logfile
1✔
162
    @lines = params[:lines].to_i
1✔
163
    if @lines == 0
1!
164
      @lines=5000
1✔
165
    end
166
    development_logfile = "#{Rails.root}/log/development.log"
1✔
167
    production_logfile = "#{Rails.root}/log/production.log"
1✔
168
    @dev_tail = `tail -#{@lines} #{development_logfile}`
1✔
169
    @prod_tail = `tail -#{@lines} #{production_logfile}`
1✔
170
  end
171

172
  def autoflag
1✔
173
    flash[:notice] = t('.flag_message')
×
174

NEW
175
    cmd = 'rake fromthepage:flag_abuse &'
×
176
    logger.info(cmd)
×
177
    system(cmd)
×
178

NEW
179
    redirect_to action: 'flag_list', page: params[:page]
×
180
  end
181

182
  def uploads
1✔
183
    @document_uploads = DocumentUpload.order('id DESC').paginate page: params[:page], per_page: PAGES_PER_SCREEN
1✔
184
  end
185

186
  def delete_upload
1✔
187
    @document_upload = DocumentUpload.find(params[:id])
1✔
188
    @document_upload.destroy
1✔
189
    flash[:notice] = t('.uploaded_document_deleted')
1✔
190
    redirect_to action: 'uploads'
1✔
191
  end
192

193
  def process_upload
1✔
194
    @document_upload = DocumentUpload.find(params[:id])
×
195
    @document_upload.submit_process
×
196
    flash[:notice] = t('.uploaded_document_queued')
×
NEW
197
    redirect_to action: 'uploads'
×
198
  end
199

200
  def view_processing_log
1✔
201
    @document_upload = DocumentUpload.find(params[:id])
×
NEW
202
    render content_type: 'text/plain', plain: `cat #{@document_upload.log_file}`, layout: false
×
203
  end
204

205
  def collection_list
1✔
206
    @collections = Collection.order(:title)
×
207
  end
208

209
  def work_list
1✔
NEW
210
    @collections = Collection.order(:title).paginate(page: params[:page], per_page: 10)
×
211
    @works = Work.order(:title)
×
212
  end
213

214
  def article_list
1✔
215
    @collections = Collection.all
×
216
  end
217

218
  def page_list
1✔
NEW
219
    @pages = Page.order(:title).paginate(page: params[:page], per_page: PAGES_PER_SCREEN)
×
220
  end
221

222
  def settings
1✔
223
    @email_text = PageBlock.find_by(view: 'new_owner').html
3✔
224
    @flag_denylist = PageBlock.find_by(view: 'flag_denylist').html
3✔
225
    @email_denylist = (PageBlock.where(view: 'email_denylist').first ? PageBlock.where(view: 'email_denylist').first.html : '')
3✔
226
  end
227

228
  def update
1✔
229
    # need the original email text to update
230
    block = PageBlock.find_by(view: 'new_owner')
1✔
231
    if params[:admin][:welcome_text] != block.html
1!
232
      block.html = params[:admin][:welcome_text]
1✔
233
      block.save!
1✔
234
    end
235

236
    block = PageBlock.find_by(view: 'flag_denylist')
1✔
237
    if params[:admin][:flag_denylist] != block.html
1!
238
      block.html = params[:admin][:flag_denylist]
1✔
239
      block.save!
1✔
240
    end
241

242
    block = PageBlock.where(view: 'email_denylist').first || PageBlock.new(view: 'email_denylist')
1✔
243
    if params[:admin][:email_denylist] != block.html
1!
244
      block.html = params[:admin][:email_denylist]
1✔
245
      block.save!
1✔
246
    end
247

248

249
    flash[:notice] = t('.admin_settings_updated')
1✔
250

251
    redirect_to action: 'settings'
1✔
252
  end
253

254
  def owner_list
1✔
255
    @collections = Collection.all
7✔
256
    # @owners = User.where(owner: true).order(paid_date: :desc).paginate(:page => params[:page], :per_page => PAGES_PER_SCREEN)
257
    if params[:search]
7!
NEW
258
      @owners = User.search(params[:search]).where(owner: true).order(paid_date: :desc).paginate(page: params[:page], per_page: PAGES_PER_SCREEN)
✔
259
    elsif params[:sort]
7✔
260
      sort = params[:sort]
3✔
261
      dir = params[:dir].upcase
3✔
262
      @owners = User.where(owner: true).order("#{sort} #{dir}").paginate(page: params[:page], per_page: PAGES_PER_SCREEN)
3✔
263
    else
4✔
264
      @owners = User.where(owner: true).order(created_at: :desc).paginate(page: params[:page], per_page: PAGES_PER_SCREEN)
4✔
265
    end
266
  end
267

268
  def downgrade
1✔
269
    u = User.find(params[:user_id])
1✔
270
    u.downgrade
1✔
271
    redirect_back fallback_location: { action: 'user_list' }, notice: t('.user_downgraded_successfully')
1✔
272
  end
273

274
  def moderation
1✔
NEW
275
    @collections = Collection.where(messageboards_enabled: true)
×
276
  end
277

278
  def searches
1✔
279
    searches = case params[:filter]
×
280
    when 'nonowner'
×
281
                 SearchAttempt.where(owner: false)
×
282
    when 'findaproject'
×
283
                 SearchAttempt.where(search_type: 'findaproject')
×
284
    when 'collectionwork'
×
285
                 SearchAttempt.where.not(search_type: 'findaproject')
×
286
    when 'collection'
×
287
                 SearchAttempt.where(search_type: 'collection')
×
288
    when 'collection-title'
×
289
                 SearchAttempt.where(search_type: 'collection-title')
×
290
    when 'work'
×
291
                 SearchAttempt.where(search_type: 'work')
×
292
    else
×
293
                 SearchAttempt.all
×
294
    end
295

296
    @searches = searches.order('id DESC').paginate(page: params[:page], per_page: PAGES_PER_SCREEN)
×
297

298
    this_week = SearchAttempt.where('created_at > ?', 1.week.ago)
×
299

300
    unless this_week.empty?
×
301
      by_visit = this_week.joins(:visit).group('visits.id')
×
302
      total_days = 7.0
×
303
      total_searches = this_week.count.nonzero? || 1
×
304
      total_visits = by_visit.size.nonzero? || 1
×
305

306
      @find_a_project_searches_per_day = (this_week.where(search_type: 'findaproject').count / total_days).round(2)
×
307
      @collection_work_searches_per_day = (this_week.where.not(search_type: 'findaproject').count / total_days).round(2)
×
308

309
      @find_a_project_average_hits = (this_week.where(search_type: 'findaproject').average(:hits) || 0).to_f
×
310
                                                                                                       .round(2)
311
      @collection_work_average_hits = (this_week.where.not(search_type: 'findaproject').average(:hits) || 0).to_f
×
312
                                                                                                            .round(2)
313

314
      @clickthrough_rate = ((this_week.where('clicks > 0').count.to_f / total_searches) * 100).round(1)
×
315
      @clickthrough_rate_visit = ((by_visit.sum(:clicks).values.count(&:positive?).to_f / total_visits) * 100).round(1)
×
316

317
      @contribution_rate = ((this_week.where('contributions > 0').count.to_f / total_searches) * 100).round(1)
×
318
      @contribution_rate_visit = ((by_visit.sum(:contributions).values.count(&:positive?).to_f / total_visits) * 100)
×
319
                                 .round(1)
320
    end
321

322
    start_d = params[:start_date]
×
323
    end_d = params[:end_date]
×
324
    max_date = 1.day.ago.end_of_day
×
325
    @start_date = start_d&.to_datetime&.beginning_of_day || 1.week.ago.beginning_of_day
×
326
    @end_date = end_d&.to_datetime&.end_of_day || max_date
×
327
    @end_date = max_date if max_date < @end_date
×
328
  end
329

330
  def delete_tag
1✔
331
    tag = Tag.find params[:tag_id]
×
332
    tag.destroy
×
333

NEW
334
    redirect_to action: 'tag_list'
×
335
  end
336

337
  def show_tag
1✔
338
    @tag = Tag.find params[:tag_id]
×
339
    @collections = @tag.collections.order(:title)
×
340
    @possible_duplicates = []
×
NEW
341
    clean_text = @tag.ai_text.gsub(/^\W*/, '').gsub(/\W*$/, '')
×
342
    Tag.where("regexp_replace(upper(ai_text), '[^A-Z0-9]', '') like regexp_replace(upper('%#{clean_text}%'), '[^A-Z0-9]', '')").each do |t|
×
343
      @possible_duplicates << t unless t == @tag
×
344
    end
345
  end
346

347
  def edit_tag
1✔
348
    @tag = Tag.find params[:tag_id]
×
349
  end
350

351
  def update_tag
1✔
352
    @tag = Tag.find params[:tag_id]
×
353
    @tag.update(tag_params)
×
NEW
354
    redirect_to action: 'tag_list'
×
355
  end
356

357
  def merge_tag
1✔
358
    target_tag = Tag.find params[:target_tag_id]
×
359
    source_tag = Tag.find params[:source_tag_id]
×
360

361
    target_tag.collections << source_tag.collections
×
362
    target_tag.save
×
363

364
    source_tag.destroy!
×
365

366
    flash[:notice] = t('.tags_merged', target_tag: target_tag.ai_text, source_tag: source_tag.ai_text)
×
367

368
    redirect_to admin_tags_show_path(target_tag.id)
×
369
  end
370

371
  def tag_list
1✔
372
    @tag_to_count_map = Tag.joins(:collections_tags).group(:id).count
×
373
    @tags = Tag.all.order(:canonical, :ai_text)
×
374
  end
375

376
  private
1✔
377
  def tag_params
1✔
378
    params.require(:tag).permit(:ai_text, :canonical, :tag_type)
×
379
  end
380

381

382
  def user_params
1✔
383
    params.require(:user).permit(:real_name, :login, :email, :account_type, :start_date, :paid_date, :user, :owner)
1✔
384
  end
385
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