cccux 0.1.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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +67 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +382 -0
  5. data/Rakefile +8 -0
  6. data/app/assets/config/cccux_manifest.js +1 -0
  7. data/app/assets/stylesheets/cccux/application.css +102 -0
  8. data/app/controllers/cccux/ability_permissions_controller.rb +271 -0
  9. data/app/controllers/cccux/application_controller.rb +37 -0
  10. data/app/controllers/cccux/authorization_controller.rb +10 -0
  11. data/app/controllers/cccux/cccux_controller.rb +64 -0
  12. data/app/controllers/cccux/dashboard_controller.rb +172 -0
  13. data/app/controllers/cccux/home_controller.rb +19 -0
  14. data/app/controllers/cccux/roles_controller.rb +290 -0
  15. data/app/controllers/cccux/simple_controller.rb +7 -0
  16. data/app/controllers/cccux/users_controller.rb +112 -0
  17. data/app/controllers/concerns/cccux/application_controller_concern.rb +32 -0
  18. data/app/helpers/cccux/application_helper.rb +4 -0
  19. data/app/helpers/cccux/authorization_helper.rb +228 -0
  20. data/app/jobs/cccux/application_job.rb +4 -0
  21. data/app/mailers/cccux/application_mailer.rb +6 -0
  22. data/app/models/cccux/ability.rb +142 -0
  23. data/app/models/cccux/ability_permission.rb +61 -0
  24. data/app/models/cccux/application_record.rb +5 -0
  25. data/app/models/cccux/role.rb +90 -0
  26. data/app/models/cccux/role_ability.rb +49 -0
  27. data/app/models/cccux/user_role.rb +42 -0
  28. data/app/models/concerns/cccux/authorizable.rb +25 -0
  29. data/app/models/concerns/cccux/scoped_ownership.rb +183 -0
  30. data/app/models/concerns/cccux/user_concern.rb +87 -0
  31. data/app/views/cccux/ability_permissions/edit.html.erb +58 -0
  32. data/app/views/cccux/ability_permissions/index.html.erb +108 -0
  33. data/app/views/cccux/ability_permissions/new.html.erb +308 -0
  34. data/app/views/cccux/dashboard/index.html.erb +69 -0
  35. data/app/views/cccux/dashboard/model_discovery.html.erb +148 -0
  36. data/app/views/cccux/home/index.html.erb +42 -0
  37. data/app/views/cccux/roles/_flash.html.erb +10 -0
  38. data/app/views/cccux/roles/_form.html.erb +78 -0
  39. data/app/views/cccux/roles/_role.html.erb +67 -0
  40. data/app/views/cccux/roles/edit.html.erb +317 -0
  41. data/app/views/cccux/roles/index.html.erb +51 -0
  42. data/app/views/cccux/roles/new.html.erb +3 -0
  43. data/app/views/cccux/roles/show.html.erb +99 -0
  44. data/app/views/cccux/users/edit.html.erb +117 -0
  45. data/app/views/cccux/users/index.html.erb +99 -0
  46. data/app/views/cccux/users/new.html.erb +94 -0
  47. data/app/views/cccux/users/show.html.erb +138 -0
  48. data/app/views/layouts/cccux/admin.html.erb +168 -0
  49. data/app/views/layouts/cccux/application.html.erb +17 -0
  50. data/app/views/shared/_footer.html.erb +101 -0
  51. data/config/routes.rb +63 -0
  52. data/db/migrate/20250626194001_create_cccux_roles.rb +15 -0
  53. data/db/migrate/20250626194007_create_cccux_ability_permissions.rb +18 -0
  54. data/db/migrate/20250626194011_create_cccux_user_roles.rb +13 -0
  55. data/db/migrate/20250626194016_create_cccux_role_abilities.rb +10 -0
  56. data/db/migrate/20250627170611_add_owned_to_cccux_role_abilities.rb +9 -0
  57. data/db/migrate/20250705193709_add_context_to_cccux_role_abilities.rb +9 -0
  58. data/db/migrate/20250706214415_add_ownership_configuration_to_role_abilities.rb +21 -0
  59. data/db/seeds.rb +136 -0
  60. data/lib/cccux/engine.rb +50 -0
  61. data/lib/cccux/version.rb +3 -0
  62. data/lib/cccux.rb +7 -0
  63. data/lib/tasks/cccux.rake +703 -0
  64. data/lib/tasks/view_helpers.rake +274 -0
  65. metadata +188 -0
@@ -0,0 +1,703 @@
1
+ # CCCUX Engine Tasks
2
+ # Clean, consolidated setup and management tasks for the CCCUX authorization engine
3
+
4
+ require 'fileutils'
5
+
6
+ namespace :cccux do
7
+ desc 'setup - Complete setup for CCCUX with Devise integration'
8
+ task setup: :environment do
9
+ puts "🚀 Starting CCCUX + Devise setup..."
10
+
11
+ # Step 1: Ensure Devise is installed and working
12
+ puts "📋 Step 1: Verifying Devise installation..."
13
+ # Check if Devise is installed and User model exists with Devise configuration
14
+ devise_installed = defined?(Devise)
15
+ user_model_exists = false
16
+ user_has_devise = false
17
+
18
+ if devise_installed
19
+ begin
20
+ user_class = Object.const_get('User')
21
+ user_model_exists = true
22
+
23
+ # Check if User model has Devise modules
24
+ user_has_devise = user_class.respond_to?(:devise_modules) && user_class.devise_modules.any?
25
+
26
+ # Also check if User model file contains Devise configuration as backup
27
+ if !user_has_devise
28
+ user_model_path = Rails.root.join('app', 'models', 'user.rb')
29
+ if File.exist?(user_model_path)
30
+ user_content = File.read(user_model_path)
31
+ user_has_devise = user_content.include?('devise :')
32
+ end
33
+ end
34
+ rescue NameError
35
+ # User model doesn't exist
36
+ end
37
+ end
38
+
39
+ unless devise_installed && user_model_exists && user_has_devise
40
+ puts "❌ Devise is not properly installed or configured. Please run the following command first:"
41
+ puts " "
42
+ puts " bundle add devise && rails generate devise:install && rails generate devise User && rails db:migrate"
43
+ puts " "
44
+ puts "Then re-run: rails cccux:setup"
45
+ exit 1
46
+ end
47
+
48
+ puts "✅ Devise is properly installed"
49
+
50
+ # Step 2: Configure routes
51
+ puts "📋 Step 2: Configuring routes..."
52
+ configure_routes
53
+ puts "✅ Routes configured"
54
+
55
+ # Step 3: Configure assets
56
+ puts "📋 Step 3: Configuring assets..."
57
+ configure_assets
58
+ puts "✅ Assets configured"
59
+
60
+ # Step 4: Run CCCUX migrations
61
+ puts "📋 Step 4: Running CCCUX migrations..."
62
+ Rake::Task['db:migrate'].invoke
63
+ puts "✅ CCCUX migrations completed"
64
+
65
+ # Step 5: Include CCCUX concern in User model
66
+ puts "📋 Step 5: Adding CCCUX to User model..."
67
+ include_cccux_concern
68
+ puts "✅ CCCUX concern added to User model"
69
+
70
+ # Step 5.5: Configure ApplicationController with CCCUX
71
+ puts "📋 Step 5.5: Configuring ApplicationController with CCCUX..."
72
+ configure_application_controller
73
+ puts "✅ ApplicationController configured with CCCUX"
74
+
75
+ # Step 6: Create initial roles and permissions
76
+ puts "📋 Step 6: Creating initial roles and permissions..."
77
+ create_default_roles_and_permissions
78
+ puts "✅ Default roles and permissions created"
79
+
80
+ # Step 7: Create default admin user (if no users exist)
81
+ puts "📋 Step 7: Creating default admin user..."
82
+ create_default_admin_user
83
+
84
+ # Step 8: Create footer partial
85
+ puts "📋 Step 8: Creating footer partial..."
86
+ create_footer_partial
87
+ puts "✅ Footer partial created"
88
+
89
+ # Step 9: Create home controller if needed
90
+ puts "📋 Step 9: Checking for home controller..."
91
+ create_home_controller
92
+ puts "✅ Home controller check completed"
93
+
94
+ # Step 10: Verify setup
95
+ puts "📋 Step 10: Verifying setup..."
96
+ verify_setup
97
+
98
+ puts ""
99
+ puts "🎉 CCCUX + Devise setup completed successfully!"
100
+ puts ""
101
+ puts "🌟 Next steps:"
102
+ puts " 1. Start your Rails server: rails server"
103
+ puts " 2. Visit http://localhost:3000/cccux to access the admin interface"
104
+ puts " 3. Sign in with your admin account"
105
+ puts ""
106
+ puts "📚 Need help? Check the CCCUX documentation or README"
107
+ end
108
+
109
+ desc 'test - Test CCCUX + Devise integration'
110
+ task test: :environment do
111
+ puts "đŸ§Ē Testing CCCUX + Devise integration..."
112
+
113
+ # Test User model
114
+ user = User.new(email: 'test@example.com', password: 'password123')
115
+ puts "✅ User model accepts CCCUX methods" if user.respond_to?(:has_role?)
116
+
117
+ # Test roles
118
+ role_manager = Cccux::Role.find_by(name: 'Role Manager')
119
+ basic_user = Cccux::Role.find_by(name: 'Basic User')
120
+ guest = Cccux::Role.find_by(name: 'Guest')
121
+ puts "✅ Role Manager role exists" if role_manager
122
+ puts "✅ Basic User role exists" if basic_user
123
+ puts "✅ Guest role exists" if guest
124
+
125
+ # Test permissions
126
+ permissions = Cccux::AbilityPermission.count
127
+ puts "✅ Found #{permissions} permissions"
128
+
129
+ puts "🎉 All tests passed!"
130
+ end
131
+
132
+ desc 'status - Show CCCUX integration status'
133
+ task status: :environment do
134
+ puts "📊 CCCUX Integration Status"
135
+ puts "=" * 50
136
+
137
+ # Check routes
138
+ routes_content = File.read('config/routes.rb')
139
+ routes_configured = routes_content.include?('mount Cccux::Engine')
140
+ puts "Routes: #{routes_configured ? '✅ Configured' : '❌ Not configured'}"
141
+
142
+ # Check User model
143
+ user_model_path = Rails.root.join('app', 'models', 'user.rb')
144
+ if File.exist?(user_model_path)
145
+ user_content = File.read(user_model_path)
146
+ cccux_included = user_content.include?('Cccux::UserConcern')
147
+ devise_configured = user_content.include?('devise :')
148
+ puts "User Model: #{cccux_included && devise_configured ? '✅ Configured' : '❌ Not configured'}"
149
+ else
150
+ puts "User Model: ❌ Not found"
151
+ end
152
+
153
+ # Check ApplicationController
154
+ app_controller_path = Rails.root.join('app', 'controllers', 'application_controller.rb')
155
+ if File.exist?(app_controller_path)
156
+ app_controller_content = File.read(app_controller_path)
157
+ cccux_configured = app_controller_content.include?('Cccux::ApplicationControllerConcern') ||
158
+ app_controller_content.include?('include CanCan::ControllerAdditions')
159
+ puts "Controller: #{cccux_configured ? '✅ CCCUX authorization configured' : '❌ Not configured'}"
160
+ else
161
+ puts "Controller: ❌ ApplicationController not found"
162
+ end
163
+
164
+ # Check database
165
+ begin
166
+ if defined?(User)
167
+ user_count = User.count
168
+ role_count = Cccux::Role.count
169
+ permission_count = Cccux::AbilityPermission.count
170
+ puts "Database: ✅ Connected (#{user_count} users, #{role_count} roles, #{permission_count} permissions)"
171
+ else
172
+ puts "Database: ❌ User model not loaded"
173
+ end
174
+ rescue => e
175
+ puts "Database: ❌ Error: #{e.message}"
176
+ end
177
+
178
+ puts ""
179
+ if routes_configured
180
+ puts "🌟 CCCUX appears to be properly configured!"
181
+ puts " Visit /cccux to access the admin interface"
182
+ else
183
+ puts "âš ī¸ CCCUX needs configuration. Run: rails cccux:setup"
184
+ end
185
+ end
186
+
187
+ desc 'reset - Remove CCCUX from host application'
188
+ task reset: :environment do
189
+ puts "đŸ—‘ī¸ Removing CCCUX Authorization Engine..."
190
+
191
+ # Remove migrations
192
+ puts "Removing migrations..."
193
+ migration_files = Dir.glob(Rails.root.join('db/migrate/*_cccux_*.rb'))
194
+ migration_files.each { |file| File.delete(file) }
195
+
196
+ # Drop tables
197
+ puts "Dropping CCCUX tables..."
198
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS cccux_role_abilities")
199
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS cccux_user_roles")
200
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS cccux_ability_permissions")
201
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS cccux_roles")
202
+
203
+ puts "✅ CCCUX removed from application"
204
+ end
205
+
206
+ private
207
+
208
+ def configure_routes
209
+ routes_path = Rails.root.join('config/routes.rb')
210
+ routes_content = File.read(routes_path)
211
+
212
+ # Ensure devise_for :users is before engine mount
213
+ unless routes_content.include?('devise_for :users')
214
+ puts " ➕ Adding devise_for :users to routes..."
215
+ new_content = "Rails.application.routes.draw do\n devise_for :users\n\n" + routes_content.lines[1..-1].join
216
+ File.write(routes_path, new_content)
217
+ routes_content = File.read(routes_path)
218
+ end
219
+
220
+ # Add engine mount if not present
221
+ unless routes_content.include?('mount Cccux::Engine')
222
+ puts " ➕ Adding CCCUX engine mount to routes..."
223
+ new_content = routes_content.gsub(
224
+ /(Rails\.application\.routes\.draw do)/,
225
+ "\\1\n\n ##### CCCUX BEGIN #####\n mount Cccux::Engine, at: '/cccux'\n ##### CCCUX END #####"
226
+ )
227
+ File.write(routes_path, new_content)
228
+ end
229
+ end
230
+
231
+ def configure_assets
232
+ # Add CSS assets
233
+ css_path = Rails.root.join('app/assets/stylesheets/application.css')
234
+ if File.exist?(css_path)
235
+ css_content = File.read(css_path)
236
+
237
+ # Check if we're using Propshaft or Sprockets
238
+ if defined?(Propshaft)
239
+ # For Propshaft, copy the actual CSS content since it doesn't process @import
240
+ unless css_content.include?('CCCUX Engine Styles')
241
+ # Read the CCCUX CSS content
242
+ cccux_css_path = File.join(File.dirname(__FILE__), '..', '..', 'app', 'assets', 'stylesheets', 'cccux', 'application.css')
243
+ if File.exist?(cccux_css_path)
244
+ cccux_css_content = File.read(cccux_css_path)
245
+ # Extract just the CSS rules, not the manifest comments
246
+ css_rules = cccux_css_content.split('*/').last.strip if cccux_css_content.include?('*/')
247
+ css_rules ||= cccux_css_content
248
+
249
+ File.open(css_path, 'a') do |f|
250
+ f.puts "\n\n/* CCCUX Engine Styles - Added by CCCUX setup */"
251
+ f.puts css_rules
252
+ end
253
+ puts " ✅ Added CCCUX CSS content to application.css (Propshaft)"
254
+ else
255
+ puts " âš ī¸ Could not find CCCUX CSS file at #{cccux_css_path}"
256
+ end
257
+ end
258
+ else
259
+ # Sprockets uses *= require syntax
260
+ unless css_content.include?('cccux/application')
261
+ File.open(css_path, 'a') { |f| f.puts "/*\n *= require cccux/application\n */" }
262
+ puts " ✅ Added CCCUX CSS to application.css (Sprockets)"
263
+ end
264
+ end
265
+ end
266
+
267
+ # Add JavaScript assets (if using legacy asset pipeline)
268
+ js_path = Rails.root.join('app/assets/javascripts/application.js')
269
+ if File.exist?(js_path)
270
+ js_content = File.read(js_path)
271
+ unless js_content.include?('cccux/application')
272
+ File.open(js_path, 'a') { |f| f.puts "//= require cccux/application" }
273
+ puts " ✅ Added CCCUX JavaScript to application.js"
274
+ end
275
+ end
276
+ end
277
+
278
+ def include_cccux_concern
279
+ user_model_path = Rails.root.join('app', 'models', 'user.rb')
280
+ user_content = File.read(user_model_path)
281
+
282
+ unless user_content.include?('Cccux::UserConcern')
283
+ updated_content = user_content.gsub(
284
+ /class User < ApplicationRecord/,
285
+ "class User < ApplicationRecord\n include Cccux::UserConcern"
286
+ )
287
+ File.write(user_model_path, updated_content)
288
+ puts " ✅ Added Cccux::UserConcern to User model"
289
+ else
290
+ puts " â„šī¸ User model already includes Cccux::UserConcern"
291
+ end
292
+ end
293
+
294
+ def configure_application_controller
295
+ application_controller_path = Rails.root.join('app', 'controllers', 'application_controller.rb')
296
+ application_controller_content = File.read(application_controller_path)
297
+
298
+ # Check if CCCUX is already configured
299
+ if application_controller_content.include?('Cccux::ApplicationControllerConcern') ||
300
+ application_controller_content.include?('include CanCan::ControllerAdditions')
301
+ puts " â„šī¸ ApplicationController already includes CCCUX authorization"
302
+ return
303
+ end
304
+
305
+ # Find the class definition line
306
+ class_line_pattern = /class ApplicationController < ActionController::Base/
307
+ unless application_controller_content.match(class_line_pattern)
308
+ puts " âš ī¸ Could not find ApplicationController class definition"
309
+ return
310
+ end
311
+
312
+ # Add CCCUX concern include
313
+ updated_content = application_controller_content.gsub(
314
+ class_line_pattern,
315
+ "class ApplicationController < ActionController::Base\n include Cccux::ApplicationControllerConcern"
316
+ )
317
+
318
+ File.write(application_controller_path, updated_content)
319
+ puts " ✅ Added CCCUX authorization to ApplicationController"
320
+ end
321
+
322
+ def create_default_roles_and_permissions
323
+ # Create Role Manager role (highest priority)
324
+ role_manager = Cccux::Role.find_or_create_by(name: 'Role Manager') do |role|
325
+ role.description = 'Can manage roles and permissions for all users'
326
+ role.priority = 100
327
+ role.active = true
328
+ end
329
+
330
+ # Create Basic User role
331
+ basic_user = Cccux::Role.find_or_create_by(name: 'Basic User') do |role|
332
+ role.description = 'Standard user with basic permissions'
333
+ role.priority = 2
334
+ role.active = true
335
+ end
336
+
337
+ # Create Guest role (lowest priority)
338
+ guest = Cccux::Role.find_or_create_by(name: 'Guest') do |role|
339
+ role.description = 'Limited access user'
340
+ role.priority = 3
341
+ role.active = true
342
+ end
343
+
344
+ # Create permissions
345
+ permissions = [
346
+ # Role Manager permissions (full access)
347
+ { action: 'read', subject: 'User' },
348
+ { action: 'create', subject: 'User' },
349
+ { action: 'update', subject: 'User' },
350
+ { action: 'destroy', subject: 'User' },
351
+ { action: 'read', subject: 'Cccux::Role' },
352
+ { action: 'create', subject: 'Cccux::Role' },
353
+ { action: 'update', subject: 'Cccux::Role' },
354
+ { action: 'destroy', subject: 'Cccux::Role' },
355
+ { action: 'read', subject: 'Cccux::AbilityPermission' },
356
+ { action: 'create', subject: 'Cccux::AbilityPermission' },
357
+ { action: 'update', subject: 'Cccux::AbilityPermission' },
358
+ { action: 'destroy', subject: 'Cccux::AbilityPermission' },
359
+
360
+ # Basic User permissions (limited access)
361
+ { action: 'read', subject: 'User' },
362
+ { action: 'update', subject: 'User' },
363
+
364
+ # Guest permissions (read-only)
365
+ { action: 'read', subject: 'User' }
366
+ ]
367
+
368
+ permissions.each do |perm|
369
+ Cccux::AbilityPermission.find_or_create_by(
370
+ action: perm[:action],
371
+ subject: perm[:subject]
372
+ ) do |permission|
373
+ permission.active = true
374
+ end
375
+ end
376
+
377
+ # Assign permissions to roles
378
+ # Role Manager gets all permissions
379
+ Cccux::AbilityPermission.all.each do |permission|
380
+ Cccux::RoleAbility.find_or_create_by(
381
+ role: role_manager,
382
+ ability_permission: permission
383
+ )
384
+ end
385
+
386
+ # Basic User gets limited permissions
387
+ basic_user_permissions = Cccux::AbilityPermission.where(
388
+ action: ['read', 'update'],
389
+ subject: 'User'
390
+ )
391
+ basic_user_permissions.each do |permission|
392
+ Cccux::RoleAbility.find_or_create_by(
393
+ role: basic_user,
394
+ ability_permission: permission
395
+ )
396
+ end
397
+
398
+ # Guest gets read-only permissions
399
+ guest_permissions = Cccux::AbilityPermission.where(
400
+ action: 'read',
401
+ subject: 'User'
402
+ )
403
+ guest_permissions.each do |permission|
404
+ Cccux::RoleAbility.find_or_create_by(
405
+ role: guest,
406
+ ability_permission: permission
407
+ )
408
+ end
409
+
410
+ puts " ✅ Created Role Manager, Basic User, and Guest roles with appropriate permissions"
411
+ end
412
+
413
+ def create_default_admin_user
414
+ begin
415
+ if defined?(User) && User.count == 0
416
+ role_manager = Cccux::Role.find_by(name: 'Role Manager')
417
+
418
+ if role_manager
419
+ # Check for ENV vars first
420
+ email = ENV['ADMIN_EMAIL']
421
+ password = ENV['ADMIN_PASSWORD']
422
+ password_confirmation = ENV['ADMIN_PASSWORD_CONFIRMATION'] || password
423
+
424
+ if email && password
425
+ puts " ⚡ Creating Role Manager user from environment variables..."
426
+ user = User.create!(email: email, password: password, password_confirmation: password_confirmation)
427
+ Cccux::UserRole.create!(user: user, role: role_manager)
428
+ puts " ✅ Created Role Manager account: #{email}"
429
+ return
430
+ end
431
+
432
+ puts " 🔧 Let's create your first Role Manager account:"
433
+ print " 📧 Enter email address: "
434
+ email = $stdin.gets.chomp
435
+
436
+ while email.blank? || !email.include?('@')
437
+ print " ❌ Please enter a valid email address: "
438
+ email = $stdin.gets.chomp
439
+ end
440
+
441
+ puts " 🔑 Enter password (input will be visible): "
442
+ password = $stdin.gets.chomp
443
+
444
+ if password.blank?
445
+ puts " âš ī¸ Password input was blank. Skipping user creation."
446
+ return
447
+ end
448
+
449
+ puts " 🔑 Confirm password (input will be visible): "
450
+ password_confirmation = $stdin.gets.chomp
451
+
452
+ if password_confirmation.blank?
453
+ puts " âš ī¸ Password confirmation was blank. Skipping user creation."
454
+ return
455
+ end
456
+
457
+ if password != password_confirmation
458
+ puts " ❌ Passwords don't match. Skipping user creation."
459
+ return
460
+ end
461
+
462
+ user = User.create!(
463
+ email: email,
464
+ password: password,
465
+ password_confirmation: password_confirmation
466
+ )
467
+ Cccux::UserRole.create!(user: user, role: role_manager)
468
+ puts " ✅ Created Role Manager account: #{email}"
469
+ else
470
+ puts " âš ī¸ No Role Manager role found - skipping user creation"
471
+ end
472
+ else
473
+ puts " â„šī¸ Users already exist, skipping default Administrator creation"
474
+ end
475
+ rescue => e
476
+ puts " âš ī¸ Could not create default admin: #{e.message}"
477
+ end
478
+ end
479
+
480
+ def create_home_controller
481
+ # Check if home controller already exists
482
+ home_controller_path = Rails.root.join('app', 'controllers', 'home_controller.rb')
483
+ home_view_path = Rails.root.join('app', 'views', 'home', 'index.html.erb')
484
+
485
+ home_controller_exists = File.exist?(home_controller_path)
486
+ if home_controller_exists
487
+ puts " â„šī¸ Home controller already exists"
488
+ else
489
+ # Create home controller
490
+ home_controller_content = <<~RUBY
491
+ class HomeController < ApplicationController
492
+ def index
493
+ # Welcome page for CCCUX powered Rails site
494
+ end
495
+ end
496
+ RUBY
497
+ File.write(home_controller_path, home_controller_content)
498
+ puts " ✅ Created home controller at #{home_controller_path}"
499
+ # Create home views directory
500
+ home_views_dir = Rails.root.join('app', 'views', 'home')
501
+ FileUtils.mkdir_p(home_views_dir) unless Dir.exist?(home_views_dir)
502
+ # Create home index view
503
+ home_view_content = <<~ERB
504
+ <div class=\"welcome-section\" style=\"text-align: center; padding: 3rem 0;\">
505
+ <h1 style=\"color: #333; margin-bottom: 1rem; font-size: 2.5rem;\">
506
+ Welcome to your CCCUX powered Rails Site
507
+ </h1>
508
+ <p style=\"color: #666; font-size: 1.2rem; max-width: 600px; margin: 0 auto; line-height: 1.6;\">
509
+ Your Rails application is now equipped with CCCUX, a powerful role-based authorization engine built on CanCanCan. Edit app/views/home/index.html.erb to change this content
510
+ </p>
511
+ <div style=\"margin-top: 2rem;\">
512
+ <% if user_signed_in? %>
513
+ <p style=\"color: #28a745; font-weight: bold;\">
514
+ ✅ You are signed in as: <%= current_user.email %>
515
+ </p>
516
+ <% if current_user.has_role?('Role Manager') %>
517
+ <p style=\"color: #007bff; margin-top: 1rem;\">
518
+ <a href=\"<%= cccux.root_path %>\" style=\"color: #007bff; text-decoration: none; font-weight: bold;\">
519
+ 🔧 Access CCCUX Admin Panel
520
+ </a>
521
+ </p>
522
+ <% end %>
523
+ <% else %>
524
+ <p style=\"color: #6c757d;\">
525
+ <a href=\"<%= new_user_session_path %>\" style=\"color: #007bff; text-decoration: none;\">
526
+ 🔑 Sign in to get started
527
+ </a>
528
+ </p>
529
+ <% end %>
530
+ </div>
531
+ </div>
532
+ ERB
533
+ File.write(home_view_path, home_view_content)
534
+ puts " ✅ Created home index view at #{home_view_path}"
535
+ end
536
+ # Always check and add root route if needed
537
+ routes_path = Rails.root.join('config', 'routes.rb')
538
+ routes_content = File.read(routes_path)
539
+ unless routes_content.include?("root 'home#index'")
540
+ if routes_content.include?('devise_for :users')
541
+ updated_content = routes_content.gsub(
542
+ /(devise_for :users)/,
543
+ "\\1\n root 'home#index'"
544
+ )
545
+ File.write(routes_path, updated_content)
546
+ puts " ✅ Added root route to routes.rb"
547
+ else
548
+ puts " âš ī¸ Could not find devise_for :users in routes - please manually add: root 'home#index'"
549
+ end
550
+ else
551
+ puts " â„šī¸ Root route already exists in routes.rb"
552
+ end
553
+ end
554
+
555
+ def create_footer_partial
556
+ # Create the shared directory if it doesn't exist
557
+ shared_dir = Rails.root.join('app', 'views', 'shared')
558
+ FileUtils.mkdir_p(shared_dir) unless Dir.exist?(shared_dir)
559
+
560
+ footer_path = shared_dir.join('_footer.html.erb')
561
+
562
+ # Create footer content
563
+ footer_content = <<~ERB
564
+ <!-- CCCUX Footer - Added by CCCUX setup -->
565
+ <footer class="cccux-footer" style="margin-top: 2rem; padding: 1rem 0; border-top: 1px solid #e5e5e5; background-color: #f8f9fa;">
566
+ <div class="container">
567
+ <div class="row">
568
+ <div class="col-md-6">
569
+ <nav class="footer-nav">
570
+ <a href="<%= main_app.root_path %>" class="footer-link">🏠 Home</a>
571
+ <% if user_signed_in? && current_user.has_role?('Role Manager') %>
572
+ <span class="footer-separator">|</span>
573
+ <a href="<%= cccux.root_path %>" class="footer-link">âš™ī¸ CCCUX Admin</a>
574
+ <% end %>
575
+ </nav>
576
+ </div>
577
+ <div class="col-md-6 text-end">
578
+ <% if user_signed_in? %>
579
+ <span class="user-info">
580
+ 👤 <strong><%= current_user.email %></strong>
581
+ <span class="footer-separator">|</span>
582
+ <%= link_to "đŸšĒ Logout", main_app.destroy_user_session_path,
583
+ method: :delete,
584
+ class: "footer-link",
585
+ data: { turbo_method: :delete } %>
586
+ </span>
587
+ <% else %>
588
+ <span class="auth-links">
589
+ <%= link_to "🔑 Sign In", main_app.new_user_session_path, class: "footer-link" %>
590
+ <span class="footer-separator">|</span>
591
+ <%= link_to "📝 Sign Up", main_app.new_user_registration_path, class: "footer-link" %>
592
+ </span>
593
+ <% end %>
594
+ </div>
595
+ </div>
596
+ </div>
597
+ </footer>
598
+
599
+ <style>
600
+ .cccux-footer {
601
+ font-size: 0.9rem;
602
+ color: #6c757d;
603
+ }
604
+ .cccux-footer .footer-link {
605
+ color: #007bff;
606
+ text-decoration: none;
607
+ margin: 0 0.5rem;
608
+ }
609
+ .cccux-footer .footer-link:hover {
610
+ color: #0056b3;
611
+ text-decoration: underline;
612
+ }
613
+ .cccux-footer .footer-separator {
614
+ color: #dee2e6;
615
+ margin: 0 0.25rem;
616
+ }
617
+ .cccux-footer .user-info,
618
+ .cccux-footer .auth-links {
619
+ font-size: 0.85rem;
620
+ }
621
+ .cccux-footer .container {
622
+ max-width: 1200px;
623
+ margin: 0 auto;
624
+ padding: 0 1rem;
625
+ }
626
+ .cccux-footer .row {
627
+ display: flex;
628
+ justify-content: space-between;
629
+ align-items: center;
630
+ flex-wrap: wrap;
631
+ }
632
+ .cccux-footer .col-md-6 {
633
+ flex: 1;
634
+ min-width: 300px;
635
+ }
636
+ .cccux-footer .text-end {
637
+ text-align: right;
638
+ }
639
+ @media (max-width: 768px) {
640
+ .cccux-footer .row {
641
+ flex-direction: column;
642
+ gap: 0.5rem;
643
+ }
644
+ .cccux-footer .col-md-6 {
645
+ text-align: center;
646
+ }
647
+ .cccux-footer .text-end {
648
+ text-align: center;
649
+ }
650
+ }
651
+ </style>
652
+ ERB
653
+
654
+ # Write the footer partial
655
+ File.write(footer_path, footer_content)
656
+ puts " ✅ Created footer partial at #{footer_path}"
657
+
658
+ # Also create a simple include instruction for the application layout
659
+ layout_path = Rails.root.join('app', 'views', 'layouts', 'application.html.erb')
660
+ if File.exist?(layout_path)
661
+ layout_content = File.read(layout_path)
662
+
663
+ # Check if footer is already included
664
+ unless layout_content.include?('render "shared/footer"')
665
+ # Add footer before closing body tag
666
+ if layout_content.include?('</body>')
667
+ updated_content = layout_content.gsub(
668
+ /(\s*)<\/body>/,
669
+ "\\1 <%= render 'shared/footer' %>\n\\1</body>"
670
+ )
671
+ File.write(layout_path, updated_content)
672
+ puts " ✅ Added footer to application layout"
673
+ else
674
+ puts " âš ī¸ Could not find </body> tag in application layout - please manually add: <%= render 'shared/footer' %>"
675
+ end
676
+ else
677
+ puts " â„šī¸ Footer already included in application layout"
678
+ end
679
+ else
680
+ puts " âš ī¸ Application layout not found - please manually add: <%= render 'shared/footer' %>"
681
+ end
682
+ end
683
+
684
+ def verify_setup
685
+ # Test that User model has CCCUX methods
686
+ user = User.new
687
+ unless user.respond_to?(:has_role?)
688
+ puts "❌ User model missing CCCUX methods"
689
+ exit 1
690
+ end
691
+
692
+ puts "✅ CCCUX methods available on User model"
693
+
694
+ # Test route helpers
695
+ begin
696
+ Rails.application.routes.url_helpers.new_user_session_path
697
+ puts "✅ Devise routes working"
698
+ rescue => e
699
+ puts "❌ Devise routes not working: #{e.message}"
700
+ exit 1
701
+ end
702
+ end
703
+ end