lesli 5.0.13 → 5.0.14
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/config/lesli_manifest.js +3 -6
- data/app/assets/images/lesli/brand/app-icon.svg +45 -39
- data/app/assets/javascripts/lesli/application.js +1 -0
- data/app/controllers/lesli/abouts_controller.rb +16 -14
- data/app/controllers/lesli/application_controller.rb +13 -0
- data/app/controllers/lesli/application_devise_controller.rb +10 -12
- data/app/controllers/lesli/application_lesli_controller.rb +12 -11
- data/app/controllers/lesli/apps_controller.rb +6 -0
- data/app/controllers/lesli/roles_controller.rb +2 -2
- data/app/helpers/lesli/general_helper.rb +18 -5
- data/app/helpers/lesli/html_helper.rb +8 -0
- data/app/helpers/lesli/navigation_helper.rb +30 -11
- data/app/helpers/lesli/system_helper.rb +2 -2
- data/app/helpers/lesli/turbo_helper.rb +58 -0
- data/app/interfaces/lesli/customization_interface.rb +42 -0
- data/app/interfaces/lesli/requester_interface.rb +103 -0
- data/app/interfaces/lesli/responder_interface.rb +127 -0
- data/app/lib/date2.rb +1 -199
- data/app/lib/lesli/courier.rb +54 -0
- data/app/mailers/lesli/application_lesli_mailer.rb +32 -59
- data/app/mailers/lesli/devise_mailer.rb +16 -8
- data/app/models/concerns/account_initializer.rb +27 -68
- data/app/models/concerns/lesli/has_activities.rb +29 -0
- data/app/models/concerns/user_extensions.rb +34 -19
- data/app/models/concerns/user_security.rb +4 -4
- data/app/models/lesli/account.rb +13 -20
- data/{lib/scss/layouts/application-container.scss → app/models/lesli/item/activity.rb} +11 -8
- data/app/models/lesli/role/{power.rb → action.rb} +6 -4
- data/app/models/lesli/role.rb +7 -15
- data/app/models/lesli/shared/catalog.rb +20 -0
- data/app/models/lesli/shared/dashboard.rb +1 -1
- data/app/models/lesli/user/activity.rb +5 -0
- data/app/models/lesli/user/detail.rb +5 -5
- data/app/models/lesli/user/{log.rb → journal.rb} +3 -3
- data/app/models/lesli/user/{power.rb → role.rb} +2 -3
- data/app/models/lesli/user/session.rb +3 -4
- data/app/models/lesli/user.rb +50 -46
- data/app/operators/lesli/controller_operator.rb +3 -1
- data/app/operators/lesli/{role_descriptor_operator.rb → role_operator.rb} +51 -28
- data/app/operators/lesli/user_registration_operator.rb +3 -2
- data/app/services/lesli/application_lesli_service.rb +8 -4
- data/app/services/lesli/role/action_service.rb +58 -0
- data/app/services/lesli/role_service.rb +232 -0
- data/app/services/lesli/{user_session_service.rb → user/session_service.rb} +23 -14
- data/app/services/lesli/user_service.rb +85 -1
- data/app/views/lesli/apps/show.html.erb +52 -0
- data/app/views/lesli/layouts/application-devise.html.erb +5 -7
- data/app/views/lesli/layouts/application-lesli.html.erb +18 -24
- data/app/views/lesli/partials/_application-analytics.html.erb +2 -2
- data/app/views/lesli/partials/_application-data.html.erb +3 -77
- data/app/views/lesli/partials/_application-head.html.erb +7 -4
- data/app/views/lesli/partials/_application-lesli-annoouncements.html.erb +49 -0
- data/app/views/lesli/partials/_application-lesli-header.html.erb +73 -49
- data/app/views/lesli/partials/_application-lesli-javascript.html.erb +3 -16
- data/app/views/lesli/partials/_application-lesli-navigation.html.erb +12 -9
- data/app/views/lesli/partials/{_application-lesli-notices.html.erb → _application-lesli-notifications.html.erb} +10 -8
- data/app/views/lesli/partials/_application-lesli-scss.html.erb +1 -1
- data/app/views/lesli/partials/_application-lesli-sidebar.html.erb +1 -1
- data/app/views/lesli/partials/_application-public-javascript.html.erb +1 -4
- data/app/views/lesli/shared/dashboards/_show.html.erb +63 -0
- data/app/views/lesli/wrappers/_application-devise.html.erb +4 -6
- data/config/importmap.rb +14 -0
- data/config/initializers/lesli.rb +20 -12
- data/config/initializers/lesli_migration_helpers.rb +61 -0
- data/config/locales/translations.en.yml +1 -26
- data/config/locales/translations.es.yml +1 -26
- data/config/locales/translations.fr.yml +1 -26
- data/config/locales/translations.it.yml +1 -26
- data/config/locales/translations.pt.yml +1 -26
- data/config/routes.rb +3 -1
- data/db/migrate/v1/{0010000110_create_lesli_accounts.rb → 0000000110_create_lesli_accounts.rb} +13 -12
- data/db/migrate/v1/0000000210_create_lesli_roles.rb +65 -0
- data/db/migrate/v1/0000000310_create_lesli_users.rb +99 -0
- data/db/migrate/v1/{0010000610_create_lesli_system_controllers.rb → 0000100110_create_lesli_system_controllers.rb} +3 -3
- data/db/migrate/v1/{0010000710_create_lesli_system_controller_actions.rb → 0000100210_create_lesli_system_controller_actions.rb} +3 -4
- data/{lib/scss/layouts/application-content.scss → db/migrate/v1/0000110310_create_lesli_account_settings.rb} +8 -6
- data/{app/models/lesli/user/agent.rb → db/migrate/v1/0000110410_create_lesli_account_activities.rb} +3 -3
- data/db/migrate/v1/0000120210_create_lesli_role_actions.rb +45 -0
- data/db/migrate/v1/{0010001410_create_lesli_account_logs.rb → 0000120310_create_lesli_role_privileges.rb} +8 -8
- data/db/{tables/0010003810_create_user_shortcuts.rb → migrate/v1/0000130210_create_lesli_user_roles.rb} +9 -12
- data/db/migrate/v1/0000130310_create_lesli_user_sessions.rb +56 -0
- data/db/{seed/production.rb → migrate/v1/0000130410_create_lesli_user_activities.rb} +7 -4
- data/db/{tables/0010001110_create_account_locations.rb → migrate2/0000100510_create_lesli_account_locations.rb} +6 -6
- data/db/{tables/0010001510_create_account_currencies.rb → migrate2/0000100610_create_lesli_account_currencies.rb} +4 -4
- data/db/seed/{development/accounts.rb → accounts.rb} +6 -2
- data/db/seed/{production/users.rb → users.rb} +4 -10
- data/db/seed/{tools.rb → xyz.rb} +2 -7
- data/db/seeds.rb +3 -2
- data/db/structure/00000020_catalogs.json +0 -0
- data/lib/generators/{application_lesli_generator.rb → application_lesli_generator_base.rb} +4 -4
- data/lib/generators/lesli/spec/spec_generator.rb +2 -2
- data/lib/generators/lesli/view/USAGE +8 -0
- data/lib/generators/lesli/view/templates/spec-factory.template +17 -0
- data/lib/generators/lesli/view/templates/spec-model.template +70 -0
- data/lib/generators/lesli/view/view_generator.rb +25 -0
- data/lib/lesli/configuration.rb +7 -10
- data/lib/lesli/engine.rb +22 -3
- data/lib/lesli/r_spec.rb +5 -2
- data/lib/lesli/routing.rb +42 -9
- data/lib/lesli/version.rb +2 -2
- data/lib/lesli.rb +11 -0
- data/lib/migrate/common.rb +94 -0
- data/lib/migrate/items/action_structure.rb +51 -0
- data/{db/migrate/v1/0010001210_create_lesli_account_activities.rb → lib/migrate/items/activity_structure.rb} +18 -16
- data/lib/migrate/items/attachment_structure.rb +62 -0
- data/{app/views/lesli/partials/_application-lesli-engines.html.erb → lib/migrate/items/discussion_structure.rb} +19 -27
- data/lib/migrate/items/subscriber_structure.rb +49 -0
- data/lib/migrate/items/version_structure.rb +53 -0
- data/lib/migrate/shared/account_structure.rb +21 -0
- data/lib/migrate/shared/catalog_structure.rb +30 -0
- data/lib/migrate/shared/dashboard_structure.rb +54 -0
- data/lib/migrate/shared/setting_structure.rb +20 -0
- data/lib/rspec/config/spec_coverage.rb +95 -0
- data/{db/migrate/v1/0010001110_create_lesli_account_settings.rb → lib/rspec/factories/lesli_account.rb} +10 -7
- data/{db/seed/development.rb → lib/rspec/factories/lesli_role.rb} +30 -3
- data/{db/seed/test.rb → lib/rspec/factories/lesli_user.rb} +32 -3
- data/lib/rspec/fixtures/files/lesli-icon.png +0 -0
- data/lib/rspec/fixtures/files/test_file_1.docx +0 -0
- data/{db/tables/0010001610_create_account_currency_exchange_rates.rb → lib/rspec/helpers/lesli_helper.rb} +21 -21
- data/lib/rspec/helpers/rails_helper.rb +134 -0
- data/lib/rspec/helpers/response_request_helper.rb +214 -0
- data/lib/rspec/helpers/response_service_helper.rb +66 -0
- data/lib/rspec/helpers/spec_helper.rb +99 -0
- data/lib/rspec/lesli_api_tester.rb +133 -0
- data/lib/rspec/lesli_service_tester.rb +46 -0
- data/{db/tables/0010001410_create_account_files.rb → lib/rspec/testers/controller.rb} +31 -20
- data/lib/rspec/testers/model.rb +36 -0
- data/lib/rspec/testers/request.rb +84 -0
- data/lib/tasks/lesli/db.rake +5 -3
- data/lib/tasks/lesli/git.rake +28 -32
- data/lib/tasks/lesli/github.rake +89 -0
- data/lib/tasks/lesli_tasks.rake +3 -3
- data/readme.md +28 -17
- metadata +134 -394
- data/app/assets/fonts/lesli/Domine/Domine-Variable.ttf +0 -0
- data/app/assets/fonts/lesli/Domine/OFL.txt +0 -97
- data/app/assets/fonts/lesli/MaterialDesign/icons.woff2 +0 -0
- data/app/assets/fonts/lesli/Montserrat/Montserrat-Variable.ttf +0 -0
- data/app/assets/fonts/lesli/OpenSans/OpenSans-Variable.ttf +0 -0
- data/app/assets/fonts/lesli/Remix/remixicon.eot +0 -0
- data/app/assets/fonts/lesli/Remix/remixicon.glyph.json +0 -1
- data/app/assets/fonts/lesli/Remix/remixicon.svg +0 -7633
- data/app/assets/fonts/lesli/Remix/remixicon.symbol.svg +0 -11
- data/app/assets/fonts/lesli/Remix/remixicon.ttf +0 -0
- data/app/assets/fonts/lesli/Remix/remixicon.woff +0 -0
- data/app/assets/fonts/lesli/Remix/remixicon.woff2 +0 -0
- data/app/assets/fonts/lesli/Roboto/LICENSE.txt +0 -202
- data/app/assets/fonts/lesli/Roboto/Roboto-Black.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-BlackItalic.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-Bold.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-BoldItalic.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-Italic.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-Light.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-LightItalic.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-Medium.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-MediumItalic.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-Regular.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-Thin.ttf +0 -0
- data/app/assets/fonts/lesli/Roboto/Roboto-ThinItalic.ttf +0 -0
- data/app/assets/icons/lesli/engine-admin.svg +0 -1
- data/app/assets/icons/lesli/engine-audit.svg +0 -1
- data/app/assets/icons/lesli/engine-babel.svg +0 -1
- data/app/assets/icons/lesli/engine-bell.svg +0 -1
- data/app/assets/icons/lesli/engine-books.svg +0 -1
- data/app/assets/icons/lesli/engine-calendar.svg +0 -1
- data/app/assets/icons/lesli/engine-dashboard.svg +0 -1
- data/app/assets/icons/lesli/engine-dispatcher.svg +0 -1
- data/app/assets/icons/lesli/engine-focus.svg +0 -1
- data/app/assets/icons/lesli/engine-kb.svg +0 -1
- data/app/assets/icons/lesli/engine-leaf.svg +0 -1
- data/app/assets/icons/lesli/engine-lesli.svg +0 -1
- data/app/assets/icons/lesli/engine-letter.svg +0 -1
- data/app/assets/icons/lesli/engine-mailer.svg +0 -1
- data/app/assets/icons/lesli/engine-one.svg +0 -1
- data/app/assets/icons/lesli/engine-profile.svg +0 -1
- data/app/assets/icons/lesli/engine-proposal.svg +0 -1
- data/app/assets/icons/lesli/engine-scraper.svg +0 -1
- data/app/assets/icons/lesli/engine-security.svg +0 -1
- data/app/assets/icons/lesli/engine-shared.svg +0 -1
- data/app/assets/icons/lesli/engine-shield.svg +0 -1
- data/app/assets/icons/lesli/engine-storage.svg +0 -1
- data/app/assets/icons/lesli/engine-support.svg +0 -1
- data/app/assets/icons/lesli/engine-talk.svg +0 -1
- data/app/assets/icons/lesli/engine-team.svg +0 -1
- data/app/assets/icons/lesli/engine-time.svg +0 -1
- data/app/assets/icons/lesli/locale-en.svg +0 -1
- data/app/assets/icons/lesli/locale-es.svg +0 -1
- data/app/assets/icons/lesli/locale-fr.svg +0 -1
- data/app/assets/icons/lesli/locale-it.svg +0 -1
- data/app/assets/icons/lesli/locale-pt.svg +0 -1
- data/app/assets/icons/readme.md +0 -10
- data/app/assets/javascripts/lesli/templates/application.js +0 -14
- data/app/assets/javascripts/lesli/templates/public.js +0 -14
- data/app/assets/stylesheets/lesli/templates/application.css +0 -2918
- data/app/assets/stylesheets/lesli/templates/public.css +0 -1
- data/app/controllers/lesli/interfaces/application/authorization.rb +0 -107
- data/app/controllers/lesli/interfaces/application/customization.rb +0 -46
- data/app/controllers/lesli/interfaces/application/logger.rb +0 -134
- data/app/controllers/lesli/interfaces/application/requester.rb +0 -84
- data/app/controllers/lesli/interfaces/application/responder.rb +0 -132
- data/app/controllers/lesli/interfaces/controllers/actions.rb +0 -250
- data/app/controllers/lesli/interfaces/controllers/activities.rb +0 -215
- data/app/controllers/lesli/interfaces/controllers/discussions.rb +0 -270
- data/app/controllers/lesli/interfaces/controllers/files.rb +0 -467
- data/app/controllers/lesli/interfaces/controllers/subscribers.rb +0 -234
- data/app/lib/lesli/system.rb +0 -110
- data/app/models/lesli/cloud_object/action.rb +0 -70
- data/app/models/lesli/cloud_object/activity.rb +0 -311
- data/app/models/lesli/cloud_object/custom_field.rb +0 -158
- data/app/models/lesli/cloud_object/discussion.rb +0 -219
- data/app/models/lesli/cloud_object/subscriber.rb +0 -186
- data/app/operators/lesli/descriptor_privilege_operator.rb +0 -75
- data/app/views/lesli/emails/devise_mailer/confirmation_instructions.html.erb +0 -23
- data/app/views/lesli/emails/devise_mailer/reset_password_instructions.html.erb +0 -23
- data/app/views/lesli/partials/_application-lesli-icons.html.erb +0 -1
- data/config/initializers/devise.rb +0 -336
- data/db/seed/development/users.rb +0 -52
- data/db/seed/production/accounts.rb +0 -50
- data/db/structure/00000000_people.json +0 -34
- data/db/structure/00000003_actions.json +0 -14
- data/db/structure/00000004_activities.json +0 -20
- data/db/structure/00000005_discussions.json +0 -8
- data/db/structure/00000006_files.json +0 -32
- data/db/structure/00000007_subscribers.json +0 -11
- data/db/structure/00000501_dashboards.json +0 -14
- data/db/structure/00000502_dashboard_components.json +0 -23
- data/db/tables/0010003410_create_user_activities.rb +0 -51
- data/db/tables/0010003710_create_user_codes.rb +0 -43
- data/db/tables/0010004110_create_user_tokens.rb +0 -45
- data/db/tables/0010005610_create_role_activities.rb +0 -50
- data/db/tables/0010009010_create_feedbacks.rb +0 -56
- data/lib/mailer_previews/devise_mailer_preview.rb +0 -49
- data/lib/scss/cloud-objects/discussion.scss +0 -80
- data/lib/scss/cloud-objects/file.scss +0 -138
- data/lib/scss/components/keypad.scss +0 -109
- data/lib/scss/elements/autocomplete.scss +0 -72
- data/lib/scss/elements/card.scss +0 -37
- data/lib/scss/elements/empty.scss +0 -43
- data/lib/scss/elements/file-uploader.scss +0 -74
- data/lib/scss/elements/gallery.scss +0 -98
- data/lib/scss/elements/input-tag.scss +0 -73
- data/lib/scss/elements/loading.scss +0 -63
- data/lib/scss/elements/map.scss +0 -107
- data/lib/scss/elements/navbar.scss +0 -115
- data/lib/scss/elements/table.scss +0 -118
- data/lib/scss/elements/toolbar.scss +0 -66
- data/lib/scss/fonts/families.scss +0 -47
- data/lib/scss/fonts/mdicons.scss +0 -82
- data/lib/scss/fonts/remixicons.scss +0 -2602
- data/lib/scss/helpers/display.scss +0 -44
- data/lib/scss/helpers/tooltip.scss +0 -91
- data/lib/scss/layouts/application-announcements.scss +0 -40
- data/lib/scss/layouts/application-component.scss +0 -39
- data/lib/scss/layouts/application-engines.scss +0 -125
- data/lib/scss/layouts/application-footer.scss +0 -102
- data/lib/scss/layouts/application-header.scss +0 -91
- data/lib/scss/layouts/application-navigation.scss +0 -79
- data/lib/scss/layouts/application-search.scss +0 -71
- data/lib/scss/layouts/application-sidebar.scss +0 -219
- data/lib/scss/overrides/notification.scss +0 -75
- data/lib/scss/overrides/sweetalert.scss +0 -106
- data/lib/scss/pages/devise-simple.scss +0 -89
- data/lib/scss/pages/devise.scss +0 -179
- data/lib/scss/pages/invites.scss +0 -81
- data/lib/scss/panels/panel-announcements.scss +0 -56
- data/lib/scss/panels/panel-notification.scss +0 -67
- data/lib/scss/panels/panel-profile.scss +0 -62
- data/lib/scss/panels/panel-support-ticket.scss +0 -56
- data/lib/scss/panels/panel-tasks.scss +0 -41
- data/lib/scss/settings/variables.scss +0 -148
- data/lib/scss/shared/workflow-status-progress.scss +0 -135
- data/lib/scss/templates/application.scss +0 -127
- data/lib/scss/templates/component.scss +0 -39
- data/lib/scss/templates/dashboards.scss +0 -53
- data/lib/scss/templates/empty.scss +0 -42
- data/lib/scss/templates/pdf.scss +0 -45
- data/lib/scss/templates/public.scss +0 -72
- data/lib/vue/application.js +0 -285
- data/lib/vue/cloudobjects/discussion/content.vue +0 -62
- data/lib/vue/cloudobjects/discussion/element.vue +0 -170
- data/lib/vue/cloudobjects/discussion/filters.vue +0 -108
- data/lib/vue/cloudobjects/discussion/new.vue +0 -134
- data/lib/vue/cloudobjects/discussion.vue +0 -99
- data/lib/vue/cloudobjects/stores/discussion.js +0 -212
- data/lib/vue/layouts/application-announcements.vue +0 -78
- data/lib/vue/layouts/application-component.vue +0 -38
- data/lib/vue/layouts/application-container.vue +0 -48
- data/lib/vue/layouts/application-engines.vue +0 -66
- data/lib/vue/layouts/application-footer.vue +0 -123
- data/lib/vue/layouts/application-header.vue +0 -252
- data/lib/vue/layouts/application-navbar.vue +0 -110
- data/lib/vue/layouts/application-search.vue +0 -86
- data/lib/vue/layouts/application-sidebar.vue +0 -63
- data/lib/vue/pages/errors/app.js +0 -32
- data/lib/vue/pages/invites/app.js +0 -76
- data/lib/vue/pages/mfas/application.js +0 -77
- data/lib/vue/pages/onboarding/application.js +0 -45
- data/lib/vue/pages/onboarding/components/address.vue +0 -120
- data/lib/vue/pages/onboarding/components/buttons.vue +0 -67
- data/lib/vue/pages/onboarding/components/contact.vue +0 -148
- data/lib/vue/pages/onboarding/components/date-time.vue +0 -265
- data/lib/vue/pages/onboarding/components/finish.vue +0 -62
- data/lib/vue/pages/onboarding/components/general-info.vue +0 -93
- data/lib/vue/pages/onboarding/components/indicators.vue +0 -78
- data/lib/vue/pages/onboarding/components/welcome.vue +0 -66
- data/lib/vue/pages/onboarding/show.vue +0 -67
- data/lib/vue/pages/onboarding/store.js +0 -165
- data/lib/vue/pages/otps/application.js +0 -90
- data/lib/vue/pages/passes/application.js +0 -80
- data/lib/vue/pages/websites/application.js +0 -34
- data/lib/vue/panels/panel-announcements.vue +0 -248
- data/lib/vue/panels/panel-bell-notifications.vue +0 -102
- data/lib/vue/panels/panel-files.vue +0 -281
- data/lib/vue/panels/panel-profile.vue +0 -76
- data/lib/vue/panels/panel-support-tickets.vue +0 -163
- data/lib/vue/panels/panel-tasks.vue +0 -124
- data/lib/vue/panels/stores/bell-notifications.js +0 -46
- data/lib/vue/panels/stores/support-tickets.js +0 -103
- data/lib/vue/public.js +0 -83
- data/lib/vue/refactor/shared/cloudobjects/action.vue +0 -193
- data/lib/vue/refactor/shared/cloudobjects/file/grid.vue +0 -215
- data/lib/vue/refactor/shared/cloudobjects/file/list.vue +0 -106
- data/lib/vue/refactor/shared/cloudobjects/file.vue +0 -145
- data/lib/vue/refactor/shared/workflows2/apps/actions/form.vue +0 -232
- data/lib/vue/refactor/shared/workflows2/apps/actions/forms/chatroom-form.vue +0 -103
- data/lib/vue/refactor/shared/workflows2/apps/actions/forms/cloud-object-clone-form.vue +0 -125
- data/lib/vue/refactor/shared/workflows2/apps/actions/forms/cloud-object-file-form.vue +0 -102
- data/lib/vue/refactor/shared/workflows2/apps/actions/forms/email-form.vue +0 -190
- data/lib/vue/refactor/shared/workflows2/apps/actions/forms/notification-form.vue +0 -124
- data/lib/vue/refactor/shared/workflows2/apps/actions/forms/send-cloud-object-file.vue +0 -170
- data/lib/vue/refactor/shared/workflows2/apps/actions/forms/task-form.vue +0 -258
- data/lib/vue/refactor/shared/workflows2/apps/actions/index.vue +0 -146
- data/lib/vue/refactor/shared/workflows2/apps/checks/form.vue +0 -200
- data/lib/vue/refactor/shared/workflows2/apps/checks/index.vue +0 -160
- data/lib/vue/refactor/shared/workflows2/apps/index.vue +0 -177
- data/lib/vue/refactor/shared/workflows2/apps/new.vue +0 -97
- data/lib/vue/refactor/shared/workflows2/apps/show.vue +0 -146
- data/lib/vue/refactor/shared/workflows2/components/associations.vue +0 -215
- data/lib/vue/refactor/shared/workflows2/components/chart.vue +0 -91
- data/lib/vue/refactor/shared/workflows2/components/workflow-form.vue +0 -466
- data/lib/vue/refactor/shared/workflows2/components/workflow-status-dropdown.vue +0 -129
- data/lib/vue/refactor/stores/cloudobjects/action.js +0 -181
- data/lib/vue/refactor/stores/cloudobjects/file.js +0 -205
- data/lib/vue/refactor/stores/entities/announcements.js +0 -75
- data/lib/vue/refactor/stores/entities/dashboard.js +0 -251
- data/lib/vue/refactor/stores/entities/workflow.js +0 -185
- data/lib/vue/refactor/stores/panels/announcements.js +0 -153
- data/lib/vue/refactor/stores/panels/notification.js +0 -114
- data/lib/vue/refactor/stores/panels/task.js +0 -66
- data/lib/vue/refactor/stores/panels/tickets.js +0 -129
- data/lib/vue/refactor/stores/role.js +0 -243
- data/lib/vue/refactor/stores/translations.json +0 -60
- data/lib/vue/refactor/stores/users.js +0 -98
- data/lib/vue/shared/dashboards/apps/edit.vue +0 -215
- data/lib/vue/shared/dashboards/apps/index.vue +0 -112
- data/lib/vue/shared/dashboards/apps/new.vue +0 -89
- data/lib/vue/shared/dashboards/apps/show.vue +0 -88
- data/lib/vue/shared/dashboards/components/form.vue +0 -246
- data/lib/vue/shared/services/firebase.js +0 -163
- data/lib/vue/shared/services/translator.js +0 -87
- data/lib/vue/shared/stores/command.js +0 -154
- data/lib/vue/shared/stores/dashboard.js +0 -253
- data/lib/vue/shared/stores/layout.js +0 -61
- data/lib/vue/shared/stores/systemController.js +0 -67
- data/lib/vue/shared/stores/users.js +0 -57
- data/lib/vue/stores/translations.json +0 -177
- data/lib/vue/translation.js +0 -45
- data/lib/webpack/base.js +0 -191
- data/lib/webpack/core.js +0 -93
- data/lib/webpack/engines.js +0 -167
- data/lib/webpack/root.js +0 -105
- data/lib/webpack/version.js +0 -78
- data/vendor/bulma/LICENSE +0 -21
- data/vendor/bulma/bulma.sass +0 -10
- data/vendor/bulma/css/bulma-rtl.css +0 -11851
- data/vendor/bulma/css/bulma-rtl.min.css +0 -1
- data/vendor/bulma/css/bulma.css +0 -11851
- data/vendor/bulma/css/bulma.min.css +0 -1
- data/vendor/bulma/sass/base/_all.sass +0 -6
- data/vendor/bulma/sass/base/animations.sass +0 -5
- data/vendor/bulma/sass/base/generic.sass +0 -145
- data/vendor/bulma/sass/base/helpers.sass +0 -1
- data/vendor/bulma/sass/base/minireset.sass +0 -79
- data/vendor/bulma/sass/components/_all.sass +0 -15
- data/vendor/bulma/sass/components/breadcrumb.sass +0 -77
- data/vendor/bulma/sass/components/card.sass +0 -103
- data/vendor/bulma/sass/components/dropdown.sass +0 -83
- data/vendor/bulma/sass/components/level.sass +0 -79
- data/vendor/bulma/sass/components/media.sass +0 -59
- data/vendor/bulma/sass/components/menu.sass +0 -59
- data/vendor/bulma/sass/components/message.sass +0 -101
- data/vendor/bulma/sass/components/modal.sass +0 -117
- data/vendor/bulma/sass/components/navbar.sass +0 -446
- data/vendor/bulma/sass/components/pagination.sass +0 -167
- data/vendor/bulma/sass/components/panel.sass +0 -121
- data/vendor/bulma/sass/components/tabs.sass +0 -176
- data/vendor/bulma/sass/elements/_all.sass +0 -16
- data/vendor/bulma/sass/elements/box.sass +0 -26
- data/vendor/bulma/sass/elements/button.sass +0 -357
- data/vendor/bulma/sass/elements/container.sass +0 -29
- data/vendor/bulma/sass/elements/content.sass +0 -162
- data/vendor/bulma/sass/elements/form.sass +0 -1
- data/vendor/bulma/sass/elements/icon.sass +0 -46
- data/vendor/bulma/sass/elements/image.sass +0 -73
- data/vendor/bulma/sass/elements/notification.sass +0 -52
- data/vendor/bulma/sass/elements/other.sass +0 -31
- data/vendor/bulma/sass/elements/progress.sass +0 -73
- data/vendor/bulma/sass/elements/table.sass +0 -134
- data/vendor/bulma/sass/elements/tag.sass +0 -140
- data/vendor/bulma/sass/elements/title.sass +0 -70
- data/vendor/bulma/sass/form/_all.sass +0 -9
- data/vendor/bulma/sass/form/checkbox-radio.sass +0 -22
- data/vendor/bulma/sass/form/file.sass +0 -184
- data/vendor/bulma/sass/form/input-textarea.sass +0 -66
- data/vendor/bulma/sass/form/select.sass +0 -88
- data/vendor/bulma/sass/form/shared.sass +0 -60
- data/vendor/bulma/sass/form/tools.sass +0 -215
- data/vendor/bulma/sass/grid/_all.sass +0 -5
- data/vendor/bulma/sass/grid/columns.sass +0 -513
- data/vendor/bulma/sass/grid/tiles.sass +0 -36
- data/vendor/bulma/sass/helpers/_all.sass +0 -12
- data/vendor/bulma/sass/helpers/color.sass +0 -39
- data/vendor/bulma/sass/helpers/flexbox.sass +0 -35
- data/vendor/bulma/sass/helpers/float.sass +0 -10
- data/vendor/bulma/sass/helpers/other.sass +0 -14
- data/vendor/bulma/sass/helpers/overflow.sass +0 -2
- data/vendor/bulma/sass/helpers/position.sass +0 -7
- data/vendor/bulma/sass/helpers/spacing.sass +0 -31
- data/vendor/bulma/sass/helpers/typography.sass +0 -103
- data/vendor/bulma/sass/helpers/visibility.sass +0 -122
- data/vendor/bulma/sass/layout/_all.sass +0 -6
- data/vendor/bulma/sass/layout/footer.sass +0 -11
- data/vendor/bulma/sass/layout/hero.sass +0 -153
- data/vendor/bulma/sass/layout/section.sass +0 -17
- data/vendor/bulma/sass/utilities/_all.sass +0 -9
- data/vendor/bulma/sass/utilities/animations.sass +0 -1
- data/vendor/bulma/sass/utilities/controls.sass +0 -49
- data/vendor/bulma/sass/utilities/derived-variables.sass +0 -114
- data/vendor/bulma/sass/utilities/extends.sass +0 -25
- data/vendor/bulma/sass/utilities/functions.sass +0 -135
- data/vendor/bulma/sass/utilities/initial-variables.sass +0 -79
- data/vendor/bulma/sass/utilities/mixins.sass +0 -303
- data/vendor/lesli-css/_index.scss +0 -34
- data/vendor/lesli-css/lesli.scss +0 -51
- data/vendor/lesli-css/license +0 -28
- data/vendor/lesli-css/src/base/fonts.scss +0 -50
- data/vendor/lesli-css/src/base/normalize.scss +0 -118
- data/vendor/lesli-css/src/components/blockquote.scss +0 -61
- data/vendor/lesli-css/src/components/columns.scss +0 -92
- data/vendor/lesli-css/src/components/container.scss +0 -47
- data/vendor/lesli-css/src/components/navigation.scss +0 -59
- data/vendor/lesli-css/src/functions/colors.scss +0 -184
- data/vendor/lesli-css/src/helpers/units.scss +0 -44
- data/vendor/lesli-css/src/mixins/breakpoint.scss +0 -184
- data/vendor/lesli-css/src/mixins/flex.scss +0 -80
- data/vendor/lesli-css/src/mixins/scrollbar.scss +0 -46
- data/vendor/lesli-css/src/settings/variables.scss +0 -26
- data/vendor/lesli-css/tests/base/normalize.spec.scss +0 -125
- data/vendor/lesli-css/tests/functions/colors.spec.scss +0 -117
- data/vendor/lesli-css/tests/mixins/breakpoint.spec.scss +0 -429
- data/vendor/lesli-css/tests/mixins/scrollbar.spec.scss +0 -82
- data/vendor/lesli-css/vendor/normalize.scss +0 -351
- data/vendor/remixicon/License +0 -201
- data/vendor/remixicon/fonts/remixicon.css +0 -2583
- /data/{vendor/lesli-css/src/components/grid.scss → app/assets/stylesheets/lesli/application.css} +0 -0
- /data/db/migrate/v1/{0010001010_create_lesli_account_details.rb → 0000110210_create_lesli_account_details.rb} +0 -0
- /data/db/structure/{00000008_custom_fields.json → 00000300_custom_fields.json} +0 -0
- /data/lib/assets/javascripts/lesli/{i18n.js → i18n_js} +0 -0
data/app/models/lesli/user.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Lesli
|
4
4
|
|
5
|
-
Copyright (c)
|
5
|
+
Copyright (c) 2025, Lesli Technologies, S. A.
|
6
6
|
|
7
7
|
This program is free software: you can redistribute it and/or modify
|
8
8
|
it under the terms of the GNU General Public License as published by
|
@@ -19,7 +19,7 @@ along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
19
|
|
20
20
|
Lesli · Ruby on Rails SaaS Development Framework.
|
21
21
|
|
22
|
-
Made with ♥ by
|
22
|
+
Made with ♥ by LesliTech
|
23
23
|
Building a better future, one line of code at a time.
|
24
24
|
|
25
25
|
@contact hello@lesli.tech
|
@@ -36,59 +36,55 @@ module Lesli
|
|
36
36
|
include UserExtensions
|
37
37
|
#include UserActivities
|
38
38
|
|
39
|
-
|
39
|
+
validates(:email,
|
40
|
+
format: { with: URI::MailTo::EMAIL_REGEXP },
|
41
|
+
presence: true,
|
42
|
+
uniqueness: true
|
43
|
+
);
|
44
|
+
|
45
|
+
# devise implementation
|
46
|
+
devise(
|
47
|
+
:database_authenticatable,
|
48
|
+
:registerable,
|
49
|
+
:rememberable,
|
50
|
+
:recoverable,
|
51
|
+
:validatable,
|
52
|
+
:confirmable,
|
53
|
+
:trackable
|
54
|
+
);
|
55
|
+
#:omniauthable, omniauth_providers: [:google_oauth2, :facebook]
|
56
|
+
|
57
|
+
|
58
|
+
# users belongs to an account only...
|
40
59
|
belongs_to :account, optional: true
|
41
60
|
|
61
|
+
|
42
62
|
# user details are saved on separate table
|
43
63
|
has_one :detail, inverse_of: :user, autosave: true, dependent: :destroy
|
44
64
|
accepts_nested_attributes_for :detail, update_only: true
|
45
65
|
|
66
|
+
|
46
67
|
# users data extensions
|
47
|
-
has_many :logs
|
48
|
-
has_many :codes
|
49
|
-
has_many :agents
|
50
68
|
has_many :tokens
|
51
69
|
has_many :settings
|
52
70
|
has_many :sessions
|
53
|
-
has_many :
|
54
|
-
has_many :shortcuts
|
55
|
-
has_many :notifications, class_name: "LesliBell::Notification"
|
56
|
-
has_many :activities, class_name: "User::Activity"
|
71
|
+
has_many :activities #, class_name: "Lesli::Item::Activity"
|
57
72
|
|
58
|
-
|
59
|
-
# every role adds a power to the user, power is just a role id
|
60
|
-
has_many :powers
|
61
|
-
has_many :roles, through: :powers, source: :role, class_name: "Lesli::Role"
|
62
|
-
has_many :privileges, through: :roles, class_name: "Lesli::Role::Privilege"
|
73
|
+
|
63
74
|
|
75
|
+
has_many :shortcuts, class_name: "LesliShield::User::Shortcuts"
|
64
76
|
|
65
|
-
# devise implementation
|
66
|
-
#if !defined?(LesliSecurity)
|
67
|
-
devise(
|
68
|
-
:database_authenticatable,
|
69
|
-
:registerable,
|
70
|
-
:rememberable,
|
71
|
-
:recoverable,
|
72
|
-
:validatable,
|
73
|
-
:confirmable,
|
74
|
-
:trackable);
|
75
|
-
#:omniauthable, omniauth_providers: [:google_oauth2, :facebook]
|
76
|
-
#end
|
77
|
-
|
78
|
-
|
79
|
-
# users belongs to an account only... and must have a role
|
80
|
-
belongs_to :account, optional: true
|
81
77
|
|
82
|
-
# users
|
83
|
-
|
84
|
-
|
85
|
-
|
78
|
+
# users can have many roles and too many privileges through the roles
|
79
|
+
# lesliroles is a shortcut to Lesli::Roles
|
80
|
+
has_many :roles
|
81
|
+
has_many :lesliroles, through: :roles, source: :role, class_name: "Lesli::Role"
|
82
|
+
has_many :privileges, through: :lesliroles, class_name: "Lesli::Role::Privilege"
|
86
83
|
|
87
84
|
|
88
85
|
# callbacks
|
89
86
|
before_create :before_create_user
|
90
|
-
after_create :
|
91
|
-
#after_create :after_account_assignation
|
87
|
+
after_create :after_create_user
|
92
88
|
#after_update :update_associated_services
|
93
89
|
|
94
90
|
|
@@ -102,7 +98,14 @@ module Lesli
|
|
102
98
|
# @return [void]
|
103
99
|
# @description Before creating a user we make sure there is no capitalized email
|
104
100
|
def before_create_user
|
105
|
-
self.email =
|
101
|
+
self.email = self.email.downcase
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def after_create_user
|
106
|
+
self.activities.create(title: "create_user", description:"User created")
|
107
|
+
after_confirmation_user
|
108
|
+
after_account_assignation
|
106
109
|
end
|
107
110
|
|
108
111
|
|
@@ -110,23 +113,24 @@ module Lesli
|
|
110
113
|
def after_confirmation_user
|
111
114
|
return unless self.confirmed?
|
112
115
|
|
113
|
-
|
114
|
-
# defined in user extensions
|
115
|
-
self.set_alias
|
116
|
+
self.activities.create(title: "create_user", description:"User confirmed")
|
116
117
|
|
117
|
-
# create user
|
118
|
-
|
118
|
+
# create an alias based on user name defined in user extensions
|
119
|
+
self.set_alias
|
119
120
|
|
120
121
|
# Minimum security settings required
|
121
|
-
self.settings.create_with(:value => false).find_or_create_by(:name => "mfa_enabled")
|
122
|
-
self.settings.create_with(:value => :email).find_or_create_by(:name => "mfa_method")
|
122
|
+
#self.settings.create_with(:value => false).find_or_create_by(:name => "mfa_enabled")
|
123
|
+
#self.settings.create_with(:value => :email).find_or_create_by(:name => "mfa_method")
|
123
124
|
end
|
124
125
|
|
125
126
|
def after_account_assignation
|
126
127
|
return unless self.account
|
127
128
|
|
128
129
|
#Courier::One::Firebase::User.sync_user(self)
|
129
|
-
#Courier
|
130
|
+
# Lesli::Courier.new(:lesli_calendar).from(:calendar_service, self).create({
|
131
|
+
# name: "Personal Calendar",
|
132
|
+
# default: true
|
133
|
+
# })
|
130
134
|
end
|
131
135
|
|
132
136
|
|
@@ -104,6 +104,8 @@ module Lesli
|
|
104
104
|
next if route[:controller].include? "rails"
|
105
105
|
next if route[:controller].include? "action_mailbox"
|
106
106
|
next if route[:controller].include? "active_storage"
|
107
|
+
next if route[:controller].include? "view_components"
|
108
|
+
next if route[:controller].include? "turbo/native/navigation"
|
107
109
|
|
108
110
|
if DEVISE_CONTROLLERS.include?(route[:controller])
|
109
111
|
list = "lesli"
|
@@ -118,7 +120,7 @@ module Lesli
|
|
118
120
|
end
|
119
121
|
|
120
122
|
# Get the list of controllers and actions from engines
|
121
|
-
|
123
|
+
LesliSystem.engines.each do |engine, engine_info|
|
122
124
|
|
123
125
|
# Do not process main Rails app
|
124
126
|
next if engine == "Root"
|
@@ -31,12 +31,45 @@ Building a better future, one line of code at a time.
|
|
31
31
|
=end
|
32
32
|
|
33
33
|
module Lesli
|
34
|
-
class
|
34
|
+
class RoleOperator < Lesli::ApplicationLesliService
|
35
35
|
|
36
|
-
@
|
36
|
+
@role = nil
|
37
37
|
|
38
|
-
def initialize
|
39
|
-
@
|
38
|
+
def initialize role
|
39
|
+
@role = role
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_profile_privileges
|
43
|
+
|
44
|
+
# Adding default system actions for profile descriptor
|
45
|
+
[
|
46
|
+
{ controller: "lesli_admin/profiles", actions: ["show"] }, # enable profile view
|
47
|
+
{ controller: "lesli/users", actions: ["options", "update"] }, # enable user edition
|
48
|
+
{ controller: "lesli/abouts", actions: ["show"] }, # system status
|
49
|
+
{ controller: "lesli/user/sessions", actions: ["index"] } # session management
|
50
|
+
].each do |controller_action|
|
51
|
+
|
52
|
+
controller_action[:actions].each do |action_name|
|
53
|
+
|
54
|
+
system_controller_action = SystemController::Action.joins(:system_controller)
|
55
|
+
.where("lesli_system_controllers.route = ?", controller_action[:controller])
|
56
|
+
.where("lesli_system_controller_actions.name = ?", action_name)
|
57
|
+
|
58
|
+
@role.actions.find_or_create_by(
|
59
|
+
action: system_controller_action.first
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_owner_actions
|
66
|
+
|
67
|
+
# Adding default system actions for profile descriptor
|
68
|
+
actions = SystemController::Action.all
|
69
|
+
|
70
|
+
actions.each do |action|
|
71
|
+
@role.actions.find_or_create_by(action: action)
|
72
|
+
end
|
40
73
|
end
|
41
74
|
|
42
75
|
# Syncronize the descriptor privileges with the role privilege cache table
|
@@ -54,50 +87,39 @@ module Lesli
|
|
54
87
|
# - the power has active that group of actions, this means that, if the power has
|
55
88
|
# not marked as active the pshow, pindex, etc column the power is not active
|
56
89
|
# even if it is assigned and active to a descriptor
|
57
|
-
records =
|
58
|
-
INNER JOIN
|
59
|
-
ON
|
90
|
+
records = Lesli::Role.joins(%(
|
91
|
+
INNER JOIN "lesli_role_actions"
|
92
|
+
ON "lesli_role_actions"."role_id" = "lesli_roles"."id"
|
60
93
|
)).joins(%(
|
61
94
|
INNER JOIN lesli_system_controller_actions
|
62
|
-
ON lesli_system_controller_actions.id =
|
95
|
+
ON lesli_system_controller_actions.id = lesli_role_actions.action_id
|
63
96
|
)).joins(%(
|
64
97
|
INNER JOIN lesli_system_controllers
|
65
98
|
ON lesli_system_controllers.id = lesli_system_controller_actions.system_controller_id
|
66
|
-
)).joins(%(
|
67
|
-
INNER JOIN lesli_role_powers
|
68
|
-
ON lesli_role_powers.descriptor_id = lesli_descriptors.id
|
69
99
|
)).select(%(
|
100
|
+
lesli_role_actions.role_id as role_id,
|
70
101
|
lesli_system_controllers.route as controller,
|
71
102
|
lesli_system_controller_actions.name as action,
|
72
|
-
|
73
|
-
when lesli_role_powers.deleted_at is not null then false
|
74
|
-
when NULLIF(lesli_system_controller_actions.name = 'list' and lesli_role_powers.plist = true, false) then true
|
75
|
-
when NULLIF(lesli_system_controller_actions.name = 'index' and lesli_role_powers.pindex = true, false) then true
|
76
|
-
when NULLIF(lesli_system_controller_actions.name = 'show' and lesli_role_powers.pshow = true, false) then true
|
77
|
-
when NULLIF(lesli_system_controller_actions.name = 'new' and lesli_role_powers.pcreate = true, false) then true
|
78
|
-
when NULLIF(lesli_system_controller_actions.name = 'create' and lesli_role_powers.pcreate = true, false) then true
|
79
|
-
when NULLIF(lesli_system_controller_actions.name = 'edit' and lesli_role_powers.pupdate = true, false) then true
|
80
|
-
when NULLIF(lesli_system_controller_actions.name = 'update' and lesli_role_powers.pupdate = true, false) then true
|
81
|
-
when NULLIF(lesli_system_controller_actions.name = 'destroy' and lesli_role_powers.pdestroy = true, false) then true
|
82
|
-
else false
|
83
|
-
end as active,
|
84
|
-
lesli_role_powers.role_id as role_id
|
103
|
+
true as active
|
85
104
|
)).with_deleted
|
86
105
|
|
87
106
|
|
88
107
|
# get privileges only for the given role, this is needed to sync only modified roles
|
89
|
-
records = records.where("
|
108
|
+
records = records.where("lesli_role_actions.role_id" => @role)
|
109
|
+
|
90
110
|
|
91
111
|
# we use the deleted_at column to know if a privilege is enable or disable, NULL values
|
92
112
|
# at the deleted_at column means privilege is active, so if we sort by deleted_at column
|
93
113
|
# all the active privileges will be at the top, then the uniq method is going to take
|
94
114
|
# always the active values, to completely disable a privilege for a specific controller/action
|
95
|
-
# we have to disable in all the
|
96
|
-
records = records.order("
|
97
|
-
|
115
|
+
# we have to disable in all the roles
|
116
|
+
records = records.order("lesli_role_actions.deleted_at DESC")
|
117
|
+
|
118
|
+
|
98
119
|
# convert the results to json so it is easy to insert/update
|
99
120
|
records = records.as_json(only: [:controller, :action, :role_id, :active])
|
100
121
|
|
122
|
+
|
101
123
|
# IMPORTANT: We must save only uniq privileges in the role_privilege table
|
102
124
|
# this means that it does not matters how many times we defined a privilege dependency
|
103
125
|
# we insert the privilege only once.
|
@@ -112,6 +134,7 @@ module Lesli
|
|
112
134
|
[privilege["controller"], privilege["action"], privilege["role_id"]]
|
113
135
|
end
|
114
136
|
|
137
|
+
|
115
138
|
# small check to ensure I have records to update/insert
|
116
139
|
return if records.blank?
|
117
140
|
|
@@ -80,6 +80,7 @@ module Lesli
|
|
80
80
|
account = Account.create!({
|
81
81
|
user: resource, # set user as owner of his just created account
|
82
82
|
name: "Lesli", # temporary company name
|
83
|
+
email: resource.email,
|
83
84
|
status: :active # account is active due user already confirmed his email
|
84
85
|
})
|
85
86
|
end
|
@@ -94,14 +95,14 @@ module Lesli
|
|
94
95
|
|
95
96
|
# add owner role to user only if multi-account is allowed
|
96
97
|
if allow_multiaccount == true
|
97
|
-
resource.powers.create({ role: account.roles.find_by(name: "owner") })
|
98
|
+
#resource.powers.create({ role: account.roles.find_by(name: "owner") })
|
98
99
|
end
|
99
100
|
|
100
101
|
# add profile role to user only if multi-account is allowed
|
101
102
|
if allow_multiaccount == false
|
102
103
|
# Assigning default role if defined in account settings
|
103
104
|
# Otherwise, the default role is "limited"
|
104
|
-
default_role_id = account.settings.find_by(:name => "default_role_id")&.value
|
105
|
+
#default_role_id = account.settings.find_by(:name => "default_role_id")&.value
|
105
106
|
|
106
107
|
if default_role_id.present?
|
107
108
|
resource.user_roles.create({ role: account.roles.find_by(:id => default_role_id)})
|
@@ -46,7 +46,7 @@ module Lesli
|
|
46
46
|
# Service constructor
|
47
47
|
# current_user is always required to initialize a service object
|
48
48
|
# current user is used to get the data only from the account context
|
49
|
-
def initialize current_user, query={}
|
49
|
+
def initialize current_user=nil, query={}
|
50
50
|
|
51
51
|
# make the current user globaly available in the service object
|
52
52
|
@current_user = current_user
|
@@ -89,7 +89,7 @@ module Lesli
|
|
89
89
|
|
90
90
|
|
91
91
|
# Standard method to create new resource into the database
|
92
|
-
def create
|
92
|
+
def create params
|
93
93
|
# Example:
|
94
94
|
# user = current_user.account.users.new(params)
|
95
95
|
|
@@ -98,8 +98,7 @@ module Lesli
|
|
98
98
|
# else
|
99
99
|
# self.error(user.errors.full_messages.to_sentence)
|
100
100
|
# end
|
101
|
-
|
102
|
-
self.resource = resource if resource
|
101
|
+
self.resource = params
|
103
102
|
self
|
104
103
|
end
|
105
104
|
|
@@ -152,6 +151,11 @@ module Lesli
|
|
152
151
|
|
153
152
|
private
|
154
153
|
|
154
|
+
def response resource = nil
|
155
|
+
self.resource = resource
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
155
159
|
attr_reader :current_user
|
156
160
|
|
157
161
|
attr_reader :resource
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Lesli
|
2
|
+
class Role::ActionService < Lesli::ApplicationLesliService
|
3
|
+
|
4
|
+
def index params
|
5
|
+
|
6
|
+
role_actions = {}
|
7
|
+
|
8
|
+
Lesli::Role::Action.joins(system_controller_action: :system_controller)
|
9
|
+
.select(
|
10
|
+
:id,
|
11
|
+
:role_id,
|
12
|
+
:action_id,
|
13
|
+
:deleted_at,
|
14
|
+
"lesli_system_controllers.id as controller_id",
|
15
|
+
"lesli_system_controllers.name as controller_name",
|
16
|
+
"lesli_system_controller_actions.name as controller_action_name",
|
17
|
+
"case when lesli_role_actions.deleted_at is null then TRUE else FALSE end active"
|
18
|
+
).each do |action|
|
19
|
+
unless role_actions.has_key?(action[:controller_name])
|
20
|
+
role_actions[action[:controller_name]] = {
|
21
|
+
list:nil,
|
22
|
+
index: nil,
|
23
|
+
show:nil,
|
24
|
+
create:nil,
|
25
|
+
update:nil,
|
26
|
+
destroy:nil
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
if action[:controller_action_name] == "list"
|
31
|
+
role_actions[action[:controller_name]][:list] = action
|
32
|
+
end
|
33
|
+
|
34
|
+
if action[:controller_action_name] == "index"
|
35
|
+
role_actions[action[:controller_name]][:index] = action
|
36
|
+
end
|
37
|
+
|
38
|
+
if action[:controller_action_name] == "show"
|
39
|
+
role_actions[action[:controller_name]][:show] = action
|
40
|
+
end
|
41
|
+
|
42
|
+
if action[:controller_action_name] == "create"
|
43
|
+
role_actions[action[:controller_name]][:create] = action
|
44
|
+
end
|
45
|
+
|
46
|
+
if action[:controller_action_name] == "update"
|
47
|
+
role_actions[action[:controller_name]][:update] = action
|
48
|
+
end
|
49
|
+
|
50
|
+
if action[:controller_action_name] == "destroy"
|
51
|
+
role_actions[action[:controller_name]][:destroy] = action
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
role_actions
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Lesli
|
4
|
+
|
5
|
+
Copyright (c) 2025, Lesli Technologies, S. A.
|
6
|
+
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU General Public License as published by
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
This program is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU General Public License
|
18
|
+
along with this program. If not, see http://www.gnu.org/licenses/.
|
19
|
+
|
20
|
+
Lesli · Ruby on Rails SaaS Development Framework.
|
21
|
+
|
22
|
+
Made with ♥ by LesliTech
|
23
|
+
Building a better future, one line of code at a time.
|
24
|
+
|
25
|
+
@contact hello@lesli.tech
|
26
|
+
@website https://www.lesli.tech
|
27
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
28
|
+
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
30
|
+
// ·
|
31
|
+
=end
|
32
|
+
|
33
|
+
module Lesli
|
34
|
+
class RoleService < Lesli::ApplicationLesliService
|
35
|
+
|
36
|
+
def find id
|
37
|
+
self.resource = current_user.account.roles.find_by_id(id)
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
# Return a list of roles that the user is able to work with
|
42
|
+
# according to object level permission
|
43
|
+
def list(params)
|
44
|
+
current_user.account.roles
|
45
|
+
.where("permission_level <= ?", current_user.max_object_level_permission)
|
46
|
+
.order(permission_level: :desc, name: :asc)
|
47
|
+
.select(:id, :name, :permission_level)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# @return [Array] Paginated index of users.
|
52
|
+
# @description Return a paginated array of users, used mostly in frontend views
|
53
|
+
def index
|
54
|
+
|
55
|
+
current_user.account.roles.where.not(
|
56
|
+
:name => ["owner"]
|
57
|
+
).joins("
|
58
|
+
left join (
|
59
|
+
select
|
60
|
+
count(1) users,
|
61
|
+
role_id
|
62
|
+
from lesli_user_roles
|
63
|
+
inner join lesli_users as u
|
64
|
+
on u.id = lesli_user_roles.user_id
|
65
|
+
and u.deleted_at is null
|
66
|
+
where lesli_user_roles.deleted_at is null
|
67
|
+
group by (role_id)
|
68
|
+
) users on users.role_id = lesli_roles.id
|
69
|
+
").joins(%(
|
70
|
+
left join (
|
71
|
+
select
|
72
|
+
count(1) actions,
|
73
|
+
role_id
|
74
|
+
from lesli_role_actions
|
75
|
+
group by role_id
|
76
|
+
) actions on actions.role_id = lesli_roles.id
|
77
|
+
)).where("lesli_roles.permission_level <= ?", current_user.max_object_level_permission)
|
78
|
+
.select(
|
79
|
+
:id,
|
80
|
+
:name,
|
81
|
+
:active,
|
82
|
+
:isolated,
|
83
|
+
:description,
|
84
|
+
:path_default,
|
85
|
+
:object_level_permission,
|
86
|
+
"users.users",
|
87
|
+
"actions.actions"
|
88
|
+
)
|
89
|
+
.page(query[:pagination][:page])
|
90
|
+
.per(query[:pagination][:perPage])
|
91
|
+
.order(object_level_permission: :desc, name: :asc)
|
92
|
+
end
|
93
|
+
|
94
|
+
# @overwrite
|
95
|
+
# @return {Object}
|
96
|
+
# @description Retrives the role
|
97
|
+
def show
|
98
|
+
self.resource
|
99
|
+
end
|
100
|
+
|
101
|
+
# @overwrite
|
102
|
+
# @return {Object}
|
103
|
+
# @param {params} Hash of the permitted attributes for a role
|
104
|
+
# @description Creates a new role
|
105
|
+
def create params
|
106
|
+
|
107
|
+
role = current_user.account.roles.new(params)
|
108
|
+
|
109
|
+
unless current_user.can_work_with_role?(role)
|
110
|
+
self.error(I18n.t("core.roles.messages_danger_creating_role_object_level_permission_too_high"))
|
111
|
+
end
|
112
|
+
|
113
|
+
# check if user can work with that object level permission
|
114
|
+
if role.object_level_permission.to_f >= current_user.roles.map(&:object_level_permission).max()
|
115
|
+
self.error(I18n.t("core.roles.messages_danger_creating_role_object_level_permission_too_high"))
|
116
|
+
end
|
117
|
+
|
118
|
+
# do not create if errors found
|
119
|
+
return self unless self.successful?
|
120
|
+
|
121
|
+
# Try to save role and logs if it went OK
|
122
|
+
if role.save
|
123
|
+
self.resource = role
|
124
|
+
#Role::Activity.log_create(current_user, self.resource)
|
125
|
+
else
|
126
|
+
self.error(role.errors.full_messages.to_sentence)
|
127
|
+
end
|
128
|
+
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
132
|
+
# @overwrite
|
133
|
+
# @return {Object}
|
134
|
+
# @param {params} Hash of the permitted attributes for a role
|
135
|
+
# @description Updates role's attributes and saves logs if it went without problem
|
136
|
+
def update params
|
137
|
+
old_attributes = self.resource.attributes
|
138
|
+
|
139
|
+
unless self.resource.update(params)
|
140
|
+
self.error(self.resource.errors.full_messages.to_sentence)
|
141
|
+
end
|
142
|
+
|
143
|
+
if self.successful?
|
144
|
+
new_attributes = self.resource.attributes
|
145
|
+
|
146
|
+
#LesliSecurity::Role::Activity.log_update(current_user, role, old_attributes, new_attributes)
|
147
|
+
end
|
148
|
+
|
149
|
+
self
|
150
|
+
end
|
151
|
+
|
152
|
+
# @overwrite
|
153
|
+
# @return {Object}
|
154
|
+
# @description Deletes the role
|
155
|
+
def destroy
|
156
|
+
unless self.resource.destroy
|
157
|
+
self.error(self.resource.errors.full_messages.to_sentence)
|
158
|
+
end
|
159
|
+
|
160
|
+
if self.successful?
|
161
|
+
LesliSecurity::Role::Activity.log_destroy(current_user, self.resource)
|
162
|
+
end
|
163
|
+
|
164
|
+
self
|
165
|
+
end
|
166
|
+
|
167
|
+
def options
|
168
|
+
{
|
169
|
+
:object_level_permissions => self.roles_with_object_level_permission
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def roles_with_object_level_permission
|
176
|
+
levels = {}
|
177
|
+
|
178
|
+
# get all the different object level permission registered in the roles
|
179
|
+
existing_levels = current_user.account.roles
|
180
|
+
.select(:object_level_permission)
|
181
|
+
.order(object_level_permission: :desc)
|
182
|
+
.distinct
|
183
|
+
.map { |level| level.object_level_permission }
|
184
|
+
|
185
|
+
# Build the next available object levels
|
186
|
+
# basically we need to add the possibles object level permissions between the
|
187
|
+
# existing ones
|
188
|
+
existing_levels.each_with_index do |level_current, i|
|
189
|
+
|
190
|
+
level_next = 0
|
191
|
+
|
192
|
+
# get the next OLP in the list of the existing roles
|
193
|
+
level_next = existing_levels.to_a[i+1] unless existing_levels.to_a[i+1].nil?
|
194
|
+
|
195
|
+
# calculate the new next level, basically we get the level right in the middle
|
196
|
+
# between the existing levels, example:
|
197
|
+
# 1000 existing level
|
198
|
+
# 750 new projected level
|
199
|
+
# 500 existing level
|
200
|
+
level_new = (level_current + level_next) / 2
|
201
|
+
|
202
|
+
# add the levels to the levels object
|
203
|
+
levels[level_current] = []
|
204
|
+
|
205
|
+
next if level_next == 0
|
206
|
+
|
207
|
+
levels[level_new] = []
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
# Get all the existing roles
|
212
|
+
current_user.account.roles
|
213
|
+
.select(:id, :name, :object_level_permission)
|
214
|
+
.where.not(object_level_permission: nil).each do |role|
|
215
|
+
levels[role.object_level_permission] = [] if levels[role.object_level_permission].blank?
|
216
|
+
# push the role grouping by the object level permission
|
217
|
+
levels[role.object_level_permission].push(role)
|
218
|
+
end
|
219
|
+
|
220
|
+
levels_sorted = []
|
221
|
+
|
222
|
+
levels.keys.each do |key|
|
223
|
+
levels_sorted.push({
|
224
|
+
level: key,
|
225
|
+
roles: levels[key]
|
226
|
+
})
|
227
|
+
end
|
228
|
+
|
229
|
+
levels_sorted
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|