diff --git a/lib/workos/user_management.rb b/lib/workos/user_management.rb index 6d59f2be..238c3cd6 100644 --- a/lib/workos/user_management.rb +++ b/lib/workos/user_management.rb @@ -7,6 +7,8 @@ module WorkOS # The UserManagement module provides convenience methods for working with the # WorkOS User platform. You'll need a valid API key. module UserManagement + autoload :Session, 'workos/user_management/session' + module Types # The ProviderEnum is a declaration of a # fixed set of values for User Management Providers. @@ -740,6 +742,40 @@ def list_auth_factors(user_id:) ) end + # Get all sessions for a user + # + # @param [String] user_id The id for the user. + # @param [Hash] options + # @option options [String] limit Maximum number of records to return. + # @option options [String] order The order in which to paginate records + # @option options [String] before Pagination cursor to receive records + # before a provided Session ID. + # @option options [String] after Pagination cursor to receive records + # after a provided Session ID. + # + # @return [WorkOS::Types::ListStruct] + def list_sessions(user_id:, options: {}) + options[:order] ||= 'desc' + response = execute_request( + request: get_request( + path: "/user_management/users/#{user_id}/sessions", + auth: true, + params: options, + ), + ) + + parsed_response = JSON.parse(response.body) + + sessions = parsed_response['data'].map do |session| + ::WorkOS::UserManagement::Session.new(session.to_json) + end + + WorkOS::Types::ListStruct.new( + data: sessions, + list_metadata: parsed_response['list_metadata'], + ) + end + # Gets an email verification object # # @param [String] id The unique ID of the EmailVerification object. diff --git a/lib/workos/user_management/session.rb b/lib/workos/user_management/session.rb new file mode 100644 index 00000000..7a9a5bef --- /dev/null +++ b/lib/workos/user_management/session.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module WorkOS + module UserManagement + # The Session class provides a lightweight wrapper around + # a WorkOS Session resource. This class is not meant to be instantiated + # in user space, and is instantiated internally but exposed. + class Session + include HashProvider + attr_accessor :id, :object, :user_id, :organization_id, :status, :auth_method, + :ip_address, :user_agent, :expires_at, :ended_at, :created_at, :updated_at + + # rubocop:disable Metrics/AbcSize + def initialize(json) + hash = JSON.parse(json, symbolize_names: true) + + @id = hash[:id] + @object = hash[:object] + @user_id = hash[:user_id] + @organization_id = hash[:organization_id] + @status = hash[:status] + @auth_method = hash[:auth_method] + @ip_address = hash[:ip_address] + @user_agent = hash[:user_agent] + @expires_at = hash[:expires_at] + @ended_at = hash[:ended_at] + @created_at = hash[:created_at] + @updated_at = hash[:updated_at] + end + # rubocop:enable Metrics/AbcSize + + def to_json(*) + { + id: id, + object: object, + user_id: user_id, + organization_id: organization_id, + status: status, + auth_method: auth_method, + ip_address: ip_address, + user_agent: user_agent, + expires_at: expires_at, + ended_at: ended_at, + created_at: created_at, + updated_at: updated_at, + } + end + + # Revoke this session + # + # @return [Bool] - returns `true` if successful + def revoke + WorkOS::UserManagement.revoke_session(session_id: id) + end + end + end +end diff --git a/spec/lib/workos/user_management_spec.rb b/spec/lib/workos/user_management_spec.rb index f852db47..d8613dd8 100644 --- a/spec/lib/workos/user_management_spec.rb +++ b/spec/lib/workos/user_management_spec.rb @@ -1797,6 +1797,45 @@ end end + describe '.list_sessions' do + context 'with a valid user_id' do + it 'returns a list of sessions' do + VCR.use_cassette('user_management/list_sessions/valid') do + result = described_class.list_sessions( + user_id: 'user_01H7TVSKS45SDHN5V9XPSM6H44', + ) + + expect(result.data).to be_an(Array) + expect(result.data.first).to be_a(WorkOS::UserManagement::Session) + expect(result.data.first.id).to eq('session_01H96FETXGTW2S0V5V9XPSM6H44') + expect(result.data.first.status).to eq('active') + expect(result.data.first.auth_method).to eq('password') + end + end + + it 'returns sessions that can be revoked' do + VCR.use_cassette('user_management/list_sessions/valid') do + result = described_class.list_sessions( + user_id: 'user_01H7TVSKS45SDHN5V9XPSM6H44', + ) + session = result.data.first + + expect(described_class).to receive(:post_request) do |options| + expect(options[:path]).to eq('/user_management/sessions/revoke') + expect(options[:body]).to eq({ session_id: 'session_01H96FETXGTW2S0V5V9XPSM6H44' }) + expect(options[:auth]).to be true + end.and_return(double('request')) + + expect(described_class).to receive(:execute_request).and_return( + double('response', is_a?: true), + ) + + expect(session.revoke).to be true + end + end + end + end + describe '.get_logout_url' do it 'returns a logout url for the given session ID' do result = described_class.get_logout_url( diff --git a/spec/support/fixtures/vcr_cassettes/user_management/list_sessions/valid.yml b/spec/support/fixtures/vcr_cassettes/user_management/list_sessions/valid.yml new file mode 100644 index 00000000..34bc3cf9 --- /dev/null +++ b/spec/support/fixtures/vcr_cassettes/user_management/list_sessions/valid.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.workos.com/user_management/users/user_01H7TVSKS45SDHN5V9XPSM6H44/sessions?order=desc + body: + encoding: US-ASCII + string: '' + headers: + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - WorkOS; ruby/3.0.2; arm64-darwin22; v2.16.0 + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 05 Jan 2026 12:00:00 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + body: + encoding: ASCII-8BIT + string: '{"object":"list","data":[{"object":"session","id":"session_01H96FETXGTW2S0V5V9XPSM6H44","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:146.0) Gecko/20100101 Firefox/146.0","ip_address":"192.168.1.1","organization_id":"org_01H96FETXGTW2SXRA136PCMAQJ0","user_id":"user_01H7TVSKS45SDHN5V9XPSM6H44","auth_method":"password","status":"active","expires_at":"2027-01-02T03:47:13.027Z","ended_at":null,"created_at":"2026-01-02T03:47:13.024Z","updated_at":"2026-01-05T02:56:09.379Z"}],"list_metadata":{"before":null,"after":null}}' + http_version: + recorded_at: Mon, 05 Jan 2026 12:00:00 GMT +recorded_with: VCR 5.0.0