zaikio-oauth_client 0.7.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: faffe2dacfd78ac4049dc0cb8897bd5f479c0333959433b3613ed7ccf683c270
4
- data.tar.gz: 18b59f470cc9fe488d00fab7c57ce5e72edbd916a79f9805447ebb0dd10d2310
3
+ metadata.gz: 84383fd7b0b03f23cc671489124b6b8f90613cad840bd668080ea04c59a4ff54
4
+ data.tar.gz: e7b8f6759983ffad763780b392be0500888affd117c1ccfb9f87449ed1b1a9de
5
5
  SHA512:
6
- metadata.gz: 9700b26771536ecedbfeaf5cf48f088e83d209d169e0bf3380c2f19c76c8cd3fd93047f2c4fcbe968db94cc008130c65016842d882564267942ad1bbbdc1148f
7
- data.tar.gz: 56ef475c436b106d17b5f145ea3053762414d0bc3c7a3aff87ee796322d63a06774aae1edfb0837dfde61fa49cc113095b2decacb14acdd2e2b1fcb398628db5
6
+ metadata.gz: caae8092591d3d47a03ddf598d8da76d474cc45ff01e5799f140d8dbad3ca171294217ceddc1e0ffbc364f8efd3153c5222e51711afbd8f17d39daf1f01f409b
7
+ data.tar.gz: 2759d26c2826f6cf06aba7c7673eaf2ee7cf30914ca4c965eefe99409efb575916c4fe0cfdde315ed64f95e20720b83712ae2d5bb3a9820dfedb908a9e38e094
data/README.md CHANGED
@@ -118,6 +118,19 @@ redirect_to zaikio_oauth_client.new_session_path(force_login: true)
118
118
  redirect_to zaikio_oauth_client.new_session_path(state: "something-my-app-uses")
