rest-graph 0.8.1 → 0.9.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/CHANGES CHANGED
@@ -1,5 +1,12 @@
1
1
  = rest-graph changes history
2
2
 
3
+ == rest-graph 0.9.0 -- 2010-05-04
4
+ * renamed :server option to :graph_server
5
+ * added :fql_server option and fql support.
6
+ * cookies related parsing utility is now instance methods.
7
+ you'll need to pass app_id and secret when initializing
8
+ * if sig in cookies is bad, then it won't extract the access_token
9
+
3
10
  == rest-graph 0.8.1 -- 2010-05-03
4
11
  * added access_token parsing utility
5
12
 
data/README CHANGED
@@ -1,4 +1,4 @@
1
- = rest-graph 0.8.0
1
+ = rest-graph 0.9.0
2
2
  by Lin Jen-Shin (aka godfat-真常[http://godfat.org])
3
3
  godfat (XD) godfat.org
4
4
 
@@ -15,30 +15,37 @@ by Lin Jen-Shin (aka godfat-真常[http://godfat.org])
15
15
  == SYNOPSIS:
16
16
 
17
17
  require 'rest-graph'
18
+
19
+ # every option is optional!!
18
20
  rg = RestGraph.new(:access_token => '...',
19
- :server => 'https://graph.facebook.com/,
21
+ :graph_server => 'https://graph.facebook.com/',
22
+ :fql_server => 'https://api.facebook.com/',
20
23
  :accept => 'text/javascript',
21
24
  :lang => 'en-us', # this affect search
22
- :auto_decode => true) # decode by json
25
+ :auto_decode => true, # decode by json
26
+ :app_id => '123',
27
+ :secret => '1829')
23
28
  rg.get('me')
24
29
  rg.post('feed/me', :message => 'bread!')
25
30
 
26
31
  # for rack
27
- app_id = '\d+'
28
32
  lambda{ |env|
29
- rg = RestGraph.new(:access_token =>
30
- RestGraph.parse_token_in_rack_env(env, app_id))
33
+ rg = RestGraph.new(:app_id => '123', :secret => '1829')
34
+ rg.parse_token_in_rack_env!(env) # auto save access_token if sig checked
35
+ rg.access_token # => ...
31
36
  }
32
37
 
33
38
  # for fully blown cookies hash
34
- app_id = '123'
35
- rg = RestGraph.new(:access_token =>
36
- RestGraph.parse_token_in_cookies(cookies, app_id))
39
+ rg = RestGraph.new(:app_id => '123', :secret => '1829')
40
+ rg.parse_token_in_cookies!(cookies) # auto save access_token if sig checked
41
+ rg.access_token # => ...
37
42
 
38
- # for fully blown cookies hash
43
+ # for fbs in cookies
39
44
  app_id = '456'
40
- rg = RestGraph.new(:access_token =>
41
- RestGraph.parse_token_in_fb_cookie(cookies["fbs_#{app_id}"]))
45
+ rg = RestGraph.new(:app_id => '123', :secret => '1829')
46
+ fbs = cookies["fbs_#{rg.app_id}"]
47
+ rg.parse_token_in_fbs!(fbs) # auto save access_token if sig checked
48
+ rg.access_token # => ...
42
49
 
43
50
  == REQUIREMENTS:
44
51
 
data/TODO CHANGED
@@ -1,3 +1,4 @@
1
1
  = rest-graph todo list
2
2
 
3
- = ?
3
+ = 1.0
4
+ * oauth support?
@@ -1,4 +1,4 @@
1
1
 
2
2
  class RestGraph
3
- VERSION = '0.8.1'
3
+ VERSION = '0.9.0'
4
4
  end
data/lib/rest-graph.rb CHANGED
@@ -3,63 +3,82 @@ require 'rest_client'
3
3
 
4
4
  require 'cgi'
5
5
 
6
- class RestGraph
7
- autoload :Rack, 'rack'
8
- def self.parse_token_in_rack_env env, app_id = '\d+'
9
- env['HTTP_COOKIE'] =~ /fbs_#{app_id}="(.+?)"/ &&
10
- Rack::Utils.parse_query($1)['access_token']
11
- end
12
-
13
- def self.parse_token_in_cookies cookies, app_id
14
- parse_token_in_fb_cookie(cookies["fbs_#{app_id}"])
15
- end
16
-
17
- def self.parse_token_in_fb_cookie fb_cookie
18
- fb_cookie && Rack::Utils.parse_query(fb_cookie[1..-2])['access_token']
19
- end
20
-
21
- attr_accessor :access_token, :server, :accept, :lang, :auto_decode
6
+ class RestGraph < Struct.new(:access_token, :graph_server, :fql_server,
7
+ :accept, :lang, :auto_decode, :app_id, :secret)
22
8
  def initialize o = {}
23
9
  self.access_token = o[:access_token]
24
- self.server = o[:server] || 'https://graph.facebook.com/'
10
+ self.graph_server = o[:graph_server] || 'https://graph.facebook.com/'
11
+ self.fql_server = o[:fql_server] || 'https://api.facebook.com/'
25
12
  self.accept = o[:accept] || 'text/javascript'
26
13
  self.lang = o[:lang] || 'en-us'
27
14
  self.auto_decode = o.key?(:auto_decode) ? o[:auto_decode] : true
15
+ self.app_id = o[:app_id]
16
+ self.secret = o[:secret]
28
17
 
29
- if auto_decode
30
- begin
31
- require 'json'
32
- rescue LoadError
33
- require 'json_pure'
34
- end
35
- end
18
+ check_arguments!
19
+ end
20
+
21
+ def get path, opts = {}
22
+ request(graph_server, path, opts, :get)
23
+ end
24
+
25
+ def delete path, opts = {}
26
+ request(graph_server, path, opts, :delete)
27
+ end
28
+
29
+ def post path, payload, opts = {}
30
+ request(graph_server, path, opts, :post, payload)
36
31
  end
37
32
 
38
- def client
39
- @client ||= RestClient::Resource.new(server)
33
+ def put path, payload, opts = {}
34
+ request(graph_server, path, opts, :put, payload)
40
35
  end
41
36
 
42
- def get path, query = {}
43
- request(path, query, :get)
37
+ def fql query, opts = {}
38
+ request(fql_server, 'method/fql.query',
39
+ {:query => query, :format => 'json'}.merge(opts), :get)
44
40
  end
45
41
 
46
- def delete path, query = {}
47
- request(path, query, :delete)
42
+ # cookies, app_id, secrect related below
43
+
44
+ def parse_token_in_rack_env! env
45
+ self.access_token = env['HTTP_COOKIE'] =~ /fbs_#{app_id}="(.+?)"/ &&
46
+ extract_token_if_sig_ok(Rack::Utils.parse_query($1))
48
47
  end
49
48
 
50
- def post path, payload, query = {}
51
- request(path, query, :post, payload)
49
+ def parse_token_in_cookies! cookies
50
+ self.access_token = parse_token_in_fbs!(cookies["fbs_#{app_id}"])
52
51
  end
53
52
 
54
- def put path, payload, query = {}
55
- request(path, query, :put, payload)
53
+ def parse_token_in_fbs! fbs
54
+ self.access_token = fbs &&
55
+ extract_token_if_sig_ok(Rack::Utils.parse_query(fbs[1..-2]))
56
56
  end
57
57
 
58
58
  private
59
- def request path, query, method, payload = nil
59
+ def check_arguments!
60
+ if auto_decode
61
+ begin
62
+ require 'json'
63
+ rescue LoadError
64
+ require 'json_pure'
65
+ end
66
+ end
67
+
68
+ if app_id && secret # want to parse access_token in cookies
69
+ require 'digest/md5'
70
+ require 'rack'
71
+ elsif app_id || secret
72
+ raise ArgumentError.new("You may want pass both" \
73
+ " app_id(#{app_id.inspect}) and" \
74
+ " secret(#{secret.inspect})")
75
+ end
76
+ end
77
+
78
+ def request server, path, opts, method, payload = nil
60
79
  post_request(
61
- client[path + build_query_string(query)].
62
- send(method, *[payload, build_headers].compact))
80
+ RestClient::Resource.new(server)[path + build_query_string(opts)].
81
+ send(method, *[payload, build_headers].compact))
63
82
  rescue RestClient::InternalServerError => e
64
83
  post_request(e.http_body)
65
84
  end
@@ -80,4 +99,15 @@ class RestGraph
80
99
  def post_request result
81
100
  auto_decode ? JSON.parse(result) : result
82
101
  end
102
+
103
+ def extract_token_if_sig_ok cookies
104
+ cookies['access_token'] if calculate_sig(cookies) == cookies['sig']
105
+ end
106
+
107
+ def calculate_sig cookies
108
+ payload = cookies.reject{ |(k, v)| k == 'sig' }.sort.
109
+ map{ |a| a.join('=') }.join
110
+
111
+ Digest::MD5.hexdigest(payload + secret)
112
+ end
83
113
  end
@@ -59,7 +59,7 @@ describe RestGraph do
59
59
  {'User-Agent' => 'Ruby'})). # this is by ruby
