f1api 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+ gem 'nokogiri'
3
+ gem 'oauth', '=0.4.4'
4
+ gem 'mocha'
5
+ gem 'activeresource'
@@ -0,0 +1,27 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.0.3)
5
+ activesupport (= 3.0.3)
6
+ builder (~> 2.1.2)
7
+ i18n (~> 0.4)
8
+ activeresource (3.0.3)
9
+ activemodel (= 3.0.3)
10
+ activesupport (= 3.0.3)
11
+ activesupport (3.0.3)
12
+ builder (2.1.2)
13
+ i18n (0.4.2)
14
+ mocha (0.9.9)
15
+ rake
16
+ nokogiri (1.4.4)
17
+ oauth (0.4.4)
18
+ rake (0.8.7)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ activeresource
25
+ mocha
26
+ nokogiri
27
+ oauth (= 0.4.4)
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Fellowship Technologies
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,24 @@
1
+ Fellowship One REST API Ruby Client Library
2
+ ===========================================
3
+
4
+ **NOTE**: This library is of alpha quality. It is not meant for use in production apps. It's definitely not feature complete and it may have bugs.
5
+
6
+ Introduction
7
+ ------------
8
+ This library is an implementation of the Fellowship One REST API. Currently we are only fielding requests and handling the OAuth tokens. The goal is to have a library that works like ActiveResource.
9
+
10
+ Usage
11
+ -----
12
+ require 'f1api'
13
+
14
+ class Person < FellowshipOneAPI::Base
15
+ end
16
+
17
+ client.authorize!
18
+ # If using creds in YAML file:
19
+ # client.authorize! "username", "password"
20
+
21
+ Person.connect client
22
+
23
+ Person.find(12345)
24
+ Person.find("search", {:searchFor => "Dearing", :include => "communications,addresses"})
@@ -0,0 +1,38 @@
1
+ BASE_DIR = File.dirname(__FILE__)
2
+
3
+ task :test do
4
+ require 'bundler/setup'
5
+ require 'test/unit'
6
+ require 'mocha'
7
+ require "#{BASE_DIR}/test/fixtures/request_token.rb"
8
+ require "#{BASE_DIR}/test/fixtures/access_token.rb"
9
+ require "#{BASE_DIR}/test/fixtures/http.rb"
10
+ require "#{BASE_DIR}/lib/f1api"
11
+ Dir["#{BASE_DIR}/test/unit/*.rb"].each do |test|
12
+ require test
13
+ end
14
+ end
15
+
16
+ task :rdoc do
17
+ `rdoc -x 'test/*'`
18
+ end
19
+
20
+ require 'jeweler'
21
+ Jeweler::Tasks.new do |gem|
22
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
23
+ gem.name = "f1api"
24
+ gem.homepage = "http://github.com/jessedearing/f1api"
25
+ gem.license = "MIT"
26
+ gem.summary = %Q{Consume the Fellowship One API in your apps using ActiveResource}
27
+ gem.description = %Q{Consumes the Fellowship One API in your apps using ActiveResource. Implements 2nd party credentials-based authenticaion and full OAuth implementation. }
28
+ gem.email = "jdearing@fellowshiptech.com"
29
+ gem.authors = ["Jesse Dearing"]
30
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
31
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
32
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
33
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
34
+ gem.add_runtime_dependency 'oauth', '= 0.4.4'
35
+ gem.add_development_dependency 'mocha'
36
+ gem.add_runtime_dependency 'activeresource'
37
+ end
38
+ Jeweler::RubygemsDotOrgTasks.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.0
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 9
4
+ :patch: 0
5
+ :build:
@@ -0,0 +1,48 @@
1
+ development:
2
+ consumer_key: ""
3
+ consumer_secret: ""
4
+ site_url: "https://{church_code}.staging.fellowshiponeapi.com"
5
+ # Store the church code if you are writing a 2nd Party implementation
6
+ # Otherwise, you'll want to ask for the church code from the user
7
+ church_code: ""
8
+ authentication_type: "oauth" #oauth or credentials
9
+ request_token_path: "/v1/Tokens/RequestToken"
10
+ access_token_path: "/v1/Tokens/AccessToken" #OAuth only
11
+ # OAuth authentication vars
12
+ portal_authorize_path: "/v1/PortalUser/Login"
13
+ weblink_authorize_path: "/v1/WeblinkUser/Login"
14
+ # Use the following for credentials based authentication
15
+ portal_credential_token_path: "/v1/PortalUser/AccessToken"
16
+ weblink_credential_token_path: "/v1/WeblinkUser/AccessToken"
17
+ test:
18
+ consumer_key: "123456789"
19
+ consumer_secret: "12345678-90ab-cdef-0123-4567890abcde"
20
+ site_url: "https://{church_code}.staging.fellowshiponeapi.com"
21
+ # Store the church code if you are writing a 2nd Party implementation
22
+ # Otherwise, you'll want to ask for the church code from the user
23
+ church_code: "test"
24
+ authentication_type: "oauth" #oauth or credentials
25
+ request_token_path: "/V1/Tokens/RequestToken"
26
+ access_token_path: "/V1/Tokens/AccessToken" #OAuth only
27
+ # OAuth authentication vars
28
+ portal_authorize_path: "/V1/PortalUser/Login"
29
+ weblink_authorize_path: "/V1/WeblinkUser/Login"
30
+ # Use the following for credentials based authentication
31
+ portal_credential_token_path: "/V1/PortalUser/AccessToken"
32
+ weblink_credential_token_path: "/V1/WeblinkUser/AccessToken"
33
+ production:
34
+ consumer_key: ""
35
+ consumer_secret: ""
36
+ site_url: "https://{church_code}.fellowshiponeapi.com"
37
+ # Store the church code if you are writing a 2nd Party implementation
38
+ # Otherwise, you'll want to ask for the church code from the user
39
+ church_code: ""
40
+ authentication_type: "oauth" #oauth or credentials
41
+ request_token_path: "/v1/Tokens/RequestToken"
42
+ access_token_path: "/v1/Tokens/AccessToken" #OAuth only
43
+ # OAuth authentication vars
44
+ portal_authorize_path: "/v1/PortalUser/Login"
45
+ weblink_authorize_path: "/v1/WeblinkUser/Login"
46
+ # Use the following for credentials based authentication
47
+ portal_credential_token_path: "/v1/PortalUser/AccessToken"
48
+ weblink_credential_token_path: "/v1/WeblinkUser/AccessToken"
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}"
2
+ require 'bundler/setup'
3
+ require 'yaml'
4
+ require 'oauth'
5
+ require 'base64'
6
+ require 'uri'
7
+ require 'active_resource'
8
+ require "f1api/configuration"
9
+ require "f1api/oauth"
10
+ require "f1api/oauth/credentials_authentication"
11
+ require "f1api/oauth/oauth_authentication"
12
+ require "f1api/client"
13
+ require "f1api/activeresource/connection"
14
+ require "f1api/activeresource/base"
@@ -0,0 +1,19 @@
1
+ module FellowshipOneAPI # :nodoc:
2
+ # The Base class should be inherited by all model classes as it provides the facilities that the class will need
3
+ class Base < ActiveResource::Base
4
+ self.site = "#{Configuration.site_url}/v1"
5
+ # Creates a new connection
6
+ #
7
+ # ==Examples
8
+ # Person.connect(FellowshipOneAPI::Client.new)
9
+ #
10
+ # If the connection needs to be forcibly refreshed then you can pass true
11
+ # Person.connect(FellowshipOneAPI::Client.new, true)
12
+ def self.connect(client, refresh = false)
13
+ if(refresh or @connection.nil?)
14
+ @connection = Connection.new(client, client.consumer.site, format)
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,39 @@
1
+ require 'nokogiri'
2
+
3
+ module FellowshipOneAPI
4
+ # Creating a wrapper for the ActiveResource::Connection class
5
+ class Connection < ActiveResource::Connection
6
+ # Pass in a new connection to the API
7
+ def initialize(f1api_connection, *args)
8
+ @f1api_connection = f1api_connection
9
+ super(*args)
10
+ end
11
+
12
+ private
13
+ # The request method that is passes the request through to the F1 API client
14
+ def request(method, path, *args)
15
+ if @f1api_connection == nil
16
+ super(method, path, *args)
17
+ else
18
+ response = @f1api_connection.request(method, path, *args)
19
+
20
+ if method == :get
21
+ response.body = transform_response response.body, path
22
+ end
23
+ handle_response(response)
24
+ end
25
+ end
26
+
27
+ #
28
+ def transform_response(response_body, path)
29
+ n = Nokogiri::XML(response_body)
30
+ res = (n/"results")
31
+ if not (res.empty?)
32
+ resource = ((path.split '/')[2]).downcase
33
+ res[0].name = resource
34
+ end
35
+
36
+ n.to_s
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,62 @@
1
+ module FellowshipOneAPI
2
+ # ==The Fellowship One API client class
3
+ # Takes an HTTP request and passes it through the OAuth library which added the approperiate headers and querystring
4
+ # parameters.
5
+ # ===Examples
6
+ # [Simple client using OAuth and default YAML config values]
7
+ # client = FellowshipOneAPI::Client.new
8
+ #
9
+ # client.authorize!
10
+ #
11
+ # client.request(:get, '/v1/People/123.xml')
12
+ #
13
+ # [Using credentials based authentication (2nd party)]
14
+ # client = FellowshipOneAPI::Client.new({:auth_type => :credentials})
15
+ #
16
+ # client.authorize!("username", "password")
17
+ #
18
+ # client.request(:get, '/v1/People/123.xml')
19
+ #
20
+ # [Authenticating against weblink passing credentials]
21
+ # client = FellowshipOneAPI::Client.new({:auth_type => :credentials, :auth_against => :weblink})
22
+ #
23
+ # client.authorize("weblinkuser", "weblinkpassword")
24
+ #
25
+ # client.request(:get, '/v1/People/123.xml')
26
+ #
27
+ # [Loading a client with an existing access token]
28
+ # client = FellowshipOneAPI::Client.new({:oauth_token => "123456", :oauth_token_secret => "987654"})
29
+ #
30
+ # client.request(:get, '/v1/People/123.xml')
31
+ class Client
32
+ # Creates a new instance of a client used to connect with the Fellowship One API
33
+ # The client can be configured with the following symbols:
34
+ # [+:auth_type+] - Can be _:credentials_ or _:oauth_ (_:oauth_ is the default)
35
+ # [+:auth_against+] - Can be _:portal_ or _:weblink_ (_:portal_ is the default)
36
+ # [+:oauth_token+] - The access token
37
+ # [+:oauth_token_secret+] - The access token secret
38
+ def initialize(args = {})
39
+ args[:auth_type] ||= Configuration.authentication_type.to_sym
40
+ if args[:auth_type] == :credentials
41
+ extend OAuth::CredentialsAuthentication
42
+ else
43
+ extend OAuth::OAuthAuthentication
44
+ end
45
+
46
+ if(args[:auth_against])
47
+ load_consumer_config args[:auth_against]
48
+ else
49
+ load_consumer_config
50
+ end
51
+
52
+ if(args[:oauth_token] and args[:oauth_token_secret])
53
+ @oauth_access_token = ::OAuth::AccessToken.from_hash(@oauth_consumer, args[:oauth_token], args[:oauth_token_secret])
54
+ end
55
+ end
56
+
57
+ # Passes through the request to the OAuth library to be signed and set out HTTP
58
+ def request(*args)
59
+ @oauth_access_token.request(*args)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,63 @@
1
+ module FellowshipOneAPI # :nodoc:
2
+ # This accesses the YAML-based F1 API config file
3
+ #
4
+ # This class was written to take rails environment variables like +RAILS_ENV+ and +Rails.root+ into account
5
+ class Configuration
6
+ # Explictly defines where the configuration file is
7
+ def self.file_path=(path)
8
+ @file_path
9
+ end
10
+
11
+ # Gets the specified key from the configuration file
12
+ # [Example] FellowshipTechAPIClient.Configuration["consumer_key"] <i># "2"</i>
13
+ #
14
+ # FellowshipTechAPIClient.Configuration["consumer_secret"] <i># "12345678-9abc-def0-1234-567890abcdef"</i>
15
+ def self.[](value)
16
+ load_yaml if @config_yaml.nil?
17
+ val = @config_yaml[self.environment][value]
18
+ # if we have the string has "{church_code}" then we'll substitute it
19
+ if val =~ /\{church_code\}/ and value != "church_code"
20
+ return val.gsub("{church_code}", self["church_code"])
21
+ end
22
+ return val
23
+ end
24
+
25
+ # Gets the current environment
26
+ def self.environment
27
+ @environment ||= "development"
28
+ @environment ||= ::Rails.env if defined? ::Rails
29
+ @environment
30
+ end
31
+
32
+ # Set the current environment
33
+ def self.environment=(env_value)
34
+ @environment = env_value
35
+ end
36
+
37
+ # Overridden method_missing to facilitate a more pleasing ruby-like syntax for accessing
38
+ # configuration values
39
+ def self.method_missing(name, *args, &block)
40
+ return self[name.to_s] unless self[name.to_s].nil?
41
+ super
42
+ end
43
+
44
+ private
45
+
46
+ # Loads the YAML file
47
+ #
48
+ # Starts by looking to see if file_path is defined then checks in current directory (.) and then your Rails.root and then the config
49
+ # directory off of the base directory of the gem
50
+ def self.load_yaml
51
+ if not @file_path.nil?
52
+ @config_yaml = YAML.load_file(@file_path)
53
+ elsif File.exists? "./f1-oauth.yml"
54
+ @config_yaml = YAML.load_file("./f1-oauth.yml")
55
+ elsif defined? ::Rails
56
+ @config_yaml = YAML.load_file("#{::Rails.root}/config/f1-oauth.yml")
57
+ else
58
+ path = File.dirname(__FILE__) + "/../../config/f1-oauth.yml"
59
+ @config_yaml = YAML.load_file(path)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,54 @@
1
+ module FellowshipOneAPI # :nodoc:
2
+ # Wrapper around the OAuth v1.0 specification using the +oauth+ gem.
3
+ #
4
+ # The Fellowship One API has two methods of authentication:
5
+ # [OAuthAuthentication] This is the default method if no method is declared. This method allows Fellowship Tech to handle
6
+ # the authentication and we redirect back to your app.
7
+ # [CredentialsAuthentication] The methods lets the consumer submit credentials and verify authentication.
8
+ module OAuth
9
+ # The OAuth consumer key.
10
+ # This will get set automatically from the YAML config file if not set explictly
11
+ attr_accessor :oauth_consumer_key
12
+ alias :consumer_key :oauth_consumer_key
13
+ alias :consumer_key= :oauth_consumer_key=
14
+
15
+ # The OAuth consumer secret.
16
+ # This will get set automatically from the YAML config file if not set explictly
17
+ attr_accessor :oauth_consumer_secret
18
+ alias :consumer_secret :oauth_consumer_secret
19
+ alias :consumer_secret= :oauth_consumer_secret=
20
+
21
+ # The OAuth access token object where all requests are made off of
22
+ attr_reader :oauth_access_token
23
+ alias :access_token :oauth_access_token
24
+
25
+ # The OAuth consumer object
26
+ attr_reader :oauth_consumer
27
+ alias :consumer :oauth_consumer
28
+
29
+ # The URI for the resource of the authenticated user
30
+ attr_reader :authenticated_user_uri
31
+
32
+ # Creates the OAuth consumer object
33
+ def load_consumer_config(type = :portal)
34
+ case type
35
+ when :portal
36
+ authorize_path = FellowshipOneAPI::Configuration.portal_authorize_path
37
+ when :weblink
38
+ authorize_path = FellowshipOneAPI::Configuration.weblink_authorize_path
39
+ end
40
+
41
+ @oauth_consumer_key ||= FellowshipOneAPI::Configuration.consumer_key
42
+ @oauth_consumer_secret ||= FellowshipOneAPI::Configuration.consumer_secret
43
+
44
+ @oauth_consumer = ::OAuth::Consumer.new(@oauth_consumer_key,
45
+ @oauth_consumer_secret,
46
+ {:site => FellowshipOneAPI::Configuration.site_url,
47
+ :request_token_path => FellowshipOneAPI::Configuration.request_token_path,
48
+ :access_token_path => FellowshipOneAPI::Configuration.access_token_path,
49
+ :authorize_path => authorize_path })
50
+ end
51
+
52
+
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ module FellowshipOneAPI # :nodoc:
2
+ module OAuth
3
+ # Implements the Credentials method of authentication. You must manage the credentials.
4
+ module CredentialsAuthentication
5
+ include OAuth
6
+ # Authorizes a user
7
+ # +username+:: The username of the user
8
+ # +password+:: The password of the user
9
+ # +type+:: Can be :portal or :weblink based on which credentials you want to authenticate against
10
+ # Returns the URI for the authenticated user
11
+ def authorize!(username, password, type = :portal)
12
+ load_consumer_config(type) if @oauth_consumer.nil?
13
+
14
+ @oauth_request = @oauth_consumer.get_request_token
15
+ cred = URI.encode(Base64.encode64("#{username} #{password}"))
16
+
17
+ case type
18
+ when :portal
19
+ auth_url = FellowshipOneAPI::Configuration.portal_credential_token_path
20
+ when :weblink
21
+ auth_url = FellowshipOneAPI::Configuration.weblink_credential_token_path
22
+ end
23
+
24
+ response = @oauth_consumer.request(:post, auth_url, nil, {}, "ec=#{cred}", {'Content-Type' => 'application/x-www-form-urlencoded'})
25
+
26
+ handle_response_code(response)
27
+
28
+ # Gettting the URI of the authenticated user
29
+ @authenticated_user_uri = response["Content-Location"]
30
+ end
31
+
32
+ private
33
+ def handle_response_code(response)
34
+ case response.code.to_i
35
+ when (200..299)
36
+ @oauth_access_token = ::OAuth::AccessToken.from_hash(@oauth_consumer, parse_access_token(response.body))
37
+ when (300..399)
38
+ # redirect
39
+ # TODO: actually redirect instead of throwing error
40
+ response.error!
41
+ when (400..499)
42
+ raise OAuth::Unauthorized, response
43
+ else
44
+ response.error!
45
+ end
46
+ end
47
+
48
+ # Parse returned OAuth access token key/secret pair
49
+ def parse_access_token(response)
50
+ oauth_hash = {}
51
+ response.split('&').each do |val|
52
+ kv = val.split('=')
53
+ oauth_hash.merge!({kv[0].to_sym => kv[1]})
54
+ end
55
+ oauth_hash
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,72 @@
1
+ module FellowshipOneAPI # :nodoc:
2
+ module OAuth
3
+ # Implements the pure OAuth method of authentication. This allows the Fellowship One API to
4
+ # manage the authentication process.
5
+ module OAuthAuthentication
6
+ include OAuth
7
+ # The OAuth request object
8
+ attr_reader :oauth_request
9
+
10
+ # The OAuth authorization URI
11
+ attr_reader :oauth_authorize_url
12
+ alias :authorize_url :oauth_authorize_url
13
+
14
+ # Gets a new request token and return the authorize URI
15
+ # +type+:: Can be :portal or :weblink based on which credentials you want to authenticate against
16
+ def authorize!(type = :portal)
17
+ load_consumer_config(type) if oauth_consumer.nil?
18
+
19
+ @oauth_request = oauth_consumer.get_request_token
20
+ @oauth_authorize_url = oauth_request.authorize_url
21
+
22
+ @oauth_consumer.instance_eval do
23
+ # The token request reponse is scoped only in the token_request method, but I need to get access to the response
24
+ # headers so that I can pull back the Content-Location header and get the authenticated user URI
25
+ def token_request(http_method, path, token = nil, request_options = {}, *arguments)
26
+ @tr_response = request(http_method, path, token, request_options, *arguments)
27
+ case @tr_response.code.to_i
28
+
29
+ when (200..299)
30
+ if block_given?
31
+ yield @tr_response.body
32
+ else
33
+ # symbolize keys
34
+ # TODO this could be considered unexpected behavior; symbols or not?
35
+ # TODO this also drops subsequent values from multi-valued keys
36
+ CGI.parse(@tr_response.body).inject({}) do |h,(k,v)|
37
+ h[k.strip.to_sym] = v.first
38
+ h[k.strip] = v.first
39
+ h
40
+ end
41
+ end
42
+ when (300..399)
43
+ # this is a redirect
44
+ @tr_response.error!
45
+ when (400..499)
46
+ raise OAuth::Unauthorized, @tr_response
47
+ else
48
+ @tr_response.error!
49
+ end
50
+ end
51
+
52
+ # The HTTP response from token_request
53
+ def token_request_response
54
+ @tr_response
55
+ end
56
+ end
57
+
58
+ oauth_authorize_url
59
+ end
60
+
61
+ # After a the user has been authenticated then we use the access token to access protected resources in the API.
62
+ # Since the authentication has taken place, we now know about the user that authenticated and
63
+ # have a URI to the record of that user.
64
+ #
65
+ # The URI for the authenticated user is returned.
66
+ def get_access_token
67
+ @oauth_access_token = oauth_request.get_access_token
68
+ @authenticated_user_uri = oauth_consumer.token_request_response["Content-Location"]
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'oauth'
3
+
4
+ class AccessTokenFixture
5
+ def self.get(oauth_consumer)
6
+ @token = "access"
7
+ @secret = "token"
8
+ return ::OAuth::AccessToken.new(oauth_consumer, @token, @secret)
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ class HttpFixture
2
+ def body
3
+ "oauth_token=access&oauth_token_secret=token"
4
+ end
5
+
6
+ def [](value)
7
+ {'Content-Location' => "#{FellowshipOneAPI::Configuration.site_url}/V1/People/123456"}[value]
8
+ end
9
+
10
+ def code
11
+ "200"
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'oauth'
3
+
4
+ class RequestTokenFixture
5
+ def self.get(oauth_consumer)
6
+ @token = "request"
7
+ @secret = "token"
8
+ return ::OAuth::RequestToken.new(oauth_consumer, @token, @secret)
9
+ end
10
+ end
@@ -0,0 +1,60 @@
1
+ class OAuthTest < Test::Unit::TestCase
2
+ include FellowshipOneAPI
3
+
4
+ def setup
5
+ Configuration.environment = "test"
6
+ Configuration.file_path = "#{File.dirname(__FILE__)}/../../config/f1-oauth.yml"
7
+ end
8
+
9
+ def test_method_missing
10
+ assert_raise NoMethodError do
11
+ Configuration.asdf
12
+ end
13
+
14
+ assert_nothing_raised do
15
+ Configuration.consumer_key
16
+ end
17
+
18
+ assert_equal Configuration["consumer_key"], Configuration.consumer_key
19
+ end
20
+
21
+ def test_consumer_key
22
+ assert_equal("123456789", Configuration.consumer_key)
23
+ end
24
+
25
+ def test_consumer_secret
26
+ assert_equal("12345678-90ab-cdef-0123-4567890abcde", Configuration.consumer_secret)
27
+ end
28
+
29
+ def test_site_url
30
+ assert_equal("https://test.staging.fellowshiponeapi.com", Configuration.site_url)
31
+ end
32
+
33
+ def test_church_code
34
+ assert_equal("test", Configuration.church_code)
35
+ end
36
+
37
+ def test_request_token_path
38
+ assert_equal("/V1/Tokens/RequestToken", Configuration.request_token_path)
39
+ end
40
+
41
+ def test_access_token_path
42
+ assert_equal("/V1/Tokens/AccessToken", Configuration.access_token_path)
43
+ end
44
+
45
+ def test_portal_authorize_path
46
+ assert_equal("/V1/PortalUser/Login", Configuration.portal_authorize_path)
47
+ end
48
+
49
+ def test_weblink_authorize_path
50
+ assert_equal("/V1/WeblinkUser/Login", Configuration.weblink_authorize_path)
51
+ end
52
+
53
+ def test_portal_credential_token_path
54
+ assert_equal("/V1/PortalUser/AccessToken", Configuration.portal_credential_token_path)
55
+ end
56
+
57
+ def test_weblink_credential_token_path
58
+ assert_equal("/V1/WeblinkUser/AccessToken", Configuration.weblink_credential_token_path)
59
+ end
60
+ end
@@ -0,0 +1,59 @@
1
+ class CredentialsAuthenticationTest
2
+ include FellowshipOneAPI::OAuth::CredentialsAuthentication
3
+ attr_accessor :oauth_consumer
4
+ end
5
+
6
+ class CredentialsTest < Test::Unit::TestCase
7
+ include FellowshipOneAPI
8
+ def setup
9
+ Configuration.environment = "test"
10
+ Configuration.file_path = "#{File.dirname(__FILE__)}/../../config/f1-oauth.yml"
11
+
12
+ @test_username = "testuser"
13
+ @test_password = "testpass"
14
+
15
+ @cred_test = CredentialsAuthenticationTest.new
16
+ @cred_test.load_consumer_config
17
+ @mocked_access_token = AccessTokenFixture.get(@cred_test.oauth_consumer)
18
+ @mocked_request_token = RequestTokenFixture.get(@cred_test.oauth_consumer)
19
+ cred = URI.encode(Base64.encode64("#{@test_username} #{@test_password}"))
20
+
21
+ @mocked_user_uri = "#{Configuration.site_url}/V1/People/123456"
22
+
23
+ @cred_test.oauth_consumer.stubs(:get_request_token).returns(@mocked_request_token)
24
+
25
+ @cred_test.oauth_consumer.stubs(:request).with(:post, ::FellowshipOneAPI::Configuration.portal_credential_token_path,
26
+ nil, {}, "ec=#{cred}", {'Content-Type' => 'application/x-www-form-urlencoded'}).
27
+ returns(HttpFixture.new)
28
+ end
29
+
30
+ def test_portal_authorize!
31
+ actual = @cred_test.authorize! @test_username, @test_password
32
+
33
+ assert_equal(@mocked_user_uri, actual)
34
+ end
35
+
36
+ def test_weblink_authorize!
37
+ cred = URI.encode(Base64.encode64("#{@test_username} #{@test_password}"))
38
+ @cred_test.oauth_consumer = nil
39
+ @cred_test.load_consumer_config(:weblink)
40
+ @cred_test.oauth_consumer.expects(:get_request_token).returns(@mocked_request_token).at_least_once
41
+ @cred_test.oauth_consumer.expects(:request).with(:post, ::FellowshipOneAPI::Configuration.weblink_credential_token_path,
42
+ nil, {}, "ec=#{cred}", {'Content-Type' => 'application/x-www-form-urlencoded'}).returns(
43
+ HttpFixture.new).at_least_once
44
+ @cred_test.authorize! @test_username, @test_password, :weblink
45
+ end
46
+
47
+ def test_get_access_token
48
+ @cred_test.authorize! @test_username, @test_password
49
+
50
+ assert_equal("access", @cred_test.access_token.token)
51
+ assert_equal("token", @cred_test.access_token.secret)
52
+ end
53
+
54
+ def test_authorized_user_uri
55
+ @cred_test.authorize! @test_username, @test_password
56
+
57
+ assert_equal(@mocked_user_uri, @cred_test.authenticated_user_uri)
58
+ end
59
+ end
@@ -0,0 +1,74 @@
1
+ class OAuthAuthenticationTest
2
+ include FellowshipOneAPI::OAuth::OAuthAuthentication
3
+ attr_accessor :oauth_consumer
4
+ end
5
+
6
+ class OAuthTest < Test::Unit::TestCase
7
+ include FellowshipOneAPI
8
+ def setup
9
+ Configuration.environment = "test"
10
+ Configuration.file_path = "#{File.dirname(__FILE__)}/../../config/f1-oauth.yml"
11
+
12
+ @oauth_test = OAuthAuthenticationTest.new
13
+ @oauth_test.load_consumer_config
14
+ @mocked_request_token = RequestTokenFixture.get(@oauth_test.oauth_consumer)
15
+ @mocked_access_token = AccessTokenFixture.get(@oauth_test.oauth_consumer)
16
+ @oauth_test.oauth_consumer.stubs(:get_request_token).returns(@mocked_request_token)
17
+ end
18
+
19
+ def test_portal_authorize!
20
+ @oauth_test.oauth_consumer.expects(:get_request_token).returns(@mocked_request_token)
21
+
22
+ assert_equal("#{Configuration.site_url}#{Configuration.portal_authorize_path}?oauth_token=request", @oauth_test.authorize!)
23
+
24
+ assert_equal("request", @oauth_test.oauth_request.token)
25
+ assert_equal("token", @oauth_test.oauth_request.secret)
26
+ assert_equal("#{Configuration.site_url}#{Configuration.portal_authorize_path}?oauth_token=#{@oauth_test.oauth_request.token}", @oauth_test.authorize_url)
27
+ end
28
+
29
+ def test_weblink_authorize!
30
+ @oauth_test.oauth_consumer = nil
31
+ @oauth_test.load_consumer_config(:weblink)
32
+ @mocked_request_token = RequestTokenFixture.get(@oauth_test.oauth_consumer)
33
+ @oauth_test.oauth_consumer.expects(:get_request_token).returns(@mocked_request_token)
34
+
35
+ @oauth_test.authorize!(:weblink)
36
+
37
+ assert_equal("request", @oauth_test.oauth_request.token)
38
+ assert_equal("token", @oauth_test.oauth_request.secret)
39
+ assert_equal("#{Configuration.site_url}#{Configuration.weblink_authorize_path}?oauth_token=#{@oauth_test.oauth_request.token}", @oauth_test.authorize_url)
40
+ end
41
+
42
+ def test_get_access_token
43
+ @oauth_test.authorize!
44
+
45
+ @oauth_test.oauth_request.expects(:get_access_token).returns(@mocked_access_token)
46
+ @oauth_test.oauth_consumer.expects(:token_request_response).returns({"Content-Location" => ""})
47
+ @oauth_test.get_access_token
48
+
49
+ assert_equal("access", @oauth_test.access_token.token)
50
+ assert_equal("token", @oauth_test.access_token.secret)
51
+ end
52
+
53
+ def test_authorized_user_uri
54
+ mocked_user_uri = "#{Configuration.site_url}/V1/People/123456"
55
+
56
+ @oauth_test.authorize!
57
+
58
+ @oauth_test.oauth_request.expects(:get_access_token).returns(@mocked_access_token)
59
+ @oauth_test.oauth_consumer.expects(:token_request_response).returns({"Content-Location" => mocked_user_uri})
60
+ @oauth_test.get_access_token
61
+
62
+ assert_equal(mocked_user_uri, @oauth_test.authenticated_user_uri)
63
+ end
64
+
65
+ def test_change_auth_types
66
+ @oauth_test.authorize!
67
+ assert_equal("#{Configuration.site_url}#{Configuration.portal_authorize_path}", @oauth_test.oauth_consumer.authorize_url)
68
+ @oauth_test.load_consumer_config(:weblink)
69
+ @oauth_test.oauth_consumer.stubs(:get_request_token).returns(@mocked_request_token)
70
+ @oauth_test.authorize!
71
+ assert_equal("#{Configuration.site_url}#{Configuration.weblink_authorize_path}", @oauth_test.oauth_consumer.authorize_url)
72
+ end
73
+
74
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: f1api
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 9
8
+ - 0
9
+ version: 0.9.0
10
+ platform: ruby
11
+ authors:
12
+ - Jesse Dearing
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-19 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: nokogiri
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: oauth
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - "="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ - 4
43
+ - 4
44
+ version: 0.4.4
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: mocha
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ type: :runtime
59
+ prerelease: false
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: activeresource
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
75
+ name: oauth
76
+ requirement: &id005 !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - "="
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 0
83
+ - 4
84
+ - 4
85
+ version: 0.4.4
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: *id005
89
+ - !ruby/object:Gem::Dependency
90
+ name: mocha
91
+ requirement: &id006 !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *id006
102
+ - !ruby/object:Gem::Dependency
103
+ name: activeresource
104
+ requirement: &id007 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ type: :runtime
113
+ prerelease: false
114
+ version_requirements: *id007
115
+ description: "Consumes the Fellowship One API in your apps using ActiveResource. Implements 2nd party credentials-based authenticaion and full OAuth implementation. "
116
+ email: jdearing@fellowshiptech.com
117
+ executables: []
118
+
119
+ extensions: []
120
+
121
+ extra_rdoc_files:
122
+ - LICENSE
123
+ - README.md
124
+ files:
125
+ - Gemfile
126
+ - Gemfile.lock
127
+ - LICENSE
128
+ - README.md
129
+ - Rakefile
130
+ - VERSION
131
+ - VERSION.yml
132
+ - config/f1-oauth.yml
133
+ - lib/f1api.rb
134
+ - lib/f1api/activeresource/base.rb
135
+ - lib/f1api/activeresource/connection.rb
136
+ - lib/f1api/client.rb
137
+ - lib/f1api/configuration.rb
138
+ - lib/f1api/oauth.rb
139
+ - lib/f1api/oauth/credentials_authentication.rb
140
+ - lib/f1api/oauth/oauth_authentication.rb
141
+ - test/fixtures/access_token.rb
142
+ - test/fixtures/http.rb
143
+ - test/fixtures/request_token.rb
144
+ - test/unit/configuration_test.rb
145
+ - test/unit/credentials_test.rb
146
+ - test/unit/oauth_test.rb
147
+ has_rdoc: true
148
+ homepage: http://github.com/jessedearing/f1api
149
+ licenses:
150
+ - MIT
151
+ post_install_message:
152
+ rdoc_options: []
153
+
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ none: false
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ segments:
162
+ - 0
163
+ version: "0"
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ none: false
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ segments:
170
+ - 0
171
+ version: "0"
172
+ requirements: []
173
+
174
+ rubyforge_project:
175
+ rubygems_version: 1.3.7
176
+ signing_key:
177
+ specification_version: 3
178
+ summary: Consume the Fellowship One API in your apps using ActiveResource
179
+ test_files:
180
+ - test/fixtures/access_token.rb
181
+ - test/fixtures/http.rb
182
+ - test/fixtures/request_token.rb
183
+ - test/unit/configuration_test.rb
184
+ - test/unit/credentials_test.rb
185
+ - test/unit/oauth_test.rb