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.
Files changed (469) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/lesli_manifest.js +3 -6
  3. data/app/assets/images/lesli/brand/app-icon.svg +45 -39
  4. data/app/assets/javascripts/lesli/application.js +1 -0
  5. data/app/controllers/lesli/abouts_controller.rb +16 -14
  6. data/app/controllers/lesli/application_controller.rb +13 -0
  7. data/app/controllers/lesli/application_devise_controller.rb +10 -12
  8. data/app/controllers/lesli/application_lesli_controller.rb +12 -11
  9. data/app/controllers/lesli/apps_controller.rb +6 -0
  10. data/app/controllers/lesli/roles_controller.rb +2 -2
  11. data/app/helpers/lesli/general_helper.rb +18 -5
  12. data/app/helpers/lesli/html_helper.rb +8 -0
  13. data/app/helpers/lesli/navigation_helper.rb +30 -11
  14. data/app/helpers/lesli/system_helper.rb +2 -2
  15. data/app/helpers/lesli/turbo_helper.rb +58 -0
  16. data/app/interfaces/lesli/customization_interface.rb +42 -0
  17. data/app/interfaces/lesli/requester_interface.rb +103 -0
  18. data/app/interfaces/lesli/responder_interface.rb +127 -0
  19. data/app/lib/date2.rb +1 -199
  20. data/app/lib/lesli/courier.rb +54 -0
  21. data/app/mailers/lesli/application_lesli_mailer.rb +32 -59
  22. data/app/mailers/lesli/devise_mailer.rb +16 -8
  23. data/app/models/concerns/account_initializer.rb +27 -68
  24. data/app/models/concerns/lesli/has_activities.rb +29 -0
  25. data/app/models/concerns/user_extensions.rb +34 -19
  26. data/app/models/concerns/user_security.rb +4 -4
  27. data/app/models/lesli/account.rb +13 -20
  28. data/{lib/scss/layouts/application-container.scss → app/models/lesli/item/activity.rb} +11 -8
  29. data/app/models/lesli/role/{power.rb → action.rb} +6 -4
  30. data/app/models/lesli/role.rb +7 -15
  31. data/app/models/lesli/shared/catalog.rb +20 -0
  32. data/app/models/lesli/shared/dashboard.rb +1 -1
  33. data/app/models/lesli/user/activity.rb +5 -0
  34. data/app/models/lesli/user/detail.rb +5 -5
  35. data/app/models/lesli/user/{log.rb → journal.rb} +3 -3
  36. data/app/models/lesli/user/{power.rb → role.rb} +2 -3
  37. data/app/models/lesli/user/session.rb +3 -4
  38. data/app/models/lesli/user.rb +50 -46
  39. data/app/operators/lesli/controller_operator.rb +3 -1
  40. data/app/operators/lesli/{role_descriptor_operator.rb → role_operator.rb} +51 -28
  41. data/app/operators/lesli/user_registration_operator.rb +3 -2
  42. data/app/services/lesli/application_lesli_service.rb +8 -4
  43. data/app/services/lesli/role/action_service.rb +58 -0
  44. data/app/services/lesli/role_service.rb +232 -0
  45. data/app/services/lesli/{user_session_service.rb → user/session_service.rb} +23 -14
  46. data/app/services/lesli/user_service.rb +85 -1
  47. data/app/views/lesli/apps/show.html.erb +52 -0
  48. data/app/views/lesli/layouts/application-devise.html.erb +5 -7
  49. data/app/views/lesli/layouts/application-lesli.html.erb +18 -24
  50. data/app/views/lesli/partials/_application-analytics.html.erb +2 -2
  51. data/app/views/lesli/partials/_application-data.html.erb +3 -77
  52. data/app/views/lesli/partials/_application-head.html.erb +7 -4
  53. data/app/views/lesli/partials/_application-lesli-annoouncements.html.erb +49 -0
  54. data/app/views/lesli/partials/_application-lesli-header.html.erb +73 -49
  55. data/app/views/lesli/partials/_application-lesli-javascript.html.erb +3 -16
  56. data/app/views/lesli/partials/_application-lesli-navigation.html.erb +12 -9
  57. data/app/views/lesli/partials/{_application-lesli-notices.html.erb → _application-lesli-notifications.html.erb} +10 -8
  58. data/app/views/lesli/partials/_application-lesli-scss.html.erb +1 -1
  59. data/app/views/lesli/partials/_application-lesli-sidebar.html.erb +1 -1
  60. data/app/views/lesli/partials/_application-public-javascript.html.erb +1 -4
  61. data/app/views/lesli/shared/dashboards/_show.html.erb +63 -0
  62. data/app/views/lesli/wrappers/_application-devise.html.erb +4 -6
  63. data/config/importmap.rb +14 -0
  64. data/config/initializers/lesli.rb +20 -12
  65. data/config/initializers/lesli_migration_helpers.rb +61 -0
  66. data/config/locales/translations.en.yml +1 -26
  67. data/config/locales/translations.es.yml +1 -26
  68. data/config/locales/translations.fr.yml +1 -26
  69. data/config/locales/translations.it.yml +1 -26
  70. data/config/locales/translations.pt.yml +1 -26
  71. data/config/routes.rb +3 -1
  72. data/db/migrate/v1/{0010000110_create_lesli_accounts.rb → 0000000110_create_lesli_accounts.rb} +13 -12
  73. data/db/migrate/v1/0000000210_create_lesli_roles.rb +65 -0
  74. data/db/migrate/v1/0000000310_create_lesli_users.rb +99 -0
  75. data/db/migrate/v1/{0010000610_create_lesli_system_controllers.rb → 0000100110_create_lesli_system_controllers.rb} +3 -3
  76. data/db/migrate/v1/{0010000710_create_lesli_system_controller_actions.rb → 0000100210_create_lesli_system_controller_actions.rb} +3 -4
  77. data/{lib/scss/layouts/application-content.scss → db/migrate/v1/0000110310_create_lesli_account_settings.rb} +8 -6
  78. data/{app/models/lesli/user/agent.rb → db/migrate/v1/0000110410_create_lesli_account_activities.rb} +3 -3
  79. data/db/migrate/v1/0000120210_create_lesli_role_actions.rb +45 -0
  80. data/db/migrate/v1/{0010001410_create_lesli_account_logs.rb → 0000120310_create_lesli_role_privileges.rb} +8 -8
  81. data/db/{tables/0010003810_create_user_shortcuts.rb → migrate/v1/0000130210_create_lesli_user_roles.rb} +9 -12
  82. data/db/migrate/v1/0000130310_create_lesli_user_sessions.rb +56 -0
  83. data/db/{seed/production.rb → migrate/v1/0000130410_create_lesli_user_activities.rb} +7 -4
  84. data/db/{tables/0010001110_create_account_locations.rb → migrate2/0000100510_create_lesli_account_locations.rb} +6 -6
  85. data/db/{tables/0010001510_create_account_currencies.rb → migrate2/0000100610_create_lesli_account_currencies.rb} +4 -4
  86. data/db/seed/{development/accounts.rb → accounts.rb} +6 -2
  87. data/db/seed/{production/users.rb → users.rb} +4 -10
  88. data/db/seed/{tools.rb → xyz.rb} +2 -7
  89. data/db/seeds.rb +3 -2
  90. data/db/structure/00000020_catalogs.json +0 -0
  91. data/lib/generators/{application_lesli_generator.rb → application_lesli_generator_base.rb} +4 -4
  92. data/lib/generators/lesli/spec/spec_generator.rb +2 -2
  93. data/lib/generators/lesli/view/USAGE +8 -0
  94. data/lib/generators/lesli/view/templates/spec-factory.template +17 -0
  95. data/lib/generators/lesli/view/templates/spec-model.template +70 -0
  96. data/lib/generators/lesli/view/view_generator.rb +25 -0
  97. data/lib/lesli/configuration.rb +7 -10
  98. data/lib/lesli/engine.rb +22 -3
  99. data/lib/lesli/r_spec.rb +5 -2
  100. data/lib/lesli/routing.rb +42 -9
  101. data/lib/lesli/version.rb +2 -2
  102. data/lib/lesli.rb +11 -0
  103. data/lib/migrate/common.rb +94 -0
  104. data/lib/migrate/items/action_structure.rb +51 -0
  105. data/{db/migrate/v1/0010001210_create_lesli_account_activities.rb → lib/migrate/items/activity_structure.rb} +18 -16
  106. data/lib/migrate/items/attachment_structure.rb +62 -0
  107. data/{app/views/lesli/partials/_application-lesli-engines.html.erb → lib/migrate/items/discussion_structure.rb} +19 -27
  108. data/lib/migrate/items/subscriber_structure.rb +49 -0
  109. data/lib/migrate/items/version_structure.rb +53 -0
  110. data/lib/migrate/shared/account_structure.rb +21 -0
  111. data/lib/migrate/shared/catalog_structure.rb +30 -0
  112. data/lib/migrate/shared/dashboard_structure.rb +54 -0
  113. data/lib/migrate/shared/setting_structure.rb +20 -0
  114. data/lib/rspec/config/spec_coverage.rb +95 -0
  115. data/{db/migrate/v1/0010001110_create_lesli_account_settings.rb → lib/rspec/factories/lesli_account.rb} +10 -7
  116. data/{db/seed/development.rb → lib/rspec/factories/lesli_role.rb} +30 -3
  117. data/{db/seed/test.rb → lib/rspec/factories/lesli_user.rb} +32 -3
  118. data/lib/rspec/fixtures/files/lesli-icon.png +0 -0
  119. data/lib/rspec/fixtures/files/test_file_1.docx +0 -0
  120. data/{db/tables/0010001610_create_account_currency_exchange_rates.rb → lib/rspec/helpers/lesli_helper.rb} +21 -21
  121. data/lib/rspec/helpers/rails_helper.rb +134 -0
  122. data/lib/rspec/helpers/response_request_helper.rb +214 -0
  123. data/lib/rspec/helpers/response_service_helper.rb +66 -0
  124. data/lib/rspec/helpers/spec_helper.rb +99 -0
  125. data/lib/rspec/lesli_api_tester.rb +133 -0
  126. data/lib/rspec/lesli_service_tester.rb +46 -0
  127. data/{db/tables/0010001410_create_account_files.rb → lib/rspec/testers/controller.rb} +31 -20
  128. data/lib/rspec/testers/model.rb +36 -0
  129. data/lib/rspec/testers/request.rb +84 -0
  130. data/lib/tasks/lesli/db.rake +5 -3
  131. data/lib/tasks/lesli/git.rake +28 -32
  132. data/lib/tasks/lesli/github.rake +89 -0
  133. data/lib/tasks/lesli_tasks.rake +3 -3
  134. data/readme.md +28 -17
  135. metadata +134 -394
  136. data/app/assets/fonts/lesli/Domine/Domine-Variable.ttf +0 -0
  137. data/app/assets/fonts/lesli/Domine/OFL.txt +0 -97
  138. data/app/assets/fonts/lesli/MaterialDesign/icons.woff2 +0 -0
  139. data/app/assets/fonts/lesli/Montserrat/Montserrat-Variable.ttf +0 -0
  140. data/app/assets/fonts/lesli/OpenSans/OpenSans-Variable.ttf +0 -0
  141. data/app/assets/fonts/lesli/Remix/remixicon.eot +0 -0
  142. data/app/assets/fonts/lesli/Remix/remixicon.glyph.json +0 -1
  143. data/app/assets/fonts/lesli/Remix/remixicon.svg +0 -7633
  144. data/app/assets/fonts/lesli/Remix/remixicon.symbol.svg +0 -11
  145. data/app/assets/fonts/lesli/Remix/remixicon.ttf +0 -0
  146. data/app/assets/fonts/lesli/Remix/remixicon.woff +0 -0
  147. data/app/assets/fonts/lesli/Remix/remixicon.woff2 +0 -0
  148. data/app/assets/fonts/lesli/Roboto/LICENSE.txt +0 -202
  149. data/app/assets/fonts/lesli/Roboto/Roboto-Black.ttf +0 -0
  150. data/app/assets/fonts/lesli/Roboto/Roboto-BlackItalic.ttf +0 -0
  151. data/app/assets/fonts/lesli/Roboto/Roboto-Bold.ttf +0 -0
  152. data/app/assets/fonts/lesli/Roboto/Roboto-BoldItalic.ttf +0 -0
  153. data/app/assets/fonts/lesli/Roboto/Roboto-Italic.ttf +0 -0
  154. data/app/assets/fonts/lesli/Roboto/Roboto-Light.ttf +0 -0
  155. data/app/assets/fonts/lesli/Roboto/Roboto-LightItalic.ttf +0 -0
  156. data/app/assets/fonts/lesli/Roboto/Roboto-Medium.ttf +0 -0
  157. data/app/assets/fonts/lesli/Roboto/Roboto-MediumItalic.ttf +0 -0
  158. data/app/assets/fonts/lesli/Roboto/Roboto-Regular.ttf +0 -0
  159. data/app/assets/fonts/lesli/Roboto/Roboto-Thin.ttf +0 -0
  160. data/app/assets/fonts/lesli/Roboto/Roboto-ThinItalic.ttf +0 -0
  161. data/app/assets/icons/lesli/engine-admin.svg +0 -1
  162. data/app/assets/icons/lesli/engine-audit.svg +0 -1
  163. data/app/assets/icons/lesli/engine-babel.svg +0 -1
  164. data/app/assets/icons/lesli/engine-bell.svg +0 -1
  165. data/app/assets/icons/lesli/engine-books.svg +0 -1
  166. data/app/assets/icons/lesli/engine-calendar.svg +0 -1
  167. data/app/assets/icons/lesli/engine-dashboard.svg +0 -1
  168. data/app/assets/icons/lesli/engine-dispatcher.svg +0 -1
  169. data/app/assets/icons/lesli/engine-focus.svg +0 -1
  170. data/app/assets/icons/lesli/engine-kb.svg +0 -1
  171. data/app/assets/icons/lesli/engine-leaf.svg +0 -1
  172. data/app/assets/icons/lesli/engine-lesli.svg +0 -1
  173. data/app/assets/icons/lesli/engine-letter.svg +0 -1
  174. data/app/assets/icons/lesli/engine-mailer.svg +0 -1
  175. data/app/assets/icons/lesli/engine-one.svg +0 -1
  176. data/app/assets/icons/lesli/engine-profile.svg +0 -1
  177. data/app/assets/icons/lesli/engine-proposal.svg +0 -1
  178. data/app/assets/icons/lesli/engine-scraper.svg +0 -1
  179. data/app/assets/icons/lesli/engine-security.svg +0 -1
  180. data/app/assets/icons/lesli/engine-shared.svg +0 -1
  181. data/app/assets/icons/lesli/engine-shield.svg +0 -1
  182. data/app/assets/icons/lesli/engine-storage.svg +0 -1
  183. data/app/assets/icons/lesli/engine-support.svg +0 -1
  184. data/app/assets/icons/lesli/engine-talk.svg +0 -1
  185. data/app/assets/icons/lesli/engine-team.svg +0 -1
  186. data/app/assets/icons/lesli/engine-time.svg +0 -1
  187. data/app/assets/icons/lesli/locale-en.svg +0 -1
  188. data/app/assets/icons/lesli/locale-es.svg +0 -1
  189. data/app/assets/icons/lesli/locale-fr.svg +0 -1
  190. data/app/assets/icons/lesli/locale-it.svg +0 -1
  191. data/app/assets/icons/lesli/locale-pt.svg +0 -1
  192. data/app/assets/icons/readme.md +0 -10
  193. data/app/assets/javascripts/lesli/templates/application.js +0 -14
  194. data/app/assets/javascripts/lesli/templates/public.js +0 -14
  195. data/app/assets/stylesheets/lesli/templates/application.css +0 -2918
  196. data/app/assets/stylesheets/lesli/templates/public.css +0 -1
  197. data/app/controllers/lesli/interfaces/application/authorization.rb +0 -107
  198. data/app/controllers/lesli/interfaces/application/customization.rb +0 -46
  199. data/app/controllers/lesli/interfaces/application/logger.rb +0 -134
  200. data/app/controllers/lesli/interfaces/application/requester.rb +0 -84
  201. data/app/controllers/lesli/interfaces/application/responder.rb +0 -132
  202. data/app/controllers/lesli/interfaces/controllers/actions.rb +0 -250
  203. data/app/controllers/lesli/interfaces/controllers/activities.rb +0 -215
  204. data/app/controllers/lesli/interfaces/controllers/discussions.rb +0 -270
  205. data/app/controllers/lesli/interfaces/controllers/files.rb +0 -467
  206. data/app/controllers/lesli/interfaces/controllers/subscribers.rb +0 -234
  207. data/app/lib/lesli/system.rb +0 -110
  208. data/app/models/lesli/cloud_object/action.rb +0 -70
  209. data/app/models/lesli/cloud_object/activity.rb +0 -311
  210. data/app/models/lesli/cloud_object/custom_field.rb +0 -158
  211. data/app/models/lesli/cloud_object/discussion.rb +0 -219
  212. data/app/models/lesli/cloud_object/subscriber.rb +0 -186
  213. data/app/operators/lesli/descriptor_privilege_operator.rb +0 -75
  214. data/app/views/lesli/emails/devise_mailer/confirmation_instructions.html.erb +0 -23
  215. data/app/views/lesli/emails/devise_mailer/reset_password_instructions.html.erb +0 -23
  216. data/app/views/lesli/partials/_application-lesli-icons.html.erb +0 -1
  217. data/config/initializers/devise.rb +0 -336
  218. data/db/seed/development/users.rb +0 -52
  219. data/db/seed/production/accounts.rb +0 -50
  220. data/db/structure/00000000_people.json +0 -34
  221. data/db/structure/00000003_actions.json +0 -14
  222. data/db/structure/00000004_activities.json +0 -20
  223. data/db/structure/00000005_discussions.json +0 -8
  224. data/db/structure/00000006_files.json +0 -32
  225. data/db/structure/00000007_subscribers.json +0 -11
  226. data/db/structure/00000501_dashboards.json +0 -14
  227. data/db/structure/00000502_dashboard_components.json +0 -23
  228. data/db/tables/0010003410_create_user_activities.rb +0 -51
  229. data/db/tables/0010003710_create_user_codes.rb +0 -43
  230. data/db/tables/0010004110_create_user_tokens.rb +0 -45
  231. data/db/tables/0010005610_create_role_activities.rb +0 -50
  232. data/db/tables/0010009010_create_feedbacks.rb +0 -56
  233. data/lib/mailer_previews/devise_mailer_preview.rb +0 -49
  234. data/lib/scss/cloud-objects/discussion.scss +0 -80
  235. data/lib/scss/cloud-objects/file.scss +0 -138
  236. data/lib/scss/components/keypad.scss +0 -109
  237. data/lib/scss/elements/autocomplete.scss +0 -72
  238. data/lib/scss/elements/card.scss +0 -37
  239. data/lib/scss/elements/empty.scss +0 -43
  240. data/lib/scss/elements/file-uploader.scss +0 -74
  241. data/lib/scss/elements/gallery.scss +0 -98
  242. data/lib/scss/elements/input-tag.scss +0 -73
  243. data/lib/scss/elements/loading.scss +0 -63
  244. data/lib/scss/elements/map.scss +0 -107
  245. data/lib/scss/elements/navbar.scss +0 -115
  246. data/lib/scss/elements/table.scss +0 -118
  247. data/lib/scss/elements/toolbar.scss +0 -66
  248. data/lib/scss/fonts/families.scss +0 -47
  249. data/lib/scss/fonts/mdicons.scss +0 -82
  250. data/lib/scss/fonts/remixicons.scss +0 -2602
  251. data/lib/scss/helpers/display.scss +0 -44
  252. data/lib/scss/helpers/tooltip.scss +0 -91
  253. data/lib/scss/layouts/application-announcements.scss +0 -40
  254. data/lib/scss/layouts/application-component.scss +0 -39
  255. data/lib/scss/layouts/application-engines.scss +0 -125
  256. data/lib/scss/layouts/application-footer.scss +0 -102
  257. data/lib/scss/layouts/application-header.scss +0 -91
  258. data/lib/scss/layouts/application-navigation.scss +0 -79
  259. data/lib/scss/layouts/application-search.scss +0 -71
  260. data/lib/scss/layouts/application-sidebar.scss +0 -219
  261. data/lib/scss/overrides/notification.scss +0 -75
  262. data/lib/scss/overrides/sweetalert.scss +0 -106
  263. data/lib/scss/pages/devise-simple.scss +0 -89
  264. data/lib/scss/pages/devise.scss +0 -179
  265. data/lib/scss/pages/invites.scss +0 -81
  266. data/lib/scss/panels/panel-announcements.scss +0 -56
  267. data/lib/scss/panels/panel-notification.scss +0 -67
  268. data/lib/scss/panels/panel-profile.scss +0 -62
  269. data/lib/scss/panels/panel-support-ticket.scss +0 -56
  270. data/lib/scss/panels/panel-tasks.scss +0 -41
  271. data/lib/scss/settings/variables.scss +0 -148
  272. data/lib/scss/shared/workflow-status-progress.scss +0 -135
  273. data/lib/scss/templates/application.scss +0 -127
  274. data/lib/scss/templates/component.scss +0 -39
  275. data/lib/scss/templates/dashboards.scss +0 -53
  276. data/lib/scss/templates/empty.scss +0 -42
  277. data/lib/scss/templates/pdf.scss +0 -45
  278. data/lib/scss/templates/public.scss +0 -72
  279. data/lib/vue/application.js +0 -285
  280. data/lib/vue/cloudobjects/discussion/content.vue +0 -62
  281. data/lib/vue/cloudobjects/discussion/element.vue +0 -170
  282. data/lib/vue/cloudobjects/discussion/filters.vue +0 -108
  283. data/lib/vue/cloudobjects/discussion/new.vue +0 -134
  284. data/lib/vue/cloudobjects/discussion.vue +0 -99
  285. data/lib/vue/cloudobjects/stores/discussion.js +0 -212
  286. data/lib/vue/layouts/application-announcements.vue +0 -78
  287. data/lib/vue/layouts/application-component.vue +0 -38
  288. data/lib/vue/layouts/application-container.vue +0 -48
  289. data/lib/vue/layouts/application-engines.vue +0 -66
  290. data/lib/vue/layouts/application-footer.vue +0 -123
  291. data/lib/vue/layouts/application-header.vue +0 -252
  292. data/lib/vue/layouts/application-navbar.vue +0 -110
  293. data/lib/vue/layouts/application-search.vue +0 -86
  294. data/lib/vue/layouts/application-sidebar.vue +0 -63
  295. data/lib/vue/pages/errors/app.js +0 -32
  296. data/lib/vue/pages/invites/app.js +0 -76
  297. data/lib/vue/pages/mfas/application.js +0 -77
  298. data/lib/vue/pages/onboarding/application.js +0 -45
  299. data/lib/vue/pages/onboarding/components/address.vue +0 -120
  300. data/lib/vue/pages/onboarding/components/buttons.vue +0 -67
  301. data/lib/vue/pages/onboarding/components/contact.vue +0 -148
  302. data/lib/vue/pages/onboarding/components/date-time.vue +0 -265
  303. data/lib/vue/pages/onboarding/components/finish.vue +0 -62
  304. data/lib/vue/pages/onboarding/components/general-info.vue +0 -93
  305. data/lib/vue/pages/onboarding/components/indicators.vue +0 -78
  306. data/lib/vue/pages/onboarding/components/welcome.vue +0 -66
  307. data/lib/vue/pages/onboarding/show.vue +0 -67
  308. data/lib/vue/pages/onboarding/store.js +0 -165
  309. data/lib/vue/pages/otps/application.js +0 -90
  310. data/lib/vue/pages/passes/application.js +0 -80
  311. data/lib/vue/pages/websites/application.js +0 -34
  312. data/lib/vue/panels/panel-announcements.vue +0 -248
  313. data/lib/vue/panels/panel-bell-notifications.vue +0 -102
  314. data/lib/vue/panels/panel-files.vue +0 -281
  315. data/lib/vue/panels/panel-profile.vue +0 -76
  316. data/lib/vue/panels/panel-support-tickets.vue +0 -163
  317. data/lib/vue/panels/panel-tasks.vue +0 -124
  318. data/lib/vue/panels/stores/bell-notifications.js +0 -46
  319. data/lib/vue/panels/stores/support-tickets.js +0 -103
  320. data/lib/vue/public.js +0 -83
  321. data/lib/vue/refactor/shared/cloudobjects/action.vue +0 -193
  322. data/lib/vue/refactor/shared/cloudobjects/file/grid.vue +0 -215
  323. data/lib/vue/refactor/shared/cloudobjects/file/list.vue +0 -106
  324. data/lib/vue/refactor/shared/cloudobjects/file.vue +0 -145
  325. data/lib/vue/refactor/shared/workflows2/apps/actions/form.vue +0 -232
  326. data/lib/vue/refactor/shared/workflows2/apps/actions/forms/chatroom-form.vue +0 -103
  327. data/lib/vue/refactor/shared/workflows2/apps/actions/forms/cloud-object-clone-form.vue +0 -125
  328. data/lib/vue/refactor/shared/workflows2/apps/actions/forms/cloud-object-file-form.vue +0 -102
  329. data/lib/vue/refactor/shared/workflows2/apps/actions/forms/email-form.vue +0 -190
  330. data/lib/vue/refactor/shared/workflows2/apps/actions/forms/notification-form.vue +0 -124
  331. data/lib/vue/refactor/shared/workflows2/apps/actions/forms/send-cloud-object-file.vue +0 -170
  332. data/lib/vue/refactor/shared/workflows2/apps/actions/forms/task-form.vue +0 -258
  333. data/lib/vue/refactor/shared/workflows2/apps/actions/index.vue +0 -146
  334. data/lib/vue/refactor/shared/workflows2/apps/checks/form.vue +0 -200
  335. data/lib/vue/refactor/shared/workflows2/apps/checks/index.vue +0 -160
  336. data/lib/vue/refactor/shared/workflows2/apps/index.vue +0 -177
  337. data/lib/vue/refactor/shared/workflows2/apps/new.vue +0 -97
  338. data/lib/vue/refactor/shared/workflows2/apps/show.vue +0 -146
  339. data/lib/vue/refactor/shared/workflows2/components/associations.vue +0 -215
  340. data/lib/vue/refactor/shared/workflows2/components/chart.vue +0 -91
  341. data/lib/vue/refactor/shared/workflows2/components/workflow-form.vue +0 -466
  342. data/lib/vue/refactor/shared/workflows2/components/workflow-status-dropdown.vue +0 -129
  343. data/lib/vue/refactor/stores/cloudobjects/action.js +0 -181
  344. data/lib/vue/refactor/stores/cloudobjects/file.js +0 -205
  345. data/lib/vue/refactor/stores/entities/announcements.js +0 -75
  346. data/lib/vue/refactor/stores/entities/dashboard.js +0 -251
  347. data/lib/vue/refactor/stores/entities/workflow.js +0 -185
  348. data/lib/vue/refactor/stores/panels/announcements.js +0 -153
  349. data/lib/vue/refactor/stores/panels/notification.js +0 -114
  350. data/lib/vue/refactor/stores/panels/task.js +0 -66
  351. data/lib/vue/refactor/stores/panels/tickets.js +0 -129
  352. data/lib/vue/refactor/stores/role.js +0 -243
  353. data/lib/vue/refactor/stores/translations.json +0 -60
  354. data/lib/vue/refactor/stores/users.js +0 -98
  355. data/lib/vue/shared/dashboards/apps/edit.vue +0 -215
  356. data/lib/vue/shared/dashboards/apps/index.vue +0 -112
  357. data/lib/vue/shared/dashboards/apps/new.vue +0 -89
  358. data/lib/vue/shared/dashboards/apps/show.vue +0 -88
  359. data/lib/vue/shared/dashboards/components/form.vue +0 -246
  360. data/lib/vue/shared/services/firebase.js +0 -163
  361. data/lib/vue/shared/services/translator.js +0 -87
  362. data/lib/vue/shared/stores/command.js +0 -154
  363. data/lib/vue/shared/stores/dashboard.js +0 -253
  364. data/lib/vue/shared/stores/layout.js +0 -61
  365. data/lib/vue/shared/stores/systemController.js +0 -67
  366. data/lib/vue/shared/stores/users.js +0 -57
  367. data/lib/vue/stores/translations.json +0 -177
  368. data/lib/vue/translation.js +0 -45
  369. data/lib/webpack/base.js +0 -191
  370. data/lib/webpack/core.js +0 -93
  371. data/lib/webpack/engines.js +0 -167
  372. data/lib/webpack/root.js +0 -105
  373. data/lib/webpack/version.js +0 -78
  374. data/vendor/bulma/LICENSE +0 -21
  375. data/vendor/bulma/bulma.sass +0 -10
  376. data/vendor/bulma/css/bulma-rtl.css +0 -11851
  377. data/vendor/bulma/css/bulma-rtl.min.css +0 -1
  378. data/vendor/bulma/css/bulma.css +0 -11851
  379. data/vendor/bulma/css/bulma.min.css +0 -1
  380. data/vendor/bulma/sass/base/_all.sass +0 -6
  381. data/vendor/bulma/sass/base/animations.sass +0 -5
  382. data/vendor/bulma/sass/base/generic.sass +0 -145
  383. data/vendor/bulma/sass/base/helpers.sass +0 -1
  384. data/vendor/bulma/sass/base/minireset.sass +0 -79
  385. data/vendor/bulma/sass/components/_all.sass +0 -15
  386. data/vendor/bulma/sass/components/breadcrumb.sass +0 -77
  387. data/vendor/bulma/sass/components/card.sass +0 -103
  388. data/vendor/bulma/sass/components/dropdown.sass +0 -83
  389. data/vendor/bulma/sass/components/level.sass +0 -79
  390. data/vendor/bulma/sass/components/media.sass +0 -59
  391. data/vendor/bulma/sass/components/menu.sass +0 -59
  392. data/vendor/bulma/sass/components/message.sass +0 -101
  393. data/vendor/bulma/sass/components/modal.sass +0 -117
  394. data/vendor/bulma/sass/components/navbar.sass +0 -446
  395. data/vendor/bulma/sass/components/pagination.sass +0 -167
  396. data/vendor/bulma/sass/components/panel.sass +0 -121
  397. data/vendor/bulma/sass/components/tabs.sass +0 -176
  398. data/vendor/bulma/sass/elements/_all.sass +0 -16
  399. data/vendor/bulma/sass/elements/box.sass +0 -26
  400. data/vendor/bulma/sass/elements/button.sass +0 -357
  401. data/vendor/bulma/sass/elements/container.sass +0 -29
  402. data/vendor/bulma/sass/elements/content.sass +0 -162
  403. data/vendor/bulma/sass/elements/form.sass +0 -1
  404. data/vendor/bulma/sass/elements/icon.sass +0 -46
  405. data/vendor/bulma/sass/elements/image.sass +0 -73
  406. data/vendor/bulma/sass/elements/notification.sass +0 -52
  407. data/vendor/bulma/sass/elements/other.sass +0 -31
  408. data/vendor/bulma/sass/elements/progress.sass +0 -73
  409. data/vendor/bulma/sass/elements/table.sass +0 -134
  410. data/vendor/bulma/sass/elements/tag.sass +0 -140
  411. data/vendor/bulma/sass/elements/title.sass +0 -70
  412. data/vendor/bulma/sass/form/_all.sass +0 -9
  413. data/vendor/bulma/sass/form/checkbox-radio.sass +0 -22
  414. data/vendor/bulma/sass/form/file.sass +0 -184
  415. data/vendor/bulma/sass/form/input-textarea.sass +0 -66
  416. data/vendor/bulma/sass/form/select.sass +0 -88
  417. data/vendor/bulma/sass/form/shared.sass +0 -60
  418. data/vendor/bulma/sass/form/tools.sass +0 -215
  419. data/vendor/bulma/sass/grid/_all.sass +0 -5
  420. data/vendor/bulma/sass/grid/columns.sass +0 -513
  421. data/vendor/bulma/sass/grid/tiles.sass +0 -36
  422. data/vendor/bulma/sass/helpers/_all.sass +0 -12
  423. data/vendor/bulma/sass/helpers/color.sass +0 -39
  424. data/vendor/bulma/sass/helpers/flexbox.sass +0 -35
  425. data/vendor/bulma/sass/helpers/float.sass +0 -10
  426. data/vendor/bulma/sass/helpers/other.sass +0 -14
  427. data/vendor/bulma/sass/helpers/overflow.sass +0 -2
  428. data/vendor/bulma/sass/helpers/position.sass +0 -7
  429. data/vendor/bulma/sass/helpers/spacing.sass +0 -31
  430. data/vendor/bulma/sass/helpers/typography.sass +0 -103
  431. data/vendor/bulma/sass/helpers/visibility.sass +0 -122
  432. data/vendor/bulma/sass/layout/_all.sass +0 -6
  433. data/vendor/bulma/sass/layout/footer.sass +0 -11
  434. data/vendor/bulma/sass/layout/hero.sass +0 -153
  435. data/vendor/bulma/sass/layout/section.sass +0 -17
  436. data/vendor/bulma/sass/utilities/_all.sass +0 -9
  437. data/vendor/bulma/sass/utilities/animations.sass +0 -1
  438. data/vendor/bulma/sass/utilities/controls.sass +0 -49
  439. data/vendor/bulma/sass/utilities/derived-variables.sass +0 -114
  440. data/vendor/bulma/sass/utilities/extends.sass +0 -25
  441. data/vendor/bulma/sass/utilities/functions.sass +0 -135
  442. data/vendor/bulma/sass/utilities/initial-variables.sass +0 -79
  443. data/vendor/bulma/sass/utilities/mixins.sass +0 -303
  444. data/vendor/lesli-css/_index.scss +0 -34
  445. data/vendor/lesli-css/lesli.scss +0 -51
  446. data/vendor/lesli-css/license +0 -28
  447. data/vendor/lesli-css/src/base/fonts.scss +0 -50
  448. data/vendor/lesli-css/src/base/normalize.scss +0 -118
  449. data/vendor/lesli-css/src/components/blockquote.scss +0 -61
  450. data/vendor/lesli-css/src/components/columns.scss +0 -92
  451. data/vendor/lesli-css/src/components/container.scss +0 -47
  452. data/vendor/lesli-css/src/components/navigation.scss +0 -59
  453. data/vendor/lesli-css/src/functions/colors.scss +0 -184
  454. data/vendor/lesli-css/src/helpers/units.scss +0 -44
  455. data/vendor/lesli-css/src/mixins/breakpoint.scss +0 -184
  456. data/vendor/lesli-css/src/mixins/flex.scss +0 -80
  457. data/vendor/lesli-css/src/mixins/scrollbar.scss +0 -46
  458. data/vendor/lesli-css/src/settings/variables.scss +0 -26
  459. data/vendor/lesli-css/tests/base/normalize.spec.scss +0 -125
  460. data/vendor/lesli-css/tests/functions/colors.spec.scss +0 -117
  461. data/vendor/lesli-css/tests/mixins/breakpoint.spec.scss +0 -429
  462. data/vendor/lesli-css/tests/mixins/scrollbar.spec.scss +0 -82
  463. data/vendor/lesli-css/vendor/normalize.scss +0 -351
  464. data/vendor/remixicon/License +0 -201
  465. data/vendor/remixicon/fonts/remixicon.css +0 -2583
  466. /data/{vendor/lesli-css/src/components/grid.scss → app/assets/stylesheets/lesli/application.css} +0 -0
  467. /data/db/migrate/v1/{0010001010_create_lesli_account_details.rb → 0000110210_create_lesli_account_details.rb} +0 -0
  468. /data/db/structure/{00000008_custom_fields.json → 00000300_custom_fields.json} +0 -0
  469. /data/lib/assets/javascripts/lesli/{i18n.js → i18n_js} +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  Lesli
