lato 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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