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
data/config/routes.rb ADDED
@@ -0,0 +1,63 @@
1
+ Cccux::Engine.routes.draw do
2
+ # Devise authentication routes - use different path to avoid conflicts
3
+ # devise_for :users, class_name: 'Cccux::User', path: 'auth'
4
+
5
+ root 'dashboard#index'
6
+ get '/test', to: 'simple#index'
7
+
8
+ # Model Discovery Routes
9
+ get 'model-discovery', to: 'dashboard#model_discovery', as: :model_discovery
10
+ post 'sync-permissions', to: 'dashboard#sync_permissions', as: :sync_permissions
11
+
12
+ # Admin CRUD routes for user management
13
+ resources :users do
14
+ member do
15
+ patch :toggle_active
16
+ post :assign_role
17
+ delete :remove_role
18
+ end
19
+ collection do
20
+ get :search
21
+ end
22
+ end
23
+
24
+ resources :roles do
25
+ member do
26
+ patch :toggle_active
27
+ get :permissions
28
+ patch :update_permissions
29
+ end
30
+ collection do
31
+ get :search
32
+ patch :reorder
33
+ get :model_columns
34
+ end
35
+ end
36
+
37
+ resources :ability_permissions do
38
+ member do
39
+ patch :toggle_active
40
+ end
41
+ collection do
42
+ get :search
43
+ get :grid
44
+ post :bulk_create
45
+ get :actions_for_subject
46
+ end
47
+ end
48
+
49
+ resources :user_roles, only: [:index, :create, :destroy] do
50
+ collection do
51
+ get :search
52
+ end
53
+ end
54
+
55
+ resources :role_abilities, only: [:index, :create, :destroy] do
56
+ collection do
57
+ get :search
58
+ end
59
+ end
60
+
61
+ # Catch-all route for any unmatched paths in CCCUX - redirect to home
62
+ match '*unmatched', to: 'dashboard#not_found', via: :all
63
+ end
@@ -0,0 +1,15 @@
1
+ class CreateCccuxRoles < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :cccux_roles do |t|
4
+ t.string :name
5
+ t.text :description
6
+ t.boolean :active
7
+ t.integer :priority
8
+
9
+ t.timestamps
10
+ end
11
+ add_index :cccux_roles, :name, unique: true
12
+ add_index :cccux_roles, :active
13
+ add_index :cccux_roles, :priority
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ class CreateCccuxAbilityPermissions < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :cccux_ability_permissions do |t|
4
+ t.string :action
5
+ t.string :subject
6
+ t.text :description
7
+ t.boolean :active
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ # Add indexes for better query performance
13
+ add_index :cccux_ability_permissions, :action
14
+ add_index :cccux_ability_permissions, :subject
15
+ add_index :cccux_ability_permissions, :active
16
+ add_index :cccux_ability_permissions, [:action, :subject], unique: true
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ class CreateCccuxUserRoles < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :cccux_user_roles do |t|
4
+ t.references :user, null: false, foreign_key: { to_table: :users }
5
+ t.references :role, null: false, foreign_key: { to_table: :cccux_roles }
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ # Add unique index to prevent duplicate user-role assignments
11
+ add_index :cccux_user_roles, [:user_id, :role_id], unique: true
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class CreateCccuxRoleAbilities < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :cccux_role_abilities do |t|
4
+ t.references :role, null: false, foreign_key: { to_table: :cccux_roles }
5
+ t.references :ability_permission, null: false, foreign_key: { to_table: :cccux_ability_permissions }
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ class AddOwnedToCccuxRoleAbilities < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :cccux_role_abilities, :owned, :boolean, default: false, null: false
4
+
5
+ # Add index for better query performance
6
+ add_index :cccux_role_abilities, [:role_id, :ability_permission_id, :owned],
7
+ name: 'index_role_abilities_on_role_permission_owned'
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class AddContextToCccuxRoleAbilities < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :cccux_role_abilities, :context, :string, default: 'global', null: false
4
+
5
+ # Add index for better query performance
6
+ add_index :cccux_role_abilities, [:role_id, :ability_permission_id, :context],
7
+ name: 'index_role_abilities_on_role_permission_context'
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ class AddOwnershipConfigurationToRoleAbilities < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :cccux_role_abilities, :ownership_source, :string
4
+ add_column :cccux_role_abilities, :ownership_conditions, :text
5
+
6
+ # Add index for ownership_source lookups
7
+ add_index :cccux_role_abilities, :ownership_source unless index_exists?(:cccux_role_abilities, :ownership_source)
8
+
9
+ # Remove old unique index if it exists
10
+ if index_exists?(:cccux_role_abilities, [:role_id, :ability_permission_id, :owned], name: 'index_role_abilities_on_role_permission_owned')
11
+ remove_index :cccux_role_abilities, name: 'index_role_abilities_on_role_permission_owned'
12
+ end
13
+
14
+ # Add new unique index including ownership_source
15
+ unless index_exists?(:cccux_role_abilities, [:role_id, :ability_permission_id, :owned, :context, :ownership_source], name: 'index_role_abilities_on_role_permission_owned_source')
16
+ add_index :cccux_role_abilities, [:role_id, :ability_permission_id, :owned, :context, :ownership_source],
17
+ unique: true,
18
+ name: 'index_role_abilities_on_role_permission_owned_source'
19
+ end
20
+ end
21
+ end
data/db/seeds.rb ADDED
@@ -0,0 +1,136 @@
1
+ # Seeds for CCCUX Engine
2
+ puts "🌱 Seeding CCCUX data..."
3
+
4
+ # Create comprehensive permissions for all CCCUX models
5
+ cccux_models = ['User', 'Role', 'AbilityPermission', 'UserRole', 'RoleAbility']
6
+ # Use granular RESTful actions instead of simplified CRUD
7
+ restful_actions = ['index', 'show', 'new', 'create', 'edit', 'update', 'destroy']
8
+
9
+ puts "📋 Creating permissions for CCCUX models..."
10
+ cccux_models.each do |model|
11
+ restful_actions.each do |action|
12
+ permission = Cccux::AbilityPermission.find_or_create_by(
13
+ action: action,
14
+ subject: "Cccux::#{model}"
15
+ ) do |p|
16
+ p.description = "#{action.capitalize} #{model.downcase.pluralize}"
17
+ p.active = true
18
+ end
19
+ end
20
+ end
21
+
22
+ # Create permissions for host app models (without Cccux namespace)
23
+ host_models = ['User', 'Role', 'AbilityPermission']
24
+ host_models.each do |model|
25
+ restful_actions.each do |action|
26
+ permission = Cccux::AbilityPermission.find_or_create_by(
27
+ action: action,
28
+ subject: model
29
+ ) do |p|
30
+ p.description = "#{action.capitalize} host app #{model.downcase.pluralize}"
31
+ p.active = true
32
+ end
33
+ end
34
+ end
35
+
36
+ # Create special 'manage' permissions for Role and AbilityPermission
37
+ ['Role', 'AbilityPermission'].each do |model|
38
+ permission = Cccux::AbilityPermission.find_or_create_by(
39
+ action: 'manage',
40
+ subject: model
41
+ ) do |p|
42
+ p.description = "Full management of #{model.downcase.pluralize}"
43
+ p.active = true
44
+ end
45
+ end
46
+
47
+ puts "✅ Created #{Cccux::AbilityPermission.count} permissions"
48
+
49
+ # Create Role Manager Role
50
+ role_manager_role = Cccux::Role.find_or_create_by(name: 'Role Manager') do |role|
51
+ role.description = 'System administrator with full access to all CCCUX functionality'
52
+ role.active = true
53
+ role.priority = 1
54
+ end
55
+
56
+ # Create Guest Role
57
+ guest_role = Cccux::Role.find_or_create_by(name: 'Guest') do |role|
58
+ role.description = 'Guest users with minimal read-only permissions'
59
+ role.active = true
60
+ role.priority = 10
61
+ end
62
+
63
+ # Create Basic User Role (for new registrations)
64
+ basic_role = Cccux::Role.find_or_create_by(name: 'Basic User') do |role|
65
+ role.description = 'Standard registered user with limited permissions'
66
+ role.active = true
67
+ role.priority = 5
68
+ end
69
+
70
+ puts "✅ Created #{Cccux::Role.count} roles"
71
+
72
+ puts "🔑 Assigning permissions to Role Manager role..."
73
+ # Assign Role Manager permissions - all RESTful actions:
74
+ role_manager_permissions = []
75
+
76
+ # CCCUX models: all RESTful actions
77
+ cccux_models.each do |model|
78
+ restful_actions.each do |action|
79
+ permission = Cccux::AbilityPermission.find_by(
80
+ action: action,
81
+ subject: "Cccux::#{model}"
82
+ )
83
+ role_manager_permissions << permission if permission
84
+ end
85
+ end
86
+
87
+ # Host app models: all RESTful actions
88
+ host_models.each do |model|
89
+ restful_actions.each do |action|
90
+ permission = Cccux::AbilityPermission.find_by(
91
+ action: action,
92
+ subject: model
93
+ )
94
+ role_manager_permissions << permission if permission
95
+ end
96
+ end
97
+
98
+ # Special manage permissions for Role and AbilityPermission
99
+ ['Role', 'AbilityPermission'].each do |model|
100
+ permission = Cccux::AbilityPermission.find_by(
101
+ action: 'manage',
102
+ subject: model
103
+ )
104
+ role_manager_permissions << permission if permission
105
+ end
106
+
107
+ # Assign all permissions to Role Manager role
108
+ role_manager_permissions.compact.each do |permission|
109
+ unless role_manager_role.ability_permissions.include?(permission)
110
+ Cccux::RoleAbility.create!(role: role_manager_role, ability_permission: permission)
111
+ end
112
+ end
113
+
114
+ puts "🔐 Assigning minimal permissions to Guest role..."
115
+ # Guest users get minimal read-only permissions
116
+ guest_permissions = [
117
+ { action: 'index', subject: 'Order' },
118
+ { action: 'show', subject: 'Order' }
119
+ ]
120
+
121
+ guest_permissions.each do |perm|
122
+ permission = Cccux::AbilityPermission.find_by(action: perm[:action], subject: perm[:subject])
123
+ if permission && !guest_role.ability_permissions.include?(permission)
124
+ Cccux::RoleAbility.create!(role: guest_role, ability_permission: permission)
125
+ end
126
+ end
127
+
128
+ puts "✅ CCCUX seeded successfully!"
129
+ puts "🔧 #{role_manager_role.ability_permissions.count} permissions assigned to Role Manager role"
130
+ puts "👥 #{guest_role.ability_permissions.count} permissions assigned to Guest role"
131
+ puts "📊 #{Cccux::Role.count} roles created"
132
+ puts ""
133
+ puts "🎯 Next steps:"
134
+ puts " 1. Run the interactive setup: rake cccux:engine_init"
135
+ puts " 2. Or manually create your first Role Manager via console"
136
+ puts " 3. Visit /cccux to access the admin interface"
@@ -0,0 +1,50 @@
1
+ module Cccux
2
+ class Engine < ::Rails::Engine
3
+ # Only isolate namespace if explicitly mounted - check this later
4
+ isolate_namespace Cccux
5
+
6
+ # Prevent automatic route registration - only register when explicitly mounted
7
+ config.autoload_paths += %W(#{config.root}/lib)
8
+
9
+ # Automatically append engine migrations to host app
10
+ initializer :append_migrations do |app|
11
+ unless app.root.to_s.match root.to_s
12
+ config.paths["db/migrate"].expanded.each do |expanded_path|
13
+ app.config.paths["db/migrate"] << expanded_path
14
+ end
15
+ end
16
+ end
17
+
18
+ # Ensure concerns are autoloaded
19
+ config.autoload_paths << root.join('app', 'models', 'concerns')
20
+ config.eager_load_paths << root.join('app', 'models', 'concerns')
21
+
22
+ # Load rake tasks
23
+ rake_tasks do
24
+ load 'tasks/cccux.rake'
25
+ end
26
+
27
+ # Configure assets for both Sprockets and Propshaft
28
+ initializer "cccux.assets" do |app|
29
+ # Add engine assets to the load path
30
+ app.config.assets.paths << root.join('app', 'assets', 'stylesheets')
31
+ app.config.assets.paths << root.join('app', 'assets', 'javascripts')
32
+
33
+ # For Propshaft, ensure engine assets are available
34
+ if defined?(Propshaft)
35
+ app.config.assets.paths << root.join('app', 'assets')
36
+ end
37
+ end
38
+
39
+ # Include helpers in host application only when mounted
40
+ config.to_prepare do
41
+ # Only include helpers if the engine is actually mounted
42
+ if Rails.application.routes.respond_to?(:include?) &&
43
+ Rails.application.routes.include?(Cccux::Engine)
44
+ # Temporarily disabled to avoid conflicts with Devise
45
+ # ActionView::Base.include Cccux::AuthorizationHelper
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module Cccux
2
+ VERSION = "0.1.0"
3
+ end
data/lib/cccux.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "cccux/version"
2
+ require "cccux/engine"
3
+ require "cancancan"
4
+
5
+ module Cccux
6
+ # Your code goes here...
7
+ end