4
4
 
5
- Copyright (c) 2023, Lesli Technologies, S. A.
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 https://www.lesli.tech
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
- # users belongs to an account only... and must have a role
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 :requests
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
- # users can have many roles and too many privileges through the roles
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 belongs to an account only... and must have a role
83
- belongs_to :account, optional: true
84
-
85
- validates :email, :presence => true
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 :after_confirmation_user, if: :confirmed?
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 = (self.email||"").downcase
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
- # create an alias based on user name
114
- # defined in user extensions
115
- self.set_alias
116
+ self.activities.create(title: "create_user", description:"User confirmed")
116
117
 
117
- # create user details
118
- User::Detail.find_or_create_by({ user: self })
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::Driver::Calendar.create_user_calendar(self, name: "Personal Calendar", default: true)
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
- Lesli::System.engines.each do |engine, engine_info|
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 RoleDescriptorOperator < Lesli::ApplicationLesliService
34
+ class RoleOperator < Lesli::ApplicationLesliService
35
35
 
36
- @roles;
36
+ @role = nil
37
37
 
38
- def initialize *roles
39
- @roles = roles
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 = Descriptor.joins(%(
58
- INNER JOIN lesli_descriptor_privileges
59
- ON lesli_descriptor_privileges.descriptor_id = lesli_descriptors.id
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 = lesli_descriptor_privileges.action_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
- case
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("lesli_role_powers.role_id" => @roles)
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 descriptors
96
- records = records.order("lesli_role_powers.deleted_at DESC")
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 resource
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