119
119
  ```
120
120
 
121
+ You can also send them to the [Subscription Redirect
122
+ flow](https://docs.zaikio.com/api/directory/guides/subscriptions/redirect-flow/), which
123
+ behaves & redirects back like a regular Organization flow except it additionally sets up a
124
+ subscription for the organization:
125
+
126
+ ```ruby
127
+ # Require them to select a plan themselves...
128
+ redirect_to zaikio_oauth_client.new_subscription_path
129
+
130
+ # Or preselect a plan for them
131
+ redirect_to zaikio_oauth_client.new_subscription_path(plan: "free")
132
+ ```
133
+
121
134
  #### Session handling
122
135
 
123
136
  The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `cookies.encrypted[:zaikio_person_id]`.
@@ -254,7 +267,7 @@ To release a new version of the gem:
254
267
  - Update the version in `lib/zaikio/oauth_client/version.rb`
255
268
  - Update `CHANGELOG.md` to include the new version and its release date
256
269
  - Commit and push your changes
257
- - Create a [new release on GitHub](https://github.com/zaikio/zaikio-directory-models/releases/new)
270
+ - Create a [new release on GitHub](https://github.com/zaikio/zaikio-oauth_client/releases/new)
258
271
  - CircleCI will build the Gem package and push it Rubygems for you
259
272
 
260
273
  ## License
@@ -0,0 +1,26 @@
1
+ module Zaikio
2
+ module OAuthClient
3
+ class SubscriptionsController < ConnectionsController
4
+ def new
5
+ opts = params.permit(:client_name, :state, :plan, :organization_id)
6
+
7
+ plan = opts.delete(:plan)
8
+ organization_id = opts.delete(:organization_id)
9
+
10
+ subscription_scope = if organization_id.present?
11
+ "Org/#{organization_id}.subscription_create"
12
+ else
13
+ "Org.subscription_create"
14
+ end
15
+
16
+ subscription_scope << ".#{plan}" if plan.present?
17
+
18
+ redirect_to oauth_client.auth_code.authorize_url(
19
+ redirect_uri: approve_url(opts.delete(:client_name)),
20
+ scope: subscription_scope,
21
+ **opts
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -78,15 +78,19 @@ module Zaikio
78
78
  attributes.slice("token", "refresh_token")
79
79
  ).refresh!
80
80
 
81
- access_token = self.class.build_from_access_token(
81
+ destroy
82
+
83
+ self.class.build_from_access_token(
82
84
  refreshed_token,
83
85
  requested_scopes: requested_scopes
84
- )
86
+ ).tap(&:save!)
87
+ end
88
+ rescue OAuth2::Error => e
89
+ raise unless e.code == "invalid_grant"
85
90
 
86
- transaction { destroy if access_token.save! }
91
+ destroy
87
92
 
88
- access_token
89
- end
93
+ nil
90
94
  end
91
95
  end
92
96
  end
data/config/routes.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  Zaikio::OAuthClient::Engine.routes.draw do
2
- sessions_controller = Zaikio::OAuthClient.configuration.sessions_controller_name
3
- connections_controller = Zaikio::OAuthClient.configuration.connections_controller_name
2
+ config = Zaikio::OAuthClient.configuration
4
3
 
5
- # People
6
- get "(/:client_name)/sessions/new", action: :new, controller: sessions_controller, as: :new_session
7
- get "(/:client_name)/sessions/approve", action: :approve, controller: sessions_controller, as: :approve_session
8
- delete "(/:client_name)/session", action: :destroy, controller: sessions_controller, as: :session
4
+ scope path: "(/:client_name)" do
5
+ # People
6
+ get "/sessions/new", action: :new, controller: config.sessions_controller_name, as: :new_session
7
+ get "/sessions/approve", action: :approve, controller: config.sessions_controller_name, as: :approve_session
8
+ delete "/session", action: :destroy, controller: config.sessions_controller_name, as: :session
9
9
 
10
- # Organizations
11
- get "(/:client_name)/connections/new", action: :new,
12
- controller: connections_controller, as: :new_connection
13
- get "(/:client_name)/connections/approve", action: :approve,
14
- controller: connections_controller, as: :approve_connection
10
+ # Organizations
11
+ get "/connections/new", action: :new, controller: config.connections_controller_name, as: :new_connection
12
+ get "/connections/approve", action: :approve, controller: config.connections_controller_name, as: :approve_connection
13
+
14
+ # Subscriptions
15
+ get "/subscriptions/new", action: :new, controller: config.subscriptions_controller_name, as: :new_subscription
16
+ end
15
17
  end
@@ -57,34 +57,61 @@ module Zaikio
57
57
  end
58
58
  end
59
59
 
60
- def get_access_token(client_name: nil, bearer_type: "Person", bearer_id: nil, scopes: nil) # rubocop:disable Metrics/MethodLength
61
- client_name ||= self.client_name
62
- client_config = client_config_for(client_name)
60
+ # Finds the best possible access token, using the DB or an API call
61
+ # * If the token has expired, it will be refreshed using the refresh_token flow
62
+ # (if this fails, we fallback to getting a new token using client_credentials)
63
+ # * If the token does not exist, we'll get a new one using the client_credentials flow
64
+ def get_access_token(bearer_id:, client_name: nil, bearer_type: "Person", scopes: nil)
65
+ client_config = client_config_for(client_name || self.client_name)
63
66
  scopes ||= client_config.default_scopes_for(bearer_type)
64
67
 
65
- access_token = Zaikio::AccessToken.where(audience: client_config.client_name)
66
- .usable(
67
- bearer_type: bearer_type,
68
- bearer_id: bearer_id,
69
- requested_scopes: scopes
70
- )
71
- .first
72
-
73
- if access_token.blank?
74
- access_token = Zaikio::AccessToken.build_from_access_token(
75
- client_config.token_by_client_credentials(
68
+ token = find_usable_access_token(client_name: client_config.client_name,
69
+ bearer_type: bearer_type,
70
+ bearer_id: bearer_id,
71
+ requested_scopes: scopes)
72
+
73
+ token = token.refresh! if token&.expired?
74
+
75
+ token ||= fetch_new_token(client_config: client_config,
76
+ bearer_type: bearer_type,
77
+ bearer_id: bearer_id,
78
+ scopes: scopes)
79
+ token
80
+ end
81
+
82
+ # Finds the best usable access token. Note that this token may have expired and
83
+ # would require refreshing.
84
+ def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:)
85
+ configuration.logger.debug "Try to fetch token for client_name: #{client_name}, "\
86
+ "bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
87
+
88
+ fetch_access_token = lambda {
89
+ Zaikio::AccessToken
90
+ .where(audience: client_name)
91
+ .usable(
76
92
  bearer_type: bearer_type,
77
93
  bearer_id: bearer_id,
78
- scopes: scopes
79
- ),
80
- requested_scopes: scopes
81
- )
82
- access_token.save!
83
- elsif access_token&.expired?
84
- access_token = access_token.refresh!
94
+ requested_scopes: requested_scopes
95
+ )
96
+ .first
97
+ }
98
+
99
+ if configuration.logger.respond_to?(:silence)
100
+ configuration.logger.silence { fetch_access_token.call }
101
+ else
102
+ fetch_access_token.call
85
103
  end
104
+ end
86
105
 
87
- access_token
106
+ def fetch_new_token(client_config:, bearer_type:, bearer_id:, scopes:)
107
+ Zaikio::AccessToken.build_from_access_token(
108
+ client_config.token_by_client_credentials(
109
+ bearer_type: bearer_type,
110
+ bearer_id: bearer_id,
111
+ scopes: scopes
112
+ ),
113
+ requested_scopes: scopes
114
+ ).tap(&:save!)
88
115
  end
89
116
 
90
117
  def get_plain_scopes(scopes)
@@ -13,19 +13,25 @@ module Zaikio
13
13
  }.freeze
14
14
 
15
15
  attr_accessor :host
16
- attr_writer :logger
17
16
  attr_reader :client_configurations, :environment, :around_auth_block,
18
- :sessions_controller_name, :connections_controller_name
17
+ :sessions_controller_name, :connections_controller_name, :subscriptions_controller_name
19
18
 
20
19
  def initialize
21
20
  @client_configurations = {}
22
21
  @around_auth_block = nil
23
22
  @sessions_controller_name = "sessions"
24
23
  @connections_controller_name = "connections"
24
+ @subscriptions_controller_name = "subscriptions"
25
+ Zaikio::AccessToken.logger = logger
25
26
  end
26
27
 
27
28
  def logger
28
- @logger ||= Logger.new($stdout)
29
+ @logger ||= ActiveSupport::Logger.new($stdout)
30
+ end
31
+
32
+ def logger=(logger)
33
+ @logger = logger
34
+ Zaikio::AccessToken.logger = @logger
29
35
  end
30
36
 
31
37
  def register_client(name)
@@ -58,6 +64,10 @@ module Zaikio
58
64
  @connections_controller_name = "/#{name}"
59
65
  end
60
66
 
67
+ def subscriptions_controller_name=(name)
68
+ @subscriptions_controller_name = "/#{name}"
69
+ end
70
+
61
71
  private
62
72
 
63
73
  def host_for(environment)
@@ -1,5 +1,5 @@
1
1
  module Zaikio
2
2
  module OAuthClient
3
- VERSION = "0.7.1".freeze
3
+ VERSION = "0.10.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,17 +1,59 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zaikio-oauth_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zaikio GmbH
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-17 00:00:00.000000000 Z
11
+ date: 2021-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rails
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 5.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 5.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 5.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 5.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: railties
15
57
  requirement: !ruby/object:Gem::Requirement
16
58
  requirements:
17
59
  - - ">="
@@ -102,6 +144,7 @@ files:
102
144
  - Rakefile
103
145
  - app/controllers/zaikio/oauth_client/connections_controller.rb
104
146
  - app/controllers/zaikio/oauth_client/sessions_controller.rb
147
+ - app/controllers/zaikio/oauth_client/subscriptions_controller.rb
105
148
  - app/helpers/zaikio/application_helper.rb
106
149
  - app/jobs/zaikio/application_job.rb
107
150
  - app/jobs/zaikio/cleanup_access_tokens_job.rb