lesli_guard 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +38 -0
  3. data/app/assets/config/lesli_guard_manifest.js +38 -0
  4. data/app/assets/images/lesli_guard/guard-logo.svg +160 -0
  5. data/app/assets/javascripts/lesli_guard/application.js +4787 -0
  6. data/app/assets/stylesheets/lesli_guard/application.scss +33 -0
  7. data/app/assets/stylesheets/lesli_guard/dashboards.scss +32 -0
  8. data/app/assets/stylesheets/lesli_guard/descriptors.scss +32 -0
  9. data/app/assets/stylesheets/lesli_guard/roles.scss +32 -0
  10. data/app/assets/stylesheets/lesli_guard/system_controller.scss +32 -0
  11. data/app/assets/stylesheets/lesli_guard/users.scss +67 -0
  12. data/app/controllers/lesli_guard/accounts_controller.rb +60 -0
  13. data/app/controllers/lesli_guard/application_controller.rb +37 -0
  14. data/app/controllers/lesli_guard/dashboard/components_controller.rb +60 -0
  15. data/app/controllers/lesli_guard/dashboards_controller.rb +36 -0
  16. data/app/controllers/lesli_guard/descriptor/activities_controller.rb +122 -0
  17. data/app/controllers/lesli_guard/descriptor/privileges_controller.rb +112 -0
  18. data/app/controllers/lesli_guard/descriptors_controller.rb +129 -0
  19. data/app/controllers/lesli_guard/role/activities_controller.rb +76 -0
  20. data/app/controllers/lesli_guard/role/descriptors_controller.rb +97 -0
  21. data/app/controllers/lesli_guard/role/privileges_controller.rb +47 -0
  22. data/app/controllers/lesli_guard/roles_controller.rb +185 -0
  23. data/app/controllers/lesli_guard/user/roles_controller.rb +98 -0
  24. data/app/controllers/lesli_guard/user/sessions_controller.rb +71 -0
  25. data/app/controllers/lesli_guard/users_controller.rb +206 -0
  26. data/app/helpers/lesli_guard/accounts_helper.rb +4 -0
  27. data/app/helpers/lesli_guard/application_helper.rb +4 -0
  28. data/app/helpers/lesli_guard/dashboards_helper.rb +4 -0
  29. data/app/helpers/lesli_guard/descriptor/activities_helper.rb +4 -0
  30. data/app/helpers/lesli_guard/descriptor/privileges_helper.rb +4 -0
  31. data/app/helpers/lesli_guard/descriptors_helper.rb +4 -0
  32. data/app/helpers/lesli_guard/role/activities_helper.rb +4 -0
  33. data/app/helpers/lesli_guard/role/descriptors_helper.rb +4 -0
  34. data/app/helpers/lesli_guard/role/privileges_helper.rb +4 -0
  35. data/app/helpers/lesli_guard/roles_helper.rb +4 -0
  36. data/app/jobs/lesli_guard/application_job.rb +37 -0
  37. data/app/mailers/lesli_guard/application_mailer.rb +39 -0
  38. data/app/models/lesli_guard/account.rb +43 -0
  39. data/app/models/lesli_guard/application_record.rb +37 -0
  40. data/app/models/lesli_guard/dashboard/component.rb +42 -0
  41. data/app/models/lesli_guard/dashboard.rb +58 -0
  42. data/app/models/lesli_guard/descriptor/activity.rb +40 -0
  43. data/app/models/lesli_guard/descriptor/privilege.rb +40 -0
  44. data/app/models/lesli_guard/descriptor.rb +41 -0
  45. data/app/models/lesli_guard/role/activity.rb +40 -0
  46. data/app/services/lesli_guard/descriptor_privilege_service.rb +74 -0
  47. data/app/services/lesli_guard/descriptor_service.rb +152 -0
  48. data/app/services/lesli_guard/role_descriptor_service.rb +61 -0
  49. data/app/services/lesli_guard/role_service.rb +215 -0
  50. data/app/services/lesli_guard/user_service.rb +305 -0
  51. data/app/views/lesli_guard/accounts/_account.html.erb +2 -0
  52. data/app/views/lesli_guard/accounts/_form.html.erb +17 -0
  53. data/app/views/lesli_guard/accounts/edit.html.erb +10 -0
  54. data/app/views/lesli_guard/accounts/index.html.erb +14 -0
  55. data/app/views/lesli_guard/accounts/new.html.erb +9 -0
  56. data/app/views/lesli_guard/accounts/show.html.erb +10 -0
  57. data/app/views/lesli_guard/dashboards/show.html.erb +1 -0
  58. data/app/views/lesli_guard/descriptor/activities/_form.html.erb +32 -0
  59. data/app/views/lesli_guard/descriptor/activities/edit.html.erb +34 -0
  60. data/app/views/lesli_guard/descriptor/activities/index.html.erb +34 -0
  61. data/app/views/lesli_guard/descriptor/activities/new.html.erb +34 -0
  62. data/app/views/lesli_guard/descriptor/activities/show.html.erb +34 -0
  63. data/app/views/lesli_guard/descriptor/privileges/_form.html.erb +32 -0
  64. data/app/views/lesli_guard/descriptor/privileges/edit.html.erb +34 -0
  65. data/app/views/lesli_guard/descriptor/privileges/index.html.erb +34 -0
  66. data/app/views/lesli_guard/descriptor/privileges/new.html.erb +34 -0
  67. data/app/views/lesli_guard/descriptor/privileges/show.html.erb +34 -0
  68. data/app/views/lesli_guard/descriptors/_form.html.erb +32 -0
  69. data/app/views/lesli_guard/descriptors/edit.html.erb +34 -0
  70. data/app/views/lesli_guard/descriptors/index.html.erb +34 -0
  71. data/app/views/lesli_guard/descriptors/new.html.erb +34 -0
  72. data/app/views/lesli_guard/descriptors/show.html.erb +34 -0
  73. data/app/views/lesli_guard/partials/_engine-navigation.html.erb +38 -0
  74. data/app/views/lesli_guard/role/activities/_form.html.erb +32 -0
  75. data/app/views/lesli_guard/role/activities/edit.html.erb +34 -0
  76. data/app/views/lesli_guard/role/activities/index.html.erb +34 -0
  77. data/app/views/lesli_guard/role/activities/new.html.erb +34 -0
  78. data/app/views/lesli_guard/role/activities/show.html.erb +34 -0
  79. data/app/views/lesli_guard/role/descriptors/_form.html.erb +32 -0
  80. data/app/views/lesli_guard/role/descriptors/edit.html.erb +34 -0
  81. data/app/views/lesli_guard/role/descriptors/index.html.erb +34 -0
  82. data/app/views/lesli_guard/role/descriptors/new.html.erb +34 -0
  83. data/app/views/lesli_guard/role/descriptors/show.html.erb +34 -0
  84. data/app/views/lesli_guard/role/privileges/_form.html.erb +32 -0
  85. data/app/views/lesli_guard/role/privileges/edit.html.erb +34 -0
  86. data/app/views/lesli_guard/role/privileges/index.html.erb +34 -0
  87. data/app/views/lesli_guard/role/privileges/new.html.erb +34 -0
  88. data/app/views/lesli_guard/role/privileges/show.html.erb +34 -0
  89. data/app/views/lesli_guard/roles/edit.html.erb +34 -0
  90. data/app/views/lesli_guard/roles/index.html.erb +34 -0
  91. data/app/views/lesli_guard/roles/new.html.erb +34 -0
  92. data/app/views/lesli_guard/roles/show.html.erb +34 -0
  93. data/app/views/lesli_guard/users/edit.html.erb +10 -0
  94. data/app/views/lesli_guard/users/index.html.erb +34 -0
  95. data/app/views/lesli_guard/users/new.html.erb +34 -0
  96. data/app/views/lesli_guard/users/show.html.erb +1 -0
  97. data/config/locales/translations.en.yml +43 -0
  98. data/config/locales/translations.es.yml +43 -0
  99. data/config/routes.rb +90 -0
  100. data/db/migrate/v1/0801000110_create_lesli_guard_accounts.rb +42 -0
  101. data/db/migrate/v1/0801050110_create_lesli_guard_dashboards.rb +51 -0
  102. data/db/migrate/v1/0801050210_create_lesli_guard_dashboard_components.rb +53 -0
  103. data/lib/lesli_guard/engine.rb +18 -0
  104. data/lib/lesli_guard/version.rb +4 -0
  105. data/lib/lesli_guard.rb +6 -0
  106. data/lib/tasks/lesli_guard_tasks.rake +50 -0
  107. data/lib/vue/application.js +112 -0
  108. data/lib/vue/apps/descriptors/components/form.vue +136 -0
  109. data/lib/vue/apps/descriptors/edit.vue +83 -0
  110. data/lib/vue/apps/descriptors/index.vue +113 -0
  111. data/lib/vue/apps/descriptors/new.vue +69 -0
  112. data/lib/vue/apps/descriptors/show.vue +233 -0
  113. data/lib/vue/apps/roles/components/descriptors.vue +81 -0
  114. data/lib/vue/apps/roles/components/form.vue +253 -0
  115. data/lib/vue/apps/roles/components/privilegeCustom.vue +86 -0
  116. data/lib/vue/apps/roles/components/privilegeStandard.vue +196 -0
  117. data/lib/vue/apps/roles/edit.vue +118 -0
  118. data/lib/vue/apps/roles/index.vue +168 -0
  119. data/lib/vue/apps/roles/logs.vue +110 -0
  120. data/lib/vue/apps/roles/new.vue +86 -0
  121. data/lib/vue/apps/roles/show.vue +109 -0
  122. data/lib/vue/apps/users/components/information-card.vue +107 -0
  123. data/lib/vue/apps/users/components/information-form.vue +176 -0
  124. data/lib/vue/apps/users/components/integrations-information.vue +61 -0
  125. data/lib/vue/apps/users/components/management-roles.vue +107 -0
  126. data/lib/vue/apps/users/components/management-security.vue +113 -0
  127. data/lib/vue/apps/users/components/management-sessions.vue +101 -0
  128. data/lib/vue/apps/users/components/management-settings.vue +93 -0
  129. data/lib/vue/apps/users/index.vue +207 -0
  130. data/lib/vue/apps/users/new.vue +181 -0
  131. data/lib/vue/apps/users/show.vue +131 -0
  132. data/lib/vue/stores/descriptor.js +117 -0
  133. data/lib/vue/stores/descriptors.js +156 -0
  134. data/lib/vue/stores/role.js +203 -0
  135. data/lib/vue/stores/roles.js +58 -0
  136. data/lib/vue/stores/translations.json +98 -0
  137. data/lib/vue/stores/user.js +331 -0
  138. data/lib/vue/stores/users.js +176 -0
  139. data/license +674 -0
  140. data/readme.md +76 -0
  141. metadata +199 -0
