goodguide-accounts 1.0.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.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+ gem 'oauth2', :git => 'git://github.com/jayferd/oauth2',
3
+ :ref => 'master'
4
+ gem 'api_smith'
5
+ gem 'activesupport', :require => 'active_support'
6
+ gemspec
@@ -0,0 +1,16 @@
1
+ require './lib/goodguide/accounts/version'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "goodguide-accounts"
5
+ s.version = GoodGuide::Accounts::VERSION
6
+ s.authors = ["Jay Adkisson", "Ryan Aipperspach"]
7
+ s.email = ["jay@goodguide.com", "ryan@goodguide.com"]
8
+ s.summary = "GoodGuide Accounts API gem"
9
+ s.description = "Gem to access the GoodGuide Accounts API"
10
+ s.homepage = "http://www.goodguide.com"
11
+ s.rubyforge_project = "goodguide"
12
+ s.files = Dir['Gemfile', 'goodguide-accounts.gemspec', 'lib/**/*.rb']
13
+
14
+ s.add_dependency('oauth2', '~> 0.5.0.rc1')
15
+ s.add_dependency('i18n')
16
+ end
@@ -0,0 +1,264 @@
1
+ require File.expand_path('issue_preferences', File.dirname(__FILE__))
2
+
3
+ module GoodGuide
4
+ module Accounts
5
+ class Base
6
+ include IssuePreferences
7
+ include Profile
8
+
9
+ NotAuthenticatedError = Class.new(StandardError)
10
+
11
+ class << self
12
+ #####
13
+ # How the auth flow works:
14
+ #
15
+ # 1. Redirect the user-agent to Account.authorize_url
16
+ # 2. After authentication, the user will be redirected
17
+ # to your pre-configured authorization endpoint,
18
+ # (e.g. /sessions/authorize), with ?code=...
19
+ # 3. Do something like this:
20
+ #
21
+ # def authorize
22
+ # # get the code from the params
23
+ # code = params[:code]
24
+ # # exchange it with the oauth2 server for an
25
+ # # access token
26
+ # credentials = User.authorize(code)
27
+ # # store credentials
28
+ # # (a hash of access_token, refresh_token, and expires_at)
29
+ # # in the session
30
+ # session[:credentials] = credentials
31
+ # # and send them on their way
32
+ # redirect_to session[:redirect] || '/'
33
+ # end
34
+ #
35
+ # 4. To get the current user, do something like this:
36
+ #
37
+ # def current_user
38
+ # User.authenticate(session[:credentials])
39
+ # end
40
+ def authenticate(credentials, opts={})
41
+ new({:credentials => credentials}.merge(opts))
42
+ end
43
+
44
+ # returns a credentials hash
45
+ # given an authorization code
46
+ def authorize(code, options={})
47
+ access_token = client.auth_code.get_token(code, {
48
+ :redirect_uri => config[:redirect_uri]
49
+ }.merge(options))
50
+
51
+ # return a credentials hash
52
+ {
53
+ :access_token => access_token.token,
54
+ :refresh_token => access_token.refresh_token,
55
+ :expires_at => access_token.expires_at
56
+ }
57
+ end
58
+
59
+ def authorize_url(opts={})
60
+ client.auth_code.authorize_url(opts)
61
+ end
62
+
63
+ def logout_url(opts={})
64
+ url = config[:site] + "/sessions/clear"
65
+ url += "?redirect=#{CGI.escape(opts[:redirect])}" if opts[:redirect]
66
+ url
67
+ end
68
+
69
+ def config=(conf)
70
+ # In the absence of #symbolize_keys...
71
+ conf = conf.dup
72
+ conf.keys.each do |k|
73
+ conf[k.to_sym] = conf.delete(k)
74
+ end
75
+
76
+ @config = default_config.merge(conf)
77
+ end
78
+
79
+ def config
80
+ return @config if instance_variable_defined? :@config
81
+
82
+ yaml = YAML.load_file('config/goodguide_accounts.yml')
83
+
84
+ self.config = env && yaml.key?(env) ? yaml[env] : yaml
85
+
86
+ @config
87
+ end
88
+
89
+ def client
90
+ @client ||= begin
91
+ my_config = config.dup
92
+
93
+ if my_config[:site]
94
+ my_config[:site] += '/api/account'
95
+ end
96
+
97
+ OAuth2::Client.new(
98
+ my_config.delete(:identifier), my_config.delete(:secret),
99
+ my_config.merge(:ssl => {:verify => false})
100
+ )
101
+ end
102
+ end
103
+
104
+ private
105
+ def default_config
106
+ {
107
+ :authorize_url => '/oauth2/authorize',
108
+ :token_url => '/oauth2/token',
109
+ :site => 'https://accounts.goodguide.com'
110
+ }
111
+ end
112
+
113
+ def env
114
+ return @env if instance_variable_defined? :@env
115
+
116
+ @env = ENV['ACCOUNTS_ENV'] || if defined?(Rails) and Rails.respond_to? :env
117
+ Rails.env
118
+ elsif defined?(RAILS_ENV)
119
+ RAILS_ENV
120
+ end
121
+ end
122
+ end
123
+
124
+ attr_reader :client
125
+ attr_reader :access_token
126
+ attr_reader :refresh_token
127
+ attr_reader :id
128
+ def initialize(opts={})
129
+ opts = opts.dup
130
+
131
+ credentials = opts.delete(:credentials) || {}
132
+ @expires_at = credentials[:expires_at]
133
+ @access_token = credentials[:access_token]
134
+ @refresh_token = credentials[:refresh_token]
135
+
136
+ opts.each do |k, v|
137
+ instance_variable_set("@#{k}", v)
138
+ end
139
+ end
140
+
141
+ def update_credentials(opts = {})
142
+ @expires_at = opts[:expires_at]
143
+ @access_token = opts[:access_token]
144
+ @refresh_token = opts[:refresh_token]
145
+
146
+ self
147
+ end
148
+
149
+ def base_body_options
150
+ opts = {}
151
+ opts[:bearer_token] = access_token if authorized?
152
+ opts
153
+ end
154
+
155
+ def refreshable?
156
+ refresh_token
157
+ end
158
+
159
+ def authorized?
160
+ authenticated? or refreshable?
161
+ end
162
+
163
+ def authenticated?
164
+ !!(access_token and not expired?)
165
+ end
166
+
167
+ def profile?
168
+ profile.present?
169
+ end
170
+
171
+ def guest?
172
+ not authorized? #and not profile?
173
+ end
174
+
175
+ def real?
176
+ not guest?
177
+ end
178
+
179
+ def needs_refresh?
180
+ authorized? and not authenticated?
181
+ end
182
+
183
+ def expires_at
184
+ Time.at(@expires_at || 0)
185
+ end
186
+
187
+ def expires_in
188
+ (expires_at - Time.now).to_i
189
+ end
190
+
191
+ def expired?
192
+ expires_in <= 0
193
+ end
194
+
195
+ def endpoint
196
+ if authorized?
197
+ '/account'
198
+ elsif profile?
199
+ "/accounts/#{id}"
200
+ end
201
+ end
202
+
203
+ def credentials
204
+ {
205
+ :expires_at => expires_at,
206
+ :access_token => access_token,
207
+ :refresh_token => refresh_token
208
+ }
209
+ end
210
+
211
+ def refresh!
212
+ if refreshable?
213
+ @connection = connection.refresh!
214
+ update_credentials(
215
+ :expires_at => connection.expires_at,
216
+ :refresh_token => connection.refresh_token,
217
+ :access_token => connection.token
218
+ )
219
+ end
220
+ rescue OAuth2::Error
221
+ $!.response
222
+ end
223
+
224
+ def connection
225
+ @connection ||= begin
226
+ if authorized?
227
+ OAuth2::AccessToken.new(self.class.client, access_token, credentials)
228
+ else
229
+ self.class.client
230
+ end
231
+ end
232
+ end
233
+
234
+ def endpoint
235
+ if authorized?
236
+ '/api/account'
237
+ else
238
+ "/api/accounts/#{id}"
239
+ end
240
+ end
241
+
242
+ # delegate http methods to the connection
243
+ %w(get put post delete head).each do |verb|
244
+ define_method(verb) do |*args|
245
+ request(verb, *args)
246
+ end
247
+ end
248
+
249
+ def request(verb, path, opts={})
250
+ path = "/#{path}" if path.is_a? Symbol
251
+
252
+ unless opts.key?(:body) || opts.key?(:headers)
253
+ opts = { :body => opts }
254
+ end
255
+
256
+ JSON.load(connection.request(verb.to_sym, endpoint + path, opts).body)
257
+ end
258
+
259
+ def profile
260
+ @profile ||= guest? ? {} : get('/')['account']
261
+ end
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,15 @@
1
+ module GoodGuide
2
+ module Accounts
3
+ module IssuePreferences
4
+
5
+ def issue_preferences
6
+ @issue_preferences ||= get(:issue_preferences)['issue_preferences']
7
+ end
8
+
9
+ def update_issue_preferences(prefs)
10
+ @issue_preferences = nil
11
+ put(:issue_preferences, :issue_preferences => prefs)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,47 @@
1
+ module GoodGuide
2
+ module Accounts
3
+ module Profile
4
+ def with_profile(default = nil, &block)
5
+ profile? ? yield(profile) : default
6
+ end
7
+
8
+ def identifier
9
+ with_profile do |profile|
10
+ profile['identifier']
11
+ end
12
+ end
13
+
14
+ def given_name
15
+ with_profile do |profile|
16
+ name = profile["name"]["givenName"] ||
17
+ profile["displayName"] ||
18
+ profile["name"]["formatted"]
19
+
20
+ !name.blank? ? name.strip : "GoodGuide User"
21
+ end
22
+ end
23
+
24
+ def full_name
25
+ with_profile do |profile|
26
+ name = profile["name"]["formatted"]
27
+
28
+ !name.blank? ? name.strip : "GoodGuide User"
29
+ end
30
+ end
31
+
32
+ def profile_picture(size = nil)
33
+ with_profile do |profile|
34
+ photo = profile["photo"]
35
+ photo.gsub!("=large", "=#{size}") if facebook? and size.present?
36
+ photo
37
+ end
38
+ end
39
+
40
+ def facebook?
41
+ with_profile(false) do |profile|
42
+ profile["identifier"] && profile["identifier"].include?("facebook.com")
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ module GoodGuide
2
+ module Accounts
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_support/core_ext'
2
+ require 'oauth2'
3
+
4
+ module GoodGuide
5
+ module Accounts
6
+ end
7
+ end
8
+
9
+ require File.expand_path('../oauth2_error', File.dirname(__FILE__))
10
+ require File.expand_path('accounts/version', File.dirname(__FILE__))
11
+ require File.expand_path('accounts/issue_preferences', File.dirname(__FILE__))
12
+ require File.expand_path('accounts/profile', File.dirname(__FILE__))
13
+ require File.expand_path('accounts/base', File.dirname(__FILE__))
@@ -0,0 +1,5 @@
1
+ class OAuth2::Error
2
+ def message
3
+ @message ||= JSON.load(response.body)['error']
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: goodguide-accounts
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 1.0.0
6
+ platform: ruby
7
+ authors:
8
+ - Jay Adkisson
9
+ - Ryan Aipperspach
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2011-08-05 00:00:00 -07:00
15
+ default_executable:
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: oauth2
19
+ prerelease: false
20
+ requirement: &id001 !ruby/object:Gem::Requirement
21
+ none: false
22
+ requirements:
23
+ - - ~>
24
+ - !ruby/object:Gem::Version
25
+ version: 0.5.0.rc1
26
+ type: :runtime
27
+ version_requirements: *id001
28
+ - !ruby/object:Gem::Dependency
29
+ name: i18n
30
+ prerelease: false
31
+ requirement: &id002 !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: "0"
37
+ type: :runtime
38
+ version_requirements: *id002
39
+ description: Gem to access the GoodGuide Accounts API
40
+ email:
41
+ - jay@goodguide.com
42
+ - ryan@goodguide.com
43
+ executables: []
44
+
45
+ extensions: []
46
+
47
+ extra_rdoc_files: []
48
+
49
+ files:
50
+ - Gemfile
51
+ - goodguide-accounts.gemspec
52
+ - lib/goodguide/accounts/issue_preferences.rb
53
+ - lib/goodguide/accounts/base.rb
54
+ - lib/goodguide/accounts/profile.rb
55
+ - lib/goodguide/accounts/version.rb
56
+ - lib/goodguide/accounts.rb
57
+ - lib/oauth2_error.rb
58
+ has_rdoc: true
59
+ homepage: http://www.goodguide.com
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ requirements: []
80
+
81
+ rubyforge_project: goodguide
82
+ rubygems_version: 1.5.2
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: GoodGuide Accounts API gem
86
+ test_files: []
87
+