b4um_generators 0.2.17 → 0.4.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.de.md +418 -4
  4. data/README.md +405 -5
  5. data/lib/b4um_generators/version.rb +1 -1
  6. data/lib/generators/b4um/admin/admin_generator.rb +614 -0
  7. data/lib/generators/b4um/admin/templates/add_admin_fields_migration.rb.tt +10 -0
  8. data/lib/generators/b4um/admin/templates/admin_base_controller.rb.tt +5 -0
  9. data/lib/generators/b4um/admin/templates/admin_dashboard.html.erb.tt +19 -0
  10. data/lib/generators/b4um/admin/templates/admin_dashboard_controller.rb.tt +6 -0
  11. data/lib/generators/b4um/admin/templates/admin_users_controller.rb.tt +70 -0
  12. data/lib/generators/b4um/admin/templates/admin_users_index.html.erb.tt +110 -0
  13. data/lib/generators/b4um/admin/templates/b4um_admin.rake.tt +106 -0
  14. data/lib/generators/b4um/authentication/authentication_generator.rb +90 -1
  15. data/lib/generators/b4um/guest/guest_generator.rb +673 -0
  16. data/lib/generators/b4um/guest/templates/add_guest_fields_migration.rb.tt +12 -0
  17. data/lib/generators/b4um/guest/templates/b4um_guests.rake.tt +12 -0
  18. data/lib/generators/b4um/guest/templates/edit.html.erb.tt +156 -0
  19. data/lib/generators/b4um/guest/templates/guest_expiration_warning.html.erb.tt +12 -0
  20. data/lib/generators/b4um/guest/templates/guests_controller.rb.tt +88 -0
  21. data/lib/generators/b4um/guest/templates/new.html.erb.tt +136 -0
  22. data/lib/generators/b4um/help/help_generator.rb +228 -0
  23. data/lib/generators/b4um/install/templates/b4um/sortable.css +158 -0
  24. data/lib/generators/b4um/install/templates/b4um.css +1 -0
  25. data/lib/generators/b4um/pagination/pagination_generator.rb +32 -5
  26. data/lib/generators/b4um/scaffold/scaffold_generator.rb +50 -0
  27. data/lib/generators/b4um/scaffold/templates/_form.html.erb.tt +18 -14
  28. data/lib/generators/b4um/search/search_generator.rb +22 -8
  29. data/lib/generators/b4um/sortable/sortable_generator.rb +529 -0
  30. data/lib/generators/b4um/sortable/templates/_sortable.html.erb.tt +40 -0
  31. data/lib/generators/b4um/sortable/templates/add_position_migration.rb.tt +26 -0
  32. data/lib/generators/b4um/sortable/templates/sort.html.erb.tt +3 -0
  33. data/lib/generators/b4um/sortable/templates/sortable_controller.js +166 -0
  34. metadata +22 -1
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Admin::UsersController < Admin::BaseController
4
+ def index
5
+ @users = <%= authentication_class_name %>.all
6
+ end
7
+
8
+ def block
9
+ user = <%= authentication_class_name %>.find(params[:id])
10
+
11
+ if user == <%= current_authentication_method %>
12
+ redirect_to admin_users_path,
13
+ alert: "You cannot block your own account."
14
+ return
15
+ end
16
+
17
+ user.update!(blocked: true)
18
+
19
+ redirect_to admin_users_path,
20
+ notice: "User was blocked."
21
+ end
22
+
23
+ def unblock
24
+ user = <%= authentication_class_name %>.find(params[:id])
25
+
26
+ user.update!(blocked: false)
27
+
28
+ redirect_to admin_users_path,
29
+ notice: "User was unblocked."
30
+ end
31
+
32
+ def grant_admin
33
+ user = <%= authentication_class_name %>.find(params[:id])
34
+
35
+ user.update!(admin: true)
36
+
37
+ redirect_to admin_users_path,
38
+ notice: "Administrator rights were granted."
39
+ end
40
+
41
+ def revoke_admin
42
+ user = <%= authentication_class_name %>.find(params[:id])
43
+
44
+ if user.admin? && <%= authentication_class_name %>.where(admin: true).count == 1
45
+ redirect_to admin_users_path,
46
+ alert: "The last administrator cannot lose administrator rights."
47
+ return
48
+ end
49
+
50
+ user.update!(admin: false)
51
+
52
+ redirect_to admin_users_path,
53
+ notice: "Administrator rights were revoked."
54
+ end
55
+
56
+ def destroy
57
+ user = <%= authentication_class_name %>.find(params[:id])
58
+
59
+ if user == <%= current_authentication_method %>
60
+ redirect_to admin_users_path,
61
+ alert: "You cannot delete your own account."
62
+ return
63
+ end
64
+
65
+ user.destroy!
66
+
67
+ redirect_to admin_users_path,
68
+ notice: "User was deleted."
69
+ end
70
+ end
@@ -0,0 +1,110 @@
1
+ <%% content_for :title, "Users" %>
2
+
3
+ <div class="page-header">
4
+ <h1>Users</h1>
5
+ </div>
6
+
7
+ <div class="b4um-grid">
8
+ <section class="b4um-card b4um-card--full">
9
+ <%% if @users.any? %>
10
+ <div class="b4um-table-wrapper">
11
+ <table class="b4um-table">
12
+ <thead>
13
+ <tr>
14
+ <% admin_user_display_fields.each do |field| -%>
15
+ <th><%= admin_user_field_label(field) %></th>
16
+ <% end -%>
17
+ <th>Admin</th>
18
+ <th>Blocked</th>
19
+ <th>Actions</th>
20
+ </tr>
21
+ </thead>
22
+
23
+ <tbody>
24
+ <%% @users.each do |user| %>
25
+ <tr>
26
+ <% admin_user_display_fields.each do |field| -%>
27
+ <td>
28
+ <%%= user.<%= field %> %>
29
+ </td>
30
+
31
+ <% end -%>
32
+ <td>
33
+ <span class="b4um-badge">
34
+ <%%= user.admin? ? "Yes" : "No" %>
35
+ </span>
36
+ </td>
37
+
38
+ <td>
39
+ <span class="b4um-badge">
40
+ <%%= user.blocked? ? "Yes" : "No" %>
41
+ </span>
42
+ </td>
43
+
44
+ <td>
45
+ <div class="b4um-table__actions">
46
+ <%% if user != <%= current_authentication_method %> %>
47
+ <%% if user.blocked? %>
48
+ <%%= link_to "Unblock",
49
+ unblock_admin_user_path(user),
50
+ class: "button button--secondary",
51
+ data: {
52
+ turbo_method: :patch,
53
+ turbo_confirm: "Unblock this user?"
54
+ } %>
55
+ <%% else %>
56
+ <%%= link_to "Block",
57
+ block_admin_user_path(user),
58
+ class: "button button--secondary",
59
+ data: {
60
+ turbo_method: :patch,
61
+ turbo_confirm: "Block this user?"
62
+ } %>
63
+ <%% end %>
64
+
65
+ <%% if user.admin? %>
66
+ <%%= link_to "Remove admin",
67
+ revoke_admin_admin_user_path(user),
68
+ class: "button button--secondary",
69
+ data: {
70
+ turbo_method: :patch,
71
+ turbo_confirm: "Remove administrator rights from this user?"
72
+ } %>
73
+ <%% else %>
74
+ <%%= link_to "Make admin",
75
+ grant_admin_admin_user_path(user),
76
+ class: "button button--secondary",
77
+ data: {
78
+ turbo_method: :patch,
79
+ turbo_confirm: "Grant administrator rights to this user?"
80
+ } %>
81
+ <%% end %>
82
+
83
+ <%%= link_to "Delete",
84
+ admin_user_path(user),
85
+ class: "button button--secondary",
86
+ data: {
87
+ turbo_method: :delete,
88
+ turbo_confirm: "Delete this user permanently?"
89
+ } %>
90
+ <%% end %>
91
+ </div>
92
+ </td>
93
+ </tr>
94
+ <%% end %>
95
+ </tbody>
96
+ </table>
97
+ </div>
98
+ <%% else %>
99
+ <section class="b4um-empty-state">
100
+ <h2 class="b4um-empty-state__title">
101
+ No users yet.
102
+ </h2>
103
+
104
+ <p class="b4um-empty-state__text">
105
+ Registered users will appear here.
106
+ </p>
107
+ </section>
108
+ <%% end %>
109
+ </section>
110
+ </div>
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "io/console"
4
+
5
+ namespace :b4um do
6
+ namespace :admin do
7
+ desc "Create an administrator"
8
+
9
+ task create: :environment do
10
+ model = <%= authentication_class_name %>
11
+
12
+ missing_columns = %w[admin blocked] - model.column_names
13
+
14
+ unless missing_columns.empty?
15
+ abort(
16
+ "Missing database columns: #{missing_columns.join(', ')}. " \
17
+ "Run bin/rails db:migrate before creating an administrator."
18
+ )
19
+ end
20
+
21
+ required_fields = model.validators
22
+ .select do |validator|
23
+ next false unless validator.is_a?(
24
+ ActiveModel::Validations::PresenceValidator
25
+ )
26
+
27
+ validator.options[:if].nil? &&
28
+ (
29
+ validator.options[:unless].nil? ||
30
+ validator.options[:unless] == :guest?
31
+ )
32
+ end
33
+ .flat_map(&:attributes)
34
+ .map(&:to_s)
35
+
36
+ attributes = {}
37
+
38
+ <% admin_creation_fields.each do |field| -%>
39
+ required = required_fields.include?("<%= field %>")
40
+ required_marker = required ? " *" : ""
41
+ <%= field %> = nil
42
+
43
+ loop do
44
+ print "<%= admin_user_field_label(field) %>#{required_marker}: "
45
+ <%= field %> = STDIN.gets&.strip
46
+
47
+ break unless required && (<%= field %>.nil? || <%= field %>.empty?)
48
+
49
+ puts "<%= admin_user_field_label(field) %> cannot be empty."
50
+ end
51
+
52
+ unless <%= field %>.nil? || <%= field %>.empty?
53
+ attributes[:<%= field %>] = <%= field %>
54
+ end
55
+
56
+ <% end -%>
57
+ email = nil
58
+ password = nil
59
+ password_confirmation = nil
60
+
61
+ loop do
62
+ print "Email *: "
63
+ email = STDIN.gets&.strip
64
+
65
+ break unless email.nil? || email.empty?
66
+
67
+ puts "Email cannot be empty."
68
+ end
69
+
70
+ if model.exists?(email: email)
71
+ abort "A user with this email already exists."
72
+ end
73
+
74
+ loop do
75
+ print "Password *: "
76
+ password = STDIN.noecho(&:gets)&.strip
77
+ puts
78
+
79
+ break unless password.nil? || password.empty?
80
+
81
+ puts "Password cannot be empty."
82
+ end
83
+
84
+ loop do
85
+ print "Confirm password *: "
86
+ password_confirmation = STDIN.noecho(&:gets)&.strip
87
+ puts
88
+
89
+ break if password == password_confirmation
90
+
91
+ puts "Passwords do not match."
92
+ end
93
+
94
+ attributes.merge!(
95
+ email: email,
96
+ password: password,
97
+ password_confirmation: password_confirmation,
98
+ admin: true
99
+ )
100
+
101
+ model.create!(attributes)
102
+
103
+ puts "Administrator #{email} was created successfully."
104
+ end
105
+ end
106
+ end
@@ -50,6 +50,89 @@ module B4um
50
50
  "#{authentication_class_name} email:string password_digest:string"
51
51
  end
52
52
 
53
+ def add_email_presence_validation
54
+ model_path = File.join(
55
+ "app/models",
56
+ "#{authentication_model_name}.rb"
57
+ )
58
+
59
+ full_model_path = File.join(
60
+ destination_root,
61
+ model_path
62
+ )
63
+
64
+ model = File.read(full_model_path)
65
+
66
+ return if model.include?(
67
+ "validates :email, presence: true"
68
+ )
69
+
70
+ inject_into_class(
71
+ model_path,
72
+ authentication_class_name,
73
+ " validates :email, presence: true\n"
74
+ )
75
+ end
76
+
77
+ def mark_registration_fields_required
78
+ form_path = File.join(
79
+ destination_root,
80
+ "app/views",
81
+ authentication_model_name.pluralize,
82
+ "_form.html.erb"
83
+ )
84
+
85
+ return unless File.exist?(form_path)
86
+
87
+ model_path = File.join(
88
+ destination_root,
89
+ "app/models",
90
+ "#{authentication_model_name}.rb"
91
+ )
92
+
93
+ model = File.read(model_path)
94
+ form = File.read(form_path)
95
+
96
+ model_required_fields =
97
+ model
98
+ .scan(
99
+ /validates\s+((?::[a-zA-Z_]\w*\s*,?\s*)+),\s*presence:\s+true/
100
+ )
101
+ .flat_map do |match|
102
+ match.first.scan(/:([a-zA-Z_]\w*)/).flatten
103
+ end
104
+
105
+ required_fields = model_required_fields.dup
106
+
107
+ if model.match?(/\bhas_secure_password\b/)
108
+ required_fields.push(
109
+ "password",
110
+ "password_confirmation"
111
+ )
112
+ end
113
+
114
+ required_fields.uniq!
115
+
116
+ required_fields.each do |field|
117
+ label = "#{field.humanize} *"
118
+
119
+ plain_label = /
120
+ form\.label\s+:#{Regexp.escape(field)},
121
+ \s*class:\s*"form-label"
122
+ /x
123
+
124
+ form.gsub!(
125
+ plain_label,
126
+ %(form.label :#{field}, "#{label}", class: "form-label")
127
+ )
128
+ end
129
+
130
+ File.write(
131
+ form_path,
132
+ form
133
+ )
134
+ end
135
+
53
136
  def validate_protected_controllers
54
137
  protected_controller_names.each do |controller_name|
55
138
  controller_path = File.join(
@@ -94,9 +177,15 @@ module B4um
94
177
  end
95
178
 
96
179
  def create_sessions_controller
180
+ controller_path = "app/controllers/sessions_controller.rb"
181
+
182
+ return if File.exist?(
183
+ File.join(destination_root, controller_path)
184
+ )
185
+
97
186
  template(
98
187
  "sessions_controller.rb.tt",
99
- "app/controllers/sessions_controller.rb"
188
+ controller_path
100
189
  )
101
190
  end
102
191