easy-admin-rails 0.2.5 → 0.2.7
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/app/assets/builds/easy_admin.base.js +95 -0
- data/app/assets/builds/easy_admin.base.js.map +3 -3
- data/app/assets/builds/easy_admin.css +226 -0
- data/app/components/easy_admin/fields/form/belongs_to_component.rb +0 -1
- data/app/components/easy_admin/form_layout_component.rb +553 -0
- data/app/components/easy_admin/navbar_component.rb +19 -4
- data/app/components/easy_admin/permissions/user_role_permissions_component.rb +1 -3
- data/app/components/easy_admin/profile/change_password_modal_component.rb +75 -0
- data/app/components/easy_admin/profile/profile_tab_component.rb +92 -0
- data/app/components/easy_admin/profile/security_tab_component.rb +53 -0
- data/app/components/easy_admin/profile/settings_component.rb +103 -0
- data/app/components/easy_admin/show_layout_component.rb +694 -24
- data/app/components/easy_admin/two_factor/backup_codes_component.rb +118 -0
- data/app/components/easy_admin/two_factor/setup_component.rb +124 -0
- data/app/components/easy_admin/two_factor/status_component.rb +92 -0
- data/app/controllers/concerns/easy_admin/two_factor.rb +110 -0
- data/app/controllers/easy_admin/application_controller.rb +10 -5
- data/app/controllers/easy_admin/batch_actions_controller.rb +0 -1
- data/app/controllers/easy_admin/concerns/inline_field_editing.rb +4 -11
- data/app/controllers/easy_admin/concerns/resource_loading.rb +10 -9
- data/app/controllers/easy_admin/concerns/resource_pagination.rb +3 -0
- data/app/controllers/easy_admin/dashboards_controller.rb +0 -1
- data/app/controllers/easy_admin/profile_controller.rb +25 -0
- data/app/controllers/easy_admin/resources_controller.rb +1 -5
- data/app/controllers/easy_admin/row_actions_controller.rb +1 -4
- data/app/controllers/easy_admin/sessions_controller.rb +107 -1
- data/app/helpers/easy_admin/fields_helper.rb +8 -22
- data/app/javascript/easy_admin/controllers/infinite_scroll_controller.js +12 -0
- data/app/javascript/easy_admin/controllers/vertical_tabs_controller.js +112 -0
- data/app/javascript/easy_admin/controllers.js +3 -1
- data/app/models/easy_admin/admin_user.rb +3 -0
- data/app/views/easy_admin/profile/backup_codes_regenerated.turbo_stream.erb +12 -0
- data/app/views/easy_admin/profile/change_password.html.erb +24 -0
- data/app/views/easy_admin/profile/index.html.erb +1 -0
- data/app/views/easy_admin/profile/password_error.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/password_invalid_current.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/password_updated.turbo_stream.erb +9 -0
- data/app/views/easy_admin/profile/two_factor_backup_codes.html.erb +24 -0
- data/app/views/easy_admin/profile/two_factor_enabled.turbo_stream.erb +12 -0
- data/app/views/easy_admin/profile/two_factor_invalid_code.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/two_factor_not_enabled.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/two_factor_setup.html.erb +24 -0
- data/app/views/easy_admin/profile/two_factor_unavailable.turbo_stream.erb +6 -0
- data/app/views/easy_admin/resources/edit.html.erb +2 -2
- data/app/views/easy_admin/resources/new.html.erb +2 -2
- data/app/views/easy_admin/resources/show.html.erb +3 -1
- data/app/views/easy_admin/sessions/two_factor_verification.html.erb +48 -0
- data/app/views/easy_admin/sessions/verify_2fa_error.turbo_stream.erb +13 -0
- data/config/routes.rb +20 -1
- data/lib/easy-admin-rails.rb +1 -0
- data/lib/easy_admin/field.rb +3 -2
- data/lib/easy_admin/layouts/builders/base_layout_builder.rb +245 -0
- data/lib/easy_admin/layouts/builders/form_layout_builder.rb +208 -0
- data/lib/easy_admin/layouts/builders/index_layout_builder.rb +22 -0
- data/lib/easy_admin/layouts/builders/show_layout_builder.rb +199 -0
- data/lib/easy_admin/layouts/dsl.rb +200 -0
- data/lib/easy_admin/layouts/layout_context.rb +189 -0
- data/lib/easy_admin/layouts/nodes/base_node.rb +88 -0
- data/lib/easy_admin/layouts/nodes/divider.rb +27 -0
- data/lib/easy_admin/layouts/nodes/field_node.rb +57 -0
- data/lib/easy_admin/layouts/nodes/grid.rb +60 -0
- data/lib/easy_admin/layouts/nodes/render_node.rb +41 -0
- data/lib/easy_admin/layouts/nodes/root.rb +25 -0
- data/lib/easy_admin/layouts/nodes/section.rb +46 -0
- data/lib/easy_admin/layouts/nodes/spacer.rb +17 -0
- data/lib/easy_admin/layouts/nodes/stubs.rb +109 -0
- data/lib/easy_admin/layouts/nodes/tab.rb +40 -0
- data/lib/easy_admin/layouts/nodes/tabs.rb +40 -0
- data/lib/easy_admin/layouts.rb +28 -0
- data/lib/easy_admin/permissions/resource_permissions.rb +1 -5
- data/lib/easy_admin/resource/base.rb +2 -2
- data/lib/easy_admin/resource/dsl.rb +2 -11
- data/lib/easy_admin/resource/field_registry.rb +58 -2
- data/lib/easy_admin/resource.rb +0 -9
- data/lib/easy_admin/resource_modules.rb +21 -4
- data/lib/easy_admin/two_factor_authentication.rb +156 -0
- data/lib/easy_admin/version.rb +1 -1
- data/lib/generators/easy_admin/permissions/install_generator.rb +0 -10
- data/lib/generators/easy_admin/permissions/templates/migrations/create_permission_tables.rb +33 -3
- data/lib/generators/easy_admin/two_factor/templates/README +29 -0
- data/lib/generators/easy_admin/two_factor/templates/migration.rb +10 -0
- data/lib/generators/easy_admin/two_factor/two_factor_generator.rb +22 -0
- metadata +49 -9
- data/lib/easy_admin/resource/form_builder.rb +0 -123
- data/lib/easy_admin/resource/layout_builder.rb +0 -249
- data/lib/easy_admin/resource/show_builder.rb +0 -359
- data/lib/generators/easy_admin/permissions/templates/migrations/update_users_for_permissions.rb +0 -6
- data/lib/generators/easy_admin/rbac/rbac_generator.rb +0 -244
- data/lib/generators/easy_admin/rbac/templates/add_rbac_to_admin_users.rb +0 -23
- data/lib/generators/easy_admin/rbac/templates/super_admin.rb +0 -34
@@ -1,6 +1,6 @@
|
|
1
1
|
class CreateEasyAdminPermissionTables < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
|
-
# Roles table
|
3
|
+
# Roles table
|
4
4
|
create_table :easy_admin_roles do |t|
|
5
5
|
t.string :name, null: false
|
6
6
|
t.string :slug, null: false
|
@@ -13,15 +13,45 @@ class CreateEasyAdminPermissionTables < ActiveRecord::Migration<%= migration_ver
|
|
13
13
|
t.index :active
|
14
14
|
end
|
15
15
|
|
16
|
-
# User-Role join table
|
16
|
+
# User-Role join table with support for scoped and temporary permissions
|
17
17
|
create_table :easy_admin_user_roles do |t|
|
18
18
|
t.references :user, null: false, foreign_key: true
|
19
19
|
t.references :role, null: false, foreign_key: { to_table: :easy_admin_roles }
|
20
|
+
|
21
|
+
# For scoped permissions (e.g., role applies only to specific organization/project)
|
22
|
+
t.string :context_type
|
23
|
+
t.integer :context_id
|
24
|
+
|
25
|
+
# For temporary permissions
|
26
|
+
t.datetime :expires_at
|
27
|
+
|
28
|
+
# Track who granted this role
|
29
|
+
t.integer :granted_by_id
|
30
|
+
|
20
31
|
t.boolean :active, default: true
|
21
32
|
t.timestamps
|
22
33
|
|
23
|
-
|
34
|
+
# Unique constraint for user-role-context combination
|
35
|
+
t.index [:user_id, :role_id, :context_type, :context_id],
|
36
|
+
unique: true,
|
37
|
+
name: 'index_easy_admin_user_roles_unique'
|
38
|
+
|
39
|
+
# Performance indexes
|
24
40
|
t.index [:user_id, :active], name: 'index_easy_admin_user_roles_active'
|
41
|
+
t.index [:user_id, :context_type, :context_id], name: 'index_easy_admin_user_roles_context'
|
42
|
+
t.index [:context_type, :context_id], name: 'index_easy_admin_user_roles_on_context'
|
43
|
+
t.index :expires_at
|
44
|
+
end
|
45
|
+
|
46
|
+
# Add permissions_cache to admin_users if needed
|
47
|
+
unless column_exists?(:easy_admin_admin_users, :permissions_cache)
|
48
|
+
add_column :easy_admin_admin_users, :permissions_cache, :json, default: {}
|
49
|
+
add_index :easy_admin_admin_users, :permissions_cache
|
50
|
+
end
|
51
|
+
|
52
|
+
# Add role_id to admin_users for default role assignment
|
53
|
+
unless column_exists?(:easy_admin_admin_users, :role_id)
|
54
|
+
add_reference :easy_admin_admin_users, :role, foreign_key: { to_table: :easy_admin_roles }
|
25
55
|
end
|
26
56
|
end
|
27
57
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
===============================================================================
|
2
|
+
|
3
|
+
Two-Factor Authentication has been added to EasyAdmin!
|
4
|
+
|
5
|
+
To complete the setup, you'll need to:
|
6
|
+
|
7
|
+
1. Install the required gems for 2FA functionality:
|
8
|
+
|
9
|
+
gem 'rotp', '~> 6.3' # TOTP generation/validation
|
10
|
+
gem 'rqrcode', '~> 2.2' # QR code generation
|
11
|
+
|
12
|
+
2. Run the migration:
|
13
|
+
|
14
|
+
rails db:migrate
|
15
|
+
|
16
|
+
3. Restart your server
|
17
|
+
|
18
|
+
4. Two-factor authentication is now available in user settings!
|
19
|
+
|
20
|
+
Features:
|
21
|
+
• Optional 2FA (disabled by default)
|
22
|
+
• TOTP-based (compatible with Google Authenticator, Authy, etc.)
|
23
|
+
• QR code setup for easy configuration
|
24
|
+
• Backup codes for account recovery
|
25
|
+
• Admin can view/manage 2FA status for users
|
26
|
+
|
27
|
+
Without the optional gems, 2FA features will be gracefully hidden.
|
28
|
+
|
29
|
+
===============================================================================
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class AddTwoFactorToEasyAdminAdminUsers < ActiveRecord::Migration[<%= ActiveRecord::VERSION::MAJOR %>.<%= ActiveRecord::VERSION::MINOR %>]
|
2
|
+
def change
|
3
|
+
add_column :easy_admin_admin_users, :otp_secret, :string
|
4
|
+
add_column :easy_admin_admin_users, :otp_required_for_login, :boolean, default: false, null: false
|
5
|
+
add_column :easy_admin_admin_users, :otp_backup_codes, :json
|
6
|
+
add_column :easy_admin_admin_users, :last_otp_at, :datetime
|
7
|
+
|
8
|
+
add_index :easy_admin_admin_users, :otp_secret, unique: true
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module EasyAdmin
|
4
|
+
module Generators
|
5
|
+
class TwoFactorGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
7
|
+
|
8
|
+
desc "Add two-factor authentication fields to EasyAdmin AdminUser model"
|
9
|
+
|
10
|
+
def create_migration
|
11
|
+
timestamp = Time.current.utc.strftime("%Y%m%d%H%M%S")
|
12
|
+
migration_file = "#{timestamp}_add_two_factor_to_easy_admin_admin_users.rb"
|
13
|
+
|
14
|
+
template 'migration.rb', "db/migrate/#{migration_file}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def show_readme
|
18
|
+
readme "README" if behavior == :invoke
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: easy-admin-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Slaurmagan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-09-
|
11
|
+
date: 2025-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -261,6 +261,7 @@ files:
|
|
261
261
|
- app/components/easy_admin/fields/show/text_component.rb
|
262
262
|
- app/components/easy_admin/fields/show/textarea_component.rb
|
263
263
|
- app/components/easy_admin/filters_component.rb
|
264
|
+
- app/components/easy_admin/form_layout_component.rb
|
264
265
|
- app/components/easy_admin/form_tabs_component.rb
|
265
266
|
- app/components/easy_admin/infinite_scroll_component.rb
|
266
267
|
- app/components/easy_admin/lazy_chart_card_component.rb
|
@@ -271,6 +272,10 @@ files:
|
|
271
272
|
- app/components/easy_admin/pagination_component.rb
|
272
273
|
- app/components/easy_admin/permissions/user_role_assignment_component.rb
|
273
274
|
- app/components/easy_admin/permissions/user_role_permissions_component.rb
|
275
|
+
- app/components/easy_admin/profile/change_password_modal_component.rb
|
276
|
+
- app/components/easy_admin/profile/profile_tab_component.rb
|
277
|
+
- app/components/easy_admin/profile/security_tab_component.rb
|
278
|
+
- app/components/easy_admin/profile/settings_component.rb
|
274
279
|
- app/components/easy_admin/quick_filters_component.rb
|
275
280
|
- app/components/easy_admin/resource_pagination_component.rb
|
276
281
|
- app/components/easy_admin/resources/index_component.rb
|
@@ -286,12 +291,16 @@ files:
|
|
286
291
|
- app/components/easy_admin/sidebar_component.rb
|
287
292
|
- app/components/easy_admin/turbo/response_component.rb
|
288
293
|
- app/components/easy_admin/turbo/stream_component.rb
|
294
|
+
- app/components/easy_admin/two_factor/backup_codes_component.rb
|
295
|
+
- app/components/easy_admin/two_factor/setup_component.rb
|
296
|
+
- app/components/easy_admin/two_factor/status_component.rb
|
289
297
|
- app/components/easy_admin/versions/diff_component.rb
|
290
298
|
- app/components/easy_admin/versions/diff_modal_component.rb
|
291
299
|
- app/components/easy_admin/versions/history_component.rb
|
292
300
|
- app/components/easy_admin/versions/pagination_component.rb
|
293
301
|
- app/components/easy_admin/versions/timeline_component.rb
|
294
302
|
- app/concerns/easy_admin/resource_versions.rb
|
303
|
+
- app/controllers/concerns/easy_admin/two_factor.rb
|
295
304
|
- app/controllers/easy_admin/application_controller.rb
|
296
305
|
- app/controllers/easy_admin/batch_actions_controller.rb
|
297
306
|
- app/controllers/easy_admin/concerns/belongs_to_editing.rb
|
@@ -304,6 +313,7 @@ files:
|
|
304
313
|
- app/controllers/easy_admin/dashboard_controller.rb
|
305
314
|
- app/controllers/easy_admin/dashboards_controller.rb
|
306
315
|
- app/controllers/easy_admin/passwords_controller.rb
|
316
|
+
- app/controllers/easy_admin/profile_controller.rb
|
307
317
|
- app/controllers/easy_admin/registrations_controller.rb
|
308
318
|
- app/controllers/easy_admin/resources_controller.rb
|
309
319
|
- app/controllers/easy_admin/row_actions_controller.rb
|
@@ -351,6 +361,7 @@ files:
|
|
351
361
|
- app/javascript/easy_admin/controllers/toggle_switch_controller.js
|
352
362
|
- app/javascript/easy_admin/controllers/turbo_stream_redirect.js
|
353
363
|
- app/javascript/easy_admin/controllers/version_revert_controller.js
|
364
|
+
- app/javascript/easy_admin/controllers/vertical_tabs_controller.js
|
354
365
|
- app/models/easy_admin/admin_user.rb
|
355
366
|
- app/models/easy_admin/application_record.rb
|
356
367
|
- app/policies/admin_user_policy.rb
|
@@ -366,6 +377,18 @@ files:
|
|
366
377
|
- app/views/easy_admin/dashboards/show.turbo_stream.erb
|
367
378
|
- app/views/easy_admin/passwords/edit.html.erb
|
368
379
|
- app/views/easy_admin/passwords/new.html.erb
|
380
|
+
- app/views/easy_admin/profile/backup_codes_regenerated.turbo_stream.erb
|
381
|
+
- app/views/easy_admin/profile/change_password.html.erb
|
382
|
+
- app/views/easy_admin/profile/index.html.erb
|
383
|
+
- app/views/easy_admin/profile/password_error.turbo_stream.erb
|
384
|
+
- app/views/easy_admin/profile/password_invalid_current.turbo_stream.erb
|
385
|
+
- app/views/easy_admin/profile/password_updated.turbo_stream.erb
|
386
|
+
- app/views/easy_admin/profile/two_factor_backup_codes.html.erb
|
387
|
+
- app/views/easy_admin/profile/two_factor_enabled.turbo_stream.erb
|
388
|
+
- app/views/easy_admin/profile/two_factor_invalid_code.turbo_stream.erb
|
389
|
+
- app/views/easy_admin/profile/two_factor_not_enabled.turbo_stream.erb
|
390
|
+
- app/views/easy_admin/profile/two_factor_setup.html.erb
|
391
|
+
- app/views/easy_admin/profile/two_factor_unavailable.turbo_stream.erb
|
369
392
|
- app/views/easy_admin/registrations/new.html.erb
|
370
393
|
- app/views/easy_admin/resources/_redirect.turbo_stream.erb
|
371
394
|
- app/views/easy_admin/resources/_table_rows.html.erb
|
@@ -382,6 +405,8 @@ files:
|
|
382
405
|
- app/views/easy_admin/resources/show.html.erb
|
383
406
|
- app/views/easy_admin/resources/update_belongs_to_attached.turbo_stream.erb
|
384
407
|
- app/views/easy_admin/sessions/new.html.erb
|
408
|
+
- app/views/easy_admin/sessions/two_factor_verification.html.erb
|
409
|
+
- app/views/easy_admin/sessions/verify_2fa_error.turbo_stream.erb
|
385
410
|
- app/views/easy_admin/settings/_form.html.erb
|
386
411
|
- app/views/easy_admin/settings/index.html.erb
|
387
412
|
- app/views/layouts/easy_admin/application.html.erb
|
@@ -401,6 +426,24 @@ files:
|
|
401
426
|
- lib/easy_admin/delete_action.rb
|
402
427
|
- lib/easy_admin/engine.rb
|
403
428
|
- lib/easy_admin/field.rb
|
429
|
+
- lib/easy_admin/layouts.rb
|
430
|
+
- lib/easy_admin/layouts/builders/base_layout_builder.rb
|
431
|
+
- lib/easy_admin/layouts/builders/form_layout_builder.rb
|
432
|
+
- lib/easy_admin/layouts/builders/index_layout_builder.rb
|
433
|
+
- lib/easy_admin/layouts/builders/show_layout_builder.rb
|
434
|
+
- lib/easy_admin/layouts/dsl.rb
|
435
|
+
- lib/easy_admin/layouts/layout_context.rb
|
436
|
+
- lib/easy_admin/layouts/nodes/base_node.rb
|
437
|
+
- lib/easy_admin/layouts/nodes/divider.rb
|
438
|
+
- lib/easy_admin/layouts/nodes/field_node.rb
|
439
|
+
- lib/easy_admin/layouts/nodes/grid.rb
|
440
|
+
- lib/easy_admin/layouts/nodes/render_node.rb
|
441
|
+
- lib/easy_admin/layouts/nodes/root.rb
|
442
|
+
- lib/easy_admin/layouts/nodes/section.rb
|
443
|
+
- lib/easy_admin/layouts/nodes/spacer.rb
|
444
|
+
- lib/easy_admin/layouts/nodes/stubs.rb
|
445
|
+
- lib/easy_admin/layouts/nodes/tab.rb
|
446
|
+
- lib/easy_admin/layouts/nodes/tabs.rb
|
404
447
|
- lib/easy_admin/permissions.rb
|
405
448
|
- lib/easy_admin/permissions/component.rb
|
406
449
|
- lib/easy_admin/permissions/configuration.rb
|
@@ -418,12 +461,10 @@ files:
|
|
418
461
|
- lib/easy_admin/resource/configuration.rb
|
419
462
|
- lib/easy_admin/resource/dsl.rb
|
420
463
|
- lib/easy_admin/resource/field_registry.rb
|
421
|
-
- lib/easy_admin/resource/form_builder.rb
|
422
|
-
- lib/easy_admin/resource/layout_builder.rb
|
423
464
|
- lib/easy_admin/resource/scope_manager.rb
|
424
|
-
- lib/easy_admin/resource/show_builder.rb
|
425
465
|
- lib/easy_admin/resource_modules.rb
|
426
466
|
- lib/easy_admin/resource_registry.rb
|
467
|
+
- lib/easy_admin/two_factor_authentication.rb
|
427
468
|
- lib/easy_admin/types/json_type.rb
|
428
469
|
- lib/easy_admin/version.rb
|
429
470
|
- lib/easy_admin/versioning.rb
|
@@ -436,7 +477,6 @@ files:
|
|
436
477
|
- lib/generators/easy_admin/permissions/install_generator.rb
|
437
478
|
- lib/generators/easy_admin/permissions/templates/initializers/permissions.rb
|
438
479
|
- lib/generators/easy_admin/permissions/templates/migrations/create_permission_tables.rb
|
439
|
-
- lib/generators/easy_admin/permissions/templates/migrations/update_users_for_permissions.rb
|
440
480
|
- lib/generators/easy_admin/permissions/templates/models/permission.rb
|
441
481
|
- lib/generators/easy_admin/permissions/templates/models/role.rb
|
442
482
|
- lib/generators/easy_admin/permissions/templates/models/role_permission.rb
|
@@ -444,9 +484,6 @@ files:
|
|
444
484
|
- lib/generators/easy_admin/permissions/templates/policies/application_policy.rb
|
445
485
|
- lib/generators/easy_admin/permissions/templates/policies/user_policy.rb
|
446
486
|
- lib/generators/easy_admin/permissions/templates/seeds/permissions.rb
|
447
|
-
- lib/generators/easy_admin/rbac/rbac_generator.rb
|
448
|
-
- lib/generators/easy_admin/rbac/templates/add_rbac_to_admin_users.rb
|
449
|
-
- lib/generators/easy_admin/rbac/templates/super_admin.rb
|
450
487
|
- lib/generators/easy_admin/resource_generator.rb
|
451
488
|
- lib/generators/easy_admin/templates/AUTH_README
|
452
489
|
- lib/generators/easy_admin/templates/README
|
@@ -454,6 +491,9 @@ files:
|
|
454
491
|
- lib/generators/easy_admin/templates/devise.rb
|
455
492
|
- lib/generators/easy_admin/templates/easy_admin.rb
|
456
493
|
- lib/generators/easy_admin/templates/resource.rb
|
494
|
+
- lib/generators/easy_admin/two_factor/templates/README
|
495
|
+
- lib/generators/easy_admin/two_factor/templates/migration.rb
|
496
|
+
- lib/generators/easy_admin/two_factor/two_factor_generator.rb
|
457
497
|
- lib/tasks/easy_admin_tasks.rake
|
458
498
|
homepage: https://github.com/Slaurmagan/easy-admin
|
459
499
|
licenses:
|
@@ -1,123 +0,0 @@
|
|
1
|
-
module EasyAdmin
|
2
|
-
module ResourceModules
|
3
|
-
# FormBuilder class for form DSL
|
4
|
-
# Handles all form tab and field definitions within forms
|
5
|
-
class FormBuilder
|
6
|
-
def initialize(resource_class)
|
7
|
-
@resource_class = resource_class
|
8
|
-
@current_tab = nil
|
9
|
-
end
|
10
|
-
|
11
|
-
def tab(name = "General", **options, &block)
|
12
|
-
tab_config = {
|
13
|
-
name: name,
|
14
|
-
label: options[:label] || name,
|
15
|
-
icon: options[:icon],
|
16
|
-
fields: []
|
17
|
-
}
|
18
|
-
|
19
|
-
@current_tab = tab_config
|
20
|
-
@resource_class.add_form_tab(tab_config)
|
21
|
-
|
22
|
-
instance_eval(&block) if block_given?
|
23
|
-
@current_tab = nil
|
24
|
-
end
|
25
|
-
|
26
|
-
# Field definition methods within tabs - delegate to resource
|
27
|
-
def field(name, type = :string, **options)
|
28
|
-
field_config = @resource_class.build_field_config(name, type, **options)
|
29
|
-
|
30
|
-
if @current_tab
|
31
|
-
@current_tab[:fields] << field_config
|
32
|
-
end
|
33
|
-
|
34
|
-
# Also add to main fields_config for compatibility
|
35
|
-
@resource_class.add_field_to_registry(field_config)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Convenience methods for form fields
|
39
|
-
def text_field(name, **options)
|
40
|
-
field(name, :string, **options)
|
41
|
-
end
|
42
|
-
|
43
|
-
def textarea_field(name, **options)
|
44
|
-
field(name, :text, **options)
|
45
|
-
end
|
46
|
-
|
47
|
-
def number_field(name, **options)
|
48
|
-
field(name, :number, **options)
|
49
|
-
end
|
50
|
-
|
51
|
-
def email_field(name, **options)
|
52
|
-
field(name, :email, **options)
|
53
|
-
end
|
54
|
-
|
55
|
-
def date_field(name, **options)
|
56
|
-
field(name, :date, **options)
|
57
|
-
end
|
58
|
-
|
59
|
-
def datetime_field(name, **options)
|
60
|
-
field(name, :datetime, **options)
|
61
|
-
end
|
62
|
-
|
63
|
-
def boolean_field(name, **options)
|
64
|
-
field(name, :boolean, **options)
|
65
|
-
end
|
66
|
-
|
67
|
-
def select_field(name, options:, **other_options)
|
68
|
-
field(name, :select, options: options, **other_options)
|
69
|
-
end
|
70
|
-
|
71
|
-
def belongs_to_field(name, **options)
|
72
|
-
field(name, :belongs_to, **options)
|
73
|
-
end
|
74
|
-
|
75
|
-
def has_many_field(name, **options)
|
76
|
-
field(name, :has_many, **options)
|
77
|
-
end
|
78
|
-
|
79
|
-
def file_field(name, **options)
|
80
|
-
field(name, :file, **options)
|
81
|
-
end
|
82
|
-
|
83
|
-
def json_field(name, **options)
|
84
|
-
field(name, :json, **options)
|
85
|
-
end
|
86
|
-
|
87
|
-
def password_field(name = :password, **options)
|
88
|
-
field(name, :password, **options)
|
89
|
-
field("#{name}_confirmation".to_sym, :password,
|
90
|
-
label: options[:confirmation_label] || "Confirm #{name.to_s.humanize}",
|
91
|
-
**options.except(:confirmation_label))
|
92
|
-
end
|
93
|
-
|
94
|
-
# Support for rendering custom components in forms
|
95
|
-
def render(component_class_or_instance, **options)
|
96
|
-
content_config = {
|
97
|
-
type: :custom_component,
|
98
|
-
component_class: component_class_or_instance.class,
|
99
|
-
component_options: options,
|
100
|
-
component_instance: component_class_or_instance
|
101
|
-
}
|
102
|
-
|
103
|
-
if @current_tab
|
104
|
-
@current_tab[:fields] << content_config
|
105
|
-
end
|
106
|
-
|
107
|
-
component_class_or_instance
|
108
|
-
end
|
109
|
-
|
110
|
-
# Support for custom content blocks in forms
|
111
|
-
def content(&block)
|
112
|
-
content_config = {
|
113
|
-
type: :custom_content,
|
114
|
-
block: block
|
115
|
-
}
|
116
|
-
|
117
|
-
if @current_tab
|
118
|
-
@current_tab[:fields] << content_config
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
@@ -1,249 +0,0 @@
|
|
1
|
-
module EasyAdmin
|
2
|
-
module ResourceModules
|
3
|
-
# LayoutBuilder module for handling form and show layout configuration
|
4
|
-
# Manages form tabs and show page layout elements
|
5
|
-
module LayoutBuilder
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
class_attribute :form_tabs_config, :show_layout_config
|
10
|
-
|
11
|
-
def self.initialize_layout_builder
|
12
|
-
self.form_tabs_config = []
|
13
|
-
self.show_layout_config = []
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class_methods do
|
18
|
-
# Form tabs management
|
19
|
-
def add_form_tab(tab_config)
|
20
|
-
self.form_tabs_config = (self.form_tabs_config || []) + [tab_config]
|
21
|
-
end
|
22
|
-
|
23
|
-
def form_tabs
|
24
|
-
form_tabs_config
|
25
|
-
end
|
26
|
-
|
27
|
-
def has_form_tabs?
|
28
|
-
form_tabs_config.any?
|
29
|
-
end
|
30
|
-
|
31
|
-
def clear_form_tabs
|
32
|
-
self.form_tabs_config = []
|
33
|
-
end
|
34
|
-
|
35
|
-
# Show layout management
|
36
|
-
def add_show_layout_element(element_config)
|
37
|
-
self.show_layout_config = (self.show_layout_config || []) + [element_config]
|
38
|
-
end
|
39
|
-
|
40
|
-
def show_layout
|
41
|
-
show_layout_config
|
42
|
-
end
|
43
|
-
|
44
|
-
def has_show_layout?
|
45
|
-
show_layout_config.any?
|
46
|
-
end
|
47
|
-
|
48
|
-
def clear_show_layout
|
49
|
-
self.show_layout_config = []
|
50
|
-
end
|
51
|
-
|
52
|
-
# Form tab utilities
|
53
|
-
def find_form_tab(tab_name)
|
54
|
-
form_tabs_config.find { |tab| tab[:name].to_s == tab_name.to_s }
|
55
|
-
end
|
56
|
-
|
57
|
-
def form_tab_names
|
58
|
-
form_tabs_config.map { |tab| tab[:name] }
|
59
|
-
end
|
60
|
-
|
61
|
-
def form_tab_fields(tab_name)
|
62
|
-
tab = find_form_tab(tab_name)
|
63
|
-
tab ? tab[:fields] : []
|
64
|
-
end
|
65
|
-
|
66
|
-
def total_form_tabs_count
|
67
|
-
form_tabs_config.count
|
68
|
-
end
|
69
|
-
|
70
|
-
# Show layout utilities
|
71
|
-
def show_layout_rows
|
72
|
-
show_layout_config.select { |element| element[:type] == :row }
|
73
|
-
end
|
74
|
-
|
75
|
-
def show_layout_elements_count
|
76
|
-
count = 0
|
77
|
-
show_layout_config.each do |element|
|
78
|
-
count += count_nested_elements(element)
|
79
|
-
end
|
80
|
-
count
|
81
|
-
end
|
82
|
-
|
83
|
-
def find_show_layout_element(element_type)
|
84
|
-
find_element_in_layout(show_layout_config, element_type)
|
85
|
-
end
|
86
|
-
|
87
|
-
def has_show_layout_tabs?
|
88
|
-
find_show_layout_element(:tabs).present?
|
89
|
-
end
|
90
|
-
|
91
|
-
def has_show_layout_cards?
|
92
|
-
find_show_layout_element(:card).present?
|
93
|
-
end
|
94
|
-
|
95
|
-
def has_metric_cards?
|
96
|
-
find_show_layout_element(:metric_card).present?
|
97
|
-
end
|
98
|
-
|
99
|
-
def has_chart_cards?
|
100
|
-
find_show_layout_element(:chart_card).present?
|
101
|
-
end
|
102
|
-
|
103
|
-
# Layout validation
|
104
|
-
def validate_form_structure
|
105
|
-
errors = []
|
106
|
-
|
107
|
-
if has_form_tabs?
|
108
|
-
form_tabs_config.each_with_index do |tab, index|
|
109
|
-
unless tab[:name].present?
|
110
|
-
errors << "Form tab at index #{index} is missing a name"
|
111
|
-
end
|
112
|
-
|
113
|
-
unless tab[:fields].is_a?(Array)
|
114
|
-
errors << "Form tab '#{tab[:name]}' fields must be an array"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
errors
|
120
|
-
end
|
121
|
-
|
122
|
-
def validate_show_layout_structure
|
123
|
-
errors = []
|
124
|
-
|
125
|
-
show_layout_config.each_with_index do |element, index|
|
126
|
-
case element[:type]
|
127
|
-
when :row
|
128
|
-
unless element[:columns].is_a?(Array)
|
129
|
-
errors << "Row at index #{index} must have columns array"
|
130
|
-
end
|
131
|
-
|
132
|
-
if element[:columns].empty?
|
133
|
-
errors << "Row at index #{index} cannot have empty columns"
|
134
|
-
end
|
135
|
-
when :column
|
136
|
-
unless element[:elements].is_a?(Array)
|
137
|
-
errors << "Column at index #{index} must have elements array"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
errors
|
143
|
-
end
|
144
|
-
|
145
|
-
# Layout rebuild methods
|
146
|
-
def rebuild_form_from_fields
|
147
|
-
return if fields_config.empty?
|
148
|
-
|
149
|
-
# Create a default tab with all non-readonly fields
|
150
|
-
default_tab = {
|
151
|
-
name: "General",
|
152
|
-
label: "General",
|
153
|
-
icon: nil,
|
154
|
-
fields: fields_config.reject { |field| field[:readonly] }
|
155
|
-
}
|
156
|
-
|
157
|
-
self.form_tabs_config = [default_tab]
|
158
|
-
end
|
159
|
-
|
160
|
-
def rebuild_show_layout_from_fields
|
161
|
-
return if fields_config.empty?
|
162
|
-
|
163
|
-
# Create a simple single-column layout with all fields
|
164
|
-
row_config = {
|
165
|
-
type: :row,
|
166
|
-
columns_count: 1,
|
167
|
-
spacing: "medium",
|
168
|
-
columns: [{
|
169
|
-
type: :column,
|
170
|
-
size: 12,
|
171
|
-
elements: [{
|
172
|
-
type: :card,
|
173
|
-
title: "Details",
|
174
|
-
color: "light",
|
175
|
-
padding: "medium",
|
176
|
-
shadow: "small",
|
177
|
-
elements: fields_config.map { |field|
|
178
|
-
{
|
179
|
-
type: :field,
|
180
|
-
name: field[:name],
|
181
|
-
label: field[:label],
|
182
|
-
field_type: :default,
|
183
|
-
format: field[:format],
|
184
|
-
css_classes: nil,
|
185
|
-
show_label: true
|
186
|
-
}
|
187
|
-
}
|
188
|
-
}]
|
189
|
-
}]
|
190
|
-
}
|
191
|
-
|
192
|
-
self.show_layout_config = [row_config]
|
193
|
-
end
|
194
|
-
|
195
|
-
private
|
196
|
-
|
197
|
-
def count_nested_elements(element)
|
198
|
-
count = 1
|
199
|
-
|
200
|
-
case element[:type]
|
201
|
-
when :row
|
202
|
-
element[:columns]&.each { |column| count += count_nested_elements(column) }
|
203
|
-
when :column
|
204
|
-
element[:elements]&.each { |child| count += count_nested_elements(child) }
|
205
|
-
when :card
|
206
|
-
element[:elements]&.each { |child| count += count_nested_elements(child) }
|
207
|
-
when :tabs
|
208
|
-
element[:tabs]&.each { |tab| count += count_nested_elements(tab) }
|
209
|
-
when :tab
|
210
|
-
element[:elements]&.each { |child| count += count_nested_elements(child) }
|
211
|
-
end
|
212
|
-
|
213
|
-
count
|
214
|
-
end
|
215
|
-
|
216
|
-
def find_element_in_layout(layout, element_type)
|
217
|
-
layout.each do |element|
|
218
|
-
return element if element[:type] == element_type
|
219
|
-
|
220
|
-
case element[:type]
|
221
|
-
when :row
|
222
|
-
element[:columns]&.each do |column|
|
223
|
-
found = find_element_in_layout([column], element_type)
|
224
|
-
return found if found
|
225
|
-
end
|
226
|
-
when :column, :card
|
227
|
-
if element[:elements]
|
228
|
-
found = find_element_in_layout(element[:elements], element_type)
|
229
|
-
return found if found
|
230
|
-
end
|
231
|
-
when :tabs
|
232
|
-
element[:tabs]&.each do |tab|
|
233
|
-
found = find_element_in_layout([tab], element_type)
|
234
|
-
return found if found
|
235
|
-
end
|
236
|
-
when :tab
|
237
|
-
if element[:elements]
|
238
|
-
found = find_element_in_layout(element[:elements], element_type)
|
239
|
-
return found if found
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
nil
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|