seshlock 0.1.2 → 0.2.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 +13 -0
- data/README.md +44 -0
- data/lib/seshlock/access_token.rb +1 -0
- data/lib/seshlock/controller_methods.rb +54 -0
- data/lib/seshlock/user_methods.rb +29 -1
- data/lib/seshlock/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fbf274a0b946e63b4705ff7c2fe438217c107cc65303f3e68af2f815d4e66b88
|
|
4
|
+
data.tar.gz: 301a0d5e8cbd576b149a69b99907d4d212ab0999e91e9b6c73278d7382f235c1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: da7ef58b5f72b5c39212117d800b286426ba1a2dd6b5ae62261d309f6dfca28c23839165714554590271f046315d297c7e14c5eefd434194e7bd049695b629f1
|
|
7
|
+
data.tar.gz: f6d2fadcdc3ed13121dcee13bfec93d4ec0f36d479b06648b8c0495f995befaf36f909d10f4ac53be180d541fb3acbc262d791ffcd80a78bf2a8e5615ea1aa86
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2026-01-13
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Session Listing**: `user.seshlock_sessions` returns all active sessions for a user, ordered by most recent first.
|
|
13
|
+
- **Revoke All Sessions**: `user.revoke_all_seshlock_sessions!` revokes all active sessions for a user (logout everywhere).
|
|
14
|
+
- **Revoke Other Sessions**: `user.revoke_other_seshlock_sessions!(except_refresh_token:)` revokes all sessions except the specified one.
|
|
15
|
+
- **Controller Helpers**:
|
|
16
|
+
- `seshlock_list_sessions` - Returns array of session info with `id`, `device`, `created_at`, `expires_at`, and `current` flag.
|
|
17
|
+
- `seshlock_revoke_all` - Revokes all sessions for the current user.
|
|
18
|
+
- `seshlock_revoke_others` - Revokes all sessions except the current one.
|
|
19
|
+
- `seshlock_revoke_session(session_id:)` - Revokes a specific session by ID.
|
|
20
|
+
|
|
8
21
|
## [0.1.2] - 2025-12-11
|
|
9
22
|
|
|
10
23
|
### Fixed
|
data/README.md
CHANGED
|
@@ -160,6 +160,50 @@ The `Seshlock::UserMethods` concern adds:
|
|
|
160
160
|
user.seshlock_refresh_tokens # => has_many association
|
|
161
161
|
user.seshlock_access_tokens # => has_many through refresh_tokens
|
|
162
162
|
user.issue_seshlock_session(device: nil) # => TokenPair
|
|
163
|
+
|
|
164
|
+
# Session Management
|
|
165
|
+
user.seshlock_sessions # => Active sessions (most recent first)
|
|
166
|
+
user.revoke_all_seshlock_sessions! # => Logout everywhere
|
|
167
|
+
user.revoke_other_seshlock_sessions!(except_refresh_token: token) # => Logout other devices
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Controller Session Management
|
|
171
|
+
|
|
172
|
+
List, revoke specific, or revoke multiple sessions:
|
|
173
|
+
|
|
174
|
+
```ruby
|
|
175
|
+
class SessionsController < ApplicationController
|
|
176
|
+
include Seshlock::ControllerMethods
|
|
177
|
+
|
|
178
|
+
before_action :authenticate_with_seshlock_access_token!,
|
|
179
|
+
only: [:index, :destroy, :destroy_others]
|
|
180
|
+
before_action :authenticate_with_seshlock_refresh_token!,
|
|
181
|
+
only: [:destroy_all]
|
|
182
|
+
|
|
183
|
+
# GET /sessions - List all active sessions
|
|
184
|
+
def index
|
|
185
|
+
render json: { sessions: seshlock_list_sessions }
|
|
186
|
+
# Returns: [{ id: 1, device: "iPhone", created_at: ..., expires_at: ..., current: true }, ...]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# DELETE /sessions/:id - Revoke specific session
|
|
190
|
+
def destroy
|
|
191
|
+
seshlock_revoke_session(session_id: params[:id])
|
|
192
|
+
head :ok
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# DELETE /sessions/others - Revoke all except current
|
|
196
|
+
def destroy_others
|
|
197
|
+
seshlock_revoke_others
|
|
198
|
+
head :ok
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# DELETE /sessions/all - Revoke all (requires refresh token)
|
|
202
|
+
def destroy_all
|
|
203
|
+
seshlock_revoke_all
|
|
204
|
+
head :ok
|
|
205
|
+
end
|
|
206
|
+
end
|
|
163
207
|
```
|
|
164
208
|
|
|
165
209
|
## Error Handling
|
|
@@ -8,6 +8,7 @@ class Seshlock::AccessToken < ActiveRecord::Base
|
|
|
8
8
|
|
|
9
9
|
# Associations
|
|
10
10
|
belongs_to :refresh_token, class_name: "Seshlock::RefreshToken", inverse_of: :access_tokens
|
|
11
|
+
has_one :user, through: :refresh_token
|
|
11
12
|
|
|
12
13
|
# Scopes
|
|
13
14
|
scope :not_expired, -> { where("expires_at > ?", Time.current) }
|
|
@@ -153,6 +153,60 @@ module Seshlock
|
|
|
153
153
|
build_token_response(user: user, token_pair: token_pair)
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
+
# -------------------------------------------------------------------------
|
|
157
|
+
# Session Management Helpers
|
|
158
|
+
# -------------------------------------------------------------------------
|
|
159
|
+
|
|
160
|
+
# Lists all active sessions for the current user.
|
|
161
|
+
#
|
|
162
|
+
# Call authenticate_with_seshlock_access_token! before this method.
|
|
163
|
+
#
|
|
164
|
+
# @return [Array<Hash>] session info for each active refresh token
|
|
165
|
+
def seshlock_list_sessions
|
|
166
|
+
@current_seshlock_user.seshlock_sessions.map do |refresh_token|
|
|
167
|
+
{
|
|
168
|
+
id: refresh_token.id,
|
|
169
|
+
device: refresh_token.device_identifier,
|
|
170
|
+
created_at: refresh_token.created_at,
|
|
171
|
+
expires_at: refresh_token.expires_at,
|
|
172
|
+
current: refresh_token.id == @current_seshlock_access_token&.refresh_token_id
|
|
173
|
+
}
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Revokes all sessions for the current user.
|
|
178
|
+
#
|
|
179
|
+
# Call authenticate_with_seshlock_refresh_token! before this method.
|
|
180
|
+
# This will log the user out of all devices including the current one.
|
|
181
|
+
#
|
|
182
|
+
# @return [void]
|
|
183
|
+
def seshlock_revoke_all
|
|
184
|
+
@current_seshlock_refresh_token.user.revoke_all_seshlock_sessions!
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Revokes all sessions except the current one.
|
|
188
|
+
#
|
|
189
|
+
# Call authenticate_with_seshlock_access_token! before this method.
|
|
190
|
+
#
|
|
191
|
+
# @return [void]
|
|
192
|
+
def seshlock_revoke_others
|
|
193
|
+
@current_seshlock_user.revoke_other_seshlock_sessions!(
|
|
194
|
+
except_refresh_token: @current_seshlock_access_token.refresh_token
|
|
195
|
+
)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Revokes a specific session by ID.
|
|
199
|
+
#
|
|
200
|
+
# Call authenticate_with_seshlock_access_token! before this method.
|
|
201
|
+
#
|
|
202
|
+
# @param session_id [Integer] the refresh token ID to revoke
|
|
203
|
+
# @return [void]
|
|
204
|
+
# @raise [ActiveRecord::RecordNotFound] if session doesn't belong to user
|
|
205
|
+
def seshlock_revoke_session(session_id:)
|
|
206
|
+
refresh_token = @current_seshlock_user.seshlock_refresh_tokens.find(session_id)
|
|
207
|
+
refresh_token.revoke!
|
|
208
|
+
end
|
|
209
|
+
|
|
156
210
|
private
|
|
157
211
|
|
|
158
212
|
# Extracts the raw refresh token from params.
|
|
@@ -18,9 +18,37 @@ module Seshlock
|
|
|
18
18
|
through: :seshlock_refresh_tokens
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
#
|
|
21
|
+
# Issue a new session for this user.
|
|
22
|
+
#
|
|
23
|
+
# @param device [String, nil] optional device identifier
|
|
24
|
+
# @return [Seshlock::TokenPair] the issued token pair
|
|
22
25
|
def issue_seshlock_session(device: nil)
|
|
23
26
|
Seshlock::Sessions.issue_tokens_to(user: self, device: device)
|
|
24
27
|
end
|
|
28
|
+
|
|
29
|
+
# List all active sessions for this user.
|
|
30
|
+
#
|
|
31
|
+
# @return [ActiveRecord::Relation<Seshlock::RefreshToken>] active refresh tokens
|
|
32
|
+
def seshlock_sessions
|
|
33
|
+
seshlock_refresh_tokens.active.order(created_at: :desc)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Revoke all sessions for this user.
|
|
37
|
+
#
|
|
38
|
+
# @return [void]
|
|
39
|
+
def revoke_all_seshlock_sessions!
|
|
40
|
+
seshlock_refresh_tokens.active.find_each(&:revoke!)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Revoke all sessions except the specified one.
|
|
44
|
+
#
|
|
45
|
+
# @param except_refresh_token [Seshlock::RefreshToken] the session to keep active
|
|
46
|
+
# @return [void]
|
|
47
|
+
def revoke_other_seshlock_sessions!(except_refresh_token:)
|
|
48
|
+
seshlock_refresh_tokens
|
|
49
|
+
.active
|
|
50
|
+
.where.not(id: except_refresh_token.id)
|
|
51
|
+
.find_each(&:revoke!)
|
|
52
|
+
end
|
|
25
53
|
end
|
|
26
54
|
end
|
data/lib/seshlock/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: seshlock
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Inoa
|
|
@@ -67,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '0'
|
|
69
69
|
requirements: []
|
|
70
|
-
rubygems_version:
|
|
70
|
+
rubygems_version: 4.0.3
|
|
71
71
|
specification_version: 4
|
|
72
72
|
summary: Session tokens (access + refresh) for Rails apps.
|
|
73
73
|
test_files: []
|