qoobaa-opensocial 0.1.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/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/opensocial.rb ADDED
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "active_support"
16
+ require "oauth"
17
+ require "oauth/consumer"
18
+ require "oauth/request_proxy/action_controller_request"
19
+ require "uri"
20
+
21
+ require "opensocial/base"
22
+ require "opensocial/request"
23
+ require "opensocial/activity"
24
+ require "opensocial/appdata"
25
+ require "opensocial/auth/action_controller_request"
26
+ require "opensocial/auth/base"
27
+ require "opensocial/connection"
28
+ require "opensocial/group"
29
+ require "opensocial/person"
30
+ require "opensocial/string/merb_string"
31
+ require "opensocial/string/os_string"
@@ -0,0 +1,113 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenSocial #:nodoc:
16
+
17
+ # Acts as a wrapper for an OpenSocial activity.
18
+ #
19
+ # The Activity class takes input JSON as an initialization parameter, and
20
+ # iterates through each of the key/value pairs of that JSON. For each key
21
+ # that is found, an attr_accessor is constructed, allowing direct access
22
+ # to the value. Each value is stored in the attr_accessor, either as a
23
+ # String, Fixnum, Hash, or Array.
24
+ #
25
+
26
+ class Activity < Base
27
+
28
+ # Initializes the Activity based on the provided json fragment. If no JSON
29
+ # is provided, an empty object (with no attributes) is created.
30
+ def initialize(json)
31
+ if json
32
+ json.each do |key, value|
33
+ proper_key = key.snake_case
34
+ begin
35
+ self.send("#{proper_key}=", value)
36
+ rescue NoMethodError
37
+ add_attr(proper_key)
38
+ self.send("#{proper_key}=", value)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ # Provides the ability to request a Collection of activities for a given
46
+ # user or set of users.
47
+ #
48
+ # The FetchActivitiesRequest wraps a simple request to an OpenSocial
49
+ # endpoint for a Collection of activities. As parameters, it accepts
50
+ # a user ID and selector (and optionally an ID of a particular activity).
51
+ # This request may be used, standalone, by calling send, or bundled into
52
+ # an RpcRequest.
53
+ #
54
+
55
+ class FetchActivitiesRequest < Request
56
+ # Defines the service fragment for use in constructing the request URL or
57
+ # JSON
58
+ SERVICE = "activities"
59
+
60
+ # This is only necessary because of a spec inconsistency
61
+ RPC_SERVICE = "activity"
62
+
63
+ # Initializes a request to fetch activities for the specified user and
64
+ # group, or the default (@me, @self). A valid Connection is not necessary
65
+ # if the request is to be used as part of an RpcRequest.
66
+ def initialize(connection = nil, guid = "@me", selector = "@self",
67
+ pid = nil)
68
+ super
69
+ end
70
+
71
+ # Sends the request, passing in the appropriate SERVICE and specified
72
+ # instance variables.
73
+ def send
74
+ json = send_request(SERVICE, @guid, @selector, @pid)
75
+
76
+ return parse_response(json["entry"])
77
+ end
78
+
79
+ # Selects the appropriate fragment from the JSON response in order to
80
+ # create a native object.
81
+ def parse_rpc_response(response)
82
+ return parse_response(response["data"]["list"])
83
+ end
84
+
85
+ # Converts the request into a JSON fragment that can be used as part of a
86
+ # larger RpcRequest.
87
+ def to_json(*a)
88
+ value = {
89
+ "method" => RPC_SERVICE + GET,
90
+ "params" => {
91
+ "userId" => ["#{@guid}"],
92
+ "groupId" => "#{@selector}",
93
+ "appId" => "#{@pid}"
94
+ },
95
+ "id" => @key
96
+ }.to_json(*a)
97
+ end
98
+
99
+ private
100
+
101
+ # Converts the JSON response into a Collection of activities, indexed by
102
+ # id.
103
+ def parse_response(response)
104
+ activities = Collection.new
105
+ for entry in response
106
+ activity = Activity.new(entry)
107
+ activities[activity.id] = activity
108
+ end
109
+
110
+ return activities
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenSocial #:nodoc:
16
+
17
+ # Acts as a wrapper for an OpenSocial appdata entry.
18
+ #
19
+ # The AppData class takes a person's ID and input JSON as initialization
20
+ # parameters, and iterates through each of the key/value pairs of that JSON.
21
+ # For each key that is found, an attr_accessor is constructed (except for
22
+ # :id which is preconstructed, and required), allowing direct access to the
23
+ # value. Each value is stored in the attr_accessor, either as a String,
24
+ # Fixnum, Hash, or Array.
25
+ #
26
+
27
+ class AppData < Base
28
+ attr_accessor :id
29
+
30
+ # Initializes the AppData entry based on the provided id and json fragment.
31
+ # If no JSON is provided, an empty object (with only an ID) is created.
32
+ def initialize(id, json)
33
+ @id = id
34
+
35
+ if json
36
+ json.each do |key, value|
37
+ begin
38
+ self.send("#{key}=", value)
39
+ rescue NoMethodError
40
+ add_attr(key)
41
+ self.send("#{key}=", value)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # Provides the ability to request a Collection of AppData for a given
49
+ # user or set of users.
50
+ #
51
+ # The FetchAppData wraps a simple request to an OpenSocial
52
+ # endpoint for a Collection of AppData. As parameters, it accepts
53
+ # a user ID and selector. This request may be used, standalone, by calling
54
+ # send, or bundled into an RpcRequest.
55
+ #
56
+
57
+ class FetchAppDataRequest < Request
58
+ # Defines the service fragment for use in constructing the request URL or
59
+ # JSON
60
+ SERVICE = "appdata"
61
+
62
+ # Initializes a request to fetch appdata for the specified user and
63
+ # group, or the default (@me, @self). A valid Connection is not necessary
64
+ # if the request is to be used as part of an RpcRequest.
65
+ def initialize(connection = nil, guid = "@me", selector = "@self",
66
+ aid = "@app")
67
+ super(connection, guid, selector, aid)
68
+ end
69
+
70
+ # Sends the request, passing in the appropriate SERVICE and specified
71
+ # instance variables. Accepts an unescape parameter, defaulting to true,
72
+ # if the returned data should be unescaped.
73
+ def send(unescape = true)
74
+ json = send_request(SERVICE, @guid, @selector, @pid, unescape)
75
+
76
+ return parse_response(json["entry"])
77
+ end
78
+
79
+ # Selects the appropriate fragment from the JSON response in order to
80
+ # create a native object.
81
+ def parse_rpc_response(response)
82
+ return parse_response(response["data"])
83
+ end
84
+
85
+ # Converts the request into a JSON fragment that can be used as part of a
86
+ # larger RpcRequest.
87
+ def to_json(*a)
88
+ value = {
89
+ "method" => SERVICE + GET,
90
+ "params" => {
91
+ "userId" => ["#{@guid}"],
92
+ "groupId" => "#{@selector}",
93
+ "appId" => "#{@pid}",
94
+ "fields" => []
95
+ },
96
+ "id" => @key
97
+ }.to_json(*a)
98
+ end
99
+
100
+ private
101
+
102
+ # Converts the JSON response into a Collection of AppData entries, indexed
103
+ # by id.
104
+ def parse_response(response)
105
+ appdata = Collection.new
106
+ response.each do |key, value|
107
+ data = AppData.new(key, value)
108
+ appdata[key] = data
109
+ end
110
+
111
+ return appdata
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright (c) 2007 Blaine Cook, Larry Halff, Pelle Braendgaard
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+ #
22
+ # Includes modifications by Robin Luckey from:
23
+ # http://github.com/robinluckey/oauth/tree/master/lib%2Foauth%2Frequest_proxy%2Faction_controller_request.rb
24
+
25
+ module OAuth::RequestProxy #:nodoc: all
26
+ class ActionControllerRequest < OAuth::RequestProxy::Base
27
+ if defined?(ActionDispatch::Request)
28
+ proxies(ActionDispatch::Request)
29
+ elsif defined?(ActionController::AbstractRequest)
30
+ proxies(ActionController::AbstractRequest)
31
+ else
32
+ proxies(ActionController::Request)
33
+ end
34
+
35
+ def method
36
+ request.method.to_s.upcase
37
+ end
38
+
39
+ def uri
40
+ uri = URI.parse(request.protocol + request.host + request.port_string + request.path)
41
+ uri.query = nil
42
+ uri.to_s
43
+ end
44
+
45
+ def parameters
46
+ if options[:clobber_request]
47
+ options[:parameters] || {}
48
+ else
49
+ params = request_params.merge(query_params).merge(header_params)
50
+ params.stringify_keys! if params.respond_to?(:stringify_keys!)
51
+ params.merge(options[:parameters] || {})
52
+ end
53
+ end
54
+
55
+ # Override from OAuth::RequestProxy::Base to avoid roundtrip
56
+ # conversion to Hash or Array and thus preserve the original
57
+ # parameter names
58
+ def parameters_for_signature
59
+ params = []
60
+ params << options[:parameters].to_query if options[:parameters]
61
+
62
+ unless options[:clobber_request]
63
+ params << header_params.to_query
64
+ params << CGI.unescape(request.query_string) unless request.query_string.blank?
65
+ if request.content_type == Mime::Type.lookup("application/x-www-form-urlencoded")
66
+ params << CGI.unescape(request.raw_post)
67
+ end
68
+ end
69
+
70
+ params.
71
+ join("&").split("&").
72
+ reject { |kv| kv =~ /^oauth_signature=.*/}.
73
+ reject(&:blank?).
74
+ map { |p| p.split("=") }
75
+ end
76
+
77
+ protected
78
+
79
+ def query_params
80
+ request.query_parameters
81
+ end
82
+
83
+ def request_params
84
+ request.request_parameters
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,109 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenSocial #:nodoc:
16
+
17
+ # Provides helper classes to be used in verifying and validating the user.
18
+ # In particular, support is provided for:
19
+ #
20
+ # * Verification of signed makeRequest using OAuth/HMAC-SHA1
21
+ # class ExampleController < ApplicationController
22
+ # OpenSocial::Auth::CONSUMER_KEY = "623061448914"
23
+ # OpenSocial::Auth::CONSUMER_SECRET = "uynAeXiWTisflWX99KU1D2q5"
24
+ #
25
+ # include OpenSocial::Auth
26
+ #
27
+ # before_filter :validate
28
+ #
29
+ # def return_private_data
30
+ # end
31
+ # end
32
+ #
33
+ # * Request for an OAuth request token
34
+ #
35
+ # * Request for an OAuth access token, when supplied with a request token
36
+ #
37
+
38
+
39
+ module Auth
40
+
41
+ # Validates an incoming request by using the OAuth library and the supplied
42
+ # key and secret.
43
+ def validate(key = CONSUMER_KEY, secret = CONSUMER_SECRET)
44
+ consumer = OAuth::Consumer.new(key, secret)
45
+ begin
46
+ signature = OAuth::Signature.build(request) do
47
+ [nil, consumer.secret]
48
+ end
49
+ pass = signature.verify
50
+ rescue OAuth::Signature::UnknownSignatureMethod => e
51
+ logger.error "An unknown signature method was supplied: " + e.to_s
52
+ end
53
+ return pass
54
+ end
55
+
56
+ # Gets an OAuth request token, and redirects the user to authorize the app
57
+ # to access data on their behalf.
58
+ def get_oauth_token(key, secret, container, callback)
59
+ consumer = OAuth::Consumer.new(key, secret, {
60
+ :site => container[:base_uri],
61
+ :request_token_path => container[:request_token_path],
62
+ :authorize_path => container[:authorize_path],
63
+ :access_token_path => container[:access_token_path],
64
+ :http_method => container[:http_method]
65
+ })
66
+ request_token = consumer.get_request_token
67
+
68
+ session[:token] = request_token.token
69
+ session[:secret] = request_token.secret
70
+
71
+ redirect_to request_token.authorize_url + "&oauth_callback=" + CGI.escape(callback)
72
+ end
73
+
74
+ # If neccesary, swaps an existing request token and secret for an access
75
+ # token, storing it in the Connection class, and returning the access token
76
+ # and secret for later use.
77
+ def get_access_token(connection, token, secret)
78
+ if (token && secret)
79
+ consumer = OAuth::Consumer.new(connection.consumer_key,
80
+ connection.consumer_secret,
81
+ connection.container)
82
+
83
+ if connection.consumer_token.token.empty? &&
84
+ connection.consumer_token.secret.empty?
85
+ connection.consumer_token = OAuth::Token.new(token, secret)
86
+
87
+ uri = URI.parse(connection.container[:base_uri] +
88
+ connection.container[:access_token_path])
89
+ http = Net::HTTP.new(uri.host, uri.port)
90
+ req = Net::HTTP::Get.new(uri.request_uri)
91
+ connection.sign!(http, req)
92
+
93
+ resp = http.get(req.path)
94
+
95
+ matches = resp.body.match(/oauth_token=(.*?)&oauth_token_secret=(.*)/)
96
+ access_token = matches[1]
97
+ access_secret = matches[2]
98
+ end
99
+
100
+ reusable_token = OAuth::AccessToken.new(consumer, access_token, access_secret)
101
+ connection.consumer_token = reusable_token
102
+
103
+ return access_token, access_secret
104
+ end
105
+
106
+ return nil, nil
107
+ end
108
+ end
109
+ end