googl 0.4.3 → 0.5.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/README.rdoc +59 -2
- data/VERSION +1 -1
- data/googl.gemspec +25 -11
- data/lib/googl.rb +44 -3
- data/lib/googl/base.rb +0 -6
- data/lib/googl/client_login.rb +11 -11
- data/lib/googl/expand.rb +9 -8
- data/lib/googl/oauth2/native.rb +25 -0
- data/lib/googl/oauth2/server.rb +28 -0
- data/lib/googl/oauth2/utils.rb +58 -0
- data/lib/googl/shorten.rb +5 -5
- data/lib/googl/utils.rb +30 -0
- data/spec/fixtures/oauth2/native.json +12 -0
- data/spec/fixtures/oauth2/native_invalid.json +12 -0
- data/spec/fixtures/oauth2/native_token_expires.json +27 -0
- data/spec/fixtures/oauth2/server.json +12 -0
- data/spec/fixtures/oauth2/server_invalid.json +12 -0
- data/spec/fixtures/oauth2/server_token_expires.json +27 -0
- data/spec/{client_spec.rb → googl/client_spec.rb} +0 -0
- data/spec/{expand_spec.rb → googl/expand_spec.rb} +10 -1
- data/spec/googl/oauth2/native_spec.rb +152 -0
- data/spec/googl/oauth2/server_spec.rb +156 -0
- data/spec/{request_spec.rb → googl/request_spec.rb} +0 -0
- data/spec/{shorten_spec.rb → googl/shorten_spec.rb} +0 -0
- data/spec/spec_helper.rb +48 -1
- metadata +56 -42
data/README.rdoc
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
= googl
|
1
|
+
= googl
|
2
2
|
|
3
3
|
Google URL Shortener API in Ruby
|
4
4
|
|
5
|
+
== Continuous Integration
|
6
|
+
|
7
|
+
http://travis-ci.org/zigotto/googl.png Travis[http://travis-ci.org/zigotto/googl]
|
8
|
+
|
5
9
|
== Basic Usage
|
6
10
|
|
7
11
|
=== Shorten a long URL
|
@@ -45,7 +49,60 @@ Go to http://goo.gl to see URL statistics.
|
|
45
49
|
|
46
50
|
=== OAuth
|
47
51
|
|
48
|
-
|
52
|
+
Google supports three flows of OAuth 2.0
|
53
|
+
|
54
|
+
* The <b>client-side</b> flow for JavaScript applications running in a browser. (TODO)
|
55
|
+
* The <b>server-side</b> flow for web applications with servers that can securely store persistent information.
|
56
|
+
* The <b>native application</b> flow for desktop and mobile applications.
|
57
|
+
|
58
|
+
Today, gem googl support only <b>server-side</b> and <b>native application</b>.
|
59
|
+
|
60
|
+
==== Server-side web applications
|
61
|
+
|
62
|
+
You'll need to register your application with Google to get a <em>client_id</em> and record the <em>redirect_uri</em> you'd like to use.
|
63
|
+
See the Registering[http://code.google.com/apis/accounts/docs/OAuth2.html#Registering] your app with Google section for details on how to register.
|
64
|
+
|
65
|
+
client = Googl::OAuth2.server("client_id", "client_secret", "redirect_uri")
|
66
|
+
|
67
|
+
Redirect your users to
|
68
|
+
|
69
|
+
client.authorize_url
|
70
|
+
|
71
|
+
After the user approves access or chooses not to, we'll redirect to the <em>redirect_uri</em> you passed us and append either an authorization code.
|
72
|
+
|
73
|
+
client.request_access_token(params["code"])
|
74
|
+
client.authorized?
|
75
|
+
=> true
|
76
|
+
|
77
|
+
Now you can get a user's history, shorten url, etc...
|
78
|
+
|
79
|
+
history = client.history
|
80
|
+
history.total_items
|
81
|
+
=> 19
|
82
|
+
|
83
|
+
url = Googl.shorten('https://github.com/zigotto/googl')
|
84
|
+
url.short_url
|
85
|
+
=> http://goo.gl/DWDfi
|
86
|
+
|
87
|
+
==== Native applications
|
88
|
+
|
89
|
+
You'll need to register your application with Google to get a <em>client_id</em> and record the special <em>redirect_uri: urn:ietf:wg:oauth:2.0:oob</em>.
|
90
|
+
See the Registering[http://code.google.com/apis/accounts/docs/OAuth2.html#Registering] your app with Google section for details on how to register.
|
91
|
+
|
92
|
+
When you use this redirect_uri, instead of redirecting the user's browser to a page on your site with an authorization code, Google will display the authorization code or error response in the title of the page and a text field with instructions for the user to copy and paste it in to your application. Your application can either monitor the window title of a web-view or browser window it launches and close it once the authorization code appears or prompt the user to copy and paste the code.
|
93
|
+
|
94
|
+
client = Googl::OAuth2.native("client_id", "client_secret")
|
95
|
+
|
96
|
+
Open a browser or a webview to the OAuth dialog at
|
97
|
+
|
98
|
+
client.authorize_url
|
99
|
+
|
100
|
+
In the native app flow, after the user approves access, we'll display the authorization code in the title of the page and in a text input with instructions for the user to copy and paste the code to your application
|
101
|
+
|
102
|
+
code = "copied code"
|
103
|
+
client.request_access_token(code)
|
104
|
+
client.authorized?
|
105
|
+
=> true
|
49
106
|
|
50
107
|
== Analytics
|
51
108
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/googl.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{googl}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jesus Lopes"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-05-01}
|
13
13
|
s.description = %q{Small library for Google URL Shortener API}
|
14
14
|
s.email = %q{jlopes@zigotto.com.br}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,11 +27,13 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/googl/base.rb",
|
28
28
|
"lib/googl/client_login.rb",
|
29
29
|
"lib/googl/expand.rb",
|
30
|
+
"lib/googl/oauth2/native.rb",
|
31
|
+
"lib/googl/oauth2/server.rb",
|
32
|
+
"lib/googl/oauth2/utils.rb",
|
30
33
|
"lib/googl/request.rb",
|
31
34
|
"lib/googl/ruby_extensions.rb",
|
32
35
|
"lib/googl/shorten.rb",
|
33
|
-
"
|
34
|
-
"spec/expand_spec.rb",
|
36
|
+
"lib/googl/utils.rb",
|
35
37
|
"spec/fixtures/client_login_invalid.json",
|
36
38
|
"spec/fixtures/client_login_valid.json",
|
37
39
|
"spec/fixtures/expand.json",
|
@@ -42,25 +44,37 @@ Gem::Specification.new do |s|
|
|
42
44
|
"spec/fixtures/expand_removed.json",
|
43
45
|
"spec/fixtures/history.json",
|
44
46
|
"spec/fixtures/history_projection_clicks.json",
|
47
|
+
"spec/fixtures/oauth2/native.json",
|
48
|
+
"spec/fixtures/oauth2/native_invalid.json",
|
49
|
+
"spec/fixtures/oauth2/native_token_expires.json",
|
50
|
+
"spec/fixtures/oauth2/server.json",
|
51
|
+
"spec/fixtures/oauth2/server_invalid.json",
|
52
|
+
"spec/fixtures/oauth2/server_token_expires.json",
|
45
53
|
"spec/fixtures/shorten.json",
|
46
54
|
"spec/fixtures/shorten_authenticated.json",
|
47
55
|
"spec/fixtures/shorten_invalid_content_type.json",
|
48
|
-
"spec/
|
56
|
+
"spec/googl/client_spec.rb",
|
57
|
+
"spec/googl/expand_spec.rb",
|
58
|
+
"spec/googl/oauth2/native_spec.rb",
|
59
|
+
"spec/googl/oauth2/server_spec.rb",
|
60
|
+
"spec/googl/request_spec.rb",
|
61
|
+
"spec/googl/shorten_spec.rb",
|
49
62
|
"spec/shared_examples.rb",
|
50
|
-
"spec/shorten_spec.rb",
|
51
63
|
"spec/spec_helper.rb"
|
52
64
|
]
|
53
65
|
s.homepage = %q{http://github.com/zigotto/googl}
|
54
66
|
s.licenses = ["MIT"]
|
55
67
|
s.require_paths = ["lib"]
|
56
|
-
s.rubygems_version = %q{1.
|
68
|
+
s.rubygems_version = %q{1.4.2}
|
57
69
|
s.summary = %q{Wrapper for Google URL Shortener API}
|
58
70
|
s.test_files = [
|
59
|
-
"spec/client_spec.rb",
|
60
|
-
"spec/expand_spec.rb",
|
61
|
-
"spec/
|
71
|
+
"spec/googl/client_spec.rb",
|
72
|
+
"spec/googl/expand_spec.rb",
|
73
|
+
"spec/googl/oauth2/native_spec.rb",
|
74
|
+
"spec/googl/oauth2/server_spec.rb",
|
75
|
+
"spec/googl/request_spec.rb",
|
76
|
+
"spec/googl/shorten_spec.rb",
|
62
77
|
"spec/shared_examples.rb",
|
63
|
-
"spec/shorten_spec.rb",
|
64
78
|
"spec/spec_helper.rb"
|
65
79
|
]
|
66
80
|
|
data/lib/googl.rb
CHANGED
@@ -2,6 +2,7 @@ require 'httparty'
|
|
2
2
|
require 'ostruct'
|
3
3
|
require 'json'
|
4
4
|
|
5
|
+
require 'googl/utils'
|
5
6
|
require 'googl/base'
|
6
7
|
require 'googl/request'
|
7
8
|
require 'googl/shorten'
|
@@ -9,7 +10,12 @@ require 'googl/expand'
|
|
9
10
|
require 'googl/client_login'
|
10
11
|
require 'googl/ruby_extensions'
|
11
12
|
|
13
|
+
require 'googl/oauth2/utils'
|
14
|
+
require 'googl/oauth2/native'
|
15
|
+
require 'googl/oauth2/server'
|
16
|
+
|
12
17
|
module Googl
|
18
|
+
extend self
|
13
19
|
|
14
20
|
# Creates a new short URL
|
15
21
|
#
|
@@ -17,7 +23,7 @@ module Googl
|
|
17
23
|
# url.short_url
|
18
24
|
# => "http://goo.gl/ump4S"
|
19
25
|
#
|
20
|
-
def
|
26
|
+
def shorten(url=nil)
|
21
27
|
raise ArgumentError.new("URL to shorten is required") if url.blank?
|
22
28
|
Googl::Shorten.new(url)
|
23
29
|
end
|
@@ -79,7 +85,7 @@ module Googl
|
|
79
85
|
#
|
80
86
|
# For mor details, see http://code.google.com/intl/pt-BR/apis/urlshortener/v1/reference.html#resource_url
|
81
87
|
#
|
82
|
-
def
|
88
|
+
def expand(url=nil, options={})
|
83
89
|
raise ArgumentError.new("URL to expand is required") if url.blank?
|
84
90
|
options = {:shortUrl => url, :projection => nil}.merge!(options)
|
85
91
|
Googl::Expand.new(options)
|
@@ -95,8 +101,43 @@ module Googl
|
|
95
101
|
#
|
96
102
|
# Go to http://goo.gl to see URL statistics.
|
97
103
|
#
|
98
|
-
def
|
104
|
+
def client(email, passwd)
|
99
105
|
Googl::ClientLogin.new(email, passwd)
|
100
106
|
end
|
101
107
|
|
108
|
+
# OAuth 2.0
|
109
|
+
#
|
110
|
+
# Google supports three flows of OAuth 2.0
|
111
|
+
#
|
112
|
+
# * client-side
|
113
|
+
# * server-side
|
114
|
+
# * native application
|
115
|
+
#
|
116
|
+
# Now, gem googl support only client-side and native application.
|
117
|
+
#
|
118
|
+
module OAuth2
|
119
|
+
extend self
|
120
|
+
|
121
|
+
# OAuth 2.0 for server-side web applications
|
122
|
+
#
|
123
|
+
# The server-side flow for web applications with servers that can securely store persistent information
|
124
|
+
#
|
125
|
+
# client = Googl::OAuth2.server("client_id", "client_secret", "redirect_uri")
|
126
|
+
#
|
127
|
+
def server(client_id, client_secret, redirect_uri)
|
128
|
+
Googl::OAuth2::Server.new(client_id, client_secret, redirect_uri)
|
129
|
+
end
|
130
|
+
|
131
|
+
# OAuth 2.0 for native applications
|
132
|
+
#
|
133
|
+
# The native application flow for desktop and mobile applications
|
134
|
+
#
|
135
|
+
# client = Googl::OAuth2.native("client_id", "client_secret")
|
136
|
+
#
|
137
|
+
def native(client_id, client_secret)
|
138
|
+
Googl::OAuth2::Native.new(client_id, client_secret)
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
102
143
|
end
|
data/lib/googl/base.rb
CHANGED
data/lib/googl/client_login.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module Googl
|
2
2
|
|
3
|
-
class ClientLogin
|
3
|
+
class ClientLogin
|
4
4
|
|
5
|
-
|
6
|
-
API_HISTORY_URL = "https://www.googleapis.com/urlshortener/v1/url/history"
|
5
|
+
include Googl::Utils
|
7
6
|
|
8
7
|
attr_accessor :code, :items
|
9
8
|
|
@@ -11,13 +10,13 @@ module Googl
|
|
11
10
|
#
|
12
11
|
def initialize(email, passwd)
|
13
12
|
modify_headers('Content-Type' => 'application/x-www-form-urlencoded')
|
14
|
-
resp =
|
15
|
-
|
13
|
+
resp = post(API_CLIENT_LOGIN_URL, :body => params.merge!('Email' => email, 'Passwd' => passwd))
|
14
|
+
self.code = resp.code
|
16
15
|
if resp.code == 200
|
17
16
|
token = resp.split('=').last.gsub(/\n/, '')
|
18
17
|
modify_headers("Authorization" => "GoogleLogin auth=#{token}")
|
19
18
|
else
|
20
|
-
raise
|
19
|
+
raise exception("#{resp.code} #{resp.parsed_response}")
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
@@ -26,7 +25,7 @@ module Googl
|
|
26
25
|
# See Googl.client
|
27
26
|
#
|
28
27
|
def shorten(url)
|
29
|
-
Googl
|
28
|
+
Googl.shorten(url)
|
30
29
|
end
|
31
30
|
|
32
31
|
# Gets a user's history of shortened URLs. (Authenticated)
|
@@ -46,11 +45,12 @@ module Googl
|
|
46
45
|
# history = client.history(:projection => :analytics_clicks)
|
47
46
|
#
|
48
47
|
def history(options={})
|
49
|
-
resp = options.blank? ? Googl::
|
50
|
-
|
51
|
-
|
48
|
+
resp = options.blank? ? get(Googl::Utils::API_HISTORY_URL) : get(Googl::Utils::API_HISTORY_URL, :query => options)
|
49
|
+
case resp.code
|
50
|
+
when 200
|
51
|
+
self.items = resp.parsed_response.to_openstruct
|
52
52
|
else
|
53
|
-
raise
|
53
|
+
raise exception("#{resp.code} #{resp.parsed_response}")
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
data/lib/googl/expand.rb
CHANGED
@@ -2,9 +2,9 @@ module Googl
|
|
2
2
|
|
3
3
|
class Expand < Base
|
4
4
|
|
5
|
-
|
5
|
+
include Googl::Utils
|
6
6
|
|
7
|
-
attr_accessor :long_url, :analytics, :status, :short_url
|
7
|
+
attr_accessor :long_url, :analytics, :status, :short_url, :created
|
8
8
|
|
9
9
|
# Expands a short URL or gets creation time and analytics. See Googl.expand
|
10
10
|
#
|
@@ -12,14 +12,15 @@ module Googl
|
|
12
12
|
|
13
13
|
options.delete_if {|key, value| value.nil?}
|
14
14
|
|
15
|
-
resp =
|
15
|
+
resp = get(API_URL, :query => options)
|
16
16
|
if resp.code == 200
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
self.created = resp['created'] if resp.has_key?('created')
|
18
|
+
self.long_url = resp['longUrl']
|
19
|
+
self.analytics = resp['analytics'].to_openstruct if resp.has_key?('analytics')
|
20
|
+
self.status = resp['status']
|
21
|
+
self.short_url = resp['id']
|
21
22
|
else
|
22
|
-
raise
|
23
|
+
raise exception("#{resp.code} #{resp.message}")
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Googl
|
2
|
+
module OAuth2
|
3
|
+
|
4
|
+
class Native
|
5
|
+
|
6
|
+
include Googl::Utils
|
7
|
+
include Googl::OAuth2::Utils
|
8
|
+
|
9
|
+
def initialize(client_id, client_secret)
|
10
|
+
self.client_id = client_id
|
11
|
+
self.client_secret = client_secret
|
12
|
+
end
|
13
|
+
|
14
|
+
def authorize_url
|
15
|
+
make_authorize_url("urn:ietf:wg:oauth:2.0:oob")
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_access_token(code)
|
19
|
+
request_token(code)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Googl
|
2
|
+
module OAuth2
|
3
|
+
|
4
|
+
class Server
|
5
|
+
|
6
|
+
include Googl::Utils
|
7
|
+
include Googl::OAuth2::Utils
|
8
|
+
|
9
|
+
attr_accessor :redirect_uri
|
10
|
+
|
11
|
+
def initialize(client_id, client_secret, redirect_uri)
|
12
|
+
self.client_id = client_id
|
13
|
+
self.client_secret = client_secret
|
14
|
+
self.redirect_uri = redirect_uri
|
15
|
+
end
|
16
|
+
|
17
|
+
def authorize_url
|
18
|
+
make_authorize_url(redirect_uri)
|
19
|
+
end
|
20
|
+
|
21
|
+
def request_access_token(code)
|
22
|
+
request_token(code, redirect_uri)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Googl
|
2
|
+
module OAuth2
|
3
|
+
|
4
|
+
module Utils
|
5
|
+
|
6
|
+
attr_accessor :client_id, :client_secret, :access_token, :refresh_token, :expires_in, :expires_at
|
7
|
+
attr_accessor :items
|
8
|
+
|
9
|
+
def expires?
|
10
|
+
expires_at < Time.now
|
11
|
+
end
|
12
|
+
|
13
|
+
def authorized?
|
14
|
+
!access_token.nil? && !refresh_token.nil? && !expires_in.nil? && !expires_at.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Gets a user's history of shortened URLs.
|
18
|
+
#
|
19
|
+
def history(options={})
|
20
|
+
return unless authorized?
|
21
|
+
resp = options.blank? ? get(Googl::Utils::API_HISTORY_URL) : get(Googl::Utils::API_HISTORY_URL, :query => options)
|
22
|
+
case resp.code
|
23
|
+
when 200
|
24
|
+
self.items = resp.parsed_response.to_openstruct
|
25
|
+
else
|
26
|
+
raise exception("#{resp.code} #{resp.parsed_response}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def request_token(code, request_uri="urn:ietf:wg:oauth:2.0:oob")
|
33
|
+
params = "code=#{code}&client_id=#{client_id}&client_secret=#{client_secret}&redirect_uri=#{request_uri}&grant_type=authorization_code"
|
34
|
+
modify_headers('Content-Type' => 'application/x-www-form-urlencoded')
|
35
|
+
resp = post("https://accounts.google.com/o/oauth2/token", :body => params)
|
36
|
+
case resp.code
|
37
|
+
when 200
|
38
|
+
modify_headers("Authorization" => "OAuth #{resp["access_token"]}")
|
39
|
+
self.access_token = resp["access_token"]
|
40
|
+
self.refresh_token = resp["refresh_token"]
|
41
|
+
self.expires_in = resp["expires_in"]
|
42
|
+
self.expires_at = Time.now + expires_in if expires_in
|
43
|
+
self
|
44
|
+
when 401
|
45
|
+
raise exception("#{resp.code} #{resp.parsed_response["error"]["message"]}")
|
46
|
+
else
|
47
|
+
raise exception("#{resp.code} #{resp.parsed_response["error"]}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def make_authorize_url(redirect_uri)
|
52
|
+
"https://accounts.google.com/o/oauth2/auth?client_id=#{client_id}&redirect_uri=#{redirect_uri}&scope=#{Googl::Utils::SCOPE_URL}&response_type=code"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
data/lib/googl/shorten.rb
CHANGED
@@ -2,7 +2,7 @@ module Googl
|
|
2
2
|
|
3
3
|
class Shorten < Base
|
4
4
|
|
5
|
-
|
5
|
+
include Googl::Utils
|
6
6
|
|
7
7
|
attr_accessor :short_url, :long_url
|
8
8
|
|
@@ -11,12 +11,12 @@ module Googl
|
|
11
11
|
def initialize(long_url)
|
12
12
|
modify_headers('Content-Type' => 'application/json')
|
13
13
|
options = {"longUrl" => long_url}.to_json
|
14
|
-
resp =
|
14
|
+
resp = post(API_URL, :body => options)
|
15
15
|
if resp.code == 200
|
16
|
-
|
17
|
-
|
16
|
+
self.short_url = resp['id']
|
17
|
+
self.long_url = resp['longUrl']
|
18
18
|
else
|
19
|
-
raise
|
19
|
+
raise exception(resp.parsed_response)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
data/lib/googl/utils.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Googl
|
2
|
+
|
3
|
+
module Utils # :nodoc:
|
4
|
+
|
5
|
+
API_URL = 'https://www.googleapis.com/urlshortener/v1/url'
|
6
|
+
API_HISTORY_URL = "https://www.googleapis.com/urlshortener/v1/url/history"
|
7
|
+
API_CLIENT_LOGIN_URL = "https://www.google.com/accounts/ClientLogin"
|
8
|
+
SCOPE_URL = "https://www.googleapis.com/auth/urlshortener"
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def modify_headers(item)
|
13
|
+
Googl::Request.headers.merge!(item)
|
14
|
+
end
|
15
|
+
|
16
|
+
def post(url, params={})
|
17
|
+
Googl::Request.post(url, params)
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(url, params={})
|
21
|
+
Googl::Request.get(url, params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def exception(msg)
|
25
|
+
Exception.new(msg)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Content-Type: application/json
|
3
|
+
Date: Thu, 17 Mar 2011 02:45:33 GMT
|
4
|
+
Expires: Thu, 17 Mar 2011 02:45:33 GMT
|
5
|
+
Cache-Control: private, max-age=0
|
6
|
+
X-Content-Type-Options: nosniff
|
7
|
+
X-Frame-Options: SAMEORIGIN
|
8
|
+
X-XSS-Protection: 1; mode=block
|
9
|
+
Server: GSE
|
10
|
+
Transfer-Encoding: chunked
|
11
|
+
|
12
|
+
{"access_token":"1/YCzoGAYT8XUuOifjNh_KqA","expires_in":3600,"refresh_token":"1/x_31GvgzdgHDMkRep5i8YxFlq76w3yjFu9Dp72Op-pI"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
HTTP/1.1 400 Bad Request
|
2
|
+
Content-Type: application/json
|
3
|
+
Date: Thu, 17 Mar 2011 03:05:33 GMT
|
4
|
+
Expires: Thu, 17 Mar 2011 03:05:33 GMT
|
5
|
+
Cache-Control: private, max-age=0
|
6
|
+
X-Content-Type-Options: nosniff
|
7
|
+
X-Frame-Options: SAMEORIGIN
|
8
|
+
X-XSS-Protection: 1; mode=block
|
9
|
+
Server: GSE
|
10
|
+
Transfer-Encoding: chunked
|
11
|
+
|
12
|
+
{"error":"invalid_token"}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
HTTP/1.1 401 Unauthorized
|
2
|
+
WWW-Authenticate: AuthSub realm="https://gaiastaging.corp.google.com/accounts/AuthSubRequest" allowed-scopes="https://www.googleapis.com/auth/urlshortener"
|
3
|
+
Content-Type: application/json; charset=UTF-8
|
4
|
+
Date: Fri, 18 Mar 2011 23:32:07 GMT
|
5
|
+
Expires: Fri, 18 Mar 2011 23:32:07 GMT
|
6
|
+
Cache-Control: private, max-age=0
|
7
|
+
X-Content-Type-Options: nosniff
|
8
|
+
X-Frame-Options: SAMEORIGIN
|
9
|
+
X-XSS-Protection: 1; mode=block
|
10
|
+
Server: GSE
|
11
|
+
Transfer-Encoding: chunked
|
12
|
+
|
13
|
+
{
|
14
|
+
"error": {
|
15
|
+
"errors": [
|
16
|
+
{
|
17
|
+
"domain": "global",
|
18
|
+
"reason": "invalid",
|
19
|
+
"message": "Invalid Credentials",
|
20
|
+
"locationType": "header",
|
21
|
+
"location": "Authorization"
|
22
|
+
}
|
23
|
+
],
|
24
|
+
"code": 401,
|
25
|
+
"message": "Invalid Credentials"
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Content-Type: application/json
|
3
|
+
Date: Fri, 18 Mar 2011 02:11:50 GMT
|
4
|
+
Expires: Fri, 18 Mar 2011 02:11:50 GMT
|
5
|
+
Cache-Control: private, max-age=0
|
6
|
+
X-Content-Type-Options: nosniff
|
7
|
+
X-Frame-Options: SAMEORIGIN
|
8
|
+
X-XSS-Protection: 1; mode=block
|
9
|
+
Server: GSE
|
10
|
+
Transfer-Encoding: chunked
|
11
|
+
|
12
|
+
{"access_token":"1/9eNgoHDXi-1u1fDzZ2wLLGATiaQZnWPB51nTvo8n9Sw","expires_in":3600,"refresh_token":"1/gvmLC5XlU0qRPIBR3mt7OBBfEoTKB6i2T-Gu4dBDupw"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
HTTP/1.1 400 Bad Request
|
2
|
+
Content-Type: application/json
|
3
|
+
Date: Fri, 18 Mar 2011 14:12:06 GMT
|
4
|
+
Expires: Fri, 18 Mar 2011 14:12:06 GMT
|
5
|
+
Cache-Control: private, max-age=0
|
6
|
+
X-Content-Type-Options: nosniff
|
7
|
+
X-Frame-Options: SAMEORIGIN
|
8
|
+
X-XSS-Protection: 1; mode=block
|
9
|
+
Server: GSE
|
10
|
+
Transfer-Encoding: chunked
|
11
|
+
|
12
|
+
{"error":"invalid_token"}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
HTTP/1.1 401 Unauthorized
|
2
|
+
WWW-Authenticate: AuthSub realm="https://gaiastaging.corp.google.com/accounts/AuthSubRequest" allowed-scopes="https://www.googleapis.com/auth/urlshortener"
|
3
|
+
Content-Type: application/json; charset=UTF-8
|
4
|
+
Date: Sat, 19 Mar 2011 00:00:35 GMT
|
5
|
+
Expires: Sat, 19 Mar 2011 00:00:35 GMT
|
6
|
+
Cache-Control: private, max-age=0
|
7
|
+
X-Content-Type-Options: nosniff
|
8
|
+
X-Frame-Options: SAMEORIGIN
|
9
|
+
X-XSS-Protection: 1; mode=block
|
10
|
+
Server: GSE
|
11
|
+
Transfer-Encoding: chunked
|
12
|
+
|
13
|
+
{
|
14
|
+
"error": {
|
15
|
+
"errors": [
|
16
|
+
{
|
17
|
+
"domain": "global",
|
18
|
+
"reason": "invalid",
|
19
|
+
"message": "Invalid Credentials",
|
20
|
+
"locationType": "header",
|
21
|
+
"location": "Authorization"
|
22
|
+
}
|
23
|
+
],
|
24
|
+
"code": 401,
|
25
|
+
"message": "Invalid Credentials"
|
26
|
+
}
|
27
|
+
}
|
File without changes
|
@@ -60,6 +60,15 @@ describe Googl::Expand do
|
|
60
60
|
|
61
61
|
subject { Googl.expand('http://goo.gl/DWDfi', :projection => :full) }
|
62
62
|
|
63
|
+
describe "#created" do
|
64
|
+
let(:element) { subject.created }
|
65
|
+
|
66
|
+
it "should be the time url was shortened" do
|
67
|
+
element.should == Time.iso8601("2011-01-13T03:48:10.309+00:00")
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
63
72
|
describe "#all_time" do
|
64
73
|
let(:element) { subject.analytics.all_time }
|
65
74
|
|
@@ -67,7 +76,7 @@ describe Googl::Expand do
|
|
67
76
|
it_should_behave_like 'a period'
|
68
77
|
|
69
78
|
it "should rename id to label" do
|
70
|
-
element.countries.first.label.should == "BR"
|
79
|
+
element.countries.first.label.should == "BR"
|
71
80
|
end
|
72
81
|
end
|
73
82
|
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Googl::OAuth2::Native do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
fake_urls? true
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
Googl::OAuth2.native("185706845724.apps.googleusercontent.com", "DrBLCdCQ3gOybHrj7TPz/B0N")
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
|
15
|
+
it "should assign client_id" do
|
16
|
+
subject.client_id.should == "185706845724.apps.googleusercontent.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should assign client_secret" do
|
20
|
+
subject.client_secret.should == "DrBLCdCQ3gOybHrj7TPz/B0N"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#authorize_url" do
|
26
|
+
|
27
|
+
it { subject.should respond_to(:authorize_url) }
|
28
|
+
|
29
|
+
it "should return url for authorize" do
|
30
|
+
subject.authorize_url.should == "https://accounts.google.com/o/oauth2/auth?client_id=185706845724.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/urlshortener&response_type=code"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should include the client_id" do
|
34
|
+
subject.authorize_url.should be_include("client_id=185706845724.apps.googleusercontent.com")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should include the redirect_uri" do
|
38
|
+
subject.authorize_url.should be_include("redirect_uri=urn:ietf:wg:oauth:2.0:oob")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should include the scope" do
|
42
|
+
subject.authorize_url.should be_include("scope=https://www.googleapis.com/auth/urlshortener")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should include the response_type" do
|
46
|
+
subject.authorize_url.should be_include("response_type=code")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#request_access_token" do
|
52
|
+
|
53
|
+
it { subject.should respond_to(:request_access_token) }
|
54
|
+
|
55
|
+
context "with valid code" do
|
56
|
+
|
57
|
+
let(:native) { subject.request_access_token("4/SuSud6RqPojUXsPpeh-wSVCwnmTQ") }
|
58
|
+
|
59
|
+
it "should return a access_token" do
|
60
|
+
native.access_token.should == "1/YCzoGAYT8XUuOifjNh_KqA"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return a refresh_token" do
|
64
|
+
native.refresh_token.should == "1/x_31GvgzdgHDMkRep5i8YxFlq76w3yjFu9Dp72Op-pI"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return a expires_in" do
|
68
|
+
native.expires_in.should == 3600
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with invalid code" do
|
74
|
+
it "should raise error" do
|
75
|
+
lambda { subject.request_access_token("my_invalid_code") }.should raise_error(/400 invalid_token/)
|
76
|
+
end
|
77
|
+
it "should raise Invalid Credentials on 401 response" do
|
78
|
+
lambda { subject.request_access_token("4/JvkEhCtr7tv1A60ENmubQT-cosRl") }.should raise_error(/401 Invalid Credentials/)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#expires_at" do
|
85
|
+
|
86
|
+
before do
|
87
|
+
@now = Time.now
|
88
|
+
Time.stub!(:now).and_return(@now)
|
89
|
+
end
|
90
|
+
|
91
|
+
let(:native) { subject.request_access_token("4/SuSud6RqPojUXsPpeh-wSVCwnmTQ") }
|
92
|
+
|
93
|
+
it "should be a time representation of #expires_in" do
|
94
|
+
native.expires_at.should == (@now + 3600)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#expires?" do
|
100
|
+
|
101
|
+
before :each do
|
102
|
+
Time.stub!(:now).and_return(Time.parse("2011-04-23 15:30:00"))
|
103
|
+
subject.request_access_token("4/SuSud6RqPojUXsPpeh-wSVCwnmTQ")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should be true if access token expires" do
|
107
|
+
Time.stub!(:now).and_return(Time.parse("2011-04-23 18:30:00"))
|
108
|
+
subject.expires?.should be_true
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should be false if access token not expires" do
|
112
|
+
subject.expires?.should be_false
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#authorized?" do
|
118
|
+
|
119
|
+
it "should return false if client is not authorized" do
|
120
|
+
subject.authorized?.should be_false
|
121
|
+
end
|
122
|
+
|
123
|
+
let(:native) { subject.request_access_token("4/SuSud6RqPojUXsPpeh-wSVCwnmTQ") }
|
124
|
+
|
125
|
+
it "should return true if client is authorized" do
|
126
|
+
native.authorized?.should be_true
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when gets a user history of shortened" do
|
132
|
+
|
133
|
+
it { subject.should respond_to(:history) }
|
134
|
+
|
135
|
+
it "should not return when client not authorized" do
|
136
|
+
subject.history.should be_nil
|
137
|
+
end
|
138
|
+
|
139
|
+
context "if authorized" do
|
140
|
+
|
141
|
+
let(:native) { subject.request_access_token("4/SuSud6RqPojUXsPpeh-wSVCwnmTQ") }
|
142
|
+
let(:history) { native.history }
|
143
|
+
|
144
|
+
it { history.should respond_to(:total_items) }
|
145
|
+
it { history.should respond_to(:items_per_page) }
|
146
|
+
it { history.should respond_to(:items) }
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Googl::OAuth2::Server do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
fake_urls? true
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
Googl::OAuth2.server("438834493660.apps.googleusercontent.com", "8i4iJJkFTukWhNpxTU1b2Zhi", "http://gooogl.heroku.com/back")
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
|
15
|
+
it "should assign client_id" do
|
16
|
+
subject.client_id.should == "438834493660.apps.googleusercontent.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should assign client_secret" do
|
20
|
+
subject.client_secret.should == "8i4iJJkFTukWhNpxTU1b2Zhi"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should assign redirect_uri" do
|
24
|
+
subject.redirect_uri.should == "http://gooogl.heroku.com/back"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#authorize_url" do
|
30
|
+
|
31
|
+
it { subject.should respond_to(:authorize_url) }
|
32
|
+
|
33
|
+
it "should return url for authorize" do
|
34
|
+
subject.authorize_url.should == "https://accounts.google.com/o/oauth2/auth?client_id=438834493660.apps.googleusercontent.com&redirect_uri=http://gooogl.heroku.com/back&scope=https://www.googleapis.com/auth/urlshortener&response_type=code"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should include the client_id" do
|
38
|
+
subject.authorize_url.should be_include("client_id=438834493660.apps.googleusercontent.com")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should include the redirect_uri" do
|
42
|
+
subject.authorize_url.should be_include("redirect_uri=http://gooogl.heroku.com/back")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should include the scope" do
|
46
|
+
subject.authorize_url.should be_include("scope=https://www.googleapis.com/auth/urlshortener")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should include the response_type" do
|
50
|
+
subject.authorize_url.should be_include("response_type=code")
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#request_access_token" do
|
56
|
+
|
57
|
+
it { subject.should respond_to(:request_access_token) }
|
58
|
+
|
59
|
+
context "with valid code" do
|
60
|
+
|
61
|
+
let(:server) { subject.request_access_token("4/z43CZpNmqd0IO3dR1Y_ouase13CH") }
|
62
|
+
|
63
|
+
it "should return a access_token" do
|
64
|
+
server.access_token.should == "1/9eNgoHDXi-1u1fDzZ2wLLGATiaQZnWPB51nTvo8n9Sw"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return a refresh_token" do
|
68
|
+
server.refresh_token.should == "1/gvmLC5XlU0qRPIBR3mt7OBBfEoTKB6i2T-Gu4dBDupw"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return a expires_in" do
|
72
|
+
server.expires_in.should == 3600
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
context "with invalid code" do
|
78
|
+
it "should raise error" do
|
79
|
+
lambda { subject.request_access_token("my_invalid_code") }.should raise_error(/400 invalid_token/)
|
80
|
+
end
|
81
|
+
it "should raise Invalid Credentials on 401 response" do
|
82
|
+
lambda { subject.request_access_token("4/JvkEhCtr7tv1A60ENmubQT-cosRl") }.should raise_error(/401 Invalid Credentials/)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#expires_at" do
|
89
|
+
|
90
|
+
before do
|
91
|
+
@now = Time.now
|
92
|
+
Time.stub!(:now).and_return(@now)
|
93
|
+
end
|
94
|
+
|
95
|
+
let(:server) { subject.request_access_token("4/z43CZpNmqd0IO3dR1Y_ouase13CH") }
|
96
|
+
|
97
|
+
it "should be a time representation of #expires_in" do
|
98
|
+
server.expires_at.should == (@now + 3600)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#expires?" do
|
104
|
+
|
105
|
+
before :each do
|
106
|
+
Time.stub!(:now).and_return(Time.parse("2011-04-23 15:30:00"))
|
107
|
+
subject.request_access_token("4/z43CZpNmqd0IO3dR1Y_ouase13CH")
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should be true if access token expires" do
|
111
|
+
Time.stub!(:now).and_return(Time.parse("2011-04-23 18:30:00"))
|
112
|
+
subject.expires?.should be_true
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should be false if access token not expires" do
|
116
|
+
subject.expires?.should be_false
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#authorized?" do
|
122
|
+
|
123
|
+
it "should return false if client is not authorized" do
|
124
|
+
subject.authorized?.should be_false
|
125
|
+
end
|
126
|
+
|
127
|
+
let(:server) { subject.request_access_token("4/z43CZpNmqd0IO3dR1Y_ouase13CH") }
|
128
|
+
|
129
|
+
it "should return true if client is authorized" do
|
130
|
+
server.authorized?.should be_true
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
context "when gets a user history of shortened" do
|
136
|
+
|
137
|
+
it { subject.should respond_to(:history) }
|
138
|
+
|
139
|
+
it "should not return when client not authorized" do
|
140
|
+
subject.history.should be_nil
|
141
|
+
end
|
142
|
+
|
143
|
+
context "if authorized" do
|
144
|
+
|
145
|
+
let(:server) { subject.request_access_token("4/z43CZpNmqd0IO3dR1Y_ouase13CH") }
|
146
|
+
let(:history) { server.history }
|
147
|
+
|
148
|
+
it { history.should respond_to(:total_items) }
|
149
|
+
it { history.should respond_to(:items_per_page) }
|
150
|
+
it { history.should respond_to(:items) }
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
File without changes
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -75,7 +75,7 @@ def fake_urls?(status)
|
|
75
75
|
:headers => {'Authorization'=>'GoogleLogin auth=DQAAAK8AAAC9ahL-o7g', 'Content-Type'=>'application/json'}).
|
76
76
|
to_return(load_fixture('shorten_authenticated.json'))
|
77
77
|
|
78
|
-
# History
|
78
|
+
# History for ClientLogin
|
79
79
|
stub_request(:get, "https://www.googleapis.com/urlshortener/v1/url/history").
|
80
80
|
with(:headers => {'Authorization'=>'GoogleLogin auth=DQAAAK8AAAC9ahL-o7g'}).
|
81
81
|
to_return(load_fixture('history.json'))
|
@@ -84,6 +84,53 @@ def fake_urls?(status)
|
|
84
84
|
stub_request(:get, "https://www.googleapis.com/urlshortener/v1/url/history?projection=analytics_clicks").
|
85
85
|
with(:headers => {'Authorization'=>'GoogleLogin auth=DQAAAK8AAAC9ahL-o7g'}).
|
86
86
|
to_return(load_fixture('history_projection_clicks.json'))
|
87
|
+
|
88
|
+
# OAuth 2.0 for native applications
|
89
|
+
stub_request(:post, "https://accounts.google.com/o/oauth2/token").
|
90
|
+
with(:body => "code=4/SuSud6RqPojUXsPpeh-wSVCwnmTQ&client_id=185706845724.apps.googleusercontent.com&client_secret=DrBLCdCQ3gOybHrj7TPz/B0N&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code",
|
91
|
+
:headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
92
|
+
to_return(load_fixture('oauth2/native.json'))
|
93
|
+
|
94
|
+
# OAuth 2.0 for native applications (invalid token)
|
95
|
+
stub_request(:post, "https://accounts.google.com/o/oauth2/token").
|
96
|
+
with(:body => "code=my_invalid_code&client_id=185706845724.apps.googleusercontent.com&client_secret=DrBLCdCQ3gOybHrj7TPz/B0N&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code",
|
97
|
+
:headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
98
|
+
to_return(load_fixture('oauth2/native_invalid.json'))
|
99
|
+
|
100
|
+
# OAuth 2.0 for native applications (expired token)
|
101
|
+
stub_request(:post, "https://accounts.google.com/o/oauth2/token").
|
102
|
+
with(:body => "code=4/JvkEhCtr7tv1A60ENmubQT-cosRl&client_id=185706845724.apps.googleusercontent.com&client_secret=DrBLCdCQ3gOybHrj7TPz/B0N&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code",
|
103
|
+
:headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
104
|
+
to_return(load_fixture('oauth2/native_token_expires.json'))
|
105
|
+
|
106
|
+
# OAuth 2.0 for native applications (history)
|
107
|
+
stub_request(:get, "https://www.googleapis.com/urlshortener/v1/url/history").
|
108
|
+
with(:headers => {'Authorization'=>'OAuth 1/YCzoGAYT8XUuOifjNh_KqA', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
109
|
+
to_return(load_fixture('history.json'))
|
110
|
+
|
111
|
+
# OAuth 2.0 for server-side web applications
|
112
|
+
stub_request(:post, "https://accounts.google.com/o/oauth2/token").
|
113
|
+
with(:body => "code=4/z43CZpNmqd0IO3dR1Y_ouase13CH&client_id=438834493660.apps.googleusercontent.com&client_secret=8i4iJJkFTukWhNpxTU1b2Zhi&redirect_uri=http://gooogl.heroku.com/back&grant_type=authorization_code",
|
114
|
+
:headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
115
|
+
to_return(load_fixture('oauth2/server.json'))
|
116
|
+
|
117
|
+
# OAuth 2.0 for server-side web applications (invalid token)
|
118
|
+
stub_request(:post, "https://accounts.google.com/o/oauth2/token").
|
119
|
+
with(:body => "code=my_invalid_code&client_id=438834493660.apps.googleusercontent.com&client_secret=8i4iJJkFTukWhNpxTU1b2Zhi&redirect_uri=http://gooogl.heroku.com/back&grant_type=authorization_code",
|
120
|
+
:headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
121
|
+
to_return(load_fixture('oauth2/server_invalid.json'))
|
122
|
+
|
123
|
+
# OAuth 2.0 for server-side web applications (expired token)
|
124
|
+
stub_request(:post, "https://accounts.google.com/o/oauth2/token").
|
125
|
+
with(:body => "code=4/JvkEhCtr7tv1A60ENmubQT-cosRl&client_id=438834493660.apps.googleusercontent.com&client_secret=8i4iJJkFTukWhNpxTU1b2Zhi&redirect_uri=http://gooogl.heroku.com/back&grant_type=authorization_code",
|
126
|
+
:headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
127
|
+
to_return(load_fixture('oauth2/server_token_expires.json'))
|
128
|
+
|
129
|
+
# OAuth 2.0 for server-side web applications (history)
|
130
|
+
stub_request(:get, "https://www.googleapis.com/urlshortener/v1/url/history").
|
131
|
+
with(:headers => {'Authorization'=>'OAuth 1/9eNgoHDXi-1u1fDzZ2wLLGATiaQZnWPB51nTvo8n9Sw'}).
|
132
|
+
to_return(load_fixture('history.json'))
|
133
|
+
|
87
134
|
else
|
88
135
|
WebMock.allow_net_connect!
|
89
136
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jesus Lopes
|
@@ -15,12 +15,14 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-05-01 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
+
prerelease: false
|
23
|
+
name: httparty
|
22
24
|
type: :runtime
|
23
|
-
|
25
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
24
26
|
none: false
|
25
27
|
requirements:
|
26
28
|
- - ">="
|
@@ -31,12 +33,12 @@ dependencies:
|
|
31
33
|
- 6
|
32
34
|
- 1
|
33
35
|
version: 0.6.1
|
34
|
-
|
35
|
-
version_requirements: *id001
|
36
|
-
prerelease: false
|
36
|
+
requirement: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
|
+
prerelease: false
|
39
|
+
name: json
|
38
40
|
type: :runtime
|
39
|
-
|
41
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
42
|
none: false
|
41
43
|
requirements:
|
42
44
|
- - ">="
|
@@ -47,12 +49,12 @@ dependencies:
|
|
47
49
|
- 4
|
48
50
|
- 6
|
49
51
|
version: 1.4.6
|
50
|
-
|
51
|
-
version_requirements: *id002
|
52
|
-
prerelease: false
|
52
|
+
requirement: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
|
+
prerelease: false
|
55
|
+
name: rspec
|
54
56
|
type: :development
|
55
|
-
|
57
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
56
58
|
none: false
|
57
59
|
requirements:
|
58
60
|
- - ~>
|
@@ -63,12 +65,12 @@ dependencies:
|
|
63
65
|
- 3
|
64
66
|
- 0
|
65
67
|
version: 2.3.0
|
66
|
-
|
67
|
-
version_requirements: *id003
|
68
|
-
prerelease: false
|
68
|
+
requirement: *id003
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
+
prerelease: false
|
71
|
+
name: bundler
|
70
72
|
type: :development
|
71
|
-
|
73
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
72
74
|
none: false
|
73
75
|
requirements:
|
74
76
|
- - ~>
|
@@ -79,12 +81,12 @@ dependencies:
|
|
79
81
|
- 0
|
80
82
|
- 0
|
81
83
|
version: 1.0.0
|
82
|
-
|
83
|
-
version_requirements: *id004
|
84
|
-
prerelease: false
|
84
|
+
requirement: *id004
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
|
+
prerelease: false
|
87
|
+
name: jeweler
|
86
88
|
type: :development
|
87
|
-
|
89
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
88
90
|
none: false
|
89
91
|
requirements:
|
90
92
|
- - ~>
|
@@ -95,12 +97,12 @@ dependencies:
|
|
95
97
|
- 5
|
96
98
|
- 2
|
97
99
|
version: 1.5.2
|
98
|
-
|
99
|
-
version_requirements: *id005
|
100
|
-
prerelease: false
|
100
|
+
requirement: *id005
|
101
101
|
- !ruby/object:Gem::Dependency
|
102
|
+
prerelease: false
|
103
|
+
name: rcov
|
102
104
|
type: :development
|
103
|
-
|
105
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
104
106
|
none: false
|
105
107
|
requirements:
|
106
108
|
- - ">="
|
@@ -109,12 +111,12 @@ dependencies:
|
|
109
111
|
segments:
|
110
112
|
- 0
|
111
113
|
version: "0"
|
112
|
-
|
113
|
-
version_requirements: *id006
|
114
|
-
prerelease: false
|
114
|
+
requirement: *id006
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
|
+
prerelease: false
|
117
|
+
name: webmock
|
116
118
|
type: :development
|
117
|
-
|
119
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
118
120
|
none: false
|
119
121
|
requirements:
|
120
122
|
- - ~>
|
@@ -125,9 +127,7 @@ dependencies:
|
|
125
127
|
- 6
|
126
128
|
- 2
|
127
129
|
version: 1.6.2
|
128
|
-
|
129
|
-
version_requirements: *id007
|
130
|
-
prerelease: false
|
130
|
+
requirement: *id007
|
131
131
|
description: Small library for Google URL Shortener API
|
132
132
|
email: jlopes@zigotto.com.br
|
133
133
|
executables: []
|
@@ -148,11 +148,13 @@ files:
|
|
148
148
|
- lib/googl/base.rb
|
149
149
|
- lib/googl/client_login.rb
|
150
150
|
- lib/googl/expand.rb
|
151
|
+
- lib/googl/oauth2/native.rb
|
152
|
+
- lib/googl/oauth2/server.rb
|
153
|
+
- lib/googl/oauth2/utils.rb
|
151
154
|
- lib/googl/request.rb
|
152
155
|
- lib/googl/ruby_extensions.rb
|
153
156
|
- lib/googl/shorten.rb
|
154
|
-
-
|
155
|
-
- spec/expand_spec.rb
|
157
|
+
- lib/googl/utils.rb
|
156
158
|
- spec/fixtures/client_login_invalid.json
|
157
159
|
- spec/fixtures/client_login_valid.json
|
158
160
|
- spec/fixtures/expand.json
|
@@ -163,12 +165,22 @@ files:
|
|
163
165
|
- spec/fixtures/expand_removed.json
|
164
166
|
- spec/fixtures/history.json
|
165
167
|
- spec/fixtures/history_projection_clicks.json
|
168
|
+
- spec/fixtures/oauth2/native.json
|
169
|
+
- spec/fixtures/oauth2/native_invalid.json
|
170
|
+
- spec/fixtures/oauth2/native_token_expires.json
|
171
|
+
- spec/fixtures/oauth2/server.json
|
172
|
+
- spec/fixtures/oauth2/server_invalid.json
|
173
|
+
- spec/fixtures/oauth2/server_token_expires.json
|
166
174
|
- spec/fixtures/shorten.json
|
167
175
|
- spec/fixtures/shorten_authenticated.json
|
168
176
|
- spec/fixtures/shorten_invalid_content_type.json
|
169
|
-
- spec/
|
177
|
+
- spec/googl/client_spec.rb
|
178
|
+
- spec/googl/expand_spec.rb
|
179
|
+
- spec/googl/oauth2/native_spec.rb
|
180
|
+
- spec/googl/oauth2/server_spec.rb
|
181
|
+
- spec/googl/request_spec.rb
|
182
|
+
- spec/googl/shorten_spec.rb
|
170
183
|
- spec/shared_examples.rb
|
171
|
-
- spec/shorten_spec.rb
|
172
184
|
- spec/spec_helper.rb
|
173
185
|
has_rdoc: true
|
174
186
|
homepage: http://github.com/zigotto/googl
|
@@ -200,14 +212,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
200
212
|
requirements: []
|
201
213
|
|
202
214
|
rubyforge_project:
|
203
|
-
rubygems_version: 1.
|
215
|
+
rubygems_version: 1.4.2
|
204
216
|
signing_key:
|
205
217
|
specification_version: 3
|
206
218
|
summary: Wrapper for Google URL Shortener API
|
207
219
|
test_files:
|
208
|
-
- spec/client_spec.rb
|
209
|
-
- spec/expand_spec.rb
|
210
|
-
- spec/
|
220
|
+
- spec/googl/client_spec.rb
|
221
|
+
- spec/googl/expand_spec.rb
|
222
|
+
- spec/googl/oauth2/native_spec.rb
|
223
|
+
- spec/googl/oauth2/server_spec.rb
|
224
|
+
- spec/googl/request_spec.rb
|
225
|
+
- spec/googl/shorten_spec.rb
|
211
226
|
- spec/shared_examples.rb
|
212
|
-
- spec/shorten_spec.rb
|
213
227
|
- spec/spec_helper.rb
|