60
60
  to_return(:body => '{"data": []}')
61
61
 
62
- RestGraph.new(:server => 'http://nothing.godfat.org',
62
+ RestGraph.new(:graph_server => 'http://nothing.godfat.org/',
63
63
  :lang => 'zh-tw',
64
64
  :accept => 'text/plain').get('me').should == {'data' => []}
65
65
  end
@@ -104,22 +104,51 @@ describe RestGraph do
104
104
  RestGraph.new.delete('123').should == []
105
105
  end
106
106
 
107
- it 'would extract correct access_token' do
107
+ it 'would extract correct access_token or fail checking sig' do
108
108
  access_token = '1|2-5|f.'
109
109
  app_id = '1829'
110
+ secret = app_id.reverse
111
+ sig = '398262caea8442bd8801e8fba7c55c8a'
110
112
  fbs = "\"access_token=#{CGI.escape(access_token)}&expires=0&" \
111
- "secret=abc&session_key=def-456&sig=zzz&uid=3\""
112
- http_cookie =
113
- "__utma=123; __utmz=456.utmcsr=(d)|utmccn=(d)|utmcmd=(n); " \
114
- "fbs_#{app_id}=#{fbs}"
113
+ "secret=abc&session_key=def-456&sig=#{sig}&uid=3\""
114
+
115
+ check = lambda{ |token|
116
+ http_cookie =
117
+ "__utma=123; __utmz=456.utmcsr=(d)|utmccn=(d)|utmcmd=(n); " \
118
+ "fbs_#{app_id}=#{fbs}"
119
+
120
+ rg = RestGraph.new(:app_id => app_id, :secret => secret)
121
+ rg.parse_token_in_rack_env!('HTTP_COOKIE' => http_cookie).
122
+ should == token
123
+ rg.access_token.should == token
124
+
125
+ rg.parse_token_in_cookies!({"fbs_#{app_id}" => fbs}).
126
+ should == token
127
+ rg.access_token.should == token
128
+
129
+ rg.parse_token_in_fbs!(fbs).
130
+ should == token
131
+ rg.access_token.should == token
132
+ }
133
+ check.call(access_token)
134
+ fbs.chop!
135
+ fbs += '&inject=evil"'
136
+ check.call(nil)
137
+ end
138
+
139
+ it 'would do fql query with/without access_token' do
140
+ fql = 'SELECT name FROM likes where id="123"'
141
+ query = "query=#{fql}&format=json"
142
+ stub_request(:get, "https://api.facebook.com/method/fql.query?#{query}").
143
+ to_return(:body => '[]')
115
144
 
116
- RestGraph.parse_token_in_rack_env('HTTP_COOKIE' => http_cookie).
117
- should == access_token
145
+ RestGraph.new.fql(fql).should == []
118
146
 
119
- RestGraph.parse_token_in_cookies({"fbs_#{app_id}" => fbs}, app_id).
120
- should == access_token
147
+ token = 'token'.reverse
148
+ stub_request(:get, "https://api.facebook.com/method/fql.query?#{query}" \
149
+ "&access_token=#{token}").
150
+ to_return(:body => '[]')
121
151
 
122
- RestGraph.parse_token_in_fb_cookie(fbs).
123
- should == access_token
152
+ RestGraph.new(:access_token => token).fql(fql).should == []
124
153
  end
125
154
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 8
8
- - 1
9
- version: 0.8.1
7
+ - 9
8
+ - 0
9
+ version: 0.9.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Lin Jen-Shin (aka godfat \xE7\x9C\x9F\xE5\xB8\xB8)"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-03 00:00:00 +08:00
17
+ date: 2010-05-04 00:00:00 +08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency