b4um_generators 0.2.7 → 0.2.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab89fe09deda48a796523b69839e38cacce98d2d91e417b0de179c3263b45be2
4
- data.tar.gz: b7c7173b4d447cd2a068fd84c06f268b4cdfd0eabfdd76115a6fdb4342b03a48
3
+ metadata.gz: 4ac1397c02b6a4475966dd32cae4aa31b251ac3b6e29cbc0fda6994a3e325a3f
4
+ data.tar.gz: fd7a685c7cbd61c96c9fd2e54ffd622b0b4593f83c0e27257d1afec24d0375ff
5
5
  SHA512:
6
- metadata.gz: 38240797ad404a9ed5092ce1222b4e02a07bed73a217d16d72d2b3dbf22beafc29e3667031bd06a732b3ab5fa22d81ee1cf5ee670ce1d380868ec5364d93aea1
7
- data.tar.gz: 982dc00957e65b8f38233184369a8cfbce9ad00236fef09f750f029f22e4b64926e1ad194e4d785ab5a492c8ff197930eb62cccce766c882714d9275640b3971
6
+ metadata.gz: 43445dcd341aa92ebca76c14eafd500bfa993110e58e203f7f8ea2b0af22127e24c97374e95c33c336cb90f10220175dbf277168edd4e31f55de2fdd1392f87b
7
+ data.tar.gz: '00147389d26a82e439a634c6712f4b42c7561f99593451c80ddf5d6b23205feb377d6f569ceb2adf2dbd82fec8335d29436451c7dad21515a22619464421c0ae'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module B4umGenerators
4
- VERSION = "0.2.7"
4
+ VERSION = "0.2.8"
5
5
  end
@@ -182,18 +182,32 @@ module B4um
182
182
 
183
183
  navigation = File.read(full_navigation_path)
184
184
 
185
- return if navigation.include?(
185
+ if navigation.include?(
186
186
  'navigation_button_to "Logout", logout_path, method: :delete'
187
187
  )
188
+ add_register_navigation_link(
189
+ navigation_path,
190
+ navigation
191
+ )
192
+ return
193
+ end
188
194
 
189
195
  marker = "<%# B4UM_NAVIGATION_LINKS %>"
190
196
 
191
197
  return unless navigation.include?(marker)
192
198
 
199
+ controller_name = authentication_model_name.pluralize
200
+ new_resource_path =
201
+ "new_#{authentication_model_name}_path"
202
+
193
203
  authentication_links = <<~ERB
194
204
  <% if logged_in? %>
195
205
  <%= navigation_button_to "Logout", logout_path, method: :delete %>
196
206
  <% else %>
207
+ <%= navigation_link_to "Register",
208
+ #{new_resource_path},
209
+ controller: :#{controller_name},
210
+ action: :new %>
197
211
  <%= navigation_link_to "Login",
198
212
  login_path,
199
213
  controller: :sessions,
@@ -210,6 +224,106 @@ module B4um
210
224
  )
211
225
  end
212
226
 
227
+ def protect_authentication_resource
228
+ controller_path = authentication_resource_controller_path
229
+ full_controller_path = File.join(
230
+ destination_root,
231
+ controller_path
232
+ )
233
+
234
+ return unless File.exist?(full_controller_path)
235
+
236
+ add_authentication_resource_callbacks(controller_path)
237
+ add_authentication_resource_authorization(controller_path)
238
+ redirect_destroyed_authentication_resource_to_root(controller_path)
239
+ end
240
+
241
+ def sign_in_after_registration
242
+ controller_path = authentication_resource_controller_path
243
+
244
+ full_controller_path = File.join(
245
+ destination_root,
246
+ controller_path
247
+ )
248
+
249
+ return unless File.exist?(full_controller_path)
250
+
251
+ controller = File.read(full_controller_path)
252
+
253
+ session_assignment =
254
+ "session[:#{authentication_model_name}_id] = " \
255
+ "@#{authentication_model_name}.id"
256
+
257
+ return if controller.include?(session_assignment)
258
+
259
+ save_pattern =
260
+ /^(\s*)if @#{Regexp.escape(authentication_model_name)}\.save\s*$/
261
+
262
+ return unless controller.match?(save_pattern)
263
+
264
+ inject_into_file(
265
+ controller_path,
266
+ after: save_pattern
267
+ ) do
268
+ "\n\\1 #{session_assignment}"
269
+ end
270
+ end
271
+
272
+ def add_profile_navigation
273
+ navigation_path = "app/views/shared/_navigation.html.erb"
274
+
275
+ full_navigation_path = File.join(
276
+ destination_root,
277
+ navigation_path
278
+ )
279
+
280
+ return unless File.exist?(full_navigation_path)
281
+
282
+ navigation = File.read(full_navigation_path)
283
+
284
+ resource_name = authentication_class_name.pluralize
285
+ controller_name = authentication_model_name.pluralize
286
+
287
+ resource_pattern = /
288
+ ^[ \t]*<%=\s*navigation_link_to\s+"#{Regexp.escape(resource_name)}",
289
+ .*?
290
+ controller:\s*:#{Regexp.escape(controller_name)}
291
+ \s*%>\s*
292
+ /mx
293
+
294
+ if navigation.match?(resource_pattern)
295
+ gsub_file(
296
+ navigation_path,
297
+ resource_pattern,
298
+ ""
299
+ )
300
+ end
301
+
302
+ navigation = File.read(full_navigation_path)
303
+
304
+ return if navigation.include?(
305
+ 'navigation_link_to "Profile"'
306
+ )
307
+
308
+ login_marker = "<% if logged_in? %>"
309
+
310
+ return unless navigation.include?(login_marker)
311
+
312
+ profile_link = <<~ERB
313
+ <% if logged_in? %>
314
+ <%= navigation_link_to "Profile",
315
+ #{current_authentication_method},
316
+ controller: :#{controller_name},
317
+ action: :show %>
318
+ ERB
319
+
320
+ gsub_file(
321
+ navigation_path,
322
+ login_marker,
323
+ profile_link.chomp
324
+ )
325
+ end
326
+
213
327
  def protect_controllers
