lato 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97957e5c077e1eb2c5fc2f543ccd910e3c9e20c31a032f1caddf6d8f367f65d5
4
- data.tar.gz: ff14d933bc169b717bc6383b384f5b88454d5d74149b3c2c8d35843f0d9e2c3b
3
+ metadata.gz: a06ea7d40cf529ec24e928cb3ad0ae2b897e4db4af3287526f8f3889e122e79f
4
+ data.tar.gz: 9fb8d0fd297e86acd19e70f9e26a41b1a4d032fec68895920d972e968147cc08
5
5
  SHA512:
6
- metadata.gz: 3f07d0df90a8c54f90eb3f8a12410a4d226710eaaaca16a63a0a9329dee6fb09e13e2abf8258555a4f45abeffc914328f5aec8c70aacb7778e70b34cd2f8e43d
7
- data.tar.gz: bcc45846cac8cf85cbe29cb2ffc5f7b90602148ab3a25f805d9d9f3414a2d6b6cce94167f57509d5e146d6df2887f7462e76bf3a0cbdcd75c71e837286e9814c
6
+ metadata.gz: 5ff61a9b5da01fc2f86e083a524ec9fa2f8d823632efd9a2d965a332130be08167940dbb8897661515d0416c2c9ed15a2392028d6ca6126e5dd978a3dc173f78
7
+ data.tar.gz: 6bc388648360531a63712342f708e25506b67313ef15a52b96b18405f9c7d076c552a305a6b8816a16fb93842343e0593a6b26efafb0bf8a1c1be8a21d8b5e2d
data/README.md CHANGED
@@ -9,15 +9,11 @@ Add required dependencies to your application's Gemfile:
9
9
  gem "importmap-rails" # NOTE: Probably already installed in default rails 7 project
10
10
 
11
11
  # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
12
- gem "turbo-rails"
12
+ gem "turbo-rails" # NOTE: Probably already installed in default rails 7 project
13
13
 
14
14
  # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
15
15
  gem "stimulus-rails" # NOTE: Probably already installed in default rails 7 project
16
16
 
17
- # Use Kredis as Redis interface [https://github.com/rails/kredis]
18
- # NOTE: Installation -> https://github.com/rails/kredis#installation
19
- gem "kredis"
20
-
21
17
  # Use Sass to process CSS
22
18
  gem "sassc-rails"
23
19
 
@@ -73,9 +69,19 @@ end
73
69
 
