signet-rails 0.0.1 → 0.0.2

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.
data/README.md CHANGED
@@ -28,6 +28,30 @@ $ gem install signet-rails
28
28
 
29
29
  TODO: Write usage instructions here
30
30
 
31
+ ## TODO
32
+
33
+ A list of items still todo or work in progress
34
+
35
+ 0. Give an example usage
36
+ * Example of setting default options
37
+ * Example of setting per provider options
38
+ * Clearly document default `extract\_from\_env`
39
+ * Clearly document default `extract\_by\_oauth\_id`
40
+ 1. Is there a better (Rails) way to creating per-request instances of signet OAuth clients?
41
+ 2. Currently use the env variable to store the handlers and references to the instances... is this thread safe (probably) and the best way (probably not)?
42
+ 3. Better way of sourcing the Google default authorization_uri and token_credential_uri? From signet directly?
43
+ 4. Clear definition of the Signet options and the `signet-rails` options
44
+ 5. More Rails-esque way of getting the `rack.session` in `extract\_from\_env`?
45
+ 6. Better way of loading persistance wrappers in builder?
46
+ 7. Check to see whether we have all required signet options at the end of Builder.provder?
47
+ 8. Sort out `approval\_prompt` vs 'prompt'
48
+ 9. Better `auth\_options` split at the end of Builder.provider?
49
+ 10. Avoid having to dup options the whole time: fix signet?
50
+ 11. Refactor Handler.handle code... messy
51
+ 12. Document handling of callback in Rails
52
+ 13. Error handling...
53
+ 14. Document the various `env` values that can/will be set and when (e.g. `signet.XXX.persistance\_obj` on `auth\_callback`)
54
+
31
55
  ## Contributing
32
56
 
33
57
  1. Fork it
@@ -1,5 +1,5 @@
1
1
  require 'signet/rails'
2
- require 'signet/rails/wrappers/active_record'
2
+ require 'active_support/core_ext/string'
3
3
 
4
4
  module Signet
5
5
  module Rails
@@ -7,7 +7,7 @@ module Signet
7
7
  @@default_options = {}
8
8
 
9
9
  def self.set_default_options opts = {}
10
- # normalize to symbol version
10
+ # normalize to symbol hash
11
11
  n_opts = opts.inject({}) { |memo,(k,v)| memo[k.to_sym] = v; memo }
12
12
  @@default_options = n_opts
13
13
  end
@@ -17,17 +17,31 @@ module Signet
17
17
  end
18
18
 
19
19
  def provider(opts = {}, &block)
20
- # normalize to symbol version
20
+ # normalize to symbol hash
21
21
  n_opts = opts.inject({}) { |memo,(k,v)| memo[k.to_sym] = v; memo }
22
+
23
+ # use the default_options as a base... then merge these changes on top
22
24
  combined_options = @@default_options.merge(n_opts)
23
25
 
24
26
  # now set some defaults if they aren't already set
25
- combined_options[:persist] ||= [:refresh_token, :access_token, :expires_in, :issued_at]
27
+
28
+ combined_options[:persist_attrs] ||= [:refresh_token, :access_token, :expires_in, :issued_at]
26
29
  combined_options[:name] ||= :google
30
+
31
+ # TODO: see https://developers.google.com/accounts/docs/OAuth2Login#authenticationuriparameters
27
32
  combined_options[:approval_prompt] ||= 'auto'
28
- combined_options[:redirect_uri] = "http://localhost:3000/signet/#{combined_options[:name]}/callback"
29
- combined_options[:authorization_uri] = 'https://accounts.google.com/o/oauth2/auth'
30
- combined_options[:token_credential_uri] = 'https://accounts.google.com/o/oauth2/token'
33
+
34
+ # unless specified, we need to set this at request-time because we need the env to get server etc
35
+ # combined_options[:redirect_uri] = ??? need env
36
+
37
+ # TODO: better way of sourcing these defaults... from signet?
38
+ combined_options[:authorization_uri] ||= 'https://accounts.google.com/o/oauth2/auth'
39
+ combined_options[:token_credential_uri] ||= 'https://accounts.google.com/o/oauth2/token'
40
+
41
+ # whether we handle the persistance of the auth callback or simply pass-through
42
+ combined_options[:handle_auth_callback] ||= true
43
+
44
+ # method to get the persistance object when creating a client via the factory
31
45
  combined_options[:extract_from_env] ||= lambda do |env, client|
32
46
  u = nil
33
47
  session = env['rack.session']
@@ -39,7 +53,8 @@ module Signet
39
53
  end
40
54
  u
41
55
  end
42
- combined_options[:handle_callback] ||= true
56
+
57
+ # when on an auth_callback, how do we get the persistance object from the id?
43
58
  combined_options[:extract_by_oauth_id] ||= lambda do |id, client|
44
59
  u = nil
45
60
  begin
@@ -51,19 +66,27 @@ module Signet
51
66
  u
52
67
  end
53
68
 
54
- def active_record_wrapper meth
69
+ combined_options[:persistance_wrapper] ||= :active_record
70
+ persistance_wrapper = lambda do |meth|
55
71
  lambda do |context, client|
56
72
  y = meth.call context, client
57
- w = Signet::Rails::Wrappers::ActiveRecord.new y, client
73
+ klass_str = combined_options[:persistance_wrapper].to_s
74
+ require "signet/rails/wrappers/#{klass_str}"
75
+ w = "Signet::Rails::Wrappers::#{klass_str.camelize}".constantize.new y, client
58
76
  end
59
77
  end
60
78
 
61
- combined_options[:extract_by_oauth_id] = active_record_wrapper combined_options[:extract_by_oauth_id]
62
- combined_options[:extract_from_env] = active_record_wrapper combined_options[:extract_from_env]
79
+ combined_options[:extract_by_oauth_id] = persistance_wrapper.call combined_options[:extract_by_oauth_id]
80
+ combined_options[:extract_from_env] = persistance_wrapper.call combined_options[:extract_from_env]
63
81
 
64
82
  # TODO: check here we have the basics?
83
+
84
+ # TODO: better auth_options split?
85
+ auth_option_keys = [:prompt, :redirect_uri, :access_type, :approval_prompt, :client_id]
86
+ base_options = combined_options
87
+ auth_options = base_options.select { |k,v| auth_option_keys.include? k }
65
88
 
66
- use Signet::Rails::Handler, combined_options, &block
89
+ use Signet::Rails::Handler, base_options, auth_options, &block
67
90
  end
68
91
 
69
92
  def call(env)
@@ -5,19 +5,25 @@ module Signet
5
5
 
6
6
  class Factory
7
7
  def self.create_from_env name, env, opt_hsh = {load_token: true}
8
- # rework this to use singleton?
9
- handler = env["signet.#{name.to_s}"]
10
8
 
11
- client = Signet::OAuth2::Client.new handler.options
9
+ # TODO: thread safe? best approach? Other uses below
10
+ client = env["signet.#{name.to_s}.instance"]
12
11
 
13
- if opt_hsh[:load_token]
14
- obj = handler.options[:extract_from_env].call env, client
15
- handler.load_token_state obj, client
12
+ return client if !!client
13
+
14
+ # TODO: again, not pretty...
15
+ handler = env["signet.#{name.to_s}"]
16
16
 
17
- env["signet.#{name.to_s}.instance"] = obj
18
- end
17
+ client = Signet::OAuth2::Client.new handler.options
19
18
 
20
- client
19
+ if opt_hsh[:load_token]
20
+ obj = handler.options[:extract_from_env].call env, client
21
+ handler.load_token_state obj, client
22
+
23
+ env["signet.#{name.to_s}.instance"] = obj
24
+ end
25
+
26
+ client
21
27
  end
22
28
  end
23
29
  end
@@ -5,52 +5,69 @@ require 'rack/utils'
5
5
  module Signet
6
6
  module Rails
7
7
  class Handler
8
- def initialize(app, opts = {}, &block)
8
+ def initialize(app, opts = {}, auth_opts = {}, &block)
9
9
  @app = app
10
10
  @options = opts
11
+ @auth_options = auth_opts
11
12
  end
12
13
 
13
14
  def options
14
- @options
15
+ # TODO: this is because signet doesn't dup what we pass in....
16
+ @options.dup
17
+ end
18
+
19
+ def auth_options env
20
+ # TODO: this is because signet doesn't dup what we pass in....
21
+ ret = @auth_options.dup
22
+ unless ret.include? :redirect_uri
23
+ req = Rack::Request.new env
24
+ scheme = req.ssl? ? 'https' : 'http'
25
+ ret[:redirect_uri] = "#{scheme}://#{req.host_with_port}/signet/#{options[:name]}/auth_callback"
26
+ end
27
+ ret
15
28
  end
16
29
 
17
30
  def handle(env)
18
31
 
19
- if "/signet/#{@options[:name]}/login" == env['PATH_INFO'] && 'GET' == env['REQUEST_METHOD']
20
- client = Factory.create_from_env @options[:name], env
21
- r = Rack::Response.new
32
+ # set these to 'handle' the request
33
+ status = headers = body = nil
22
34
 
