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