rest-graph 0.8.1 → 0.9.0

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