23
- # TODO: a better way of filtering down to the auth options
24
- auth_options_whitelist = [:approval_prompt]
25
- auth_options = @options.select { |k,_| auth_options_whitelist.include?(k) }
26
- redirect_uri = client.authorization_uri(auth_options).to_s
35
+ # TODO: better way than a gross if elsif block?
36
+ if "/signet/#{options[:name]}/auth" == env['PATH_INFO'] && 'GET' == env['REQUEST_METHOD']
37
+
38
+ # we are looking to auth... so nothing to load
39
+ client = Factory.create_from_env options[:name], env, load_token: false
40
+
41
+ r = Rack::Response.new
42
+ redirect_uri = client.authorization_uri(auth_options(env)).to_s
27
43
  r.redirect(redirect_uri)
28
- r.finish
29
- elsif "/signet/#{@options[:name]}/callback" == env['PATH_INFO']
30
- client = Factory.create_from_env @options[:name], env, load_token: false
44
+ status, headers, body = r.finish
45
+ elsif "/signet/#{options[:name]}/auth_callback" == env['PATH_INFO'] && 'GET' == env['REQUEST_METHOD']
46
+ client = Factory.create_from_env options[:name], env, load_token: false
31
47
  query_string_params = Rack::Utils.parse_query(env['QUERY_STRING'])
32
48
  client.code = query_string_params['code']
33
- fat = client.fetch_access_token!
49
+ client.redirect_uri = auth_options(env)[:redirect_uri]
50
+ client.fetch_access_token!
34
51
 
35
- if @options[:handle_callback]
36
- # try to get the token store
37
- obj = @options[:extract_by_oauth_id].call client.decoded_id_token['id'], client
52
+ if options[:handle_auth_callback]
53
+ # TODO: remove
54
+ puts '******************************************'
55
+ puts client.decoded_id_token.inspect
56
+
57
+ obj = options[:extract_by_oauth_id].call client.decoded_id_token['id'], client
38
58
  persist_token_state obj, client
39
59
  obj.persist
40
- env["signet.#{options[:name]}.obj"] = obj.obj
41
-
60
+ env["signet.#{options[:name]}.persistance_obj"] = obj.obj
42
61
  else
43
- # pass this on for handling by the rails app
44
- env["signet.#{options[:name]}.client"] = client
45
-
62
+ env["signet.#{options[:name]}.auth_client"] = client
46
63
  end
47
-
48
- [nil,nil,nil]
49
64
  end
65
+
66
+ [status, headers, body]
50
67
  end
51
68
 
52
69
  def persist_token_state wrapper, client
53
- for i in @options[:persist]
70
+ for i in options[:persist_attrs]
54
71
  if client.respond_to?(i) && wrapper.obj.respond_to?(i.to_s+'=')
55
72
  wrapper.obj.method(i.to_s+'=').call(client.method(i).call)
56
73
  end
@@ -58,7 +75,7 @@ module Signet
58
75
  end
59
76
 
60
77
  def load_token_state wrapper, client
61
- for i in @options[:persist]
78
+ for i in options[:persist_attrs]
62
79
  if wrapper.obj.respond_to?(i) && client.respond_to?(i.to_s+'=')
63
80
  client.method(i.to_s+'=').call(wrapper.obj.method(i).call)
64
81
  end
@@ -67,15 +84,15 @@ module Signet
67
84
 
68
85
  def call(env)
69
86
  # rework this to use singleton?
70
- env["signet.#{@options[:name]}"] = self
87
+ env["signet.#{options[:name]}"] = self
71
88
 
72
89
  status, headers, body = handle(env)
73
-
90
+
74
91
  unless status
75
92
 
76
93
  status, headers, body = @app.call(env)
77
94
 
78
- obj = env["signet.#{@options[:name]}.instance"]
95
+ obj = env["signet.#{options[:name]}.instance"]
79
96
  if !!obj
80
97
  obj.persist
81
98
  end
@@ -84,7 +101,6 @@ module Signet
84
101
 
85
102
  [status, headers, body]
86
103
  end
87
-
88
104
  end
89
105
  end
90
106
  end
@@ -1,5 +1,5 @@
1
1
  module Signet
2
2
  module Rails
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -2,20 +2,20 @@ module Signet
2
2
  module Rails
3
3
  module Wrappers
4
4
  class ActiveRecord
5
- def initialize obj, client
6
- @obj = obj
7
- @client = client
8
- end
5
+ def initialize obj, client
6
+ @obj = obj
7
+ @client = client
8
+ end
9
9
 
10
- def obj
11
- @obj
12
- end
10
+ def obj
11
+ @obj
12
+ end
13
13
 
14
- def persist
15
- if @obj.changed?
16
- @obj.save
17
- end
18
- end
14
+ def persist
15
+ if @obj.changed?
16
+ @obj.save
17
+ end
18
+ end
19
19
  end
20
20
  end
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signet-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: