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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +67 -0
- data/MIT-LICENSE +20 -0
- data/README.md +382 -0
- data/Rakefile +8 -0
- data/app/assets/config/cccux_manifest.js +1 -0
- data/app/assets/stylesheets/cccux/application.css +102 -0
- data/app/controllers/cccux/ability_permissions_controller.rb +271 -0
- data/app/controllers/cccux/application_controller.rb +37 -0
- data/app/controllers/cccux/authorization_controller.rb +10 -0
- data/app/controllers/cccux/cccux_controller.rb +64 -0
- data/app/controllers/cccux/dashboard_controller.rb +172 -0
- data/app/controllers/cccux/home_controller.rb +19 -0
- data/app/controllers/cccux/roles_controller.rb +290 -0
- data/app/controllers/cccux/simple_controller.rb +7 -0
- data/app/controllers/cccux/users_controller.rb +112 -0
- data/app/controllers/concerns/cccux/application_controller_concern.rb +32 -0
- data/app/helpers/cccux/application_helper.rb +4 -0
- data/app/helpers/cccux/authorization_helper.rb +228 -0
- data/app/jobs/cccux/application_job.rb +4 -0
- data/app/mailers/cccux/application_mailer.rb +6 -0
- data/app/models/cccux/ability.rb +142 -0
- data/app/models/cccux/ability_permission.rb +61 -0
- data/app/models/cccux/application_record.rb +5 -0
- data/app/models/cccux/role.rb +90 -0
- data/app/models/cccux/role_ability.rb +49 -0
- data/app/models/cccux/user_role.rb +42 -0
- data/app/models/concerns/cccux/authorizable.rb +25 -0
- data/app/models/concerns/cccux/scoped_ownership.rb +183 -0
- data/app/models/concerns/cccux/user_concern.rb +87 -0
- data/app/views/cccux/ability_permissions/edit.html.erb +58 -0
- data/app/views/cccux/ability_permissions/index.html.erb +108 -0
- data/app/views/cccux/ability_permissions/new.html.erb +308 -0
- data/app/views/cccux/dashboard/index.html.erb +69 -0
- data/app/views/cccux/dashboard/model_discovery.html.erb +148 -0
- data/app/views/cccux/home/index.html.erb +42 -0
- data/app/views/cccux/roles/_flash.html.erb +10 -0
- data/app/views/cccux/roles/_form.html.erb +78 -0
- data/app/views/cccux/roles/_role.html.erb +67 -0
- data/app/views/cccux/roles/edit.html.erb +317 -0
- data/app/views/cccux/roles/index.html.erb +51 -0
- data/app/views/cccux/roles/new.html.erb +3 -0
- data/app/views/cccux/roles/show.html.erb +99 -0
- data/app/views/cccux/users/edit.html.erb +117 -0
- data/app/views/cccux/users/index.html.erb +99 -0
- data/app/views/cccux/users/new.html.erb +94 -0
- data/app/views/cccux/users/show.html.erb +138 -0
- data/app/views/layouts/cccux/admin.html.erb +168 -0
- data/app/views/layouts/cccux/application.html.erb +17 -0
- data/app/views/shared/_footer.html.erb +101 -0
- data/config/routes.rb +63 -0
- data/db/migrate/20250626194001_create_cccux_roles.rb +15 -0
- data/db/migrate/20250626194007_create_cccux_ability_permissions.rb +18 -0
- data/db/migrate/20250626194011_create_cccux_user_roles.rb +13 -0
- data/db/migrate/20250626194016_create_cccux_role_abilities.rb +10 -0
- data/db/migrate/20250627170611_add_owned_to_cccux_role_abilities.rb +9 -0
- data/db/migrate/20250705193709_add_context_to_cccux_role_abilities.rb +9 -0
- data/db/migrate/20250706214415_add_ownership_configuration_to_role_abilities.rb +21 -0
- data/db/seeds.rb +136 -0
- data/lib/cccux/engine.rb +50 -0
- data/lib/cccux/version.rb +3 -0
- data/lib/cccux.rb +7 -0
- data/lib/tasks/cccux.rake +703 -0
- data/lib/tasks/view_helpers.rake +274 -0
- 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"
|
data/lib/cccux/engine.rb
ADDED
|
@@ -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
|