brevio-session 0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c515c318b1b9d9dcc8f157a9fd507511d2462d43ddb62de9f439ce55e21c5da3
4
+ data.tar.gz: d104172c65410bf4e52d8087a2e8bcb30220cf1ef18d75d7d3f0a5eeaba2cb7d
5
+ SHA512:
6
+ metadata.gz: 5cfcdc09b39e5162e49d1ae0f386dfa59a5e5c62a6a80c7e763d5b67fd029bea0b422efba229caf6c525e1e9011f4d84bdf48ada003d92b5918c7a00da80b244
7
+ data.tar.gz: f2deb2e307e1bdcf2f91744bffd969ef5a48dd34638079b22693ca6ba0ac38cdbe342a7ecd525b12b666faff15338ec682add782738693f1ddf0ad0e69288e2e
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .byebug_history
2
+ *.gem
data/.rubocop.yml ADDED
@@ -0,0 +1,56 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ TargetRubyVersion: 3.2
4
+
5
+ Layout/EmptyLineAfterGuardClause:
6
+ Enabled: false
7
+
8
+ Layout/FirstHashElementIndentation:
9
+ EnforcedStyle: consistent
10
+
11
+ Layout/HashAlignment:
12
+ EnforcedHashRocketStyle: table
13
+
14
+ Layout/LineLength:
15
+ Max: 100
16
+
17
+ Layout/MultilineMethodCallIndentation:
18
+ EnforcedStyle: indented_relative_to_receiver
19
+
20
+ Metrics/BlockLength:
21
+ Exclude:
22
+ - "*.gemspec"
23
+
24
+ Naming/AccessorMethodName:
25
+ Exclude:
26
+ - test/**/*
27
+
28
+ Metrics/AbcSize:
29
+ Exclude:
30
+ - test/**/stubs/**/*
31
+
32
+ Metrics/ClassLength:
33
+ Exclude:
34
+ - test/**/stubs/**/*
35
+
36
+ Metrics/MethodLength:
37
+ Exclude:
38
+ - test/**/*
39
+
40
+ Style/Alias:
41
+ Exclude:
42
+ - test/**/*
43
+
44
+ Style/ClassAndModuleChildren:
45
+ Enabled: false
46
+
47
+ Style/ClassVars:
48
+ Exclude:
49
+ - test/**/*
50
+
51
+ Style/Documentation:
52
+ Enabled: false
53
+
54
+ Style/ModuleFunction:
55
+ Enabled: true
56
+ EnforcedStyle: extend_self
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,102 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ brevio-session (0.1)
5
+ actionpack (~> 7.0.3)
6
+ redis (~> 5.0)
7
+ zeitwerk (~> 2.6.7)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actionpack (7.0.4)
13
+ actionview (= 7.0.4)
14
+ activesupport (= 7.0.4)
15
+ rack (~> 2.0, >= 2.2.0)
16
+ rack-test (>= 0.6.3)
17
+ rails-dom-testing (~> 2.0)
18
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
19
+ actionview (7.0.4)
20
+ activesupport (= 7.0.4)
21
+ builder (~> 3.1)
22
+ erubi (~> 1.4)
23
+ rails-dom-testing (~> 2.0)
24
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
25
+ activesupport (7.0.4)
26
+ concurrent-ruby (~> 1.0, >= 1.0.2)
27
+ i18n (>= 1.6, < 2)
28
+ minitest (>= 5.1)
29
+ tzinfo (~> 2.0)
30
+ ast (2.4.2)
31
+ builder (3.2.4)
32
+ concurrent-ruby (1.1.10)
33
+ connection_pool (2.4.0)
34
+ crass (1.0.6)
35
+ debug (1.5.0)
36
+ irb (>= 1.3.6)
37
+ reline (>= 0.2.7)
38
+ erubi (1.11.0)
39
+ i18n (1.12.0)
40
+ concurrent-ruby (~> 1.0)
41
+ io-console (0.6.0)
42
+ irb (1.6.1)
43
+ reline (>= 0.3.0)
44
+ json (2.6.2)
45
+ loofah (2.19.0)
46
+ crass (~> 1.0.2)
47
+ nokogiri (>= 1.5.9)
48
+ mini_portile2 (2.8.1)
49
+ minitest (5.16.3)
50
+ nokogiri (1.13.9)
51
+ mini_portile2 (~> 2.8.0)
52
+ racc (~> 1.4)
53
+ parallel (1.22.1)
54
+ parser (3.1.2.1)
55
+ ast (~> 2.4.1)
56
+ racc (1.6.1)
57
+ rack (2.2.4)
58
+ rack-test (2.0.2)
59
+ rack (>= 1.3)
60
+ rails-dom-testing (2.0.3)
61
+ activesupport (>= 4.2.0)
62
+ nokogiri (>= 1.6)
63
+ rails-html-sanitizer (1.4.3)
64
+ loofah (~> 2.3)
65
+ rainbow (3.1.1)
66
+ redis (5.0.6)
67
+ redis-client (>= 0.9.0)
68
+ redis-client (0.14.1)
69
+ connection_pool
70
+ regexp_parser (2.5.0)
71
+ reline (0.3.2)
72
+ io-console (~> 0.5)
73
+ rexml (3.2.5)
74
+ rubocop (1.36.0)
75
+ json (~> 2.3)
76
+ parallel (~> 1.10)
77
+ parser (>= 3.1.2.1)
78
+ rainbow (>= 2.2.2, < 4.0)
79
+ regexp_parser (>= 1.8, < 3.0)
80
+ rexml (>= 3.2.5, < 4.0)
81
+ rubocop-ast (>= 1.20.1, < 2.0)
82
+ ruby-progressbar (~> 1.7)
83
+ unicode-display_width (>= 1.4.0, < 3.0)
84
+ rubocop-ast (1.21.0)
85
+ parser (>= 3.1.1.0)
86
+ ruby-progressbar (1.11.0)
87
+ tzinfo (2.0.5)
88
+ concurrent-ruby (~> 1.0)
89
+ unicode-display_width (2.2.0)
90
+ zeitwerk (2.6.7)
91
+
92
+ PLATFORMS
93
+ arm64-darwin-21
94
+
95
+ DEPENDENCIES
96
+ brevio-session!
97
+ bundler (~> 2.1)
98
+ debug (~> 1.5.0, <= 1.6.0)
99
+ rubocop (~> 1.35)
100
+
101
+ BUNDLED WITH
102
+ 2.3.22
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Nicolay Hvidsten
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Brevio Session
2
+
3
+ This gem is a thin wrapper around the Brevio HTTP session, which is created by the [Brevio ID](https://github.com/team-brevio/id) service, and stored in Redis. The HTTP session is shared by all customer-facing Brevio services, enabling single sign-on.
4
+
5
+ The session is shared by storing the encrypted Redis key in an agreed-upon cookie (`BREVIO_ID_COOKIE`). The passphrase used for the encryption is also agreed-upon between services (`BREVIO_ID_SECRET_KEY`).
6
+
7
+ The gem provides three utility functions, used in the application controllers:
8
+
9
+ - `fetch_brevio_session`: Loads the Brevio session from Redis and returns a `HashWithIndifferentAccess` wrapper around it.
10
+ - `fetch_brevio_session!`: Same as above, but raises an error if the session isn't present.
11
+ - `brevio_logged_in?`: Returns a boolean flag indicating whether there exists a current Brevio session.
12
+
13
+ ## Installation
14
+
15
+ ```ruby
16
+ # Gemfile
17
+ gem 'brevio-session'
18
+
19
+ # config/initializers/brevio_session.rb
20
+ Brevio::Session::Config.configure do |config|
21
+ config.debug = ENV.fetch('BREVIO_SESSION_DEBUG', false) # Logs additional information for session retrieval
22
+ config.production = Rails.env.production?
23
+ config.redis = Brevio::Redis::Client.new(ENV.fetch('BREVIO_ID_REDIS_URL'))
24
+ config.secret_key = ENV.fetch('BREVIO_ID_SECRET_KEY')
25
+ config.session_cookie = ENV.fetch('BREVIO_ID_COOKIE')
26
+ config.session_expire = Integer(ENV.fetch('BREVIO_ID_EXPIRE')).minutes
27
+ end
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ To gain access to the utility functions mentioned above, you need to include the `Brevio::Session` module in
33
+ any Rails controller. The module is a [Rails Concern](https://api.rubyonrails.org/v7.0.4/classes/ActiveSupport/Concern.html) which ensures it is being included in the correct context.
34
+
35
+ ```ruby
36
+ class ApiController
37
+ include Brevio::Session
38
+
39
+ def action
40
+ brevio_session = fetch_brevio_session
41
+ puts brevio_session
42
+ # => { user_id: 1, audit_company_id: 1, user_stamp: '2022-01-0107:39:58.281894000' }
43
+ end
44
+ end
45
+ ```
46
+
47
+ The session itself contains the following information (subject to change in Brevio ID):
48
+
49
+ - `user_id`: The primary key for the user in the Brevio ID database.
50
+ - `audit_company_id`: The primary key for the audit company in the Brevio ID database.
51
+ - `user_stamp`: Timestamp indicating when the user was last updated in Brevio ID.
52
+
53
+ ## Testing
54
+
55
+ Since we want to test features with logged-in users, we need to be able to emulate a shared Brevio session.
56
+
57
+ First off, we need to mock the Redis session, which is done by calling the `Brevio::Session::Testing.setup!` function.
58
+
59
+ ```ruby
60
+ Brevio::Session::Testing.setup!(logger: Rails.logger)
61
+ # => '--- 👨‍🔬 Setting up Brevio Session gem for testing 👨‍🔬 ---'
62
+ ```
63
+
64
+ We can then simulate a logged-in user by calling the `Brevio::Session::Testing.brevio_login` function.
65
+
66
+ ```ruby
67
+ class TestCase < ActionDispatch::IntegrationTest
68
+ include Brevio::Session::Testing
69
+
70
+ let(:user) { create(:user) }
71
+
72
+ test 'is logged in' do
73
+ brevio_login(user)
74
+ get(dashboard_path(user))
75
+ assert_response(:ok)
76
+ end
77
+ end
78
+ ```
79
+
80
+ ## License
81
+
82
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'brevio-session'
5
+ spec.version = '0.1'
6
+ spec.authors = ['Brevio AS']
7
+ spec.email = ['support@brevio.com']
8
+ spec.files = `git ls-files -z`.split("\0")
9
+
10
+ spec.homepage = 'https://github.com/team-brevio/brevio-session'
11
+ spec.summary = 'Brevio session wrapper'
12
+ spec.required_ruby_version = '3.2'
13
+ spec.description = 'Wrapper around HTTP session set by Brevio ID'
14
+ spec.license = 'MIT'
15
+
16
+ spec.add_development_dependency 'bundler', '~> 2.1'
17
+ spec.add_development_dependency 'debug', '~> 1.5.0', '<= 1.6.0'
18
+ spec.add_development_dependency 'rubocop', '~> 1.35'
19
+ spec.add_dependency 'actionpack', '~> 7.0.3'
20
+ spec.add_dependency 'redis', '~> 5.0'
21
+ spec.add_dependency 'zeitwerk', '~> 2.6.7'
22
+ spec.metadata['rubygems_mfa_required'] = 'true'
23
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Brevio::Session::Config
4
+ extend self
5
+
6
+ attr_accessor :config
7
+
8
+ def configure
9
+ self.config ||= Configuration.new
10
+ yield(config)
11
+ end
12
+
13
+ class Configuration
14
+ attr_accessor(
15
+ :debug,
16
+ :encryption_key,
17
+ :logger,
18
+ :production,
19
+ :redis,
20
+ :session_cookie,
21
+ :session_expire
22
+ )
23
+ alias debug? debug
24
+ alias production? production
25
+ end
26
+
27
+ module Redis
28
+ module Prefixes
29
+ AUDIT_COMPANY = 'brevio-id:audit-company'
30
+ SESSION = 'brevio-id:session'
31
+ USER = 'brevio-id:user'
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Brevio::Session
4
+ module Cookies::Parse
5
+ extend self
6
+
7
+ def perform!(cookie)
8
+ raise NilSession if cookie.nil?
9
+ data, iv, auth_tag = cookie.split('--').map { |value| Base64.decode64(value) }
10
+ cipher = OpenSSL::Cipher.new(CIPHER)
11
+ secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1(brevio_config.encryption_key,
12
+ SALT, 1000, cipher.key_len)
13
+
14
+ cipher.decrypt
15
+ cipher.key = secret
16
+ cipher.iv = iv
17
+ cipher.auth_tag = auth_tag
18
+ cipher.auth_data = ''
19
+
20
+ cookie_payload = cipher.update(data)
21
+ cookie_payload << cipher.final
22
+ cookie_payload = JSON.parse(cookie_payload)
23
+ key = JSON.parse(Base64.decode64(cookie_payload['_rails']['message']))
24
+
25
+ "#{Config::Redis::Prefixes::SESSION}:#{key}"
26
+ end
27
+
28
+ private
29
+
30
+ # https://github.com/team-brevio/brevio-id-gem/blob/master/lib/brevio_id/session/cookie_jar.rb#L79
31
+ CIPHER = 'aes-256-gcm'
32
+ # https://github.com/team-brevio/brevio-id-gem/blob/master/lib/brevio_id/session/cookie_jar.rb#L84
33
+ SALT = 'authenticated encrypted cookie'
34
+
35
+ def brevio_config
36
+ Config.config
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Brevio::Session
4
+ module Redis
5
+ extend self
6
+
7
+ def get(key)
8
+ brevio_config.redis.get(key)
9
+ end
10
+
11
+ def expire(key, exp)
12
+ brevio_config.redis.expire(key, exp)
13
+ end
14
+
15
+ private
16
+
17
+ def brevio_config
18
+ Config.config
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Brevio::Session
4
+ # Module used to enable testing for controllers using the Brevio session.
5
+ # Mocks a login to a shared redis, with keys generated by the Brevio::Session::CookieJar.
6
+ #
7
+ module Testing
8
+ # Simulates a user with a shared Brevio session. We can specify which *brevio_id* the
9
+ # mocked ID service should return (as well as a custom last updated_at timestamp).
10
+ #
11
+ # The user needs to have the following methods defined: #brevio_id, #audit_company
12
+ #
13
+ def brevio_login(user, updated_at: Time.current.yesterday)
14
+ redis_key = SecureRandom.hex(6)
15
+
16
+ session_hash = { user_id: user.brevio_id,
17
+ audit_company_id: user.audit_company.brevio_id,
18
+ user_stamp: updated_at }
19
+
20
+ Testing.config.logger.info "setting Brevio session to #{session_hash}"
21
+
22
+ Testing.config.gem_config.redis.set(
23
+ redis_key,
24
+ session_hash
25
+ )
26
+ set_cookie(redis_key)
27
+ end
28
+
29
+ def brevio_logout
30
+ cookies[Testing.config.gem_config.session_cookie] = nil
31
+ end
32
+
33
+ # rubocop:disable Naming/AccessorMethodName (set makes sense here)
34
+ def set_cookie(value)
35
+ cookies[Testing.config.gem_config.session_cookie] = value
36
+ end
37
+ # rubocop:enable Naming/AccessorMethodName
38
+
39
+ extend self
40
+
41
+ attr_accessor :sessions, :config
42
+
43
+ def setup!(logger:)
44
+ self.config = Config.new
45
+ config.logger = logger
46
+ config.gem_config = Brevio::Session::Config.config
47
+ config.logger.info '--- 👨‍🔬 Setting up Brevio Session gem for testing 👨‍🔬 ---'
48
+
49
+ # Ensures we return a mocked value of the session, rather than something which depends on
50
+ # the cryptographically signed value.
51
+ #
52
+ Brevio::Session::Cookies::Parse.send(:define_method, :perform!) do |cookie|
53
+ raise NilSession if cookie.nil?
54
+ cookie
55
+ end
56
+ end
57
+
58
+ class Config
59
+ attr_accessor :logger, :gem_config
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module Brevio::Session
6
+ extend ActiveSupport::Concern
7
+
8
+ # By including this module into a Rails controller you will have access to the convenience methods
9
+ # fetch_brevio_session(!) and brevio_logged_in? which acts as a wrapper around the decrypting of
10
+ # predefined session cookies and sessions stored in Redis.
11
+ #
12
+ # We also require access to instance attributes like #request and the cookie jar, which are only
13
+ # available in the context of a controller.
14
+ #
15
+ included do
16
+ raise 'Included Brevio::Session outside of controller' unless self <= ActionController::Base
17
+ end
18
+
19
+ # Fetches the Brevio session from Redis, based on the encrypted key stored in the client's cookie.
20
+ # Returns *nil* if there's no session present.
21
+ #
22
+ def fetch_brevio_session
23
+ brevio_session, redis_key = fetch_session
24
+ return nil if brevio_session.nil?
25
+ if brevio_config.debug?
26
+ brevio_config.logger.info "[brevio-session] Found session #{brevio_session.inspect}"
27
+ end
28
+ refresh_session(redis_key) unless params.transform_keys(&:underscore)[:no_session].present?
29
+ brevio_session
30
+ rescue RuntimeError => e
31
+ brevio_config.logger.error "[brevio-session] #{e.message}"
32
+ nil
33
+ end
34
+
35
+ # Calls the above function, but raises an exception if the session isn't present.
36
+ def fetch_brevio_session!
37
+ brevio_session, redis_key = fetch_session
38
+ raise NilSession, 'Brevio session was nil' if brevio_session.nil?
39
+ refresh_session(redis_key) unless params.transform_keys(&:underscore)[:no_session].present?
40
+ brevio_session
41
+ end
42
+
43
+ # Returns a boolean flag indicating whether the current client has a Brevio session cookie set,
44
+ # and whether this cookie contains a user ID.
45
+ #
46
+ def brevio_logged_in?
47
+ fetch_session&.dig(:user_id).present?
48
+ end
49
+
50
+ private
51
+
52
+ def brevio_config
53
+ Config.config
54
+ end
55
+
56
+ def fetch_session
57
+ brevio_config.logger.info '[brevio-session] Fetching Brevio session'
58
+ cookie = request.cookie_jar[brevio_config.session_cookie]
59
+ redis_key = Cookies::Parse.perform!(cookie)
60
+ brevio_session = Redis.get(redis_key)
61
+ raise NilSession if brevio_session.nil?
62
+ [brevio_session.with_indifferent_access, redis_key]
63
+ rescue RuntimeError => e
64
+ brevio_config.logger.error "[brevio-session] --- 💣 Couldn't fetch Brevio session 💣 ---"
65
+ brevio_config.logger.error "[brevio-session] #{e.message}"
66
+ nil
67
+ end
68
+
69
+ # Refreshes the Brevio session cookie, avoding its expiry. This is helpful to
70
+ # ensure the user stays logged in through interacting with the application.
71
+ #
72
+ def refresh_session(redis_key)
73
+ brevio_config.logger.info '[brevio-session] Refreshing Brevio session' if brevio_config.debug?
74
+ cookies[brevio_config.session_cookie] = {
75
+ value: request.cookie_jar[brevio_config.session_cookie],
76
+ domain: :all,
77
+ expires: brevio_config.session_expire,
78
+ httponly: true,
79
+ secure: true
80
+ }
81
+ Redis.expire(redis_key, brevio_config.session_expire)
82
+ rescue RuntimeError => e
83
+ brevio_config.logger.error "[brevio-session] --- 💣 Couldn't refresh Brevio session 💣 ---"
84
+ brevio_config.logger.error "[brevio-session] #{e.message}"
85
+ end
86
+
87
+ class << self
88
+ # Function used to fetch the current audit company session for a given Brevio ID.
89
+ # This session contains information about an audit company shared by any number of
90
+ # users. If the audit company has been updated in ID (e.g. changed logo or name), the
91
+ # database record of the local service (e.g. Confirm/Sign) will fetch the updates if
92
+ # the timestamp in this session is greater than their own local timestamps.
93
+ #
94
+ def audit_company_updated_at(brevio_id)
95
+ Config.config.redis.get("#{Config::Redis::Prefixes::AUDIT_COMPANY}:#{brevio_id}")
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file exists so we can do require 'brevio-session'
4
+ # See:
5
+ # https://github.com/rest-client/rest-client/blob/master/lib/rest_client.rb
6
+ require "#{File.dirname(__FILE__)}/brevio_session"
7
+
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zeitwerk'
4
+
5
+ # Silences warnings for auto-defined constants, e.g. "Brevio" in this case due to having a "Brevio" folder
6
+ Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
7
+
8
+ loader = Zeitwerk::Loader.for_gem
9
+ loader.ignore("#{__dir__}/brevio-session.rb")
10
+ loader.setup # ready!
11
+
12
+ require 'action_dispatch'
13
+
14
+ module Brevio::Session
15
+ class NilSession < StandardError; end
16
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class BrevioSessionIntegrationTest < Minitest::Test
6
+ include Rack::Test::Methods
7
+ include Brevio::Session::Testing
8
+
9
+ def brevio_redis
10
+ Brevio::Session::Config.config.redis
11
+ end
12
+
13
+ def user
14
+ UserStub.new(brevio_id: 1)
15
+ end
16
+
17
+ def test_sets_brevio_session_in_redis
18
+ session = brevio_login(user)
19
+ get '/', nil, cookie: "brevio_session=#{session}"
20
+ assert last_response.ok?
21
+ assert current_session.cookie_jar['brevio_session']
22
+ assert_equal user.brevio_id, brevio_redis.get("brevio-id:session:#{session}")[:user_id]
23
+ json_body = JSON.parse(last_response.body)
24
+ assert_equal user.brevio_id, json_body['user_id']
25
+ end
26
+
27
+ def test_user_stamp
28
+ time = Time.current
29
+ session = brevio_login(user, updated_at: time)
30
+ get '/', nil, cookie: "brevio_session=#{session}"
31
+ assert last_response.ok?
32
+ json_body = JSON.parse(last_response.body)
33
+ # ceil ceils the subsecond to a default decimal (0) by default. We don't really care about
34
+ # microsecond precision here during the JSON parsing/dumping
35
+ assert_equal time.ceil, Time.parse(json_body['user_stamp']).ceil
36
+ end
37
+
38
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Brevio ID stores its session using redis-session-store, which stores all values as JSON.
4
+ # The returned value is a JSON string, which needs to be parsed by the redis client. The native
5
+ # Redis.get would simply return the JSON string, so we need to wrap it.
6
+ #
7
+ # The services consuming the Brevio::Session (e.g. Confirm/Sign) already assume the values
8
+ # in Redis are all JSON (see domain/brevio/redis/client.rb).
9
+ #
10
+ #
11
+ class RedisJSONWrapper
12
+ def set(key, value)
13
+ redis.set(key, value.to_json)
14
+ end
15
+
16
+ def get(key)
17
+ raw = redis.get(key)
18
+ return nil if raw.nil?
19
+
20
+ value = JSON.parse(raw)
21
+ return value if value.empty?
22
+
23
+ value.with_indifferent_access
24
+ end
25
+
26
+ def del(keys)
27
+ redis.del(keys)
28
+ end
29
+
30
+ def expire(key, expiry)
31
+ redis.expire(key, expiry)
32
+ end
33
+
34
+ private
35
+
36
+ def redis
37
+ @redis ||= ::Redis.new
38
+ end
39
+ end
data/test/stubs.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UserStub
4
+ attr_accessor :brevio_id, :audit_company
5
+
6
+ def initialize(attrs)
7
+ @brevio_id = attrs[:brevio_id]
8
+ @audit_company = AuditCompanyStub.new(brevio_id: @brevio_id + 1)
9
+ end
10
+ end
11
+
12
+ class AuditCompanyStub
13
+ attr_accessor :brevio_id
14
+
15
+ def initialize(attrs)
16
+ @brevio_id = attrs[:brevio_id]
17
+ end
18
+ end
data/test/test_app.rb ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Based on https://github.com/rails/rails/blob/6-0-stable/guides/bug_report_templates/action_controller_master.rb
4
+
5
+ require 'action_controller/railtie'
6
+ require 'rack/test'
7
+ require 'brevio-session'
8
+
9
+ class TestApp < Rails::Application
10
+ config.root = __dir__
11
+ config.hosts << 'example.org'
12
+ config.session_store :cookie_store, key: 'brevio_session'
13
+ secrets.secret_key_base = 'secret_key_base'
14
+
15
+ config.logger = Logger.new($stdout)
16
+ config.log_level = :info
17
+ Rails.logger = config.logger
18
+
19
+ routes.draw do
20
+ get '/' => 'test#index'
21
+ end
22
+ end
23
+
24
+ class TestController < ActionController::Base
25
+ include Brevio::Session
26
+ include Rails.application.routes.url_helpers
27
+
28
+ def logger
29
+ Rails.logger
30
+ end
31
+
32
+ def index
33
+ brevio_session = fetch_brevio_session
34
+ render json: brevio_session.to_json
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'rack/test'
5
+
6
+ require 'debug'
7
+ require 'fakeredis'
8
+ require 'priscilla'
9
+ require 'brevio-session'
10
+ require 'brevio_session/testing'
11
+
12
+ require 'redis_json_wrapper'
13
+ require 'stubs'
14
+ require 'test_app'
15
+
16
+ Brevio::Session::Config.configure do |config|
17
+ config.debug = true
18
+ config.production = false
19
+ config.redis = RedisJSONWrapper.new
20
+ config.secret_key = 'secret_key_base'
21
+ config.session_cookie = 'brevio_session'
22
+ config.session_expire = 45.minutes
23
+ end
24
+
25
+ Brevio::Session::Testing.setup!(logger: Rails.logger)
26
+
27
+ module Minitest
28
+ class Test
29
+ include Rack::Test::Methods
30
+ include TestApp.routes.url_helpers
31
+
32
+ def app
33
+ TestApp
34
+ end
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brevio-session
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Brevio AS
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-04-18 00:00:00.000000000 Z
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.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: debug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.0
34
+ - - "<="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.6.0
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: 1.5.0
44
+ - - "<="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.6.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rubocop
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.35'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.35'
61
+ - !ruby/object:Gem::Dependency
62
+ name: actionpack
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 7.0.3
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 7.0.3
75
+ - !ruby/object:Gem::Dependency
76
+ name: redis
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '5.0'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '5.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: zeitwerk
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 2.6.7
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 2.6.7
103
+ description: Wrapper around HTTP session set by Brevio ID
104
+ email:
105
+ - support@brevio.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".gitignore"
111
+ - ".rubocop.yml"
112
+ - ".ruby-version"
113
+ - Gemfile
114
+ - Gemfile.lock
115
+ - LICENSE.txt
116
+ - README.md
117
+ - brevio-session.gemspec
118
+ - lib/brevio-session.rb
119
+ - lib/brevio/session.rb
120
+ - lib/brevio/session/config.rb
121
+ - lib/brevio/session/cookies/parse.rb
122
+ - lib/brevio/session/redis.rb
123
+ - lib/brevio/session/testing.rb
124
+ - lib/brevio_session.rb
125
+ - test/brevio_session_integration_test.rb
126
+ - test/redis_json_wrapper.rb
127
+ - test/stubs.rb
128
+ - test/test_app.rb
129
+ - test/test_helper.rb
130
+ homepage: https://github.com/team-brevio/brevio-session
131
+ licenses:
132
+ - MIT
133
+ metadata:
134
+ rubygems_mfa_required: 'true'
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - '='
142
+ - !ruby/object:Gem::Version
143
+ version: '3.2'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubygems_version: 3.4.1
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: Brevio session wrapper
154
+ test_files: []