tachiban 1.0.0 → 2.0.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: 2b2e100df48cb7de260705114b0c7d282bf2e67f8073442d987cb0295e985d48
4
- data.tar.gz: 810a6b68cef7fd9177ef3083b05b0cc083eaecbc26e02b0621194c7f8c582db3
3
+ metadata.gz: 4f726149a2c73b44a9eb4ead5ea276752babfe6e627b71ff059604c1c3a81581
4
+ data.tar.gz: a598cc9a3425cfd5b5fc9f27e9abd3b1e32a8fbf9bcc6707e4f93ebb069a9739
5
5
  SHA512:
6
- metadata.gz: b884dd3638bc74fb54ccd11a1957d5fa6d4b32bf5a20aff39cfc300ce794069d4812b1decef520a2f31db2b91e2c4d41424e1747b4892b8321b67c0680dbe4e5
7
- data.tar.gz: 64b5a67347b6cfc4c62ef3df0afb8e21305ef140807334ebbf3748fba2d8d9445d014b385735434fa238fb1b441df00b4e341156e78e9650b3df16e962779a91
6
+ metadata.gz: 75a5e0d5e5596859d868a29368fbb228d20badf0f67eca13dbcbf6f00b56c579f22da3b5855fc3f14577dcb61cf75ce000c6e802586639a0c1269a8a3681277a
7
+ data.tar.gz: e559a58ebd9907225906166d222da3f95e5071e7d2cb2ae3f00ea2763502911d20aceadb1f89e909565a2ecd71014034000abac46d2086942b2fa56675f281aa
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Tachiban
2
2
 
