lesli_shield 1.0.2 → 1.0.4

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/lesli_shield/confirmations.css +18763 -0
  3. data/app/assets/stylesheets/lesli_shield/devise/oauth.css +32 -0
  4. data/app/assets/stylesheets/lesli_shield/passwords.css +18717 -1
  5. data/app/assets/stylesheets/lesli_shield/registrations.css +18804 -1
  6. data/app/assets/stylesheets/lesli_shield/sessions.css +18804 -1
  7. data/app/assets/stylesheets/lesli_shield/users.css +30 -0
  8. data/app/controllers/lesli_shield/dashboards_controller.rb +1 -8
  9. data/app/controllers/lesli_shield/invites_controller.rb +80 -0
  10. data/app/controllers/lesli_shield/role/actions_controller.rb +32 -20
  11. data/app/controllers/lesli_shield/roles_controller.rb +16 -8
  12. data/app/controllers/lesli_shield/sessions_controller.rb +5 -8
  13. data/app/controllers/lesli_shield/user/roles_controller.rb +62 -0
  14. data/app/controllers/lesli_shield/users_controller.rb +57 -20
  15. data/app/controllers/users/confirmations_controller.rb +42 -8
  16. data/app/controllers/users/passwords_controller.rb +52 -37
  17. data/app/controllers/users/registrations_controller.rb +2 -8
  18. data/app/controllers/users/sessions_controller.rb +57 -50
  19. data/app/helpers/lesli_shield/invites_helper.rb +4 -0
  20. data/app/helpers/lesli_shield/user/roles_helper.rb +4 -0
  21. data/app/interfaces/lesli_shield/authorization_interface.rb +8 -2
  22. data/app/mailers/lesli_shield/devise_mailer.rb +98 -0
  23. data/app/mailers/lesli_shield/invitation.html.erb +23 -0
  24. data/app/models/concerns/lesli_shield/user_security.rb +222 -0
  25. data/app/models/lesli_shield/account.rb +1 -1
  26. data/app/models/lesli_shield/dashboard.rb +1 -4
  27. data/app/models/lesli_shield/invite.rb +24 -0
  28. data/{lib/vue/confirmations.js → app/models/lesli_shield/role/action.rb} +17 -10
  29. data/{db/migrate/v1/0801003010_create_lesli_shield_dashboards.rb → app/models/lesli_shield/role/privilege.rb} +5 -4
  30. data/app/models/lesli_shield/user/role.rb +8 -0
  31. data/app/models/lesli_shield/user/session.rb +80 -0
  32. data/app/services/lesli_shield/invite_service.rb +43 -0
  33. data/app/services/lesli_shield/role_action_service.rb +118 -0
  34. data/app/services/lesli_shield/role_privilege_service.rb +112 -0
  35. data/app/{operators/lesli_shield/user_registration_operator.rb → services/lesli_shield/user_registration_service.rb} +26 -29
  36. data/app/services/lesli_shield/user_session_service.rb +78 -0
  37. data/app/services/lesli_shield/user_validator_service.rb +221 -0
  38. data/app/views/devise/confirmations/show.html.erb +4 -6
  39. data/app/views/devise/passwords/edit.html.erb +1 -2
  40. data/app/views/devise/passwords/new.html.erb +1 -1
  41. data/app/views/devise/registrations/new.html.erb +5 -4
  42. data/app/views/devise/sessions/new.html.erb +3 -2
  43. data/app/views/devise/shared/_application-devise-simple.erb +59 -0
  44. data/app/views/devise/shared/_application-devise.html.erb +76 -0
  45. data/app/views/lesli_shield/dashboards/_component-calendar.html.erb +1 -0
  46. data/app/views/lesli_shield/dashboards/_component-chart-bar.html.erb +6 -0
  47. data/app/views/lesli_shield/dashboards/_component-chart-line.html.erb +8 -0
  48. data/app/views/lesli_shield/dashboards/_component-count.html.erb +1 -0
  49. data/app/views/lesli_shield/dashboards/_component-date.html.erb +1 -0
  50. data/app/views/lesli_shield/dashboards/_component-weather.html.erb +1 -0
  51. data/app/views/lesli_shield/invites/_form.html.erb +10 -0
  52. data/app/views/lesli_shield/invites/_invite.html.erb +2 -0
  53. data/app/views/lesli_shield/invites/edit.html.erb +12 -0
  54. data/app/views/lesli_shield/invites/index.html.erb +66 -0
  55. data/{db/migrate/v1/0801001710_create_lesli_shield_settings.rb → app/views/lesli_shield/invites/new.html.erb} +9 -10
  56. data/{lib/vue/apps/dashboards/components/engine-version.vue → app/views/lesli_shield/invites/show.html.erb} +26 -43
  57. data/app/views/lesli_shield/partials/_navigation.html.erb +2 -4
  58. data/app/views/lesli_shield/{roles/_form-privileges.html.erb → role/actions/_form.html.erb} +5 -30
  59. data/app/views/lesli_shield/role/actions/index.html.erb +14 -0
  60. data/app/views/lesli_shield/roles/index.html.erb +2 -6
  61. data/app/views/lesli_shield/roles/new.html.erb +0 -11
  62. data/app/views/lesli_shield/roles/show.html.erb +5 -8
  63. data/app/views/lesli_shield/user/roles/_form.html.erb +17 -0
  64. data/app/views/lesli_shield/user/roles/_role.html.erb +2 -0
  65. data/app/views/lesli_shield/user/roles/edit.html.erb +12 -0
  66. data/app/views/lesli_shield/user/roles/index.html.erb +16 -0
  67. data/app/views/lesli_shield/user/roles/new.html.erb +11 -0
  68. data/app/views/lesli_shield/user/roles/show.html.erb +10 -0
  69. data/app/views/lesli_shield/users/{_viewer-activities.html.erb → _activities-viewer.html.erb} +2 -4
  70. data/app/views/lesli_shield/users/_information-card.html.erb +3 -3
  71. data/app/views/lesli_shield/users/_management-privileges.html.erb +74 -0
  72. data/app/views/lesli_shield/users/_management-security.html.erb +5 -0
  73. data/app/views/lesli_shield/users/index.html.erb +3 -7
  74. data/app/views/lesli_shield/users/new.html.erb +5 -11
  75. data/app/views/lesli_shield/users/show.html.erb +7 -5
  76. data/config/initializers/devise.rb +305 -304
  77. data/config/locales/translations.en.yml +4 -1
  78. data/config/locales/translations.es.yml +4 -1
  79. data/config/locales/translations.it.yml +4 -1
  80. data/config/routes.rb +7 -8
  81. data/db/migrate/v1/0801100210_create_lesli_shield_role_actions.rb +48 -0
  82. data/db/migrate/v1/0801100410_create_lesli_shield_role_privileges.rb +45 -0
  83. data/db/migrate/v1/0801110110_create_lesli_shield_user_roles.rb +43 -0
  84. data/db/migrate/v1/0801111210_create_lesli_shield_user_sessions.rb +56 -0
  85. data/db/migrate/v1/0801120110_create_lesli_shield_invites.rb +49 -0
  86. data/lib/lesli_shield/engine.rb +3 -3
  87. data/lib/lesli_shield/router.rb +21 -0
  88. data/lib/lesli_shield/version.rb +2 -2
  89. data/lib/lesli_shield.rb +1 -1
  90. data/lib/scss/_devise.scss +10 -0
  91. data/lib/scss/confirmations.scss +24 -24
  92. data/lib/tasks/lesli_shield_tasks.rake +1 -1
  93. data/readme.md +59 -20
  94. metadata +69 -44
  95. data/app/controllers/lesli_shield/dashboard/components_controller.rb +0 -60
  96. data/app/models/lesli_shield/dashboard/component.rb +0 -18
  97. data/app/views/lesli_shield/dashboards/edit.html.erb +0 -1
  98. data/app/views/lesli_shield/dashboards/index.html.erb +0 -9
  99. data/app/views/lesli_shield/dashboards/new.html.erb +0 -1
  100. data/app/views/lesli_shield/dashboards/show.html.erb +0 -1
  101. data/app/views/lesli_shield/roles/_session.html.erb +0 -2
  102. data/app/views/lesli_shield/roles/edit.html.erb +0 -12
  103. data/app/views/lesli_shield/roles/update.turbo_stream.erb +0 -3
  104. data/app/views/lesli_shield/users/update.turbo_stream.erb +0 -3
  105. data/lib/lesli_shield/routing.rb +0 -23
  106. data/lib/vue/application.js +0 -83
  107. data/lib/vue/apps/sessions/index.vue +0 -50
  108. data/lib/vue/passwords.js +0 -137
  109. data/lib/vue/registrations.js +0 -144
  110. data/lib/vue/sessions.js +0 -148
  111. data/lib/vue/stores/sessions.js +0 -43
  112. data/lib/vue/stores/translations.json +0 -162
  113. /data/app/views/lesli_shield/roles/{_form-information.html.erb → _form.html.erb} +0 -0
  114. /data/db/migrate/v1/{0801120310_create_lesli_shield_user_shortcuts.rb → 0801111010_create_lesli_shield_user_shortcuts.rb} +0 -0
  115. /data/db/migrate/v1/{0801120410_create_lesli_shield_user_tokens.rb → 0801111110_create_lesli_shield_user_tokens.rb} +0 -0
@@ -0,0 +1,221 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2023, 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 https://www.lesli.tech
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 LesliShield
34
+ class UserValidatorService < Lesli::ApplicationLesliService
35
+
36
+ def validate
37
+ active?()
38
+ confirmed?()
39
+ roles_empty?()
40
+ active_roles?()
41
+ end
42
+
43
+
44
+ # validates if password meet with the minimum password requirements
45
+ # this settings are stored in the account_settings table
46
+ def password_complexity(password)
47
+
48
+ if password.blank?
49
+ failures.push('error_password_cannot_be_blank')
50
+ return self
51
+ end
52
+
53
+ # remove all the special characters for easy validations of some rules
54
+ password_string_no_special = password.gsub(/[^0-9A-Za-z]/, '')
55
+
56
+ # database keys with the parameters to validate
57
+ password_values = [
58
+ 'password_expiration_time_days',
59
+ 'password_enforce_complexity',
60
+ 'password_special_char_count',
61
+ 'password_lowercase_count',
62
+ 'password_uppercase_count',
63
+ 'password_minimum_length',
64
+ 'password_digit_count'
65
+ ].map do |setting_name|
66
+ "name = '#{setting_name}'"
67
+ end
68
+
69
+ password_settings = []
70
+
71
+ # get password settings from the database
72
+ if @resource.account
73
+
74
+ # if user is already registered
75
+ password_settings = @resource.account.settings.where(password_values.join(" or "))
76
+
77
+ elseif Account.first
78
+
79
+ # for new accounts just take the first account in the database
80
+ password_settings = Account.first.settings.where(password_values.join(" or "))
81
+
82
+ end
83
+
84
+ password_settings.each do |settings|
85
+
86
+ # exit validations if password complexity is not enabled
87
+ if settings[:name] == 'password_enforce_complexity' && settings[:value] != "1"
88
+ failures = []
89
+ break
90
+ end
91
+
92
+ # check if the password has te minimum number of special characters required
93
+ if settings[:name] == 'password_special_char_count'
94
+
95
+ # this regex removes all "normal" letters and numbers leaving special characters
96
+ if settings[:value].to_i > password.scan(/[^0-9A-Za-z]/).length
97
+ failures.push('error_password_special_char_count')
98
+ end
99
+
100
+ end
101
+
102
+ # check if the password has te minimum number of lowercase letters required
103
+ if settings[:name] == 'password_lowercase_count'
104
+
105
+ if settings[:value].to_i > password_string_no_special.scan(/[^0-9A-Z]/).length
106
+ failures.push('error_password_lowercase_count')
107
+ end
108
+
109
+ end
110
+
111
+ # check if the password has te minimum number of uppercase letters required
112
+ if settings[:name] == 'password_uppercase_count'
113
+
114
+ if settings[:value].to_i > password_string_no_special.scan(/[^0-9a-z]/).length
115
+ failures.push('error_password_uppercase_count')
116
+ end
117
+
118
+ end
119
+
120
+ # check if the password has te minium number of numbers required xD
121
+ if settings[:name] == 'password_digit_count'
122
+
123
+ if settings[:value].to_i > password_string_no_special.scan(/[^A-Za-z]/).length
124
+ failures.push('error_password_digit_count')
125
+ end
126
+
127
+ end
128
+
129
+ # check if the password has te minimum size required
130
+ if settings[:name] == 'password_minimum_length'
131
+
132
+ if settings[:value].to_i > password.length
133
+ failures.push('error_password_minimum_length')
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+
140
+ return self
141
+
142
+ end
143
+
144
+ def valid?
145
+ failures.empty?
146
+ end
147
+
148
+ private
149
+
150
+
151
+ # check if user is able to create a new session
152
+ def active?
153
+
154
+ unless @resource.active? && @resource.locked_until != nil
155
+
156
+ # save a locked log for the requested user
157
+ @resource.logs.create({
158
+ title: "session_creation_failed",
159
+ description: "user_locked"
160
+ })
161
+
162
+ return false
163
+
164
+ end
165
+
166
+ return true
167
+ end
168
+
169
+ def confirmed?
170
+
171
+ # check if user is already confirmed
172
+ unless @resource.confirmed?
173
+
174
+ # save a invalid credentials log for the requested user
175
+ @resource.logs.create({
176
+ title: "session_creation_failed",
177
+ description: "email_not_confirmed"
178
+ })
179
+
180
+ return false
181
+
182
+ end
183
+
184
+ return true
185
+
186
+ end
187
+
188
+ def roles_empty?
189
+
190
+ # check if user has roles assigned
191
+ if @resource.roles.empty?
192
+
193
+ @resource.logs.create({
194
+ title: "session_creation_failed",
195
+ description: "user_has_no_assigned_role"
196
+ })
197
+
198
+ return true
199
+
200
+ end
201
+
202
+ return false
203
+
204
+ end
205
+
206
+ def active_roles?
207
+
208
+ # check user has at least one active role before authorize the sign-in request
209
+ unless (@resource.roles.map {|role| role.active}.include? true)
210
+ @resource.logs.create({
211
+ title: "session_creation_failed",
212
+ description: "user_has_no_active_role"
213
+ })
214
+
215
+ return false
216
+ end
217
+
218
+ return true
219
+ end
220
+ end
221
+ end
@@ -38,7 +38,7 @@ Building a better future, one line of code at a time.
38
38
  </script>