@@ -0,0 +1,305 @@
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 LesliGuard
34
+ class UserService < Lesli::ApplicationLesliService
35
+
36
+ def find id
37
+ #super(current_user.account.users.joins(:detail).find_by(id: id))
38
+ super(current_user.account.users.find_by(id: id))
39
+ end
40
+
41
+ # @return [Array] Paginated index of users.
42
+ # @description Return a paginated array of users, used mostly in frontend views
43
+ # TODO: Implement pg_search
44
+ def index params
45
+
46
+ # sql string to join to user_roles and get all the roles assigned to a user
47
+ sql_string_for_user_roles = "left join (
48
+ select
49
+ ur.user_id, string_agg(r.\"name\", ', ') rolenames
50
+ from lesli_user_powers ur
51
+ join lesli_roles r
52
+ on r.id = ur.role_id
53
+ where ur.deleted_at is null
54
+ group by ur.user_id
55
+ ) roles on roles.user_id = lesli_users.id"
56
+
57
+ # sql string to joing to user_sessions and get all the active sessions of a user
58
+ sql_string_for_user_sessions = "left join (
59
+ select
60
+ max(last_used_at) as last_action_performed_at,
61
+ user_id
62
+ from lesli_user_sessions us
63
+ where us.deleted_at is null
64
+ group by(us.user_id)
65
+ ) sessions on sessions.user_id = lesli_users.id"
66
+
67
+ users = current_user.account.users
68
+ .joins(sql_string_for_user_roles)
69
+ #.joins(sql_string_for_user_sessions)
70
+ users = users.page(query[:pagination][:page])
71
+ .per(query[:pagination][:perPage])
72
+ .order("#{query[:order][:by]} #{query[:order][:dir]} NULLS LAST")
73
+
74
+ users.select(
75
+ :id,
76
+ "CONCAT(COALESCE(first_name, ''), ' ', COALESCE(last_name, '')) as name",
77
+ :email,
78
+ :active,
79
+ :rolenames,
80
+ Date2.new.date_time.db_column("current_sign_in_at")
81
+ )
82
+
83
+ end
84
+
85
+
86
+ # Creates a query that selects all user information from several tables if CloudLock is present
87
+ def show
88
+
89
+ user = resource
90
+
91
+ return {
92
+ id: user[:id],
93
+ email: user[:email],
94
+ alias: user[:alias],
95
+ active: user[:active],
96
+ full_name: user.full_name,
97
+ salutation: user[:salutation],
98
+ first_name: user[:first_name],
99
+ last_name: user[:last_name],
100
+ telephone: user[:telephone],
101
+ locale: user.locale, #settings.select(:value).find_by(:name => "locale"),
102
+ roles: user.roles.map { |r| { id: r[:id], name: r[:name], permission_level: r[:object_level_permission]} },
103
+
104
+ #mfa_enabled: user.mfa_settings[:enabled],
105
+ #mfa_method: user.mfa_settings[:method],
106
+
107
+ created_at: user[:created_at],
108
+ updated_at: user[:updated_at],
109
+ detail_attributes: {
110
+ title: user.detail[:title] || "",
111
+ address: user.detail[:address],
112
+ # work_city: user.detail[:work_city],
113
+ # work_region: user.detail[:work_region],
114
+ # work_address: user.detail[:work_address]
115
+ }
116
+ }
117
+ end
118
+
119
+ def create user_params
120
+
121
+ # check if request has an email to create the user
122
+ if user_params[:email].blank?
123
+ self.error(I18n.t("core.users.messages_danger_not_valid_email_found"))
124
+ end
125
+
126
+
127
+ # register the new user
128
+ user = User.new({
129
+ :active => true,
130
+ :email => user_params[:email],
131
+ :alias => user_params[:alias] || "",
132
+ :first_name => user_params[:first_name] || "",
133
+ :last_name => user_params[:last_name] || "",
134
+ :telephone => user_params[:telephone] || "",
135
+ #:detail_attributes => user_params[:detail_attributes] || {}
136
+ })
137
+
138
+
139
+
140
+ # assign a random password
141
+ user.password = Devise.friendly_token
142
+
143
+ # enrol user to my own account
144
+ user.account = current_user.account
145
+
146
+ # users created through the administration area does not need to confirm their accounts
147
+ # instead we send a password reset link, so they can have access to the platform
148
+ #user.confirm
149
+
150
+ if user.save
151
+
152
+ # if a role is provided to assign to the new user
153
+ # unless user_params[:roles_id].blank?
154
+ # # check if current user can work with the sent role
155
+ # if current_user.can_work_with_role?(user_params[:roles_id])
156
+ # # Search the role assigned
157
+ # role = current_user.account.roles.find_by(id: user_params[:roles_id])
158
+ # # assign role to the new user
159
+ # user.user_roles.create({ role: role })
160
+ # end
161
+ # end
162
+
163
+ # role validation - if new user does not have any role assigned
164
+ # if user.roles.blank?
165
+
166
+ # default_role_id = current_user.account.settings.find_by(:name => "default_role_id")&.value
167
+ # owner_role_id = current_user.account.roles.find_by(:name => "owner").id
168
+ # if default_role_id.present? && default_role_id != owner_role_id
169
+ # # assign default role
170
+ # user.user_roles.create({ role: current_user.account.roles.find_by(:id => default_role_id)})
171
+
172
+ # else
173
+ # # assign limited role
174
+ # user.user_roles.create({ role: current_user.account.roles.find_by(:name => "limited") })
175
+ # end
176
+ # end
177
+
178
+ # saving logs with information about the creation of the user
179
+ # user.logs.create({ title: "user_created_at", description: Date2.new.date_time.to_s })
180
+ # user.logs.create({ title: "user_created_by", description: current_user.email })
181
+ # user.logs.create({ title: "user_created_with_role", description: user.user_roles.first.role.name + " " + user.user_roles.first.role.id.to_s})
182
+ # User.log_activity_create(current_user, user)
183
+
184
+ self.resource = user
185
+
186
+ begin
187
+ # users created through the administration area does not need to confirm their accounts
188
+ # instead we send a password reset link, so they can have access to the platform
189
+ #UserMailer.with(user: user).invitation_instructions.deliver_now
190
+ rescue => exception
191
+ #Honeybadger.notify(exception)
192
+ #user.logs.create({ title: "user_creation_email_failed ", description: exception.message })
193
+ end
194
+
195
+ else
196
+ self.error(user.errors.full_messages.to_sentence)
197
+ end
198
+
199
+ self
200
+
201
+ end
202
+
203
+ def update params
204
+
205
+ # old_attributes = resource.detail.attributes.merge({
206
+ # active: resource.active
207
+ # })
208
+
209
+ if resource.update(params)
210
+ # new_attributes = resource.detail.attributes.merge({
211
+ # active: resource.active
212
+ # })
213
+ #resource.log_activity_update(current_user, resource, old_attributes, new_attributes)
214
+ else
215
+ self.error(resource.errors.full_messages.to_sentence)
216
+ end
217
+
218
+ self
219
+ end
220
+
221
+
222
+ # force the user to change the password (at next login)
223
+ def request_password
224
+
225
+ # expire password
226
+ resource.set_password_as_expired
227
+
228
+ resource.logs.create({ title: "request_password", description: "by_user: " + current_user.email })
229
+ end
230
+
231
+
232
+ # generate a random password for the user
233
+ def password_reset
234
+
235
+ # generate random password
236
+ pass = resource.password_reset
237
+
238
+ resource.logs.create({ title: "password_reset", description: "by_user: " + current_user.email })
239
+
240
+ pass
241
+ end
242
+
243
+ def logout
244
+ # delete user active sessions
245
+ resource.sessions.destroy_all
246
+
247
+ resource.logs.create({ title: "close_sessions", description: "by_user: " + current_user.email })
248
+ end
249
+
250
+ def revoke_access
251
+
252
+ # delete user active sessions
253
+ self.logout
254
+
255
+ # add delete date to the last active session
256
+ resource.revoke_access
257
+
258
+ resource.logs.create({ title: "revoke_access", description: "by_user: " + current_user.email })
259
+ end
260
+
261
+ def sessions(current_session_id)
262
+ current_user.sessions
263
+ .joins(:user)
264
+ .where("expiration_at > ? or expiration_at is ?", Time.now.utc, nil)
265
+ .select(
266
+ :id,
267
+ :session_source,
268
+ Date2.new.date_time.db_column("created_at", "lesli_user_sessions"),
269
+ Date2.new.date_time.db_column("last_used_at"),
270
+ Date2.new.date_time.db_column("expiration_at"),
271
+ "CONCAT_WS(' ', agent_platform, agent_os, '/', agent_browser, agent_version) as device",
272
+ "case when #{current_session_id} = lesli_user_sessions.id then true else false end as current_session"
273
+ )
274
+ .page(query[:pagination][:page])
275
+ .per(query[:pagination][:perPage])
276
+ .order(updated_at: :desc)
277
+ end
278
+
279
+ def available_roles
280
+ roles = current_user.account.roles
281
+ .joins(%(
282
+ left join lesli_user_powers
283
+ on lesli_user_powers.role_id = lesli_roles.id
284
+ and lesli_user_powers.deleted_at is null
285
+ and lesli_user_powers.user_id = #{ resource.id }
286
+ ))
287
+ #.where("object_level_permission < ?", current_user.max_object_level_permission)
288
+ .order(object_level_permission: :desc)
289
+ .select(
290
+ "coalesce(lesli_roles.id, lesli_user_powers.role_id) as id",
291
+ "name",
292
+ "description",
293
+ "object_level_permission",
294
+ "case when lesli_user_powers.role_id is null then false else true end as active"
295
+ )
296
+
297
+ # only owner can assign any role
298
+ #unless self.has_roles?("owner")
299
+ # roles = roles.where("object_level_permission < ?", (self.roles.map{ |r| r[:object_level_permission] }).max)
300
+ #end
301
+
302
+ roles || []
303
+ end
304
+ end
305
+ end
@@ -0,0 +1,2 @@
1
+ <div id="<%= dom_id account %>">
2
+ </div>
@@ -0,0 +1,17 @@
1
+ <%= form_with(model: account) do |form| %>
2
+ <% if account.errors.any? %>
3
+ <div style="color: red">
4
+ <h2><%= pluralize(account.errors.count, "error") %> prohibited this account from being saved:</h2>
5
+
6
+ <ul>
7
+ <% account.errors.each do |error| %>
8
+ <li><%= error.full_message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div>
15
+ <%= form.submit %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <h1>Editing account</h1>
2
+
3
+ <%= render "form", account: @account %>
4
+
5
+ <br>
6
+
7
+ <div>
8
+ <%= link_to "Show this account", @account %> |
9
+ <%= link_to "Back to accounts", accounts_path %>
10
+ </div>
@@ -0,0 +1,14 @@
1
+ <p style="color: green"><%= notice %></p>
2
+
3
+ <h1>Accounts</h1>
4
+
5
+ <div id="accounts">
6
+ <% @accounts.each do |account| %>
7
+ <%= render account %>
8
+ <p>
9
+ <%= link_to "Show this account", account %>
10
+ </p>
11
+ <% end %>
12
+ </div>
13
+
14
+ <%= link_to "New account", new_account_path %>
@@ -0,0 +1,9 @@
1
+ <h1>New account</h1>
2
+
3
+ <%= render "form", account: @account %>
4
+
5
+ <br>
6
+
7
+ <div>
8
+ <%= link_to "Back to accounts", accounts_path %>
9
+ </div>
@@ -0,0 +1,10 @@
1
+ <p style="color: green"><%= notice %></p>
2
+
3
+ <%= render @account %>
4
+
5
+ <div>
6
+ <%= link_to "Edit this account", edit_account_path(@account) %> |
7
+ <%= link_to "Back to accounts", accounts_path %>
8
+
9
+ <%= button_to "Destroy this account", @account, method: :delete %>
10
+ </div>
@@ -0,0 +1 @@
1
+ <router-view></router-view>
@@ -0,0 +1,32 @@
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 platform.
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
+ %>
@@ -0,0 +1,34 @@
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 platform.
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
+
34
+ <router-view></router-view>
@@ -0,0 +1,34 @@
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 platform.
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
+
34
+ <router-view></router-view>
@@ -0,0 +1,34 @@
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 platform.
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
+
34
+ <router-view></router-view>
@@ -0,0 +1,34 @@
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 platform.
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
+
34
+ <router-view></router-view>
@@ -0,0 +1,32 @@
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 platform.
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
+ %>
@@ -0,0 +1,34 @@
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 platform.
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
+
34
+ <router-view></router-view>
@@ -0,0 +1,34 @@
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 platform.
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
+
34
+ <router-view></router-view>