3
- [![Join the chat at https://gitter.im/sebastjan-hribar/tachiban](https://badges.gitter.im/sebastjan-hribar/tachiban.svg)](https://gitter.im/sebastjan-hribar/tachiban?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Gem Version](https://badge.fury.io/rb/tachiban.svg)](https://badge.fury.io/rb/tachiban) [![Build Status](https://travis-ci.org/sebastjan-hribar/tachiban.svg?branch=master)](https://travis-ci.org/sebastjan-hribar/tachiban)
3
+ [![Join the chat at https://gitter.im/sebastjan-hribar/tachiban](https://badges.gitter.im/sebastjan-hribar/tachiban.svg)](https://gitter.im/sebastjan-hribar/tachiban?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Gem Version](https://badge.fury.io/rb/tachiban.svg?kill_cache=1)](https://badge.fury.io/rb/tachiban)
4
4
 
5
- Tachiban (立ち番 - standing watch) provides simple authentication system for [Hanami web applications](http://hanamirb.org/) by using Argon2 for password hashing and
5
+ Tachiban (立ち番 - standing watch) provides simple authentication system for [Hanami 2.x web applications](http://hanamirb.org/) by using Argon2 for password hashing and
6
6
  offers the following functionalities (with methods listed below
7
7
  under Methods by features):
8
8
  - Signup
@@ -12,7 +12,10 @@ offers the following functionalities (with methods listed below
12
12
  - Password reset
13
13
  - Authorization has been moved to [Rokku](https://github.com/sebastjan-hribar/rokku)
14
14
 
15
- ## Installation
15
+ **Note:** For Hanami 1.3 support, see the [1.0.0 branch](https://github.com/sebastjan-hribar/tachiban/tree/1.0.0) or install Tachiban 1.0.
16
+
17
+
18
+ ## 1. Installation
16
19
 
17
20
  Add this line to your application's Gemfile:
18
21
 
@@ -28,21 +31,43 @@ Or install it yourself as:
28
31
 
29
32
  $ gem install tachiban
30
33
 
31
- Tachiban is already setup to be included by your Hanami application:
34
+
35
+ Tachiban 2.0 needs to be included in the action:
32
36
 
33
37
  ```ruby
34
- ::Hanami::Controller.configure do
35
- prepare do
38
+ # app/action.rb
39
+ # auto_register: false
40
+ # frozen_string_literal: true
41
+
42
+ require "hanami/action"
43
+ require "dry/monads"
44
+ require "tachiban"
45
+
46
+ module MyApplication
47
+ class Action < Hanami::Action
48
+ # Provide `Success` and `Failure` for pattern matching on operation results
49
+ include Dry::Monads[:result]
36
50
  include Hanami::Tachiban
51
+
52
+ handle_exception "ROM::TupleCountMismatchError" => :handle_not_found
53
+
54
+ private
55
+
56
+ def handle_not_found(request, response, exception)
57
+ response.status = 404
58
+ response.format = :html
59
+ response.body = "Not found"
60
+ end
37
61
  end
38
62
  end
39
63
  ```
40
64
 
41
- ## Usage
65
+ ## 2. Usage
42
66
 
43
- ### Prerequisites
67
+ ### 2.1 Prerequisites
44
68
  Prior to logging in or authenticating the user, retrieve the entity from the
45
- database and assign it to the instance variable of `@user`.
69
+ database and assign it to a variable (e.g. `user`), which you then pass to
70
+ the methods as required.
46
71
 
47
72
  In addition to that, the user entity must have the following attributes:
48
73
 
@@ -51,136 +76,225 @@ In addition to that, the user entity must have the following attributes:
51
76
  * **hashed_pass** (to hold the generated hashed password)
52
77
 
53
78
 
54
- ### Usage
79
+ ### 2.2 Usage
55
80
 
56
- #### Signup
81
+ #### 2.2.3 Signup
57
82
  To create a user with a hashed password use the `hashed_password(password)`
58
83
  method for the password and store it as the user's attribute `hashed_pass`.
59
84
 
60
85
  *Example*
61
86
 
62
87
  ```ruby
63
- # Create action for an entity
64
- def call(params)
65
- password = params[:newuser][:password]
88
+ # Create action for the user
89
+ def handle(request, response)
90
+ password = request.params[:newuser][:password]
66
91
  hashed_pass = hashed_password(password)
67
- repository = UserRepository.new
68
92
 
69
- @user = repository.create(name: name, surname: surname, email: email,
70
- hashed_pass: hashed_pass))
93
+ user = user_repo.create(name: name, surname: surname, email: email,
94
+ hashed_pass: hashed_pass)
71
95
  end
72
96
  ```
73
97
 
74
- #### Authentication and login
75
- To authenticate a user use the `authenticated?(input_password)` method and log
76
- them in with the `login` method. Authentication is successful if the user exists and passwords match.
98
+ #### 2.2.4 Authentication and login
99
+ To authenticate a user use the `authenticated?(input_password, user)` method and log
100
+ them in with the `login(request, response, user_id, flash_message: nil, login_redirect_url: nil)` method.
101
+
102
+ Authentication is successful if the user exists and passwords match. It's possible to provide your own flash message and / or redirect url. Otherwise, the **default values** will be used (see the table below).
77
103
 
78
- The user is logged in by setting the user object ID as the `session[:current_user]`.
79
- After the user is logged in the session start time is defined as
80
- `session[:session_start_time] = Time.now`. A default flash message is also
104
+ The user is logged in by setting the user object ID as the `request.session[:current_user]`.
105
+ After the user is logged in, the session start time is defined as
106
+ `request.session[:session_start_time] = Time.now`. A default flash message is also
81
107
  assigned as 'You have been successfully logged in.'.
82
108
 
83
- The `session[:session_start_time]` is then used by the `session_expired?`
84
- method to determine whether the session has expired or not.
109
+ The `request.session[:session_start_time]` is then used by the `session_expired?(request, response)` method to determine whether the session has expired or not.
85
110
 
86
- *Example of session creation for an entity*
111
+ **_Example of session creation for an entity_**
87
112
 
88
113
  ```ruby
89
- # Create action for an entity session
90
- email = params[:entity_session][:email]
91
- password = params[:entity_session][:password]
114
+ # Create action for the user session
115
+ email = request.params[:entity_session][:email]
116
+ password = request.params[:entity_session][:password]
92
117
 
93
- @user = EntityRepository.new.find_by_email(email)
94
- login if authenticated?(password)
118
+ user = user_repo.find_by_email(email) #required by login
119
+ login(request, response, user.id) if authenticated?(password, user)
95
120
  ```
96
121
 
97
- To check whether the user is logged in use the `check_for_logged_in_user` method.
98
- If the user is not logged in the `logout` method takes over.
122
+ To check whether a user is logged in, use the `check_for_logged_in_user(request, response)` method. If the user is not logged in, the `logout(request, response, logout_redirect_url: nil)` method takes over.
99
123
 
100
124
 
101
- #### Session handling
125
+ #### 2.2.5 Session handling
102
126
  Tachiban handles session expiration by checking if a session has
103
127
  expired and then restarts the session start time if the session
104
128
  is still valid or proceeds with the following if the session
105
129
  has expired:
106
130
 
107
- - setting the `session[:current_user]` to `nil`,
108
- - a flash message is set: `flash[:failed_notice] = "Your session has expired"`,
109
- - redirects to the `routes.root_path` which can be overwritten by assigning
110
- a different url to @redirect_url.
131
+ - setting the `request.session[:current_user]` to `nil`,
132
+ - a flash message is set: `response.flash[:failed_notice] = "Your session has expired"`,
133
+ - redirects to the root path `/`, which can be overwritten.
111
134
 
112
135
 
113
- The `session_expired?` method compares the session start time
114
- increased for the defined `@validity_time` (set to 10 minutes
136
+ The `session_expired?(request, validity_time: nil)` method compares the session start time
137
+ increased for the defined `validity_time` (set to 10 minutes
115
138
  by default, but can be overwritten) with the current time.
116
139
 
117
- `handle_session` method:
140
+ `handle_session(request, response, redirect_url: nil)` method:
118
141
  ```ruby
119
- def handle_session
120
- if session_expired?
121
- @redirect_url ||= routes.root_path
122
- session[:current_user] = nil
123
- flash[:failed_notice] = "Your session has expired."
124
- redirect_to @redirect_url
142
+ def handle_session(request, response, redirect_url: nil)
143
+ if session_expired?(request)
144
+ redirect_url ||= '/'
145
+ request.session[:current_user] = nil
146
+ response.flash[:failed_notice] ||= "Your session has expired."
147
+ response.redirect_to redirect_url
125
148
  else
126
- restart_session_counter
149
+ restart_session_counter(request)
127
150
  end
128
151
  end
129
152
  ```
130
153
 
131
- *Example of session handling in a share code module*
154
+ #### 2.2.6 Session handling in a share code module
155
+ It is possible to enable session handling in a share code module as provided by Hanami.
156
+ To do this, create an authentication module in **app/actions/authentication.rb**.
157
+ The example below shows also how to custom values to replace default values in
158
+ actions.
132
159
 
133
160
  ```ruby
134
- module Web
135
- module HandleSession
136
-
137
- def self.included(action)
138
- action.class_eval do
139
- before :handle_session
140
- end
141
- end
142
-
161
+ module MyApplication
162
+ module Actions
163
+ module Authentication
164
+ def self.included(action_class)
165
+ action_class.class_eval do
166
+ before :check_for_logged_in_user
167
+ before :handle_session
168
+ end
169
+ end
170
+
171
+ private
172
+
173
+ def custom_handle_session_redirect_url
174
+ '/login'
175
+ end
176
+
177
+ def custom_logout_redirect_url
178
+ '/login'
179
+ end
180
+
181
+ def custom_login_redirect_url
182
+ '/'
183
+ end
184
+
185
+ def custom_session_validity_time
186
+ if ENV['HANAMI_ENV'] == 'test'
187
+ 600
188
+ else
189
+ 1800
190
+ end
191
+ end
192
+ end
143
193
  end
144
194
  end
145
195
  ```
196
+ We can then simply include the `Authentication` module in actions, where required.
146
197
 
147
-
148
- #### Password reset
149
- The password reset feature provides a few simple methods to generate a
150
- token, email subject and body. It is also possible to specify and
151
- check the validity of the password reset url.
198
+ However, if we include this in the base action class, it will be available in all
199
+ actions and there is no need for separate includes in actions:
152
200
 
153
201
  ```ruby
154
- token # => "YbRucc8YUlFJrYYp04eQKQ"
155
- ```
202
+ #
203
+ #
204
+ module MyApplication
205
+ class Action < Hanami::Action
206
+ # Provide `Success` and `Failure` for pattern matching on operation results
207
+ include Dry::Monads[:result]
208
+ include Hanami::Tachiban
209
+ include MyApplication::Actions::Authentication
156
210
 
157
- ```ruby
158
- email_subject(SomeApp) # => "SomeApp -- password reset request"
211
+ handle_exception "ROM::TupleCountMismatchError" => :handle_not_found
212
+
213
+ private
214
+ #
215
+ #
159
216
  ```
160
217
 
161
218
 
162
- Provide the base url, the token and the number and type of the time units
163
- for the validity of the link.
219
+ **_Disabling the authentication shared module in specific actions_**
220
+
221
+ Sometimes we might not want to check for authenticated user. For example,
222
+ doing so in the `login` action will cause an infinite loop. There we can
223
+ disable the module by overwriting the desired methods in the action:
164
224
 
165
225
  ```ruby
166
- body = email_body(base_url, url_token, 2, "hour")
167
- # => "Visit this url to reset your password: http://localhost:2300/passwordupdate/asdasdasdaerwrw.
168
- # The url will be valid for 2 hour(s).")
226
+ private
227
+
228
+ def check_for_logged_in_user; end
229
+ def handle_session; end
169
230
  ```
170
231
 
232
+ #### 2.2.7 Password reset
233
+ The password reset feature provides a few simple methods to:
234
+ * generate a token, email subject and body (text and html part)
235
+ * specify and check the validity of the password reset url and
236
+ * set the default application name for the email subject (it can be
237
+ overwritten or set as a ENV variable).
238
+
171
239
  The link validity must me specified in seconds. The method compares the
172
240
  current time with the time when the password reset link was sent increased
173
- by the link validity: `Time.now > @user.password_reset_sent_at + link_validity`
241
+ by the link validity: `Time.now > user.password_reset_sent_at + link_validity`.
242
+
243
+
244
+ ```ruby
245
+ token # => "YbRucc8YUlFJrYYp04eQKQ"
246
+ ```
247
+
248
+ ```ruby
249
+ email_subject("SomeApp") # => "SomeApp -- password reset request"
250
+ ```
174
251
 
175
252
  ```ruby
176
253
  password_reset_url_valid?(link_validity)
177
254
  ```
178
255
 
179
- ### Example of use in an application
180
- [Using Tachiban with a Hanami app](https://sebastjan-hribar.github.io/programming/2021/09/03/tachiban-with-hanami.html)
181
256
 
182
257
 
183
- ### Changelog
258
+ Provide the following values when building the email body: reset url, user's name,
259
+ link validity, time unit and optionally the application name. Below is an example of
260
+ html_body in a mailer class:
261
+
262
+ ```ruby
263
+ html_body = email_body_html(
264
+ reset_url: reset_url,
265
+ user_name: "#{user.name} #{user.surname}",
266
+ link_validity: 2,
267
+ time_unit: "hour",
268
+ app_name: nil
269
+ )
270
+ ```
271
+
272
+ ### 3. Default values
273
+ There are a few default values set which can be overwritten. See the table below.
274
+
275
+ |Required by method |Variable |Default value |
276
+ |--- |--- |--- |
277
+ |login |flash_message |'You have been successfully logged in.'|
278
+ |login |login_redirect_url |'/' |
279
+ |logout |logout_redirect_url |'/login' |
280
+ |session_expired? |validity_time |600 |
281
+ |handle_session |redirect_url |'/' |
282
+
283
+
284
+
285
+
286
+ ### 4. Changelog
287
+
288
+ #### 2.0.0
289
+
290
+ **Breaking Changes:**
291
+ - Supports Hanami ~> 2.0 applications only.
292
+ - Method signatures updated: `login`, `logout`, `check_for_logged_in_user`, and `handle_session` now require `(request, response)` parameters.
293
+ - Methods `session_expired?` and `restart_session_counter` now require `(request)` parameter.
294
+ - Tachiban must be explicitly included in the base action: `include Hanami::Tachiban`.
295
+ - Tachiban 2.0.0 doesn't rely on instance variable like `@user` anymore. Instead, a `user` variable must be passed as an argument to a method.
296
+
297
+ For Hanami 1.3 support, use Tachiban 1.0.
184
298
 
185
299
  #### 1.0.0
186
300
 
data/Rakefile CHANGED
@@ -1,7 +1,5 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
- require "hanami/controller"
4
- require 'hanami/action/session'
5
3
 
6
4
  Rake::TestTask.new(:test) do |t|
7
5
  t.libs << "test"
@@ -1,3 +1,3 @@
1
1
  module Tachiban
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/tachiban.rb CHANGED
@@ -28,8 +28,8 @@ private
28
28
  # - a user exists
29
29
  # - a user's hashed password from the database matches the input password
30
30
 
31
- def authenticated?(input_pass)
32
- @user && Argon2::Password.verify_password(input_pass, @user.hashed_pass)
31
+ def authenticated?(input_pass, user)
32
+ user && Argon2::Password.verify_password(input_pass, user.hashed_pass)
33
33
  end
34
34
 
35
35
  # The login method can be used in combination with the authenticated? method to
@@ -41,30 +41,30 @@ private
41
41
 
42
42
  # There are two defualt values set: one for flash message and
43
43
  # the other for redirect url. Both can be overwritten by assigning
44
- # new values for @flash_message and @login_redirect_url.
44
+ # new values for flash_message and login_redirect_url arguments.
45
45
 
46
46
  # Example:
47
47
  # login if authenticated?(input_pass)
48
48
 
49
- def login
50
- session[:current_user] = @user.id
51
- session[:session_start_time] = Time.now
52
- @flash_message ||= 'You have been successfully logged in.'
53
- flash[:success_notice] = @flash_message
54
- @login_redirect_url ||= routes.root_path
55
- redirect_to @login_redirect_url
49
+ def login(request, response, user_id, flash_message: nil, login_redirect_url: nil)
50
+ request.session[:current_user] = user_id
51
+ request.session[:session_start_time] = Time.now
52
+ flash_message ||= 'You have been successfully logged in.'
53
+ response.flash[:success_notice] = flash_message
54
+ login_redirect_url ||= "/"
55
+ response.redirect_to login_redirect_url
56
56
  end
57
57
 
58
58
  # The logout method sets the current user in the session to nil
59
59
  # and performs a redirect to the redirect_url which is set to
60
60
  # /login, but can be overwritten as needed with a specific url
61
- # by setting a new value for @logout_redirect_url.
61
+ # by setting a new value for logout_redirect_url.
62
62
 
63
- def logout
64
- session[:current_user] = nil
65
- session.clear
66
- @logout_redirect_url ||= '/login'
67
- redirect_to @logout_redirect_url
63
+ def logout(request, response, logout_redirect_url: nil)
64
+ request.session[:current_user] = nil
65
+ request.session.clear
66
+ logout_redirect_url ||= '/login'
67
+ response.redirect_to logout_redirect_url
68
68
  end
69
69
 
70
70
  # ### Authentication ###
@@ -73,8 +73,8 @@ private
73
73
  # request whether the user is logged in. If the user is not logged in
74
74
  # the logout method takes over.
75
75
 
76
- def check_for_logged_in_user
77
- logout unless session[:current_user]
76
+ def check_for_logged_in_user(request, response)
77
+ logout(request, response) unless request.session[:current_user]
78
78
  end
79
79
 
80
80
  # ### Session handling ###
@@ -86,18 +86,18 @@ private
86
86
  # increased for the defined validity time (set to 10 minutes
87
87
  # by default and can be overwritten) with the current time.
88
88
 
89
- def session_expired?
90
- if session[:current_user]
91
- @validity_time ||= 600
92
- session[:session_start_time] + @validity_time.to_i < Time.now
89
+ def session_expired?(request, validity_time: nil)
90
+ if request.session[:current_user]
91
+ validity_time ||= 600
92
+ request.session[:session_start_time] + validity_time.to_i < Time.now
93
93
  end
94
94
  end
95
95
 
96
96
  # The restart_session_counter method resets the session start time to
97
97
  # Time.now. It's used in the handle session method.
98
98
 
99
- def restart_session_counter
100
- session[:session_start_time] = Time.now
99
+ def restart_session_counter(request)
100
+ request.session[:session_start_time] = Time.now
101
101
  end
102
102
 
103
103
  # The handle_session method is used to handle the incoming requests
@@ -109,40 +109,83 @@ private
109
109
  # If the session hasn't expired the restart_session_counter method is
110
110
  # called to reset the session start time.
111
111
 
112
- def handle_session
113
- if session_expired?
114
- @redirect_url ||= routes.root_path
115
- session[:current_user] = nil
116
- flash[:failed_notice] = 'Your session has expired.'
117
- redirect_to @redirect_url
112
+ def handle_session(request, response, redirect_url: nil)
113
+ if session_expired?(request)
114
+ redirect_url ||= "/"
115
+ request.session[:current_user] = nil
116
+ response.flash[:failed_notice] ||= 'Your session has expired.'
117
+ response.redirect_to redirect_url
118
118
  else
119
- restart_session_counter
119
+ restart_session_counter(request)
120
120
  end
121
121
  end
122
122
 
123
123
  # ### Password reset ###
124
+ # The password reset functionalities include token generation, email subject,
125
+ # email body in the text as well as in the html format, checking the reset link
126
+ # validity and getting the app name.
127
+
124
128
  def token
125
129
  SecureRandom.urlsafe_base64
126
130
  end
127
131
 
128
132
  def email_subject(app_name)
133
+ app_name ||= default_app_name
129
134
  "#{app_name} -- password reset request"
130
135
  end
131
136
 
132
- def email_body(url, token, link_validity, time_unit)
133
- "Visit this url to reset your password: #{url}#{token}. \n
134
- The url will be valid for #{link_validity} #{time_unit}(s)."
137
+ def email_body_text(reset_url:, user_name:, link_validity:, time_unit:, app_name: nil)
138
+ app_name ||= default_app_name
139
+
140
+ <<~TEXT
141
+ Hello #{user_name},
142
+
143
+ Click the link below to reset your password:
144
+
145
+ #{reset_url}
146
+
147
+ This link will expire in #{link_validity} #{time_unit}(s).
148
+
149
+ Kind regards,
150
+ The #{app_name} Team
151
+ TEXT
152
+ end
153
+
154
+ def email_body_html(reset_url:, user_name:, link_validity:, time_unit:, app_name: nil)
155
+ app_name ||= default_app_name
156
+
157
+ <<~HTML
158
+ <!DOCTYPE html>
159
+ <html>
160
+ <body style="font-family: Arial, sans-serif;">
161
+ <h2>Password reset request</h2>
162
+ <br>
163
+ <p>Hello #{user_name},</p>
164
+ <br>
165
+ <p>Click the button below to reset your password:</p>
166
+ <p>
167
+ <a href="#{reset_url}" style="background: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">
168
+ Reset Password
169
+ </a>
170
+ </p>
171
+ <br>
172
+ <p>Or copy this link: #{reset_url}</p>
173
+ <p style="color: #666; font-size: 12px;">This link expires in #{link_validity} #{time_unit}(s).</p>
174
+ </body>
175
+ </html>
176
+ HTML
135
177
  end
136
178
 
137
179
  # State the link_validity in seconds.
138
- def password_reset_url_valid?(link_validity)
139
- Time.now < @user.password_reset_sent_at + link_validity
180
+ def password_reset_url_valid?(link_validity, user)
181
+ Time.now < user.password_reset_sent_at + link_validity
182
+ end
183
+
184
+ def default_app_name
185
+ ENV.fetch("APP_NAME") { Hanami.app.namespace.to_s }
186
+ rescue
187
+ "Application"
140
188
  end
141
- end
142
- end
143
189
 
144
- ::Hanami::Controller.configure do
145
- prepare do
146
- include Hanami::Tachiban
147
190
  end
148
- end
191
+ end
data/tachiban.gemspec CHANGED
@@ -17,16 +17,13 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_development_dependency "bundler", "~> 2.0"
21
- spec.add_development_dependency "rake", "~> 12.3", ">= 12.3.3"
20
+ spec.add_development_dependency "rake"
22
21
  spec.add_development_dependency "minitest", "~> 5.0"
23
- spec.add_development_dependency "hanami-model", "~> 1.0"
24
- spec.add_development_dependency "timecop", "0.8.1"
25
- spec.add_development_dependency 'hanami-controller', "~> 1.0"
26
- spec.add_development_dependency 'hanami-router', "~> 1.0"
27
- spec.add_development_dependency 'pry', "~> 0"
22
+ spec.add_development_dependency "timecop", "0.9.0"
23
+ spec.add_development_dependency 'hanami', "~> 2.0"
24
+ spec.add_development_dependency 'pry', "~> 0.16.0"
28
25
 
29
26
  spec.add_runtime_dependency "argon2", "~> 2.3"
30
- spec.add_runtime_dependency 'hanami-controller', "~> 1.0"
31
- spec.add_runtime_dependency 'hanami-router', "~> 1.0"
32
- end
27
+ spec.add_runtime_dependency 'hanami', "~> 2.0"
28
+ spec.add_runtime_dependency "hanami-controller", "~> 2.0"
29
+ end
metadata CHANGED
@@ -1,49 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tachiban
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastjan Hribar
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-09 00:00:00.000000000 Z
11
+ date: 2026-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '12.3'
34
17
  - - ">="
35
18
  - !ruby/object:Gem::Version
36
- version: 12.3.3
19
+ version: '0'
37
20
  type: :development
38
21
  prerelease: false
39
22
  version_requirements: !ruby/object:Gem::Requirement
40
23
  requirements:
41
- - - "~>"
42
- - !ruby/object:Gem::Version
43
- version: '12.3'
44
24
  - - ">="
45
25
  - !ruby/object:Gem::Version
46
- version: 12.3.3
26
+ version: '0'
47
27
  - !ruby/object:Gem::Dependency
48
28
  name: minitest
49
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,76 +38,48 @@ dependencies:
58
38
  - - "~>"
59
39
  - !ruby/object:Gem::Version
60
40
  version: '5.0'
61
- - !ruby/object:Gem::Dependency
62
- name: hanami-model
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '1.0'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '1.0'
75
41
  - !ruby/object:Gem::Dependency
76
42
  name: timecop
77
43
  requirement: !ruby/object:Gem::Requirement
78
44
  requirements:
79
45
  - - '='
80
46
  - !ruby/object:Gem::Version
81
- version: 0.8.1
47
+ version: 0.9.0
82
48
  type: :development
83
49
  prerelease: false
84
50
  version_requirements: !ruby/object:Gem::Requirement
85
51
  requirements:
86
52
  - - '='
87
53
  - !ruby/object:Gem::Version
88
- version: 0.8.1
89
- - !ruby/object:Gem::Dependency
90
- name: hanami-controller
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '1.0'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '1.0'
54
+ version: 0.9.0
103
55
  - !ruby/object:Gem::Dependency
104
- name: hanami-router
56
+ name: hanami
105
57
  requirement: !ruby/object:Gem::Requirement
106
58
  requirements:
107
59
  - - "~>"
108
60
  - !ruby/object:Gem::Version
109
- version: '1.0'
61
+ version: '2.0'
110
62
  type: :development
111
63
  prerelease: false
112
64
  version_requirements: !ruby/object:Gem::Requirement
113
65
  requirements:
114
66
  - - "~>"
115
67
  - !ruby/object:Gem::Version
116
- version: '1.0'
68
+ version: '2.0'
117
69
  - !ruby/object:Gem::Dependency
118
70
  name: pry
119
71
  requirement: !ruby/object:Gem::Requirement
120
72
  requirements:
121
73
  - - "~>"
122
74
  - !ruby/object:Gem::Version
123
- version: '0'
75
+ version: 0.16.0
124
76
  type: :development
125
77
  prerelease: false
126
78
  version_requirements: !ruby/object:Gem::Requirement
127
79
  requirements:
128
80
  - - "~>"
129
81
  - !ruby/object:Gem::Version
130
- version: '0'
82
+ version: 0.16.0
131
83
  - !ruby/object:Gem::Dependency
132
84
  name: argon2
133
85
  requirement: !ruby/object:Gem::Requirement
@@ -143,34 +95,34 @@ dependencies:
143
95
  - !ruby/object:Gem::Version
144
96
  version: '2.3'
145
97
  - !ruby/object:Gem::Dependency
146
- name: hanami-controller
98
+ name: hanami
147
99
  requirement: !ruby/object:Gem::Requirement
148
100
  requirements:
149
101
  - - "~>"
150
102
  - !ruby/object:Gem::Version
151
- version: '1.0'
103
+ version: '2.0'
152
104
  type: :runtime
153
105
  prerelease: false
154
106
  version_requirements: !ruby/object:Gem::Requirement
155
107
  requirements:
156
108
  - - "~>"
157
109
  - !ruby/object:Gem::Version
158
- version: '1.0'
110
+ version: '2.0'
159
111
  - !ruby/object:Gem::Dependency
160
- name: hanami-router
112
+ name: hanami-controller
161
113
  requirement: !ruby/object:Gem::Requirement
162
114
  requirements:
163
115
  - - "~>"
164
116
  - !ruby/object:Gem::Version
165
- version: '1.0'
117
+ version: '2.0'
166
118
  type: :runtime
167
119
  prerelease: false
168
120
  version_requirements: !ruby/object:Gem::Requirement
169
121
  requirements:
170
122
  - - "~>"
171
123
  - !ruby/object:Gem::Version
172
- version: '1.0'
173
- description:
124
+ version: '2.0'
125
+ description:
174
126
  email:
175
127
  - sebastjan.hribar@gmail.com
176
128
  executables:
@@ -197,7 +149,7 @@ homepage: https://github.com/sebastjan-hribar/tachiban
197
149
  licenses:
198
150
  - MIT
199
151
  metadata: {}
200
- post_install_message:
152
+ post_install_message:
201
153
  rdoc_options: []
202
154
  require_paths:
203
155
  - lib
@@ -212,8 +164,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
164
  - !ruby/object:Gem::Version
213
165
  version: '0'
214
166
  requirements: []
215
- rubygems_version: 3.1.6
216
- signing_key:
167
+ rubygems_version: 3.5.9
168
+ signing_key:
217
169
  specification_version: 4
218
170
  summary: Tachiban provides simple password hashing for user authentication with Argon2
219
171
  for Hanami web applications.