39
39
  <% end %>
40
40
 
41
- <%= render("lesli/wrappers/application-devise-simple", title: "Account confirmation") do %>
41
+ <%= render("devise/shared/application-devise-simple", title:"Account confirmation") do %>
42
42
 
43
43
  <% if flash[:danger] %>
44
44
  <% flash.each do |type, msg| %>
@@ -50,14 +50,12 @@ Building a better future, one line of code at a time.
50
50
 
51
51
  <% if flash[:success] %>
52
52
  <div class="confirmation-message">
53
- <svg version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
54
- <path d="M256,6.998c-137.533,0-249,111.467-249,249c0,137.534,111.467,249,249,249s249-111.467,249-249 C505,118.464,393.533,6.998,256,6.998z M256,485.078c-126.309,0-229.08-102.771-229.08-229.081 c0-126.31,102.771-229.08,229.08-229.08c126.31,0,229.08,102.771,229.08,229.08C485.08,382.307,382.31,485.078,256,485.078z"/>
55
- <polygon points="384.235,158.192 216.919,325.518 127.862,236.481 113.72,250.624 216.919,353.803 398.28,172.334"/>
56
- </svg>
57
- <p>Confirmation successfully</p>
53
+ <p>Your account has been successfully verified</p>
58
54
  </div>
