veri 2.0.3 → 2.1.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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +38 -7
- data/lib/veri/controllers/concerns/authentication.rb +2 -9
- data/lib/veri/inputs/authenticatable.rb +2 -0
- data/lib/veri/inputs/base.rb +5 -2
- data/lib/veri/inputs/non_empty_string.rb +2 -0
- data/lib/veri/inputs/tenant.rb +3 -0
- data/lib/veri/models/concerns/authenticatable.rb +7 -3
- data/lib/veri/models/session.rb +6 -9
- data/lib/veri/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 703094a8e90e3fde6888629b9702406548122bed4ab199e1a02eac174c68ee07
|
|
4
|
+
data.tar.gz: 337701b97ed23c8cffd7b8ffb6d649e3e520c09bc61de6ed69e7c9d8b1905462
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e717d0cf3a4a8d9c673919548c739820ed15b42e7ab7140c9a95cd0f4740cd20a1678cf2a9dfbbcbaeb1257b60f9b8b2a28c2030d9b893fbf382a309e90b1445
|
|
7
|
+
data.tar.gz: 515e5fee62f96f4ddf4982419207565a905faa00246b5d1b483581ba86fd1063e0bbe06eaa253274c6e73d69395b1f8afd296210afd8aed3c067e264d872d7a4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## v2.1.0
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- Added `Veri::Session#switch_tenant` method to move a session to another tenant
|
|
6
|
+
- Added `password_set?` method to check whether a user has a password
|
|
7
|
+
|
|
8
|
+
### Bugs
|
|
9
|
+
|
|
10
|
+
- Fixed `log_in` using the previous tenant when `current_tenant` changes within the same request
|
|
11
|
+
- Fixed `Veri::Session.in_tenant` raising an error without a message when given an invalid tenant
|
|
12
|
+
|
|
1
13
|
## v2.0.3
|
|
2
14
|
|
|
3
15
|
### Bugs
|
data/README.md
CHANGED
|
@@ -93,6 +93,9 @@ user.update_password("password")
|
|
|
93
93
|
|
|
94
94
|
# Verify a password
|
|
95
95
|
user.verify_password("password")
|
|
96
|
+
|
|
97
|
+
# Check if a password is set
|
|
98
|
+
user.password_set?
|
|
96
99
|
```
|
|
97
100
|
Changing a password does not automatically terminate existing sessions. If you want to invalidate the user's sessions after a password change, do so explicitly:
|
|
98
101
|
|
|
@@ -398,6 +401,40 @@ user.sessions.in_tenant(tenant)
|
|
|
398
401
|
user.sessions.in_tenant(tenant).terminate_all
|
|
399
402
|
```
|
|
400
403
|
|
|
404
|
+
### Switching Tenants
|
|
405
|
+
|
|
406
|
+
A session belongs to one tenant, and a browser holds one session per host. A user is therefore logged in to one tenant at a time, unless your tenants live on separate subdomains, where each subdomain keeps its own session.
|
|
407
|
+
|
|
408
|
+
To move a user to another tenant, call `switch_tenant` on their session and make `current_tenant` return the new tenant from then on:
|
|
409
|
+
|
|
410
|
+
```rb
|
|
411
|
+
class ApplicationController < ActionController::Base
|
|
412
|
+
include Veri::Authentication
|
|
413
|
+
|
|
414
|
+
with_authentication
|
|
415
|
+
|
|
416
|
+
private
|
|
417
|
+
|
|
418
|
+
def current_tenant
|
|
419
|
+
# This example keeps the tenant in a cookie; your app can keep it anywhere
|
|
420
|
+
Company.find_by(id: cookies.signed[:company_id])
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
class CompaniesController < ApplicationController
|
|
425
|
+
def switch
|
|
426
|
+
company = current_user.companies.find(params[:id])
|
|
427
|
+
|
|
428
|
+
current_session.switch_tenant(company)
|
|
429
|
+
cookies.signed[:company_id] = company.id
|
|
430
|
+
|
|
431
|
+
redirect_to root_path, notice: "Switched to #{company.name}"
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
The user stays logged in and the session keeps its expiration.
|
|
437
|
+
|
|
401
438
|
### User Impersonation with Tenants
|
|
402
439
|
|
|
403
440
|
When using user impersonation in a multi-tenant setup, Veri allows cross-tenant shapeshifting while preserving the original tenant context:
|
|
@@ -418,18 +455,12 @@ All other session methods work the same way in multi-tenant applications as in s
|
|
|
418
455
|
|
|
419
456
|
When a tenant object is deleted from your database, its associated sessions become orphaned.
|
|
420
457
|
|
|
421
|
-
|
|
458
|
+
Ideally, the application should be designed so that this doesn't happen: whenever a tenant object is deleted, its sessions are terminated as part of the same operation. However, if that wasn't done, you can clean up the orphaned sessions as a fallback:
|
|
422
459
|
|
|
423
460
|
```rb
|
|
424
461
|
Veri::Session.prune
|
|
425
462
|
```
|
|
426
463
|
|
|
427
|
-
Or, for a specific user:
|
|
428
|
-
|
|
429
|
-
```rb
|
|
430
|
-
user.sessions.prune
|
|
431
|
-
```
|
|
432
|
-
|
|
433
464
|
### Tenant Migrations
|
|
434
465
|
|
|
435
466
|
When you rename or remove models used as tenants, you need to update Veri's stored data accordingly. Use these irreversible data migrations:
|
|
@@ -33,10 +33,7 @@ module Veri
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def log_in(authenticatable)
|
|
36
|
-
processed_authenticatable = Veri::Inputs::Authenticatable.new(
|
|
37
|
-
authenticatable,
|
|
38
|
-
message: "Expected an instance of #{Veri::Configuration.user_model_name}, got `#{authenticatable.inspect}`"
|
|
39
|
-
).process
|
|
36
|
+
processed_authenticatable = Veri::Inputs::Authenticatable.new(authenticatable).process
|
|
40
37
|
|
|
41
38
|
return false if processed_authenticatable.locked?
|
|
42
39
|
|
|
@@ -87,11 +84,7 @@ module Veri
|
|
|
87
84
|
def current_tenant = nil
|
|
88
85
|
|
|
89
86
|
def resolved_tenant
|
|
90
|
-
|
|
91
|
-
current_tenant,
|
|
92
|
-
error: Veri::InvalidTenantError,
|
|
93
|
-
message: "Expected a string, an ActiveRecord model instance, or nil, got `#{current_tenant.inspect}`"
|
|
94
|
-
).resolve
|
|
87
|
+
Veri::Inputs::Tenant.new(current_tenant).resolve
|
|
95
88
|
end
|
|
96
89
|
|
|
97
90
|
def reset_memoization
|
|
@@ -3,6 +3,8 @@ module Veri
|
|
|
3
3
|
class Authenticatable < Veri::Inputs::Base
|
|
4
4
|
private
|
|
5
5
|
|
|
6
|
+
def default_message = "Expected an instance of #{Veri::Configuration.user_model_name}, got `#{@value.inspect}`"
|
|
7
|
+
|
|
6
8
|
def processor = -> { @value.is_a?(Veri::Configuration.user_model) ? @value : raise_error }
|
|
7
9
|
end
|
|
8
10
|
end
|
data/lib/veri/inputs/base.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Veri
|
|
2
2
|
module Inputs
|
|
3
3
|
class Base
|
|
4
|
-
def initialize(value, optional: false, error:
|
|
4
|
+
def initialize(value, optional: false, error: nil, message: nil)
|
|
5
5
|
@value = value
|
|
6
6
|
@optional = optional
|
|
7
7
|
@error = error
|
|
@@ -20,8 +20,11 @@ module Veri
|
|
|
20
20
|
raise NotImplementedError
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
def default_error = Veri::InvalidArgumentError
|
|
24
|
+
def default_message = nil
|
|
25
|
+
|
|
23
26
|
def raise_error
|
|
24
|
-
raise @error, @message
|
|
27
|
+
raise @error || default_error, @message || default_message
|
|
25
28
|
end
|
|
26
29
|
end
|
|
27
30
|
end
|
data/lib/veri/inputs/tenant.rb
CHANGED
|
@@ -16,16 +16,20 @@ module Veri
|
|
|
16
16
|
def update_password(password)
|
|
17
17
|
update!(
|
|
18
18
|
hashed_password: hasher.create(
|
|
19
|
-
Veri::Inputs::NonEmptyString.new(password
|
|
19
|
+
Veri::Inputs::NonEmptyString.new(password).process
|
|
20
20
|
),
|
|
21
21
|
password_updated_at: Time.current
|
|
22
22
|
)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def password_set?
|
|
26
|
+
hashed_password.present?
|
|
27
|
+
end
|
|
28
|
+
|
|
25
29
|
def verify_password(password)
|
|
26
|
-
processed_password = Veri::Inputs::NonEmptyString.new(password
|
|
30
|
+
processed_password = Veri::Inputs::NonEmptyString.new(password).process
|
|
27
31
|
|
|
28
|
-
return false
|
|
32
|
+
return false unless password_set?
|
|
29
33
|
|
|
30
34
|
stored_hasher = Veri::Configuration::HASHERS.values.find { _1.match?(hashed_password) }
|
|
31
35
|
|
data/lib/veri/models/session.rb
CHANGED
|
@@ -60,11 +60,7 @@ module Veri
|
|
|
60
60
|
def shapeshift(user, tenant: nil)
|
|
61
61
|
raise Veri::Error, "Cannot shapeshift from a shapeshifted session" if shapeshifted?
|
|
62
62
|
|
|
63
|
-
resolved_tenant = Veri::Inputs::Tenant.new(
|
|
64
|
-
tenant,
|
|
65
|
-
error: Veri::InvalidTenantError,
|
|
66
|
-
message: "Expected a string, an ActiveRecord model instance, or nil, got `#{tenant.inspect}`"
|
|
67
|
-
).resolve
|
|
63
|
+
resolved_tenant = Veri::Inputs::Tenant.new(tenant).resolve
|
|
68
64
|
|
|
69
65
|
update!(
|
|
70
66
|
shapeshifted_at: Time.current,
|
|
@@ -72,10 +68,7 @@ module Veri
|
|
|
72
68
|
original_tenant_type: tenant_type,
|
|
73
69
|
original_tenant_id: tenant_id,
|
|
74
70
|
**resolved_tenant,
|
|
75
|
-
authenticatable: Veri::Inputs::Authenticatable.new(
|
|
76
|
-
user,
|
|
77
|
-
message: "Expected an instance of #{Veri::Configuration.user_model_name}, got `#{user.inspect}`"
|
|
78
|
-
).process
|
|
71
|
+
authenticatable: Veri::Inputs::Authenticatable.new(user).process
|
|
79
72
|
)
|
|
80
73
|
end
|
|
81
74
|
|
|
@@ -91,6 +84,10 @@ module Veri
|
|
|
91
84
|
)
|
|
92
85
|
end
|
|
93
86
|
|
|
87
|
+
def switch_tenant(tenant)
|
|
88
|
+
update!(**Veri::Inputs::Tenant.new(tenant).resolve)
|
|
89
|
+
end
|
|
90
|
+
|
|
94
91
|
def tenant
|
|
95
92
|
resolve_tenant(tenant_type, tenant_id) { super }
|
|
96
93
|
end
|
data/lib/veri/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: veri
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- enjaku4
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: argon2
|
|
@@ -147,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
147
147
|
- !ruby/object:Gem::Version
|
|
148
148
|
version: '0'
|
|
149
149
|
requirements: []
|
|
150
|
-
rubygems_version: 4.0.
|
|
150
|
+
rubygems_version: 4.0.16
|
|
151
151
|
specification_version: 4
|
|
152
152
|
summary: Minimal cookie-based authentication library for Ruby on Rails
|
|
153
153
|
test_files: []
|