rails_sso 0.0.1 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6c8245291e6e960c35dfa2e46a034e44ba3ee1d0
4
- data.tar.gz: acbd5d0746f35fcdb1e9bf0ff2ba727a00393d4c
3
+ metadata.gz: 5d21cea945bc44cb3fb84f1d2da048091d6f4661
4
+ data.tar.gz: 9f4bef5ac2353b226593a063a301cad4f618818a
5
5
  SHA512:
6
- metadata.gz: 207514bc02f2ed7fbede366398fb45b79d76341b7173e92c78a937ddbb7b3afcf75d9a11d1020a5d6e470c05f06e77d74c7acf74a9492bc9a38ab458665fa4e3
7
- data.tar.gz: 2326dd8b701d1797e3c970c6436d09c428c08cc60cf39c82f28c4928b3fe948d599ed8f469f52bec7682d94acf30d5bb192967833b8024724116a5eb169be568
6
+ metadata.gz: 8a2dd465782b4e9372594fbfd531edf0d769f0f285fbf663e8e2855ad12c348cfb0e8614ba75dc573b8d0fcd622ff0f7946efcc6e0b306cd24db7f56c26b9799
7
+ data.tar.gz: 8efb688b7383bcb5aa783e610d94317ecd22fb7aa5f514d829da0cde7836f76ed3a42a5567a17a88516fb38b96314ace659d81bd829eec0e514c49c8691e694f
data/README.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # SSO client Rails Engine
2
2
 