59
55
  <% end %>
60
56
 
57
+ <%= render("devise/shared/links", login:true) %>
58
+
61
59
  <% end %>
62
60
 
63
61
 
@@ -1,5 +1,4 @@
1
-
2
- <%= render("lesli/wrappers/application-devise-simple", title:"Cambiar contraseña") do %>
1
+ <%= render("devise/shared/application-devise-simple", title:"Password update") do %>
3
2
 
4
3
  <%= form_for(
5
4
  resource,
@@ -1,5 +1,5 @@
1
1
 
2
- <%= render("lesli/wrappers/application-devise-simple", title:"Forgot your password?") do %>
2
+ <%= render("devise/shared/application-devise-simple", title:"Forgot your password?") do %>
3
3
 
4
4
  <%= form_for(
5
5
  resource,
@@ -28,11 +28,12 @@ Building a better future, one line of code at a time.
28
28
  // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
29
29
  // ·
30
30
  %>
31
+ <%
32
+ resource.email = 'test2@lesli.tech'
33
+ resource.password = 'Test123!'
34
+ %>
35
+ <%= render("devise/shared/application-devise", title:"Create an account to discover Lesli") do %>
31
36
 
32
-
33
- <%= render("lesli/wrappers/application-devise", title:"Create an account to discover Lesli") do %>
34
-
35
- <%# Log in form %>
36
37
  <%= form_for(
37
38
  resource,
38
39
  as: resource_name,
@@ -39,13 +39,14 @@ if Lesli.config.demo
39
39
  end
40
40
  %>
41
41
 
42
- <%= render("lesli/wrappers/application-devise", title:"Welcome to Lesli") do %>
42
+ <%= render("devise/shared/application-devise", title:"Welcome to Lesli") do %>
43
43
 
44
44
  <%= form_for(
45
45
  resource,
46
46
  as: resource_name,
47
47
  url: user_session_path,
48
- builder: LesliView::Forms::Builder
48
+ builder: LesliView::Forms::Builder,
49
+ data: { turbo: false }
49
50
  ) do |form| %>
50
51
 
51
52
  <% if Lesli.config.demo %>
@@ -0,0 +1,59 @@
1
+ <%
2
+ =begin
3
+
4
+ Lesli
5
+
6
+ Copyright (c) 2023, Lesli Technologies, S. A.
7
+
8
+ This program is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation, either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ This program is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with this program. If not, see http://www.gnu.org/licenses/.
20
+
21
+ Lesli · Ruby on Rails SaaS development platform.
22
+
23
+ Made with ♥ by https://www.lesli.tech
24
+ Building a better future, one line of code at a time.
25
+
26
+ @contact hello@lesli.tech
27
+ @website https://www.lesli.tech
28
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
29
+
30
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
31
+ // ·
32
+ =end
33
+ %>
34
+
35
+ <% title = defined?(title) ? title : "" %>
36
+
37
+ <main id="lesli-application">
38
+ <section class="hero is-fullheight">
39
+ <div class="hero-head has-text-centered">
40
+ <%# Logo container %>
41
+ <div class="logo mb-4">
42
+ <%= image_tag(
43
+ "#{lesli_instance_code}/brand/app-auth.svg", # dynamic path to the instance main logo
44
+ :class => "#{lesli_instance_code}-logo", # dynamic class according to the instance
45
+ :alt => "Main logo")
46
+ %>
47
+ <h1 class="title is-size-4 has-text-primary">
48
+ <%#= I18n.t("core.users/sessions.view_text_welcome") %>
49
+ <%= title %>
50
+ </h1>
51
+ </div>
52
+ </div>
53
+ <div class="hero-body">
54
+
55
+ <%= yield %>
56
+
57
+ </div>
58
+ </section>
59
+ </main>
@@ -0,0 +1,76 @@
1
+ <%#
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
+ %>
32
+
33
+ <% title = defined?(title) ? title : "" %>
34
+ <% back_to_login = defined?(back_to_login) ? back_to_login : false %>
35
+
36
+ <main id="lesli-application" class="standard-auth-view">
37
+ <section class="columns is-gapless">
38
+ <div class="column login-form">
39
+ <div class="hero is-fullheight">
40
+ <% if back_to_login %>
41
+ <div class="hero-head pt-6 pl-6">
42
+ <%= link_to new_user_session_path, :class => "has-text-primary" do %>
43
+ <span class="icon-text">
44
+ <span class="icon ri-lg">
45
+ <i class="ri-arrow-left-s-line"></i>
46
+ </span>
47
+ <span>Back to Login</span>
48
+ </span>
49
+ <% end %>
50
+ </div>
51
+ <% end %>
52
+ <div class="hero-body is-flex-direction-column is-justify-content-center">
53
+
54
+ <%# Logo container %>
55
+ <div class="logo has-text-centered mb-6">
56
+ <%= image_tag(
57
+ "#{lesli_instance_code}/brand/app-auth.svg", # dynamic path to the instance main logo
58
+ :class => "#{lesli_instance_code}-logo mb-2", # dynamic class according to the instance
59
+ :alt => "Main logo")
60
+ %>
61
+ <h1 class="is-title is-size-3 has-text-primary">
62
+ <%#= I18n.t("core.users/sessions.view_text_welcome") %>
63
+ <%= title %>
64
+ </h1>
65
+ </div>
66
+
67
+ <%= yield %>
68
+
69
+ </div>
70
+ <%# footer %>
71
+ <%#= render partial: "devise/shared/footer" %>
72
+ </div>
73
+ </div>
74
+ <div class="column background is-hidden-touch"></div>
75
+ </section>
76
+ </main>
@@ -0,0 +1 @@
1
+ <%= render(LesliView::Widgets::Calendar.new) %>
@@ -0,0 +1,6 @@
1
+
2
+ <%= render(LesliView::Widgets::Chart.new("Priorities", {
3
+ "High": 10,
4
+ "Low": 16,
5
+ "Medium": 4
6
+ }, type: :bar))%>
@@ -0,0 +1,8 @@
1
+
2
+ <%= render(LesliView::Widgets::Chart.new("Requests", {
3
+ "1": 13,
4
+ "2": 17,
5
+ "3": 10,
6
+ "4": 5,
7
+ "5": 15,
8
+ }, type: :line))%>
@@ -0,0 +1 @@
1
+ <%= render(LesliView::Widgets::Count.new('Total users today', rand(1...9999))) %>
@@ -0,0 +1 @@
1
+ <%= render(LesliView::Widgets::Date.new) %>
@@ -0,0 +1 @@
1
+ <%= render(LesliView::Widgets::Weather.new) %>
@@ -0,0 +1,10 @@
1
+ <%= form_with(model: @invite, builder: LesliView::Forms::Builder) do |form| %>
2
+ <%= form.fieldset do %>
3
+ <%= form.field_control_email(:email) %>
4
+ <%= form.field_control(:full_name) %>
5
+ <%= form.field_control(:telephone) %>
6
+ <%= form.field_control_textarea(:notes) %>
7
+ <hr/>
8
+ <%= form.field_control_submit %>
9
+ <% end %>
10
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <div id="<%= dom_id invite %>">
2
+ </div>
@@ -0,0 +1,12 @@
1
+ <% content_for :title, "Editing invite" %>
2
+
3
+ <h1>Editing invite</h1>
4
+
5
+ <%= render "form", invite: @invite %>
6
+
7
+ <br>
8
+
9
+ <div>
10
+ <%= link_to "Show this invite", @invite %> |
11
+ <%= link_to "Back to invites", invites_path %>
12
+ </div>
@@ -0,0 +1,66 @@
1
+ <%#
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2023, 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 https://www.lesli.tech
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
+ %>
32
+ <%
33
+ columns = [{
34
+ field: "id",
35
+ label: "ID",
36
+ sort: true
37
+ }, {
38
+ field: "full_name",
39
+ label: "Name",
40
+ sort: true
41
+ }, {
42
+ field: "email",
43
+ label: "Email",
44
+ sort: true
45
+ }, {
46
+ field: "telephone",
47
+ label: "Telephone",
48
+ sort: true
49
+ }, {
50
+ field: "status",
51
+ label: "status",
52
+ sort: true
53
+ }]
54
+ %>
55
+ <%= render LesliView::Layout::Container.new('shield-invites') do %>
56
+ <%= render LesliView::Components::Header.new('Invites') do %>
57
+ <%= render(LesliView::Elements::Button.new('Create invitation', url: new_invite_path, icon: "add", solid:true)) %>
58
+ <%= render(LesliView::Elements::Button.new(icon: 'refresh')) %>
59
+ <% end %>
60
+ <%= render LesliView::Components::Toolbar.new() %>
61
+ <%= render(LesliView::Elements::Table.new(
62
+ columns: columns,
63
+ records: @invites[:records],
64
+ link: lambda {|invite| invite_path(invite.id) }
65
+ )) %>
66
+ <% end %>
@@ -1,4 +1,4 @@
1
- =begin
1
+ <%#
2
2
 
3
3
  Lesli
4
4
 
@@ -17,7 +17,7 @@ GNU General Public License for more details.
17
17
  You should have received a copy of the GNU General Public License
18
18
  along with this program. If not, see http://www.gnu.org/licenses/.
19
19
 
20
- Lesli · Ruby on Rails Development Platform.
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
21
 
22
22
  Made with ♥ by https://www.lesli.tech
23
23
  Building a better future, one line of code at a time.
@@ -27,11 +27,10 @@ Building a better future, one line of code at a time.
27
27
  @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
28
 
29
29
  // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
- // ·
31
- =end
32
-
33
- class CreateLesliShieldSettings < ActiveRecord::Migration[6.0]
34
- def change
35
- create_table_lesli_shared_settings_10(:lesli_shield)
36
- end
37
- end
30
+ // ·
31
+ %>
32
+
33
+ <%= render LesliView::Layout::Container.new('shield-invites') do %>
34
+ <%= render LesliView::Components::Header.new('Invites')%>
35
+ <%= render "form" %>
36
+ <% end %>
@@ -1,5 +1,5 @@
1
- <script setup>
2
- /*
1
+ <%#
2
+
3
3
  Lesli
4
4
 
5
5
  Copyright (c) 2023, Lesli Technologies, S. A.
@@ -28,44 +28,27 @@ Building a better future, one line of code at a time.
28
28
 
29
29
  // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
30
  // ·
31
- */
32
-
33
-
34
- // ·
35
- import { onMounted, inject, ref } from "vue"
36
-
37
-
38
- // ·
39
- const url = inject("url")
40
- const http = inject("http")
41
-
42
-
43
- // ·
44
- const lesliVersion = ref({
45
- name: "",
46
- code: "",
47
- path: "",
48
- version: "",
49
- build: ""
50
- })
51
-
52
-
53
- // ·
54
- onMounted(() => {
55
- http.get(url.lesli("about")).then(result => {
56
- lesliVersion.value = result.find(engine => engine.name == "Lesli")
57
- }).catch(error => {
58
- console.log(error)
59
- })
60
- })
61
- </script>
62
- <template>
63
- <lesli-card>
64
- <h6 class="title is-6 mb-2">
65
- {{ lesliVersion.name }}
66
- </h6>
67
- <p class="p-0 m-0">version: {{ lesliVersion.version }}</p>
68
- <p class="p-0 m-0">buid: {{ lesliVersion.build }}</p>
69
- <p class="p-0 m-0">path: {{ lesliVersion.path }}</p>
70
- </lesli-card>
71
- </template>
31
+ %>
32
+ <%= render LesliView::Layout::Container.new('shield-invites') do %>
33
+ <%= render LesliView::Components::Header.new("Invite for #{ @invite.full_name.presence || @invite.email }") do %>
34
+ <%= render(LesliView::Elements::Button.new(
35
+ 'Send invitation',
36
+ success:true,
37
+ solid:true,
38
+ icon:'send',
39
+ url: invite_path(@invite),
40
+ method: :put,
41
+ params: { invite: { status: :sent } }
42
+ )) %>
43
+ <%= render(LesliView::Elements::Button.new(
44
+ 'Cancel invitation',
45
+ danger:true,
46
+ solid:true,
47
+ icon:'cancel',
48
+ url: invite_path(@invite),
49
+ method: :put,
50
+ params: { invite: { status: :cancelled } }
51
+ )) %>
52
+ <% end %>
53
+ <%= render "form" %>
54
+ <% end %>