214
328
  protected_controller_names.each do |controller_name|
215
329
  controller_path = File.join(
@@ -251,6 +365,247 @@ module B4um
251
365
 
252
366
  private
253
367
 
368
+ def add_register_navigation_link(navigation_path, navigation)
369
+ return if navigation.include?(
370
+ 'navigation_link_to "Register",'
371
+ )
372
+
373
+ controller_name = authentication_model_name.pluralize
374
+ new_resource_path =
375
+ "new_#{authentication_model_name}_path"
376
+
377
+ login_pattern = /
378
+ ^([ \t]*)<%=\s*navigation_link_to\s+"Login",
379
+ /x
380
+
381
+ return unless navigation.match?(login_pattern)
382
+
383
+ register_link = <<~ERB
384
+ <%= navigation_link_to "Register",
385
+ #{new_resource_path},
386
+ controller: :#{controller_name},
387
+ action: :new %>
388
+ ERB
389
+
390
+ gsub_file(
391
+ navigation_path,
392
+ login_pattern
393
+ ) do |match|
394
+ indentation = match[/\A[ \t]*/]
395
+
396
+ indented_register = register_link.lines.map do |line|
397
+ "#{indentation}#{line}"
398
+ end.join
399
+
400
+ "#{indented_register}#{match}"
401
+ end
402
+ end
403
+
404
+ def authentication_resource_controller_path
405
+ File.join(
406
+ "app/controllers",
407
+ "#{authentication_model_name.pluralize}_controller.rb"
408
+ )
409
+ end
410
+
411
+ def redirect_destroyed_authentication_resource_to_root(controller_path)
412
+ resource_path =
413
+ "#{authentication_model_name.pluralize}_path"
414
+
415
+ redirect =
416
+ "redirect_to #{resource_path}, status: :see_other"
417
+
418
+ return unless controller_contains?(controller_path, redirect)
419
+
420
+ gsub_file(
421
+ controller_path,
422
+ redirect,
423
+ "redirect_to root_path, status: :see_other"
424
+ )
425
+ end
426
+
427
+ def add_authentication_resource_callbacks(controller_path)
428
+ add_require_login_callback(controller_path)
429
+ add_prevent_authentication_index_callback(controller_path)
430
+ add_require_current_authentication_callback(controller_path)
431
+ add_clear_authentication_session_callback(controller_path)
432
+ end
433
+
434
+ def add_require_login_callback(controller_path)
435
+ callback = "before_action :require_login, except: %i[ new create ]"
436
+
437
+ return if controller_contains?(controller_path, callback)
438
+
439
+ inject_into_file(
440
+ controller_path,
441
+ after: /^class .*Controller < ApplicationController\s*$/
442
+ ) do
443
+ "\n #{callback}"
444
+ end
445
+ end
446
+
447
+ def add_prevent_authentication_index_callback(controller_path)
448
+ callback =
449
+ "before_action :prevent_authentication_index, only: :index"
450
+
451
+ return if controller_contains?(controller_path, callback)
452
+
453
+ inject_into_file(
454
+ controller_path,
455
+ after: /^\s*before_action :require_login, except: %i\[ new create \]\s*$/
456
+ ) do
457
+ "\n #{callback}"
458
+ end
459
+ end
460
+
461
+ def add_require_current_authentication_callback(controller_path)
462
+ callback =
463
+ "before_action :require_current_#{authentication_model_name}, " \
464
+ "only: %i[ show edit update destroy ]"
465
+
466
+ return if controller_contains?(controller_path, callback)
467
+
468
+ set_callback =
469
+ /^\s*before_action :set_#{authentication_model_name}, only: %i\[ show edit update destroy \]\s*$/
470
+
471
+ if controller_matches?(controller_path, set_callback)
472
+ inject_into_file(
473
+ controller_path,
474
+ after: set_callback
475
+ ) do
476
+ "\n #{callback}"
477
+ end
478
+ else
479
+ inject_into_file(
480
+ controller_path,
481
+ after: /^class .*Controller < ApplicationController\s*$/
482
+ ) do
483
+ "\n #{callback}"
484
+ end
485
+ end
486
+ end
487
+
488
+ def add_clear_authentication_session_callback(controller_path)
489
+ callback =
490
+ "after_action :clear_authentication_session, only: :destroy"
491
+
492
+ return if controller_contains?(controller_path, callback)
493
+
494
+ current_user_callback =
495
+ /^\s*before_action :require_current_#{authentication_model_name}, only: %i\[ show edit update destroy \]\s*$/
496
+
497
+ inject_into_file(
498
+ controller_path,
499
+ after: current_user_callback
500
+ ) do
501
+ "\n #{callback}"
502
+ end
503
+ end
504
+
505
+ def add_authentication_resource_authorization(controller_path)
506
+ add_prevent_authentication_index_method(controller_path)
507
+ add_require_current_authentication_method(controller_path)
508
+ add_clear_authentication_session_method(controller_path)
509
+ end
510
+
511
+ def add_prevent_authentication_index_method(controller_path)
512
+ method_name = "def prevent_authentication_index"
513
+
514
+ return if controller_contains?(controller_path, method_name)
515
+
516
+ inject_private_method(
517
+ controller_path,
518
+ <<~RUBY
519
+ def prevent_authentication_index
520
+ redirect_to #{current_authentication_method}
521
+ end
522
+ RUBY
523
+ )
524
+ end
525
+
526
+ def add_require_current_authentication_method(controller_path)
527
+ method_name =
528
+ "def require_current_#{authentication_model_name}"
529
+
530
+ return if controller_contains?(controller_path, method_name)
531
+
532
+ inject_private_method(
533
+ controller_path,
534
+ <<~RUBY
535
+ def require_current_#{authentication_model_name}
536
+ return if @#{authentication_model_name} == #{current_authentication_method}
537
+
538
+ redirect_to root_path, alert: "Access denied."
539
+ end
540
+ RUBY
541
+ )
542
+ end
543
+
544
+ def add_clear_authentication_session_method(controller_path)
545
+ method_name = "def clear_authentication_session"
546
+
547
+ return if controller_contains?(controller_path, method_name)
548
+
549
+ inject_private_method(
550
+ controller_path,
551
+ <<~RUBY
552
+ def clear_authentication_session
553
+ session.delete(:#{authentication_model_name}_id)
554
+ end
555
+ RUBY
556
+ )
557
+ end
558
+
559
+ def inject_private_method(controller_path, method_body)
560
+ full_controller_path = File.join(
561
+ destination_root,
562
+ controller_path
563
+ )
564
+
565
+ content = File.read(full_controller_path)
566
+
567
+ class_end_position = content.rindex(/^end\s*$/)
568
+
569
+ unless class_end_position
570
+ raise Thor::Error,
571
+ "Could not find the closing class end in #{controller_path}"
572
+ end
573
+
574
+ indented_body = method_body.lines.map do |line|
575
+ line.strip.empty? ? "\n" : " #{line}"
576
+ end.join
577
+
578
+ updated_content = content.dup
579
+
580
+ updated_content.insert(
581
+ class_end_position,
582
+ "\n#{indented_body}"
583
+ )
584
+
585
+ File.write(
586
+ full_controller_path,
587
+ updated_content
588
+ )
589
+ end
590
+
591
+ def controller_contains?(controller_path, content)
592
+ full_controller_path = File.join(
593
+ destination_root,
594
+ controller_path
595
+ )
596
+
597
+ File.read(full_controller_path).include?(content)
598
+ end
599
+
600
+ def controller_matches?(controller_path, pattern)
601
+ full_controller_path = File.join(
602
+ destination_root,
603
+ controller_path
604
+ )
605
+
606
+ File.read(full_controller_path).match?(pattern)
607
+ end
608
+
254
609
  def protect_index_actions_for(controller_name)
255
610
  index_path = File.join(
256
611
  "app/views",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: b4um_generators
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Baum