goodguide-accounts 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+