3
+ [![Dependency Status](https://gemnasium.com/monterail/rails_sso.svg)](https://gemnasium.com/monterail/rails_sso)
4
+ [![Gem Version](https://badge.fury.io/rb/rails_sso.svg)](http://badge.fury.io/rb/rails_sso)
5
+
6
+ ## About
7
+
8
+ *SOON*
9
+
3
10
  ## Installation
4
11
 
5
12
  Add engine and [omniauth](https://github.com/intridea/omniauth-oauth2) provider gems to your project:
@@ -26,6 +33,8 @@ RailsSso.configure do |config|
26
33
  config.provider_profile_path = '/api/v1/profile'
27
34
  # set if you support single sign out
28
35
  config.provider_sign_out_path = '/api/v1/session'
36
+ # enable cache (will use Rails.cache store)
37
+ config.use_cache = Rails.application.config.action_controller.perform_caching
29
38
 
30
39
  # user fields to synchronize from API
31
40
  config.user_fields = [
@@ -56,9 +65,11 @@ Available helpers for controllers and views:
56
65
  * `current_user`
57
66
  * `user_signed_in?`
58
67
 
59
- Available filters for controllers:
68
+ Available filters and helpers for controllers:
60
69
 
61
70
  * `authenticate_user!`
71
+ * `save_access_token!`
72
+ * `invalidate_access_token!`
62
73
 
63
74
  Available helpers for views:
64
75
 
@@ -69,11 +80,11 @@ Available helpers for views:
69
80
 
70
81
  Required methods:
71
82
 
72
- * `find_by({ key: value })`
73
- * `create_with_id(id, attrs)`
83
+ * `find_by_sso_id(id)`
84
+ * `create_with_sso_id(id, attrs)`
74
85
  * `update(record, attrs)`
75
86
 
76
- Example:
87
+ Example with `ActiveRecord` user model:
77
88
 
78
89
  ```ruby
79
90
  # app/repositories/user_repository.rb
@@ -85,13 +96,13 @@ class UserRepository
85
96
  self.adapter = adapter
86
97
  end
87
98
 
88
- def find_by(attrs)
89
- adapter.find_by(attrs)
99
+ def find_by_sso_id(id)
100
+ adapter.find_by(sso_id: id)
90
101
  end
91
102
 
92
- def create_with_id(id, attrs)
103
+ def create_with_sso_id(id, attrs)
93
104
  adapter.new(attrs) do |user|
94
- user.id = id
105
+ user.sso_id = id
95
106
  user.save!
96
107
  end
97
108
  end
data/Rakefile CHANGED
@@ -4,21 +4,6 @@ rescue LoadError
4
4
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
5
  end
6
6
 
7
- require 'rdoc/task'
8
-
9
- RDoc::Task.new(:rdoc) do |rdoc|
10
- rdoc.rdoc_dir = 'rdoc'
11
- rdoc.title = 'RailsSso'
12
- rdoc.options << '--line-numbers'
13
- rdoc.rdoc_files.include('README.rdoc')
14
- rdoc.rdoc_files.include('lib/**/*.rb')
15
- end
16
-
17
-
18
-
19
-
20
-
21
-
22
7
  Bundler::GemHelper.install_tasks
23
8
 
24
9
  require 'rake/testtask'
@@ -3,14 +3,13 @@ module RailsSso
3
3
  skip_before_action :authenticate_user!, only: [:create]
4
4
 
5
5
  def create
6
- session[:access_token] = auth_hash.credentials.token
7
- session[:refresh_token] = auth_hash.credentials.refresh_token
6
+ save_access_token!(auth_hash.credentials)
8
7
 
9
8
  redirect_to root_path
10
9
  end
11
10
 
12
11
  def destroy
13
- invalidate_user!
12
+ invalidate_access_token!
14
13
 
15
14
  redirect_to root_path
16
15
  end
@@ -0,0 +1,19 @@
1
+ module RailsSso
2
+ class FetchUser
3
+ def initialize(access_token)
4
+ @access_token = access_token
5
+ end
6
+
7
+ def call
8
+ yield(get)
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :access_token
14
+
15
+ def get
16
+ access_token.get(RailsSso.provider_profile_path).parsed
17
+ end
18
+ end
19
+ end
@@ -1,16 +1,16 @@
1
1
  module RailsSso
2
2
  class UpdateUser
3
3
  def initialize(data, options = {})
4
- @id, @data = data.delete('id'), data
4
+ @id, @data = data['id'], data.except('id')
5
5
  @fields, @repository = options.values_at(:fields, :repository)
6
6
  end
7
7
 
8
8
  def call
9
- if user = repository.find_by(id: id)
9
+ if user = repository.find_by_sso_id(id)
10
10
  repository.update(user, params)
11
11
  user
12
12
  else
13
- repository.create_with_id(id, params)
13
+ repository.create_with_sso_id(id, params)
14
14
  end
15
15
  end
16
16
 
@@ -0,0 +1,52 @@
1
+ require 'faraday-http-cache'
2
+
3
+ module RailsSso
4
+ class AccessToken
5
+ attr_reader :token, :refresh_token
6
+
7
+ delegate :get, :patch, :post, :put, :delete, to: :access_token
8
+
9
+ def self.from_access_token(access_token)
10
+ new(access_token.token, access_token.refresh_token)
11
+ end
12
+
13
+ def initialize(token, refresh_token)
14
+ @token, @refresh_token = token, refresh_token
15
+ end
16
+
17
+ def refresh!
18
+ self.class.from_access_token(access_token.refresh!)
19
+ end
20
+
21
+ def access_token
22
+ @access_token ||= OAuth2::AccessToken.new(client, token, {
23
+ refresh_token: refresh_token
24
+ })
25
+ end
26
+
27
+ private
28
+
29
+ def client
30
+ strategy.client.tap do |c|
31
+ if RailsSso.use_cache
32
+ c.options[:connection_build] = Proc.new do |conn|
33
+ conn.use :http_cache,
34
+ store: Rails.cache,
35
+ logger: Rails.logger,
36
+ shared_cache: false
37
+
38
+ conn.adapter Faraday.default_adapter
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def strategy
45
+ @strategy ||= strategy_class.new(nil, RailsSso.provider_key, RailsSso.provider_secret)
46
+ end
47
+
48
+ def strategy_class
49
+ "OmniAuth::Strategies::#{RailsSso.provider_name.classify}".constantize
50
+ end
51
+ end
52
+ end
@@ -7,7 +7,9 @@ module RailsSso
7
7
  end
8
8
 
9
9
  def current_user
10
- @current_user ||= fetch_user
10
+ @current_user ||= fetch_user do |user|
11
+ update_user(user).call
12
+ end
11
13
  end
12
14
 
13
15
  def user_signed_in?
@@ -18,7 +20,11 @@ module RailsSso
18
20
  redirect_to sign_in_path unless user_signed_in?
19
21
  end
20
22
 
21
- def invalidate_user!
23
+ def access_token
24
+ RailsSso::AccessToken.new(session[:access_token], session[:refresh_token])
25
+ end
26
+
27
+ def invalidate_access_token!
22
28
  if RailsSso.provider_sign_out_path
23
29
  access_token.delete(RailsSso.provider_sign_out_path)
24
30
  end
@@ -26,32 +32,40 @@ module RailsSso
26
32
  reset_session
27
33
  end
28
34
 
29
- private
35
+ def save_access_token!(access_token)
36
+ session[:access_token] = access_token.token
37
+ session[:refresh_token] = access_token.refresh_token
38
+ end
30
39
 
31
- def fetch_user
32
- return unless session[:access_token]
40
+ def refresh_access_token!
41
+ save_access_token!(access_token.refresh!)
33
42
 
34
- RailsSso::FetchUser.new(access_token, session).get_and_cache
43
+ yield if block_given?
35
44
  rescue ::OAuth2::Error
36
45
  nil
37
46
  end
38
47
 
39
- def access_token
40
- OAuth2::AccessToken.new(oauth_client, session[:access_token], {
41
- refresh_token: session[:refresh_token]
42
- })
43
- end
48
+ private
44
49
 
45
- def oauth_client
46
- oauth_strategy.client
50
+ def fetch_user(&block)
51
+ return unless session[:access_token]
52
+
53
+ RailsSso::FetchUser.new(access_token).call(&block)
54
+ rescue ::OAuth2::Error
55
+ refresh_access_token! do
56
+ RailsSso::FetchUser.new(access_token).call(&block)
57
+ end
47
58
  end
48
59
 
49
- def oauth_strategy
50
- oauth_strategy_class.new(nil, RailsSso.provider_key, RailsSso.provider_secret)
60
+ def update_user(data)
61
+ RailsSso::UpdateUser.new(data, update_user_options).call
51
62
  end
52
63
 
53
- def oauth_strategy_class
54
- "OmniAuth::Strategies::#{RailsSso.provider_name.classify}".constantize
64
+ def update_user_options
65
+ {
66
+ fields: RailsSso.user_fields,
67
+ repository: RailsSso.user_repository.new
68
+ }
55
69
  end
56
70
  end
57
71
  end
@@ -1,3 +1,3 @@
1
1
  module RailsSso
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/rails_sso.rb CHANGED
@@ -14,6 +14,9 @@ module RailsSso
14
14
  mattr_accessor :user_fields
15
15
  @@user_fields = [:email]
16
16
 
17
+ mattr_accessor :use_cache
18
+ @@use_cache = false
19
+
17
20
  def self.configure
18
21
  yield self
19
22
  end
@@ -27,8 +30,8 @@ module RailsSso
27
30
  end
28
31
  end
29
32
 
33
+ require 'omniauth-oauth2'
30
34
  require 'rails_sso/version'
31
35
  require 'rails_sso/engine'
32
36
  require 'rails_sso/helpers'
33
- require 'rails_sso/update_user'
34
- require 'rails_sso/fetch_user'
37
+ require 'rails_sso/access_token'
@@ -0,0 +1,43 @@
1
+ require 'test_helper'
2
+
3
+ class RailsSso::SessionsControllerTest < ActionController::TestCase
4
+ def setup
5
+ @routes = RailsSso::Engine.routes
6
+
7
+ @auth_hash = OmniAuth::AuthHash.new({
8
+ provider: 'developer',
9
+ uid: '1',
10
+ name: 'Kowalski',
11
+ email: 'jan@kowalski.pl',
12
+ key: 'value'
13
+ })
14
+
15
+ OmniAuth.config.mock_auth[:developer] = @auth_hash
16
+
17
+ request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:developer]
18
+ end
19
+
20
+ def teardown
21
+ OmniAuth.config.mock_auth[:developer] = nil
22
+ end
23
+
24
+ test 'create should save access token and redirect to root path' do
25
+ @controller.expects(:save_access_token!).with(@auth_hash.credentials).once
26
+
27
+ get :create, { provider: 'developer' }
28
+
29
+ assert_redirected_to main_app.root_path
30
+ end
31
+
32
+ test 'destroy should invalidate access token and redirect to root path' do
33
+ @controller.expects(:invalidate_access_token!).once
34
+
35
+ delete :destroy, {}, { access_token: 'abc', refresh_token: 'def' }
36
+
37
+ assert_redirected_to main_app.root_path
38
+ end
39
+
40
+ def main_app
41
+ Rails.application.class.routes.url_helpers
42
+ end
43
+ end
@@ -2,4 +2,8 @@ class ApplicationController < ActionController::Base
2
2
  # Prevent CSRF attacks by raising an exception.
3
3
  # For APIs, you may want to use :null_session instead.
4
4
  protect_from_forgery with: :exception
5
+
6
+ def index
7
+ render text: 'Hello'
8
+ end
5
9
  end
@@ -0,0 +1,13 @@
1
+ RailsSso.configure do |config|
2
+ config.provider_name = 'developer'
3
+ config.provider_key = 'key'
4
+ config.provider_secret = 'secret'
5
+ config.provider_profile_path = '/api/v1/me'
6
+ config.provider_sign_out_path = '/api/v1/me'
7
+ config.use_cache = false
8
+ config.user_fields = [
9
+ :email,
10
+ :name
11
+ ]
12
+ config.user_repository = 'UserRepository'
13
+ end
@@ -1,4 +1,5 @@
1
1
  Rails.application.routes.draw do
2
+ mount RailsSso::Engine => '/sso', as: 'sso'
2
3
  # The priority is based upon order of creation: first created -> highest priority.
3
4
  # See how all your routes lay out with "rake routes".
4
5
 
@@ -53,4 +54,5 @@ Rails.application.routes.draw do
53
54
  # # (app/controllers/admin/products_controller.rb)
54
55
  # resources :products
55
56
  # end
57
+ root to: 'application#index'
56
58
  end
File without changes