orats 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,853 @@
1
+ # =====================================================================================================
2
+ # Template for generating authentication and authorization on top of the base template
3
+ # =====================================================================================================
4
+
5
+ # ----- Helper functions and variables ----------------------------------------------------------------
6
+
7
+ require 'securerandom'
8
+
9
+ def generate_token
10
+ SecureRandom.hex(64)
11
+ end
12
+
13
+ def create_migration(table_name, migration='')
14
+ utc_now = Time.now.getutc.strftime("%Y%m%d%H%M%S")
15
+ class_name = table_name.to_s.classify.pluralize
16
+
17
+ file "db/migrate/#{utc_now}_create_#{table_name}.rb", %{
18
+ class Create#{class_name} < ActiveRecord::Migration
19
+ def change
20
+ #{migration}
21
+ end
22
+ end
23
+ }
24
+ end
25
+
26
+ app_name_upper = app_name.upcase
27
+
28
+ # ----- Delete application.css ------------------------------------------------------------------------
29
+
30
+ # This gets created by rails automatically when you make a new project
31
+ run 'rm -f app/assets/stylesheets/application.css'
32
+
33
+ # ----- Modify Gemfile --------------------------------------------------------------------------------
34
+
35
+ puts
36
+ say_status 'root', 'Modifying Gemfile..', :yellow
37
+ puts '-'*80, ''; sleep 0.25
38
+
39
+ inject_into_file 'Gemfile', before: "\ngem 'kaminari'" do <<-CODE
40
+
41
+ gem 'devise', '~> 3.2.2'
42
+ gem 'devise-async', '~> 0.9.0'
43
+ gem 'pundit', '~> 0.2.1'
44
+ CODE
45
+ end
46
+
47
+ git add: '.'
48
+ git commit: "-m 'Add devise, devise-async and pundit gems'"
49
+
50
+ # ----- Run bundle install ----------------------------------------------------------------------------
51
+
52
+ puts
53
+ say_status 'action', 'Running bundle install, it should not take too long', :yellow
54
+ puts '-'*80, ''; sleep 0.25
55
+
56
+ run 'bundle install'
57
+
58
+ # ----- Modify sidekiq config -------------------------------------------------------------------------
59
+
60
+ puts
61
+ say_status 'config', 'Modifying the sidekiq config', :yellow
62
+ puts '-'*80, ''; sleep 0.25
63
+
64
+ append_file 'config/sidekiq.yml' do <<-FILE
65
+ - mailer
66
+ FILE
67
+ end
68
+
69
+ git add: '.'
70
+ git commit: "-m 'Add the devise mailer queue to the sidekiq config'"
71
+
72
+ # ----- Create the account fixtures -------------------------------------------------------------------
73
+
74
+ puts
75
+ say_status 'test', 'Creating the account fixtures...', :yellow
76
+ puts '-'*80, ''; sleep 0.25
77
+
78
+ file 'test/fixtures/accounts.yml' do <<-'CODE'
79
+ foo:
80
+ id: 1
81
+ email: foo@bar.com
82
+ encrypted_password: passwordisnotreallyencrypted
83
+ role: admin
84
+ created_at: 2012-01-01 01:45:17
85
+ current_sign_in_at: 2013-03-15 11:22:33
86
+
87
+ no_role:
88
+ id: 2
89
+ email: joey@almostcool.com
90
+ encrypted_password: hackthegibson
91
+ created_at: 1995-09-15 08:10:12
92
+
93
+ bad_role:
94
+ id: 3
95
+ email: hello@world.com
96
+ encrypted_password: reallysecure
97
+ role: ahhhh
98
+ created_at: 2011-09-20 10:10:10
99
+
100
+ beep:
101
+ id: 4
102
+ email: beep@beep.com
103
+ encrypted_password: beepbeepbeep
104
+ created_at: 2010-03-6 05:15:45
105
+ CODE
106
+ end
107
+
108
+ git add: '.'
109
+ git commit: "-m 'Add the account model'"
110
+
111
+ # ----- Modify the test helper ------------------------------------------------------------------------
112
+
113
+ puts
114
+ say_status 'test', 'Modifying the test helper...', :yellow
115
+ puts '-'*80, ''; sleep 0.25
116
+
117
+ inject_into_file 'test/test_helper.rb', after: "end\n" do <<-CODE
118
+
119
+ class ActionController::TestCase
120
+ include Devise::TestHelpers
121
+ end
122
+ CODE
123
+ end
124
+
125
+ git add: '.'
126
+ git commit: "-m 'Add the devise helpers to test helper'"
127
+
128
+ # ----- Create the account unit tests -----------------------------------------------------------------
129
+
130
+ puts
131
+ say_status 'test', 'Creating the account unit tests...', :yellow
132
+ puts '-'*80, ''; sleep 0.25
133
+
134
+ file 'test/models/account_test.rb' do <<-'CODE'
135
+ require 'test_helper'
136
+
137
+ class AccountTest < ActiveSupport::TestCase
138
+ def setup
139
+ @account = accounts(:foo)
140
+ end
141
+
142
+ def teardown
143
+ @account = nil
144
+ end
145
+
146
+ test 'expect new account' do
147
+ assert @account.valid?
148
+ assert_not_nil @account.email
149
+ assert_not_nil @account.encrypted_password
150
+ end
151
+
152
+ test 'expect guest to be default role' do
153
+ no_role = accounts(:no_role)
154
+ assert_equal 'guest', no_role.role
155
+ end
156
+
157
+ test 'expect invalid role to not save' do
158
+ bad_role = accounts(:bad_role)
159
+ assert_not bad_role.valid?
160
+ end
161
+
162
+ test 'expect e-mail to be unique' do
163
+ duplicate = Account.create(email: 'foo@bar.com')
164
+
165
+ assert_not duplicate.valid?
166
+ end
167
+
168
+ test 'expect random password if password is empty' do
169
+ @account.password = ''
170
+ @account.encrypted_password = ''
171
+ @account.save
172
+
173
+ random_password = Account.generate_password
174
+ assert_equal 10, random_password.length
175
+ end
176
+
177
+ test 'expect random password of 20 characters' do
178
+ assert_equal 20, Account.generate_password(20).length
179
+ end
180
+ end
181
+ CODE
182
+ end
183
+
184
+ git add: '.'
185
+ git commit: "-m 'Add the account unit tests'"
186
+
187
+ # ----- Create the account model ----------------------------------------------------------------------
188
+
189
+ puts
190
+ say_status 'models', 'Creating the account model...', :yellow
191
+ puts '-'*80, ''; sleep 0.25
192
+
193
+ file 'app/models/account.rb' do <<-'CODE'
194
+ class Account < ActiveRecord::Base
195
+ ROLES = %w[admin guest]
196
+
197
+ devise :database_authenticatable, :registerable, :recoverable, :rememberable,
198
+ :trackable, :timeoutable, :lockable, :validatable, :async
199
+
200
+ before_validation :ensure_password, on: :create
201
+
202
+ after_save :invalidate_cache
203
+
204
+ validates :role, inclusion: { in: ROLES }
205
+
206
+ def self.serialize_from_session(key, salt)
207
+ # store the current_account in the cache so we do not perform a db lookup on each authenticated page
208
+ single_key = key.is_a?(Array) ? key.first : key
209
+
210
+ Rails.cache.fetch("account:#{single_key}") do
211
+ Account.where(id: single_key).entries.first
212
+ end
213
+ end
214
+
215
+ def self.generate_password(length = 10)
216
+ Devise.friendly_token.first(length)
217
+ end
218
+
219
+ def is?(role_check)
220
+ role.to_sym == role_check
221
+ end
222
+
223
+ private
224
+
225
+ def ensure_password
226
+ # only generate a password if it does not exist
227
+ self.password ||= Account.generate_password
228
+ end
229
+
230
+ def invalidate_cache
231
+ Rails.cache.delete("account:#{id}")
232
+ end
233
+ end
234
+ CODE
235
+ end
236
+
237
+ git add: '.'
238
+ git commit: "-m 'Add the account model'"
239
+
240
+ # ----- Create devise migration -----------------------------------------------------------------------
241
+
242
+ puts
243
+ say_status 'db', 'Creating devise model migration...', :yellow
244
+ puts '-'*80, ''; sleep 0.25
245
+
246
+ create_migration :accounts, %{
247
+ create_table(:accounts) do |t|
248
+ ## Database authenticatable
249
+ t.string :email, :null => false, :default => ''
250
+ t.string :encrypted_password, :null => false, :default => ''
251
+
252
+ ## Recoverable
253
+ t.string :reset_password_token
254
+ t.datetime :reset_password_sent_at
255
+
256
+ ## Rememberable
257
+ t.datetime :remember_created_at
258
+
259
+ ## Trackable
260
+ t.integer :sign_in_count, :default => 0, :null => false
261
+ t.datetime :current_sign_in_at
262
+ t.datetime :last_sign_in_at
263
+ t.string :current_sign_in_ip
264
+ t.string :last_sign_in_ip
265
+
266
+ ## Lockable
267
+ t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
268
+ t.string :unlock_token # Only if unlock strategy is :email or :both
269
+ t.datetime :locked_at
270
+
271
+ ## Role
272
+ t.string :role, default: 'guest'
273
+
274
+ t.timestamps
275
+ end
276
+
277
+ add_index :accounts, :email, :unique => true
278
+ add_index :accounts, :reset_password_token, :unique => true
279
+ add_index :accounts, :unlock_token, :unique => true
280
+ }
281
+
282
+ git add: '.'
283
+ git commit: "-m 'Add devise model migration'"
284
+
285
+ # ----- Create a seed user ----------------------------------------------------------------------------
286
+
287
+ puts
288
+ say_status 'db', 'Creating a seed user...', :yellow
289
+ puts '-'*80, ''; sleep 0.25
290
+
291
+ append_file 'db/seeds.rb', "\nAccount.create({ email: \"admin@#{app_name}.com\", password: \"password\", role: \"admin\" })"
292
+
293
+ git add: '.'
294
+ git commit: "-m 'Add a seed user'"
295
+
296
+ # ----- Create en i18n entries ------------------------------------------------------------------------
297
+
298
+ puts
299
+ say_status 'db', 'Creating en i18n entries...', :yellow
300
+ puts '-'*80, ''; sleep 0.25
301
+
302
+ gsub_file 'config/locales/en.yml', "hello: \"Hello world\"\n", ''
303
+
304
+ append_file 'config/locales/en.yml' do <<-CODE
305
+ authorization:
306
+ error: 'You are not authorized to perform this action.'
307
+ CODE
308
+ end
309
+
310
+ git add: '.'
311
+ git commit: "-m 'Add en i18n entries'"
312
+
313
+ # ----- Modify the application controller -------------------------------------------------------------
314
+
315
+ puts
316
+ say_status 'db', 'Modifying the application controller...', :yellow
317
+ puts '-'*80, ''; sleep 0.25
318
+
319
+ inject_into_file 'app/controllers/application_controller.rb', after: "::Base\n" do <<-'CODE'
320
+ alias_method :current_user, :current_account
321
+
322
+ CODE
323
+ end
324
+
325
+ git add: '.'
326
+ git commit: "-m 'Alias current_user to current_account to play nice with other gems'"
327
+
328
+ inject_into_file 'app/controllers/application_controller.rb', before: "end\n" do <<-'CODE'
329
+
330
+ private
331
+
332
+ # Override devise to customize the after sign in path.
333
+ #def after_sign_in_path_for(resource)
334
+ # if resource.is? :admin
335
+ # admin_path
336
+ # else
337
+ # somewhere_path
338
+ # end
339
+ #end
340
+ CODE
341
+ end
342
+
343
+ git add: '.'
344
+ git commit: "-m 'Change the application controller to allow overriding the devise sign in path'"
345
+
346
+ # ----- Create the devise views -----------------------------------------------------------------------
347
+
348
+ puts
349
+ say_status 'views', 'Creating the devise views...', :yellow
350
+ puts '-'*80, ''; sleep 0.25
351
+
352
+ file 'app/views/devise/confirmations/new.html.erb' do <<-HTML
353
+ <%
354
+ title 'Confirm'
355
+ meta_description '...'
356
+ heading 'Confirm'
357
+ %>
358
+
359
+ <div class="row">
360
+ <div class="col-sm-4">
361
+ <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
362
+ <div class="form-group">
363
+ <%= f.label :email %>
364
+ <%= f.email_field :email, class: 'form-control', maxlength: 254, autofocus: true,
365
+ data: {
366
+ 'rule-required' => 'true',
367
+ 'rule-maxlength' => '254'
368
+ } %>
369
+ </div>
370
+ <%= button_tag type: 'submit', class: 'btn btn-primary' do %>
371
+ Send
372
+ <% end %>
373
+ <% end %>
374
+ </div>
375
+ <div class="col-sm-6 col-sm-offset-2">
376
+ <%= render 'devise/shared/links' %>
377
+ </div>
378
+ </div>
379
+ HTML
380
+ end
381
+
382
+ file 'app/views/devise/mailer/confirmation_instructions.html.erb' do <<-HTML
383
+ <p>Welcome <%= @email %>!</p>
384
+
385
+ <p>You can confirm your account email through the link below:</p>
386
+
387
+ <p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
388
+ HTML
389
+ end
390
+
391
+ file 'app/views/devise/mailer/reset_password_instructions.html.erb' do <<-HTML
392
+ <p>Hello <%= @resource.email %>!</p>
393
+
394
+ <p>Someone has requested a link to change your password. You can do this through the link below.</p>
395
+
396
+ <p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
397
+
398
+ <p>If you didn't request this, please ignore this email.</p>
399
+ <p>Your password won't change until you access the link above and create a new one.</p>
400
+ HTML
401
+ end
402
+
403
+ file 'app/views/devise/mailer/unlock_instructions.html.erb' do <<-HTML
404
+ <p>Hello <%= @resource.email %>!</p>
405
+
406
+ <p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
407
+
408
+ <p>Click the link below to unlock your account:</p>
409
+
410
+ <p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
411
+ HTML
412
+ end
413
+
414
+ file 'app/views/devise/passwords/edit.html.erb' do <<-HTML
415
+ <%
416
+ title 'Change your password'
417
+ meta_description '...'
418
+ heading 'Change your password'
419
+ %>
420
+
421
+ <div class="row">
422
+ <div class="col-sm-4">
423
+ <%= form_for resource, as: resource_name, url: password_path(resource_name), html: { method: :put } do |f| %>
424
+ <%= f.hidden_field :reset_password_token %>
425
+ <div class="form-group">
426
+ <%= f.label :password, 'New password' %>
427
+ <%= f.password_field :password, maxlength: 128, class: 'form-control', autofocus: true,
428
+ data: {
429
+ 'rule-required' => 'true',
430
+ 'rule-minlength' => '8',
431
+ 'rule-maxlength' => '128'
432
+ } %>
433
+ </div>
434
+ <%= button_tag type: 'submit', class: 'btn btn-primary' do %>
435
+ Send
436
+ <% end %>
437
+ <% end %>
438
+ </div>
439
+ <div class="col-sm-6 col-sm-offset-2">
440
+ <%= render 'devise/shared/links' %>
441
+ </div>
442
+ </div>
443
+ HTML
444
+ end
445
+
446
+ file 'app/views/devise/passwords/new.html.erb' do <<-HTML
447
+ <%
448
+ title 'Forgot your password?'
449
+ meta_description '...'
450
+ heading 'Forgot your password?'
451
+ %>
452
+
453
+ <div class="row">
454
+ <div class="col-sm-4">
455
+ <%= form_for resource, as: resource_name, url: password_path(resource_name), html: { method: :post } do |f| %>
456
+ <div class="form-group">
457
+ <%= f.label :email %>
458
+ <%= f.email_field :email, class: 'form-control', autofocus: true, maxlength: 254,
459
+ data: {
460
+ 'rule-required' => 'true',
461
+ 'rule-maxlength' => '254'
462
+ } %>
463
+ </div>
464
+ <%= button_tag type: 'submit', class: 'btn btn-primary' do %>
465
+ Send
466
+ <% end %>
467
+ <% end %>
468
+ </div>
469
+ <div class="col-sm-6 col-sm-offset-2">
470
+ <%= render 'devise/shared/links' %>
471
+ </div>
472
+ </div>
473
+ HTML
474
+ end
475
+
476
+ file 'app/views/devise/registrations/edit.html.erb' do <<-HTML
477
+ <%
478
+ title 'Edit your account'
479
+ meta_description '...'
480
+ heading 'Edit your account'
481
+ %>
482
+
483
+ <div class="row">
484
+ <div class="col-sm-6">
485
+ <%= form_for resource, as: resource_name, url: registration_path(resource_name), html: { method: :patch } do |f| %>
486
+ <div class="form-group">
487
+ <%= f.label :current_password %>
488
+ <span class="help-block form-help-adjust-margin">
489
+ <small>
490
+ Supply your current password to make any changes
491
+ </small>
492
+ </span>
493
+ <%= f.password_field :current_password, maxlength: 128, class: 'form-control',
494
+ data: {
495
+ 'rule-required' => 'true',
496
+ 'rule-minlength' => '8',
497
+ 'rule-maxlength' => '128'
498
+ } %>
499
+ </div>
500
+ <div class="form-group">
501
+ <%= f.label :email %>
502
+ <%= f.email_field :email, class: 'form-control', maxlength: 254, autofocus: true %>
503
+ </div>
504
+ <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
505
+ <h3>Currently waiting confirmation for: <%= resource.unconfirmed_email %></h3>
506
+ <% end %>
507
+ <div class="form-group">
508
+ <%= f.label :password %>
509
+ <span class="help-block form-help-adjust-margin">
510
+ <small>
511
+ Leave this blank if you do not want to change it
512
+ </small>
513
+ </span>
514
+ <%= f.password_field :password, class: 'form-control' %>
515
+ </div>
516
+ <%= button_tag type: 'submit', class: 'btn btn-primary' do %>
517
+ Save
518
+ <% end %>
519
+ <% end %>
520
+ </div>
521
+ <div class="col-sm-6">
522
+ <p>
523
+ Unhappy? <%= button_to 'Cancel my account', registration_path(resource_name), method: :delete %>
524
+ </p>
525
+ </div>
526
+ </div>
527
+ HTML
528
+ end
529
+
530
+ file 'app/views/devise/registrations/new.html.erb' do <<-HTML
531
+ <%
532
+ title 'Register a new account'
533
+ meta_description '...'
534
+ heading 'Register a new account'
535
+ %>
536
+
537
+ <div class="row">
538
+ <div class="col-sm-4">
539
+ <%= form_for resource, as: resource_name, url: registration_path(resource_name) do |f| %>
540
+ <div class="form-group">
541
+ <%= f.label :email %>
542
+ <%= f.email_field :email, class: 'form-control', maxlength: 254, autofocus: true %>
543
+ </div>
544
+ <div class="form-group">
545
+ <%= f.label :password %>
546
+ <%= f.password_field :password, maxlength: 128, class: 'form-control',
547
+ data: {
548
+ 'rule-required' => 'true',
549
+ 'rule-minlength' => '8',
550
+ 'rule-maxlength' => '128'
551
+ } %>
552
+ </div>
553
+ <%= button_tag type: 'submit', class: 'btn btn-primary' do %>
554
+ Register
555
+ <% end %>
556
+ <% end %>
557
+ </div>
558
+ <div class="col-sm-6 col-sm-offset-2">
559
+ <%= render 'devise/shared/links' %>
560
+ </div>
561
+ </div>
562
+ HTML
563
+ end
564
+
565
+ file 'app/views/devise/sessions/new.html.erb' do <<-HTML
566
+ <%
567
+ title 'Sign in'
568
+ meta_description '...'
569
+ heading 'Sign in'
570
+ %>
571
+
572
+ <div class="row">
573
+ <div class="col-sm-4">
574
+ <%= form_for resource, as: resource_name, url: session_path(resource_name) do |f| %>
575
+ <div class="form-group">
576
+ <%= f.label :email %>
577
+ <%= f.email_field :email, maxlength: 254, class: 'form-control', autofocus: true %>
578
+ </div>
579
+ <div class="form-group">
580
+ <%= f.label :password %>
581
+ <%= f.password_field :password, maxlength: 128, class: 'form-control',
582
+ data: {
583
+ 'rule-required' => 'true',
584
+ 'rule-minlength' => '8',
585
+ 'rule-maxlength' => '128'
586
+ } %>
587
+ </div>
588
+ <% if devise_mapping.rememberable? -%>
589
+ <div class="checkbox">
590
+ <%= f.label :remember_me do %>
591
+ <%= f.check_box :remember_me %> Stay signed in
592
+ <% end %>
593
+ </div>
594
+ <% end -%>
595
+ <%= button_tag type: 'submit', class: 'btn btn-primary' do %>
596
+ Sign in
597
+ <% end %>
598
+ <% end %>
599
+ </div>
600
+ <div class="col-sm-6 col-sm-offset-2">
601
+ <h4 class="success-color">Having trouble accessing your account?</h4>
602
+ <%= render 'devise/shared/links' %>
603
+ </div>
604
+ </div>
605
+ HTML
606
+ end
607
+
608
+ file 'app/views/devise/unlocks/new.html.erb' do <<-HTML
609
+ <%
610
+ title 'Re-send unlock instructions'
611
+ meta_description '...'
612
+ heading 'Re-send unlock instructions'
613
+ %>
614
+
615
+ <div class="row">
616
+ <div class="col-sm-4">
617
+ <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
618
+ <div class="form-group">
619
+ <%= f.label :email %>
620
+ <%= f.email_field :email, class: 'form-control', maxlength: 254, autofocus: true,
621
+ data: {
622
+ 'rule-required' => 'true',
623
+ 'rule-maxlength' => '254'
624
+ } %>
625
+ </div>
626
+ <%= button_tag type: 'submit', class: 'btn btn-primary' do %>
627
+ Send
628
+ <% end %>
629
+ <% end %>
630
+ </div>
631
+ <div class="col-sm-6 col-sm-offset-2">
632
+ <%= render 'devise/shared/links' %>
633
+ </div>
634
+ </div>
635
+ HTML
636
+ end
637
+
638
+ file 'app/views/devise/shared/_links.html.erb' do <<-'HTML'
639
+ <%= content_tag(:h4, 'Or do something else') if controller_name != 'sessions' %>
640
+ <ul>
641
+ <%- if controller_name != 'sessions' %>
642
+ <li>
643
+ <%= link_to 'Sign in', new_session_path(resource_name) %>
644
+ </li>
645
+ <% end -%>
646
+
647
+ <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
648
+ <li>
649
+ <%= link_to 'Sign up', new_registration_path(resource_name) %>
650
+ </li>
651
+ <% end -%>
652
+
653
+ <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
654
+ <li>
655
+ <%= link_to 'Forgot your password?', new_password_path(resource_name) %>
656
+ </li>
657
+ <% end -%>
658
+
659
+ <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
660
+ <li>
661
+ <%= link_to 'Re-send confirmation instructions?', new_confirmation_path(resource_name) %>
662
+ </li>
663
+ <% end -%>
664
+
665
+ <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
666
+ <li>
667
+ <%= link_to 'Are you locked out of your account?', new_unlock_path(resource_name) %>
668
+ </li>
669
+ <% end -%>
670
+
671
+ <%- if devise_mapping.omniauthable? %>
672
+ <%- resource_class.omniauth_providers.each do |provider| %>
673
+ <li><%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %></li>
674
+ <% end -%>
675
+ <% end -%>
676
+ </ul>
677
+ HTML
678
+ end
679
+
680
+ git add: '.'
681
+ git commit: "-m 'Add the devise views'"
682
+
683
+ # ----- Modify the layout files ------------------------------------------------------------------------
684
+
685
+ puts
686
+ say_status 'views', 'Modifying the layout files...', :yellow
687
+ puts '-'*80, ''; sleep 0.25
688
+
689
+ file 'app/views/layouts/_navigation_auth.html.erb', <<-HTML
690
+ <% if current_account %>
691
+ <li>
692
+ <%= link_to 'Settings', edit_account_registration_path %>
693
+ </li>
694
+ <li>
695
+ <%= link_to 'Sign out', destroy_account_session_path, method: :delete %>
696
+ </li>
697
+ <% else %>
698
+ <li>
699
+ <%= link_to 'Sign in', new_account_session_path %>
700
+ </li>
701
+ <li>
702
+ <%= link_to 'Register', new_account_registration_path %>
703
+ </li>
704
+ <% end %>
705
+ HTML
706
+
707
+ inject_into_file 'app/views/layouts/_navigation.html.erb', after: "</ul>\n" do <<-CODE
708
+ <ul class="nav navbar-nav nav-auth">
709
+ <%= render 'layouts/navigation_auth' %>
710
+ </ul>
711
+ CODE
712
+ end
713
+
714
+ append_file 'app/assets/stylesheets/application.css.scss' do <<-CODE
715
+
716
+ @media (min-width: $screen-sm) {
717
+ .nav-auth {
718
+ float: right;
719
+ }
720
+ }
721
+ CODE
722
+ end
723
+
724
+ git add: '.'
725
+ git commit: "-m 'Add account management links to the layout and add the necessary css selectors'"
726
+
727
+ # ----- Modify the .env file --------------------------------------------------------------------------
728
+
729
+ puts
730
+ say_status 'root', 'Modifying the .env file...', :yellow
731
+ puts '-'*80, ''; sleep 0.25
732
+
733
+ inject_into_file '.env', before: "\n#{app_name_upper}_SMTP_ADDRESS" do <<-CODE
734
+ #{app_name_upper}_TOKEN_DEVISE_SECRET: #{generate_token}
735
+ #{app_name_upper}_TOKEN_DEVISE_PEPPER: #{generate_token}
736
+ CODE
737
+ end
738
+
739
+ inject_into_file '.env', before: "\n#{app_name_upper}_DATABASE_NAME" do <<-CODE
740
+ #{app_name_upper}_ACTION_MAILER_DEVISE_DEFAULT_EMAIL: info@#{app_name}.com
741
+ CODE
742
+ end
743
+
744
+ git add: '.'
745
+ git commit: "-m 'Add the devise tokens and default email to the .env file'"
746
+
747
+ # ----- Create the config files -----------------------------------------------------------------------
748
+
749
+ puts
750
+ say_status 'config', 'Creating the devise async initializer...', :yellow
751
+ puts '-'*80, ''; sleep 0.25
752
+
753
+ file 'config/initializers/devise_async.rb', 'Devise::Async.backend = :sidekiq'
754
+ generate 'devise:install'
755
+
756
+ git add: '.'
757
+ git commit: "-m 'Add the devise and devise async initializers'"
758
+
759
+ # ----- Modify the config files -----------------------------------------------------------------------
760
+
761
+ puts
762
+ say_status 'config', 'Modifying the devise initializer...', :yellow
763
+ puts '-'*80, ''; sleep 0.25
764
+
765
+ gsub_file 'config/initializers/devise.rb',
766
+ "'please-change-me-at-config-initializers-devise@example.com'", "ENV['#{app_name_upper}_ACTION_MAILER_DEVISE_DEFAULT_EMAIL']"
767
+ gsub_file 'config/initializers/devise.rb', /(?<=key = )'\w{128}'/, "ENV['#{app_name_upper}_TOKEN_DEVISE_SECRET']"
768
+ gsub_file 'config/initializers/devise.rb', /(?<=pepper = )'\w{128}'/, "ENV['#{app_name_upper}_TOKEN_DEVISE_PEPPER']"
769
+
770
+ gsub_file 'config/initializers/devise.rb', '# config.timeout_in = 30.minutes',
771
+ 'config.timeout_in = 2.hours'
772
+
773
+ gsub_file 'config/initializers/devise.rb', '# config.expire_auth_token_on_timeout = false',
774
+ 'config.expire_auth_token_on_timeout = true'
775
+
776
+ gsub_file 'config/initializers/devise.rb', '# config.lock_strategy = :failed_attempts',
777
+ 'config.lock_strategy = :failed_attempts'
778
+
779
+ gsub_file 'config/initializers/devise.rb', '# config.unlock_strategy = :both',
780
+ 'config.unlock_strategy = :both'
781
+
782
+ gsub_file 'config/initializers/devise.rb', '# config.maximum_attempts = 20',
783
+ 'config.maximum_attempts = 7'
784
+
785
+ gsub_file 'config/initializers/devise.rb', '# config.unlock_in = 1.hour',
786
+ 'config.unlock_in = 2.hours'
787
+
788
+ gsub_file 'config/initializers/devise.rb', '# config.last_attempt_warning = false',
789
+ 'config.last_attempt_warning = true'
790
+
791
+ git add: '.'
792
+ git commit: "-m 'Change the devise initializer default values'"
793
+
794
+ # ----- Modify the routes file ------------------------------------------------------------------------
795
+
796
+ puts
797
+ say_status 'config', 'Modifying the routes file...', :yellow
798
+ puts '-'*80, ''; sleep 0.25
799
+
800
+ inject_into_file 'config/routes.rb', after: "collection\n end\n" do <<-CODE
801
+
802
+ # disable users from being able to register by uncommenting the lines below
803
+ # get 'accounts/sign_up(.:format)', to: redirect('/')
804
+ # post 'accounts(.:format)', to: redirect('/')
805
+
806
+ # disable users from deleting their own account by uncommenting the line below
807
+ # delete 'accounts(.:format)', to: redirect('/')
808
+
809
+ devise_for :accounts
810
+
811
+ authenticate :account, lambda { |account| account.is?(:admin) } do
812
+ mount Sidekiq::Web => '/sidekiq'
813
+ end
814
+
815
+ CODE
816
+ end
817
+
818
+ git add: '.'
819
+ git commit: "-m 'Add devise to the routes file'"
820
+
821
+ # ----- Add pundit support ----------------------------------------------------------------------------
822
+
823
+ puts
824
+ say_status 'root', 'Adding pundit support...', :yellow
825
+ puts '-'*80, ''; sleep 0.25
826
+
827
+ generate 'pundit:install'
828
+
829
+ git add: '.'
830
+ git commit: "-m 'Add pundit application policy'"
831
+
832
+ inject_into_file 'app/controllers/application_controller.rb', after: "::Base\n" do <<-'CODE'
833
+ include Pundit
834
+
835
+ CODE
836
+ end
837
+
838
+ inject_into_file 'app/controllers/application_controller.rb', after: ":exception\n" do <<-'CODE'
839
+
840
+ rescue_from Pundit::NotAuthorizedError, with: :account_not_authorized
841
+ CODE
842
+ end
843
+
844
+ inject_into_file 'app/controllers/application_controller.rb', after: " #end\n" do <<-'CODE'
845
+
846
+ def account_not_authorized
847
+ redirect_to request.headers['Referer'] || root_path, flash: { error: I18n.t('authorization.error') }
848
+ end
849
+ CODE
850
+ end
851
+
852
+ git add: '.'
853
+ git commit: "-m 'Add pundit logic to the application controller'"