74
70
  ```
75
71
 
76
- ## Development
72
+ ### Extra tasks
73
+ Lato integrates by default a basic PWAs manifest and service worker. To re-generate them with all required assets follow these steps:
77
74
 
78
- Be sure to have Redis locally installed and running.
75
+ 1. Complete the configuration of lato on a custom initializer (see [configuration](https://github.com/lato-gam/lato/blob/main/lib/lato/config.rb) options for more details)
76
+ 2. Add an icon.png file on **public/icon.png** with minimum size of 512x512px
77
+ 3. Run the following commands:
78
+
79
+ ```bash
80
+ $ rails lato:generate:favicon
81
+ $ rails lato:generate:pwa
82
+ ```
83
+
84
+ ## Development
79
85
 
80
86
  Clone repository, install dependencies, run migrations and start:
81
87
 
@@ -5,6 +5,20 @@ import "bootstrap"
5
5
  // Import controllers (stimulus rails)
6
6
  import "controllers"
7
7
 
8
+ /**
9
+ * Include service worker
10
+ */
11
+
12
+ if (navigator.serviceWorker) {
13
+ navigator.serviceWorker.register("/service-worker.js", { scope: "/" })
14
+ .then(() => navigator.serviceWorker.ready)
15
+ .then((registration) => {
16
+ const event = new CustomEvent("service-worker:ready", { detail: registration })
17
+ document.dispatchEvent(event)
18
+ })
19
+ .then(() => console.log("[App]", "Service worker registered! -> listen to 'service-worker:ready' document event to get the registration object"))
20
+ }
21
+
8
22
  /**
9
23
  * Fix form inside turbo-frame tag with redirect
10
24
  * https://github.com/hotwired/turbo-rails/issues/440
@@ -22,15 +36,11 @@ document.addEventListener("turbo:frame-missing", event => {
22
36
  const PAGE_TRANSITION_TIME = 50
23
37
 
24
38
  document.addEventListener('DOMContentLoaded', () => {
25
- console.log('DOMContentLoaded')
26
-
27
39
  // add is-loaded class
28
40
  document.body.classList.add('is-loaded')
29
41
  })
30
42
 
31
43
  document.addEventListener('turbo:load', () => {
32
- console.log('turbo:load')
33
-
34
44
  setTimeout(() => {
35
45
  // add is-loaded class
36
46
  document.body.classList.add('is-loaded')
@@ -2,11 +2,6 @@ module Lato
2
2
  class Invitation < ApplicationRecord
3
3
  attr_accessor :actions
4
4
 
5
- # Kredis
6
- ##
7
-
8
- kredis_boolean :email_invite_semaphore, expires_in: 2.minutes
9
-
10
5
  # Validations
11
6
  ##
12
7
 
@@ -64,7 +59,7 @@ module Lato
64
59
  return false
65
60
  end
66
61
 
67
- if email_invite_semaphore.value
62
+ if c_email_invite_semaphore
68
63
  errors.add(:base, :email_sending_limit)
69
64
  return false
70
65
  end
@@ -75,9 +70,21 @@ module Lato
75
70
  return false
76
71
  end
77
72
 
78
- email_invite_semaphore.value = true
73
+ c_email_invite_semaphore(true)
79
74
 
80
75
  true
81
76
  end
77
+
78
+
79
+ # Cache
80
+ ##
81
+
82
+ def c_email_invite_semaphore(value = nil)
83
+ cache_key = "Lato::Invitation/c_email_invite_semaphore/#{id}"
84
+ return Rails.cache.read(cache_key) if value.nil?
85
+
86
+ Rails.cache.write(cache_key, value, expires_in: 2.minutes)
87
+ value
88
+ end
82
89
  end
83
90
  end
@@ -4,13 +4,6 @@ module Lato
4
4
 
5
5
  has_secure_password
6
6
 
7
- # Kredis
8
- ##
9
-
10
- kredis_boolean :email_verification_semaphore, expires_in: 2.minutes
11
- kredis_string :email_verification_code, expires_in: 30.minutes
12
- kredis_string :password_update_code, expires_in: 30.minutes
13
-
14
7
  # Validations
15
8
  ##
16
9
 
@@ -113,7 +106,7 @@ module Lato
113
106
  end
114
107
 
115
108
  def request_verify_email
116
- if email_verification_semaphore.value
109
+ if c_email_verification_semaphore
117
110
  errors.add(:base, :email_verification_limit)
118
111
  return
119
112
  end
@@ -125,25 +118,27 @@ module Lato
125
118
  return
126
119
  end
127
120
 
128
- email_verification_code.value = code
129
- email_verification_semaphore.value = true
121
+ c_email_verification_code(code)
122
+ c_email_verification_semaphore(true)
130
123
 
131
124
  true
132
125
  end
133
126
 
134
127
  def verify_email(params)
135
- unless email_verification_code.value
128
+ email_verification_code = c_email_verification_code
129
+
130
+ if email_verification_code.blank?
136
131
  errors.add(:base, :email_verification_code_expired)
137
132
  return
138
133
  end
139
134
 
140
- unless email_verification_code.value == params[:code]
135
+ unless email_verification_code == params[:code]
141
136
  errors.add(:base, :email_verification_code_invalid)
142
137
  return
143
138
  end
144
139
 
145
- email_verification_code.value = nil
146
- email_verification_semaphore.value = nil
140
+ c_email_verification_code('')
141
+ c_email_verification_semaphore(false)
147
142
 
148
143
  update_column(:email_verified_at, Time.now)
149
144
  true
@@ -166,23 +161,25 @@ module Lato
166
161
  self.id = user.id
167
162
  reload
168
163
 
169
- password_update_code.value = code
164
+ c_password_update_code(code)
170
165
 
171
166
  true
172
167
  end
173
168
 
174
169
  def update_password(params)
175
- unless password_update_code.value
170
+ password_update_code = c_password_update_code
171
+
172
+ if password_update_code.blank?
176
173
  errors.add(:base, :password_update_code_expired)
177
174
  return
178
175
  end
179
176
 
180
- unless password_update_code.value == params[:code]
177
+ unless password_update_code == params[:code]
181
178
  errors.add(:base, :password_update_code_invalid)
182
179
  return
183
180
  end
184
181
 
185
- password_update_code.value = nil
182
+ c_password_update_code('')
186
183
 
187
184
  update(params.permit(:password, :password_confirmation))
188
185
  end
@@ -230,5 +227,32 @@ module Lato
230
227
  true
231
228
  end
232
229
  end
230
+
231
+ # Cache
232
+ ##
233
+
234
+ def c_email_verification_semaphore(value = nil)
235
+ cache_key = "Lato::User/c_email_verification_semaphore/#{id}"
236
+ return Rails.cache.read(cache_key) if value.nil?
237
+
238
+ Rails.cache.write(cache_key, value, expires_in: 2.minutes)
239
+ value
240
+ end
241
+
242
+ def c_email_verification_code(value = nil)
243
+ cache_key = "Lato::User/c_email_verification_code/#{id}"
244
+ return Rails.cache.read(cache_key) if value.nil?
245
+
246
+ Rails.cache.write(cache_key, value, expires_in: 30.minutes)
247
+ value
248
+ end
249
+
250
+ def c_password_update_code(value = nil)
251
+ cache_key = "Lato::User/c_password_update_code/#{id}"
252
+ return Rails.cache.read(cache_key) if value.nil?
253
+
254
+ Rails.cache.write(cache_key, value, expires_in: 30.minutes)
255
+ value
256
+ end
233
257
  end
234
258
  end
@@ -1 +1,13 @@
1
+ <meta name="application-name" content="<%= Lato.config.application_title %>">
2
+ <meta name="theme-color" content="<%= Lato.config.application_brand_color %>">
3
+ <meta name="full-screen" content="yes">
4
+ <meta name="browsermode" content="application">
5
+ <meta name="screen-orientation" content="portrait">
6
+ <meta name="apple-mobile-web-app-capable" content="yes">
7
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
8
+ <meta name="apple-mobile-web-app-title" content="<%= Lato.config.application_title %>">
9
+
10
+ <link rel="icon" href="/favicon.ico">
11
+ <link rel="manifest" href="/manifest.json">
12
+
1
13
  <!-- Free for head tags -->
data/lib/lato/config.rb CHANGED
@@ -4,7 +4,7 @@ module Lato
4
4
  ##
5
5
  class Config
6
6
  # Applicaction configs
7
- attr_accessor :application_title, :application_version, :application_company_name, :application_company_url
7
+ attr_accessor :application_title, :application_version, :application_company_name, :application_company_url, :application_brand_color
8
8
 
9
9
  # Session configs
10
10
  attr_accessor :session_lifetime, :session_root_path
@@ -26,6 +26,7 @@ module Lato
26
26
  @application_version = '1.0.0'
27
27
  @application_company_name = 'Lato Team'
28
28
  @application_company_url = 'https://github.com/Lato-GAM'
29
+ @application_brand_color = '#03256c'
29
30
 
30
31
  @auth_disable_signup = false
31
32
  @auth_disable_recover_password = false
data/lib/lato/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lato
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require 'json'
2
3
 
3
4
  namespace :lato do
4
5
  namespace :install do
@@ -33,6 +34,145 @@ namespace :lato do
33
34
  gem_concern_path = Lato::Engine.root.join('app', 'models', 'concerns', 'lato_user_application.rb').to_s
34
35
  app_concern_path = Rails.root.join('app', 'models', 'concerns', 'lato_user_application.rb').to_s
35
36
  FileUtils.copy(gem_concern_path, app_concern_path) unless File.exist? app_concern_path
37
+
38
+ # Generate sample manifest.json file in public folder
39
+ ##
40
+
41
+ manifest_path = Rails.root.join('public', 'manifest.json')
42
+ unless File.exist? manifest_path
43
+ manifest = {
44
+ name: "Application",
45
+ short_name: "Application",
46
+ start_url: "/",
47
+ scope: "/",
48
+ display: "standalone",
49
+ orientation: "portrait",
50
+ theme_color: "#000000",
51
+ background_color: "#000000",
52
+ icons: []
53
+ }
54
+ File.open(manifest_path, 'w') { |f| f.write(JSON.pretty_generate(manifest)) }
55
+ end
56
+
57
+ # Generate sample service-worker.js file in public folder
58
+ ##
59
+
60
+ service_worker_path = Rails.root.join('public', 'service-worker.js')
61
+ unless File.exist? service_worker_path
62
+ service_worker = <<-JS
63
+ function onInstall(event) {
64
+ console.log('[Serviceworker]', "Installing!", event);
65
+ }
66
+ function onActivate(event) {
67
+ console.log('[Serviceworker]', "Activating!", event);
68
+ }
69
+ function onFetch(event) {
70
+ console.log('[Serviceworker]', "Fetching!", event);
71
+ }
72
+ self.addEventListener('install', onInstall);
73
+ self.addEventListener('activate', onActivate);
74
+ self.addEventListener('fetch', onFetch);
75
+ JS
76
+ File.open(service_worker_path, 'w') { |f| f.write(service_worker) }
77
+ end
78
+ end
79
+ end
80
+
81
+ namespace :generate do
82
+ desc "Generate PWA icons from a single icon.png file (512x512) that should be placed inside 'public' folder"
83
+ # Usage: rails lato:generate:pwa
84
+ task :pwa do
85
+ # check if icon.png exists
86
+ icon_path = Rails.root.join('public', 'icon.png')
87
+ unless File.exist? icon_path
88
+ puts 'ERROR: icon.png file not found inside public folder'
89
+ return
90
+ end
91
+
92
+ # check MiniMagick is installed
93
+ begin
94
+ require 'mini_magick'
95
+ rescue LoadError
96
+ puts 'ERROR: mini_magick gem not found, please add it to your Gemfile'
97
+ return
98
+ end
99
+
100
+ # be sure icon.png is min 512x512
101
+ image = MiniMagick::Image.open(icon_path)
102
+ if image.width < 512 || image.height < 512 || image.width != image.height
103
+ puts 'ERROR: icon.png image size is not valid, it should be square and min 512x512'
104
+ return
105
+ end
106
+
107
+ # create icons folder if not exists
108
+ icons_path = Rails.root.join('public', 'icons')
109
+ FileUtils.mkdir_p(icons_path) unless File.exist? icons_path
110
+
111
+ # create icons
112
+ sizes = [16, 32, 48, 72, 96, 144, 152, 192, 384, 512]
113
+ sizes.each do |size|
114
+ file_path = "#{icons_path}/icon_#{size}x#{size}.png"
115
+ file_image = MiniMagick::Image.open(icon_path)
116
+ FileUtils.rm(file_path) if File.exist? file_path
117
+ file_image.resize "#{size}x#{size}"
118
+ file_image.write file_path
119
+ end
120
+
121
+ # create manifest.json
122
+ manifest_path = Rails.root.join('public', 'manifest.json')
123
+ manifest = {
124
+ name: Lato.config.application_title,
125
+ short_name: Lato.config.application_title,
126
+ start_url: '/',
127
+ scope: '/',
128
+ display: 'standalone',
129
+ orientation: 'portrait',
130
+ theme_color: Lato.config.application_brand_color,
131
+ background_color: Lato.config.application_brand_color,
132
+ icons: []
133
+ }
134
+ sizes.each do |size|
135
+ manifest[:icons] << {
136
+ src: "/icons/icon_#{size}x#{size}.png",
137
+ sizes: "#{size}x#{size}",
138
+ type: 'image/png'
139
+ }
140
+ end
141
+ FileUtils.rm(manifest_path) if File.exist? manifest_path
142
+ File.open(manifest_path, 'w') { |f| f.write(JSON.pretty_generate(manifest)) }
143
+ end
144
+
145
+ desc "Generate favicon.ico from a single icon.png file (512x512) that should be placed inside 'public' folder"
146
+ # Usage: rails lato:generate:favicon
147
+ task :favicon do
148
+ # check if icon.png exists
149
+ icon_path = Rails.root.join('public', 'icon.png')
150
+ unless File.exist? icon_path
151
+ puts 'ERROR: icon.png file not found inside public folder'
152
+ return
153
+ end
154
+
155
+ # check MiniMagick is installed
156
+ begin
157
+ require 'mini_magick'
158
+ rescue LoadError
159
+ puts 'ERROR: mini_magick gem not found, please add it to your Gemfile'
160
+ return
161
+ end
162
+
163
+ # be sure icon.png is min 512x512
164
+ image = MiniMagick::Image.open(icon_path)
165
+ if image.width < 512 || image.height < 512 || image.width != image.height
166
+ puts 'ERROR: icon.png image size is not valid, it should be square and min 512x512'
167
+ return
168
+ end
169
+
170
+ # create favicon.ico
171
+ file_path = Rails.root.join('public', 'favicon.ico')
172
+ file_image = MiniMagick::Image.open(icon_path)
173
+ FileUtils.rm(file_path) if File.exist? file_path
174
+ file_image.resize '48x48'
175
+ file_image.write file_path
36
176
  end
37
177
  end
38
178
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lato
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregorio Galante
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-15 00:00:00.000000000 Z
11
+ date: 2023-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails