cccux 0.1.0 â 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/README.md +124 -112
- data/Rakefile +57 -4
- data/app/assets/stylesheets/cccux/application.css +96 -72
- data/app/controllers/cccux/ability_permissions_controller.rb +138 -33
- data/app/controllers/cccux/application_controller.rb +7 -0
- data/app/controllers/cccux/cccux_controller.rb +20 -10
- data/app/controllers/cccux/dashboard_controller.rb +203 -32
- data/app/controllers/cccux/role_abilities_controller.rb +70 -0
- data/app/controllers/cccux/roles_controller.rb +70 -81
- data/app/controllers/cccux/users_controller.rb +22 -7
- data/app/controllers/concerns/cccux/application_controller_concern.rb +6 -2
- data/app/helpers/cccux/authorization_helper.rb +29 -21
- data/app/models/cccux/ability.rb +83 -32
- data/app/models/cccux/ability_permission.rb +9 -0
- data/app/models/cccux/post.rb +5 -0
- data/app/models/cccux/role.rb +19 -1
- data/app/models/cccux/role_ability.rb +3 -0
- data/app/models/concerns/cccux/user_concern.rb +5 -2
- data/app/views/cccux/ability_permissions/new.html.erb +2 -2
- data/app/views/cccux/dashboard/model_discovery.html.erb +7 -2
- data/app/views/cccux/roles/_form.html.erb +24 -71
- data/app/views/cccux/roles/edit.html.erb +5 -5
- data/app/views/cccux/roles/index.html.erb +1 -8
- data/app/views/cccux/roles/new.html.erb +1 -3
- data/app/views/cccux/users/edit.html.erb +4 -4
- data/app/views/cccux/users/new.html.erb +30 -15
- data/app/views/layouts/cccux/admin.html.erb +1 -2
- data/app/views/shared/_footer.html.erb +1 -1
- data/config/routes.rb +7 -6
- data/lib/cccux/engine.rb +7 -6
- data/lib/cccux/version.rb +1 -1
- data/lib/cccux.rb +12 -0
- data/lib/tasks/cccux.rake +271 -159
- metadata +10 -22
data/lib/tasks/cccux.rake
CHANGED
|
@@ -10,91 +10,117 @@ namespace :cccux do
|
|
|
10
10
|
|
|
11
11
|
# Step 1: Ensure Devise is installed and working
|
|
12
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
13
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
14
|
+
# Check if Devise files exist (more reliable than checking loaded state)
|
|
15
|
+
devise_gem_in_gemfile = File.exist?(Rails.root.join('Gemfile')) &&
|
|
16
|
+
File.read(Rails.root.join('Gemfile')).include?('gem "devise"')
|
|
17
|
+
devise_initializer_exists = File.exist?(Rails.root.join('config', 'initializers', 'devise.rb'))
|
|
18
|
+
user_model_has_devise = File.exist?(Rails.root.join('app', 'models', 'user.rb')) &&
|
|
19
|
+
File.read(Rails.root.join('app', 'models', 'user.rb')).include?('devise :')
|
|
20
|
+
routes_has_devise = File.exist?(Rails.root.join('config', 'routes.rb')) &&
|
|
21
|
+
File.read(Rails.root.join('config', 'routes.rb')).include?('devise_for :users')
|
|
22
|
+
|
|
23
|
+
# Check if Devise is loaded in the current environment (optional check)
|
|
24
|
+
devise_loaded = defined?(Devise)
|
|
25
|
+
user_model_exists = defined?(User)
|
|
26
|
+
user_has_devise_methods = user_model_exists && User.respond_to?(:devise)
|
|
27
|
+
|
|
28
|
+
puts " đ Devise status check:"
|
|
29
|
+
puts " - Devise gem in Gemfile: #{devise_gem_in_gemfile ? 'â
' : 'â'}"
|
|
30
|
+
puts " - Devise initializer: #{devise_initializer_exists ? 'â
' : 'â'}"
|
|
31
|
+
puts " - User model has Devise: #{user_model_has_devise ? 'â
' : 'â'}"
|
|
32
|
+
puts " - Routes have Devise: #{routes_has_devise ? 'â
' : 'â'}"
|
|
33
|
+
puts " - Devise loaded in environment: #{devise_loaded ? 'â
' : 'â'}"
|
|
34
|
+
puts " - User model has Devise methods: #{user_has_devise_methods ? 'â
' : 'â'}"
|
|
35
|
+
|
|
36
|
+
# If Devise files exist but aren't loaded, that's normal - just continue
|
|
37
|
+
if devise_gem_in_gemfile && devise_initializer_exists && user_model_has_devise && routes_has_devise
|
|
38
|
+
if devise_loaded && user_has_devise_methods
|
|
39
|
+
puts "â
Devise is properly installed and loaded"
|
|
40
|
+
else
|
|
41
|
+
puts "â
Devise files are properly installed"
|
|
42
|
+
puts "đĄ Devise will be fully loaded after server restart"
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
puts "â Devise is not properly installed or configured."
|
|
46
|
+
puts "run the following commands to install Devise: "
|
|
42
47
|
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"
|
|
48
|
+
puts " then run: rails cccux:setup again after Devise is installed"
|
|
45
49
|
exit 1
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
puts "â
Devise is properly installed"
|
|
49
53
|
|
|
50
|
-
# Step 2:
|
|
51
|
-
puts "đ Step 2:
|
|
54
|
+
# Step 2: Verify Devise is using default controllers
|
|
55
|
+
puts "đ Step 2: Verifying Devise configuration..."
|
|
56
|
+
if Dir.exist?(Rails.root.join('app', 'controllers', 'users'))
|
|
57
|
+
puts " â ī¸ Custom Devise controllers detected - these may cause conflicts"
|
|
58
|
+
puts " âšī¸ Using default Devise controllers is recommended for stability"
|
|
59
|
+
else
|
|
60
|
+
puts " â
Using default Devise controllers (recommended)"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Step 3: Configure routes
|
|
64
|
+
puts "đ Step 3: Configuring routes..."
|
|
52
65
|
configure_routes
|
|
53
66
|
puts "â
Routes configured"
|
|
54
67
|
|
|
55
|
-
# Step
|
|
56
|
-
puts "đ Step
|
|
68
|
+
# Step 4: Configure assets
|
|
69
|
+
puts "đ Step 4: Configuring assets..."
|
|
57
70
|
configure_assets
|
|
58
71
|
puts "â
Assets configured"
|
|
59
72
|
|
|
60
|
-
# Step
|
|
61
|
-
puts "đ Step
|
|
62
|
-
|
|
73
|
+
# Step 5: Run CCCUX migrations
|
|
74
|
+
puts "đ Step 5: Running CCCUX migrations..."
|
|
75
|
+
begin
|
|
76
|
+
Rake::Task['db:migrate'].invoke
|
|
77
|
+
rescue RuntimeError => e
|
|
78
|
+
if e.message.include?("Don't know how to build task 'db:migrate'")
|
|
79
|
+
puts " â ī¸ Skipping migrations (not available in engine context)"
|
|
80
|
+
else
|
|
81
|
+
raise e
|
|
82
|
+
end
|
|
83
|
+
end
|
|
63
84
|
puts "â
CCCUX migrations completed"
|
|
64
85
|
|
|
65
|
-
# Step
|
|
66
|
-
puts "đ Step
|
|
86
|
+
# Step 6: Include CCCUX concern in User model
|
|
87
|
+
puts "đ Step 6: Adding CCCUX to User model..."
|
|
67
88
|
include_cccux_concern
|
|
68
89
|
puts "â
CCCUX concern added to User model"
|
|
69
90
|
|
|
70
|
-
# Step
|
|
71
|
-
puts "đ Step
|
|
91
|
+
# Step 7: Configure ApplicationController with CCCUX
|
|
92
|
+
puts "đ Step 7: Configuring ApplicationController with CCCUX..."
|
|
72
93
|
configure_application_controller
|
|
73
94
|
puts "â
ApplicationController configured with CCCUX"
|
|
74
95
|
|
|
75
|
-
# Step
|
|
76
|
-
puts "đ Step
|
|
96
|
+
# Step 8: Create initial roles and permissions
|
|
97
|
+
puts "đ Step 8: Creating initial roles and permissions..."
|
|
77
98
|
create_default_roles_and_permissions
|
|
78
99
|
puts "â
Default roles and permissions created"
|
|
79
100
|
|
|
80
|
-
# Step
|
|
81
|
-
puts "đ Step
|
|
101
|
+
# Step 9: Create default admin user (if no users exist)
|
|
102
|
+
puts "đ Step 9: Creating default admin user..."
|
|
82
103
|
create_default_admin_user
|
|
83
104
|
|
|
84
|
-
|
|
85
|
-
puts "đ Step
|
|
105
|
+
# Step 10: Create footer partial
|
|
106
|
+
puts "đ Step 10: Creating footer partial..."
|
|
86
107
|
create_footer_partial
|
|
87
108
|
puts "â
Footer partial created"
|
|
88
109
|
|
|
89
|
-
# Step
|
|
90
|
-
puts "đ Step
|
|
110
|
+
# Step 11: Create home controller if needed
|
|
111
|
+
puts "đ Step 11: Checking for home controller..."
|
|
91
112
|
create_home_controller
|
|
92
113
|
puts "â
Home controller check completed"
|
|
93
114
|
|
|
94
|
-
# Step
|
|
95
|
-
puts "đ Step
|
|
115
|
+
# Step 12: Verify setup
|
|
116
|
+
puts "đ Step 12: Verifying setup..."
|
|
96
117
|
verify_setup
|
|
97
118
|
|
|
119
|
+
# Step 13: Precompile assets
|
|
120
|
+
puts "đ Step 13: Precompiling assets..."
|
|
121
|
+
precompile_assets
|
|
122
|
+
puts "â
Assets precompiled"
|
|
123
|
+
|
|
98
124
|
puts ""
|
|
99
125
|
puts "đ CCCUX + Devise setup completed successfully!"
|
|
100
126
|
puts ""
|
|
@@ -106,6 +132,19 @@ namespace :cccux do
|
|
|
106
132
|
puts "đ Need help? Check the CCCUX documentation or README"
|
|
107
133
|
end
|
|
108
134
|
|
|
135
|
+
desc 'test:prepare - Prepare test database for CCCUX engine'
|
|
136
|
+
task 'test:prepare' => :environment do
|
|
137
|
+
puts "đ§Ē Preparing CCCUX test database..."
|
|
138
|
+
|
|
139
|
+
# Switch to test environment
|
|
140
|
+
Rails.env = 'test'
|
|
141
|
+
|
|
142
|
+
# Load schema into test database
|
|
143
|
+
system("cd #{Rails.root.join('..', '..')} && RAILS_ENV=test rails db:schema:load")
|
|
144
|
+
|
|
145
|
+
puts "â
Test database prepared"
|
|
146
|
+
end
|
|
147
|
+
|
|
109
148
|
desc 'test - Test CCCUX + Devise integration'
|
|
110
149
|
task test: :environment do
|
|
111
150
|
puts "đ§Ē Testing CCCUX + Devise integration..."
|
|
@@ -203,12 +242,124 @@ namespace :cccux do
|
|
|
203
242
|
puts "â
CCCUX removed from application"
|
|
204
243
|
end
|
|
205
244
|
|
|
245
|
+
desc 'megabar:create_mega_role - Discover MegaBar models and create comprehensive permissions'
|
|
246
|
+
task 'megabar:create_mega_role' => :environment do
|
|
247
|
+
puts "đ Discovering MegaBar models and creating permissions..."
|
|
248
|
+
|
|
249
|
+
# Check if MegaBar is available
|
|
250
|
+
unless defined?(MegaBar)
|
|
251
|
+
puts "â MegaBar engine not detected"
|
|
252
|
+
puts "đĄ Make sure MegaBar is properly installed and configured"
|
|
253
|
+
exit 1
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Use the new engine discovery approach
|
|
257
|
+
megabar_models = []
|
|
258
|
+
|
|
259
|
+
begin
|
|
260
|
+
# Get all database tables that start with 'mega_bar_'
|
|
261
|
+
application_tables = ActiveRecord::Base.connection.tables.select do |table|
|
|
262
|
+
table.start_with?('mega_bar_')
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
application_tables.each do |table|
|
|
266
|
+
# Convert table name to proper namespaced model name
|
|
267
|
+
model_part = table.gsub('mega_bar_', '').singularize.camelize
|
|
268
|
+
model_name = "MegaBar::#{model_part}"
|
|
269
|
+
|
|
270
|
+
# Verify the model exists and is valid
|
|
271
|
+
begin
|
|
272
|
+
if Object.const_defined?(model_name)
|
|
273
|
+
model_class = Object.const_get(model_name)
|
|
274
|
+
if model_class.respond_to?(:table_name) &&
|
|
275
|
+
model_class.table_name == table
|
|
276
|
+
megabar_models << model_name
|
|
277
|
+
end
|
|
278
|
+
else
|
|
279
|
+
# Model constant doesn't exist yet, but table does - likely a valid model
|
|
280
|
+
megabar_models << model_name
|
|
281
|
+
end
|
|
282
|
+
rescue => e
|
|
283
|
+
# Skip if there's an error
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
rescue => e
|
|
288
|
+
puts "â Error detecting MegaBar models: #{e.message}"
|
|
289
|
+
exit 1
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
if megabar_models.empty?
|
|
293
|
+
puts "â ī¸ No MegaBar models found"
|
|
294
|
+
puts "đĄ Make sure MegaBar is properly set up and models exist"
|
|
295
|
+
exit 1
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
puts "đ Found #{megabar_models.count} MegaBar models:"
|
|
299
|
+
megabar_models.each { |model| puts " - #{model}" }
|
|
300
|
+
|
|
301
|
+
# Create "Mega Role" if it doesn't exist
|
|
302
|
+
mega_role = Cccux::Role.find_or_create_by(name: 'Mega Role') do |role|
|
|
303
|
+
role.description = 'Global permissions for all MegaBar models'
|
|
304
|
+
role.active = true
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
if mega_role.persisted? && !mega_role.previously_persisted?
|
|
308
|
+
puts "â
Created 'Mega Role'"
|
|
309
|
+
puts "đĄ Visit /cccux/users/ to assign users to the 'Mega Role'"
|
|
310
|
+
else
|
|
311
|
+
puts "âšī¸ 'Mega Role' already exists"
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Create CRUD permissions for each MegaBar model
|
|
315
|
+
actions = %w[create read update destroy]
|
|
316
|
+
permissions_created = 0
|
|
317
|
+
|
|
318
|
+
megabar_models.each do |model_name|
|
|
319
|
+
actions.each do |action|
|
|
320
|
+
permission = Cccux::AbilityPermission.find_or_create_by(
|
|
321
|
+
action: action,
|
|
322
|
+
subject: model_name
|
|
323
|
+
) do |p|
|
|
324
|
+
p.description = "#{action.capitalize} #{model_name.pluralize.downcase}"
|
|
325
|
+
p.active = true
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
if permission.persisted? && !permission.previously_persisted?
|
|
329
|
+
permissions_created += 1
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Assign all permissions to the Mega Role
|
|
335
|
+
assigned_permissions = 0
|
|
336
|
+
Cccux::AbilityPermission.where(subject: megabar_models).each do |permission|
|
|
337
|
+
role_ability = Cccux::RoleAbility.find_or_create_by(
|
|
338
|
+
role: mega_role,
|
|
339
|
+
ability_permission: permission
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
if role_ability.persisted? && !role_ability.previously_persisted?
|
|
343
|
+
assigned_permissions += 1
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
puts "â
Created #{permissions_created} permissions for MegaBar models"
|
|
348
|
+
puts "â
Assigned #{assigned_permissions} permissions to 'Mega Role'"
|
|
349
|
+
puts ""
|
|
350
|
+
puts "đ MegaBar permissions setup completed!"
|
|
351
|
+
puts "đĄ Users with 'Mega Role' will have full access to all MegaBar models"
|
|
352
|
+
end
|
|
353
|
+
|
|
206
354
|
private
|
|
207
355
|
|
|
208
356
|
def configure_routes
|
|
209
357
|
routes_path = Rails.root.join('config/routes.rb')
|
|
210
358
|
routes_content = File.read(routes_path)
|
|
211
359
|
|
|
360
|
+
# Check if Devise controllers exist
|
|
361
|
+
devise_controllers_exist = Dir.exist?(Rails.root.join('app', 'controllers', 'users'))
|
|
362
|
+
|
|
212
363
|
# Ensure devise_for :users is before engine mount
|
|
213
364
|
unless routes_content.include?('devise_for :users')
|
|
214
365
|
puts " â Adding devise_for :users to routes..."
|
|
@@ -217,6 +368,12 @@ namespace :cccux do
|
|
|
217
368
|
routes_content = File.read(routes_path)
|
|
218
369
|
end
|
|
219
370
|
|
|
371
|
+
# Ensure routes use default Devise controllers (recommended for stability)
|
|
372
|
+
if devise_controllers_exist
|
|
373
|
+
puts " â ī¸ Custom Devise controllers detected - consider removing them for stability"
|
|
374
|
+
puts " âšī¸ Routes will use default Devise controllers"
|
|
375
|
+
end
|
|
376
|
+
|
|
220
377
|
# Add engine mount if not present
|
|
221
378
|
unless routes_content.include?('mount Cccux::Engine')
|
|
222
379
|
puts " â Adding CCCUX engine mount to routes..."
|
|
@@ -229,40 +386,9 @@ namespace :cccux do
|
|
|
229
386
|
end
|
|
230
387
|
|
|
231
388
|
def configure_assets
|
|
232
|
-
#
|
|
233
|
-
|
|
234
|
-
|
|
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
|
|
389
|
+
# Note: CCCUX styles are now loaded via the engine's asset pipeline
|
|
390
|
+
# No need to copy styles to host app's application.css
|
|
391
|
+
puts " âšī¸ CCCUX styles will be loaded via engine asset pipeline"
|
|
266
392
|
|
|
267
393
|
# Add JavaScript assets (if using legacy asset pipeline)
|
|
268
394
|
js_path = Rails.root.join('app/assets/javascripts/application.js')
|
|
@@ -559,10 +685,10 @@ namespace :cccux do
|
|
|
559
685
|
|
|
560
686
|
footer_path = shared_dir.join('_footer.html.erb')
|
|
561
687
|
|
|
562
|
-
# Create footer content
|
|
688
|
+
# Create footer content - No inline styles, uses CCCUX engine CSS
|
|
563
689
|
footer_content = <<~ERB
|
|
564
|
-
<!-- CCCUX Footer -
|
|
565
|
-
<footer class="cccux-footer"
|
|
690
|
+
<!-- CCCUX Footer - Styles loaded from CCCUX engine -->
|
|
691
|
+
<footer class="cccux-footer">
|
|
566
692
|
<div class="container">
|
|
567
693
|
<div class="row">
|
|
568
694
|
<div class="col-md-6">
|
|
@@ -570,7 +696,7 @@ namespace :cccux do
|
|
|
570
696
|
<a href="<%= main_app.root_path %>" class="footer-link">đ Home</a>
|
|
571
697
|
<% if user_signed_in? && current_user.has_role?('Role Manager') %>
|
|
572
698
|
<span class="footer-separator">|</span>
|
|
573
|
-
<a href="
|
|
699
|
+
<a href="/cccux" class="footer-link">âī¸ CCCUX Admin</a>
|
|
574
700
|
<% end %>
|
|
575
701
|
</nav>
|
|
576
702
|
</div>
|
|
@@ -579,10 +705,7 @@ namespace :cccux do
|
|
|
579
705
|
<span class="user-info">
|
|
580
706
|
đ¤ <strong><%= current_user.email %></strong>
|
|
581
707
|
<span class="footer-separator">|</span>
|
|
582
|
-
<%=
|
|
583
|
-
method: :delete,
|
|
584
|
-
class: "footer-link",
|
|
585
|
-
data: { turbo_method: :delete } %>
|
|
708
|
+
<%= button_to "Logout", main_app.destroy_user_session_path, method: :delete, class: "footer-link auth-link", style: "background: none; border: none; color: #007bff; text-decoration: none; padding: 5px 10px; border-radius: 4px; transition: all 0.2s ease; font-weight: 500; cursor: pointer; font: inherit;" %>
|
|
586
709
|
</span>
|
|
587
710
|
<% else %>
|
|
588
711
|
<span class="auth-links">
|
|
@@ -595,73 +718,23 @@ namespace :cccux do
|
|
|
595
718
|
</div>
|
|
596
719
|
</div>
|
|
597
720
|
</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
721
|
ERB
|
|
653
722
|
|
|
654
723
|
# Write the footer partial
|
|
655
724
|
File.write(footer_path, footer_content)
|
|
656
|
-
puts "
|
|
725
|
+
puts "â
Created footer partial at #{footer_path}"
|
|
657
726
|
|
|
658
|
-
#
|
|
727
|
+
# Include footer in application layout
|
|
728
|
+
include_footer_in_layout
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
def include_footer_in_layout
|
|
659
732
|
layout_path = Rails.root.join('app', 'views', 'layouts', 'application.html.erb')
|
|
660
733
|
if File.exist?(layout_path)
|
|
661
734
|
layout_content = File.read(layout_path)
|
|
662
735
|
|
|
663
736
|
# Check if footer is already included
|
|
664
|
-
unless layout_content.include?(
|
|
737
|
+
unless layout_content.include?("render 'shared/footer'")
|
|
665
738
|
# Add footer before closing body tag
|
|
666
739
|
if layout_content.include?('</body>')
|
|
667
740
|
updated_content = layout_content.gsub(
|
|
@@ -669,35 +742,74 @@ namespace :cccux do
|
|
|
669
742
|
"\\1 <%= render 'shared/footer' %>\n\\1</body>"
|
|
670
743
|
)
|
|
671
744
|
File.write(layout_path, updated_content)
|
|
672
|
-
puts "
|
|
745
|
+
puts "â
Added footer to application layout"
|
|
673
746
|
else
|
|
674
|
-
puts "
|
|
747
|
+
puts "â ī¸ Could not find </body> tag in application layout - please manually add: <%= render 'shared/footer' %>"
|
|
675
748
|
end
|
|
676
749
|
else
|
|
677
|
-
puts "
|
|
750
|
+
puts "âšī¸ Footer already included in application layout"
|
|
678
751
|
end
|
|
679
752
|
else
|
|
680
|
-
puts "
|
|
753
|
+
puts "â ī¸ Application layout not found - please manually add: <%= render 'shared/footer' %>"
|
|
681
754
|
end
|
|
682
755
|
end
|
|
683
756
|
|
|
684
757
|
def verify_setup
|
|
685
758
|
# Test that User model has CCCUX methods
|
|
759
|
+
# First, try to reload the User model file to pick up the concern
|
|
760
|
+
begin
|
|
761
|
+
load Rails.root.join('app', 'models', 'user.rb')
|
|
762
|
+
rescue => e
|
|
763
|
+
puts " â ī¸ Could not reload User model: #{e.message}"
|
|
764
|
+
end
|
|
765
|
+
|
|
686
766
|
user = User.new
|
|
687
767
|
unless user.respond_to?(:has_role?)
|
|
688
768
|
puts "â User model missing CCCUX methods"
|
|
769
|
+
puts " đĄ This sometimes happens on the first run. Try running 'rails cccux:setup' again."
|
|
770
|
+
puts " đ§ The concern was added to the User model file, but Rails needs to reload it."
|
|
689
771
|
exit 1
|
|
690
772
|
end
|
|
691
773
|
|
|
692
774
|
puts "â
CCCUX methods available on User model"
|
|
693
775
|
|
|
694
|
-
#
|
|
776
|
+
# Check if Devise files exist (more reliable than testing routes in rake context)
|
|
777
|
+
devise_initializer_exists = File.exist?(Rails.root.join('config', 'initializers', 'devise.rb'))
|
|
778
|
+
user_model_has_devise = File.exist?(Rails.root.join('app', 'models', 'user.rb')) &&
|
|
779
|
+
File.read(Rails.root.join('app', 'models', 'user.rb')).include?('devise :')
|
|
780
|
+
routes_has_devise = File.exist?(Rails.root.join('config', 'routes.rb')) &&
|
|
781
|
+
File.read(Rails.root.join('config', 'routes.rb')).include?('devise_for :users')
|
|
782
|
+
|
|
783
|
+
puts " đ Devise file verification:"
|
|
784
|
+
puts " - Devise initializer: #{devise_initializer_exists ? 'â
' : 'â'}"
|
|
785
|
+
puts " - User model has Devise: #{user_model_has_devise ? 'â
' : 'â'}"
|
|
786
|
+
puts " - Routes have Devise: #{routes_has_devise ? 'â
' : 'â'}"
|
|
787
|
+
|
|
788
|
+
if devise_initializer_exists && user_model_has_devise && routes_has_devise
|
|
789
|
+
puts "â
Devise files properly configured"
|
|
790
|
+
puts "đĄ Devise routes will be available after server restart"
|
|
791
|
+
else
|
|
792
|
+
puts "â ī¸ Some Devise files may be missing or incomplete"
|
|
793
|
+
puts "đĄ This is normal if Devise was just installed - restart your server to complete setup"
|
|
794
|
+
end
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
def precompile_assets
|
|
798
|
+
puts " đ§ Precompiling CCCUX assets..."
|
|
799
|
+
|
|
695
800
|
begin
|
|
696
|
-
|
|
697
|
-
|
|
801
|
+
# Run assets:precompile task
|
|
802
|
+
Rake::Task['assets:precompile'].invoke
|
|
803
|
+
puts " â
Assets precompiled successfully"
|
|
804
|
+
rescue RuntimeError => e
|
|
805
|
+
if e.message.include?("Don't know how to build task 'assets:precompile'")
|
|
806
|
+
puts " â ī¸ Assets precompile task not available (this is normal in some contexts)"
|
|
807
|
+
puts " âšī¸ Assets will be compiled automatically when the server starts"
|
|
808
|
+
else
|
|
809
|
+
puts " â Error precompiling assets: #{e.message}"
|
|
810
|
+
end
|
|
698
811
|
rescue => e
|
|
699
|
-
puts "â
|
|
700
|
-
exit 1
|
|
812
|
+
puts " â Unexpected error during asset precompilation: #{e.message}"
|
|
701
813
|
end
|
|
702
814
|
end
|
|
703
815
|
end
|
metadata
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cccux
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2025-07-
|
|
10
|
+
date: 2025-07-28 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rails
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "~>"
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '7.1'
|
|
19
16
|
- - ">="
|
|
20
17
|
- !ruby/object:Gem::Version
|
|
21
18
|
version: 7.1.5.1
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '9.0'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
25
|
requirements:
|
|
26
|
-
- - "~>"
|
|
27
|
-
- !ruby/object:Gem::Version
|
|
28
|
-
version: '7.1'
|
|
29
26
|
- - ">="
|
|
30
27
|
- !ruby/object:Gem::Version
|
|
31
28
|
version: 7.1.5.1
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '9.0'
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: cancancan
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -71,20 +71,6 @@ dependencies:
|
|
|
71
71
|
- - "~>"
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
73
|
version: '1.4'
|
|
74
|
-
- !ruby/object:Gem::Dependency
|
|
75
|
-
name: rspec-rails
|
|
76
|
-
requirement: !ruby/object:Gem::Requirement
|
|
77
|
-
requirements:
|
|
78
|
-
- - "~>"
|
|
79
|
-
- !ruby/object:Gem::Version
|
|
80
|
-
version: '6.0'
|
|
81
|
-
type: :development
|
|
82
|
-
prerelease: false
|
|
83
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
84
|
-
requirements:
|
|
85
|
-
- - "~>"
|
|
86
|
-
- !ruby/object:Gem::Version
|
|
87
|
-
version: '6.0'
|
|
88
74
|
description: CCCUX provides a comprehensive admin interface and user experience layer
|
|
89
75
|
for CanCanCan authorization. It includes role-based access control (RBAC) models,
|
|
90
76
|
admin controllers for managing users, roles, and permissions, and a clean interface
|
|
@@ -107,6 +93,7 @@ files:
|
|
|
107
93
|
- app/controllers/cccux/cccux_controller.rb
|
|
108
94
|
- app/controllers/cccux/dashboard_controller.rb
|
|
109
95
|
- app/controllers/cccux/home_controller.rb
|
|
96
|
+
- app/controllers/cccux/role_abilities_controller.rb
|
|
110
97
|
- app/controllers/cccux/roles_controller.rb
|
|
111
98
|
- app/controllers/cccux/simple_controller.rb
|
|
112
99
|
- app/controllers/cccux/users_controller.rb
|
|
@@ -118,6 +105,7 @@ files:
|
|
|
118
105
|
- app/models/cccux/ability.rb
|
|
119
106
|
- app/models/cccux/ability_permission.rb
|
|
120
107
|
- app/models/cccux/application_record.rb
|
|
108
|
+
- app/models/cccux/post.rb
|
|
121
109
|
- app/models/cccux/role.rb
|
|
122
110
|
- app/models/cccux/role_ability.rb
|
|
123
111
|
- app/models/cccux/user_role.rb
|