gemagent 0.0.1.pre

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/CONTRIBUTORS ADDED
@@ -0,0 +1 @@
1
+ Ryan Stenhouse <ryan@ryanstenhouse.eu>
data/HACKING ADDED
@@ -0,0 +1,8 @@
1
+ The process for accepting patches is as follows:
2
+
3
+ 1. Fork the repository
4
+ 2. Make your changes (bonus points for feature branches)
5
+ 3. Have some tests for your changes
6
+ 4. Submit a pull request
7
+
8
+ Do not change the version number in the GemSpec.
data/LICENCE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Ryan Stenhouse and CONTRIBUTORS
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.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ Gemagent
2
+ ========
3
+
4
+ By Ryan Stenhouse http://ryanstenhouse.eu
5
+
6
+ What is it?
7
+ -----------
8
+
9
+ Gemagent is a purely Standard Ruby implementation of a consumer of
10
+ the FreeAgent Central API.
11
+
12
+ The goal of this project was not to build a 'fast' API consumer, but
13
+ instead to build a 'correct' one. All published API features of the
14
+ FreeAgent application are implemented.
15
+
16
+ If it's fast, it's a bonus!
17
+
18
+ Installation
19
+ ------------
20
+
21
+ Install via rubygems:
22
+
23
+ $ gem install gemagent
24
+
25
+ It requires OpenSSL in order to create the HTTPS connection to the
26
+ FreeAgent API.
27
+
28
+ Extension
29
+ ---------
30
+
31
+ The main purpose of this gem was to allow me to become more familiar
32
+ with the FreeAgent API and to shake out some cobwebs when it came to
33
+ my knowledge of Ruby's Standard Library.
34
+
35
+ Because of this, some parts (like local data storage) are sub-optimal.
36
+
37
+ I have, however, build some abstraction on top of the data storage,
38
+ HTTP requests and XML parsing to allow for some or all of these
39
+ components to be replaced at a later date.
40
+
41
+ See the documentation online for more information.
42
+
43
+
@@ -0,0 +1,13 @@
1
+ # GemAgent API Interface
2
+ # Ryan Stenhouse, 20 January 2011
3
+
4
+ # Longhand representation of connecting to the FreeAgent API
5
+ #
6
+ ga = GemAgent::NetHttpConnection.new 'you.freeagentcentral.com', GemAgent::HttpBasicAuthentication.new('username','password')
7
+ ga.verify # => { :user_id => 1, :permission_level => 8, :company_type => UK_LIMITED }
8
+
9
+ # Sexy sugary version of the above.
10
+ #
11
+ GemAgent::Api.connect 'you.freeagentcentral.com', 'username', 'password' do |api|
12
+ api.verify # => { :user_id => 1, :permission_level => 8, :company_type => UK_LIMITED }
13
+ end
data/gemagent.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ summary = "GemAgent is a clean and light way to interact with the FreeAgent API. "
2
+ description = <<-TXT
3
+ GemAgent lets users of FreeAgent Central's online accounting software
4
+ to interact with the API simply and cleanly by only using functionality
5
+ provided by Ruby's Standard Library.
6
+ TXT
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "gemagent"
10
+ spec.version = '0.0.1.pre'
11
+ spec.platform = Gem::Platform::RUBY
12
+ spec.files = Dir.glob("{bin,lib,.}/**/**/*") +
13
+ ["gemagent.rb","README.md","HACKING",'LICENCE','CONTRIBUTORS', "gemagent.gemspec"]
14
+ spec.require_path = "lib"
15
+ spec.required_ruby_version = '>= 1.8.4'
16
+ spec.required_rubygems_version = ">= 1.3.0"
17
+ spec.test_files = Dir[ "test/*_test.rb" ]
18
+ spec.has_rdoc = false
19
+ spec.author = "Ryan Stenhouse"
20
+ spec.email = "ryan@ryanstenhouse.eu"
21
+ spec.rubyforge_project = "gemagemt"
22
+ spec.homepage = "http://ryanstenhouse.eu"
23
+ spec.summary = summary
24
+ spec.description = description
25
+ end
data/gemagent.rb ADDED
@@ -0,0 +1,8 @@
1
+ GEMAGENT_ROOT = File.expand_path(File.dirname(__FILE__))
2
+ require GEMAGENT_ROOT + '/lib/connection.rb'
3
+ require GEMAGENT_ROOT + '/lib/authentication.rb'
4
+ require GEMAGENT_ROOT + '/lib/api_classes.rb'
5
+ require GEMAGENT_ROOT + '/lib/api_handler.rb'
6
+
7
+ module GemAgent
8
+ end
@@ -0,0 +1,36 @@
1
+ require "rexml/document"
2
+
3
+ module GemAgent
4
+ module Api
5
+
6
+ def self.connect(freeagent_url, username, password, connection = GemAgent::NetHttpConnection,
7
+ authenticator = GemAgent::HttpBasicAuthentication,
8
+ api_version = GemAgent::ApiHandler)
9
+ if !block_given?
10
+ raise "I need to have a block" and return
11
+ end
12
+ api = connection.new(freeagent_url, authenticator.new(username, password), api_version)
13
+ yield api
14
+ end
15
+
16
+ class ApiBase
17
+ def method
18
+ 'GET'
19
+ end
20
+
21
+ def path
22
+ end
23
+
24
+ def expected_status
25
+ '200'
26
+ end
27
+
28
+ end
29
+
30
+ class Verify < ApiBase
31
+ def path
32
+ '/verify'
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/api_classes.rb'
2
+ module GemAgent
3
+ class ApiHandler
4
+
5
+ def initialize(connection)
6
+ @connection = connection
7
+ end
8
+
9
+ def verify
10
+ verify = GemAgent::Api::Verify.new
11
+ response = @connection.send_request(verify)
12
+ unless response.has_error?
13
+ {
14
+ :company_type => response.headers['company-type'],
15
+ :user_id => response.headers['user-id'].to_i,
16
+ :permission_level => response.headers['user-permission-level'].to_i
17
+ }
18
+ else
19
+ {
20
+ :error => response.headers[:error],
21
+ :body => response.body,
22
+ :company_type => 'ERROR'
23
+ }
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ module GemAgent
2
+ class ApiAuthentication
3
+ def authenticate_for(obj)
4
+ end
5
+ end
6
+
7
+ class HttpBasicAuthentication < ApiAuthentication
8
+
9
+ def initialize(username, password)
10
+ @username = username
11
+ @password = password
12
+ end
13
+
14
+ def authenticate_for(obj)
15
+ if obj.respond_to?(:basic_auth)
16
+ obj.basic_auth @username, @password
17
+ else
18
+ raise "Can't do basic authentication with this, I expect a NetHTTP request"
19
+ end
20
+ end
21
+
22
+ end
23
+ end
data/lib/connection.rb ADDED
@@ -0,0 +1,116 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+
4
+ module GemAgent
5
+
6
+ # ConnectionMethod implements the basic interface all child
7
+ # classes must implement to allow connection to the FreeAgent
8
+ # API.
9
+ #
10
+ class ConnectionMethod
11
+
12
+ attr_reader :freeagent_url
13
+ attr_reader :api
14
+ attr_reader :authenticator
15
+
16
+ @@method_map = {}
17
+
18
+ def initialize(freeagent_url, authenticator, api_handler = GemAgent::ApiHandler)
19
+ @freeagent_url = freeagent_url
20
+ @authenticator = authenticator
21
+ @api = api_handler.new(self)
22
+ end
23
+
24
+ def send_request(request)
25
+ raise "Subclasses of ConnectionMethod must implement their own send_request method"
26
+ end
27
+
28
+ def wrap_response(response)
29
+ raise "Subclasses of ConnectionMethod must implement their own wrap_response method"
30
+ end
31
+
32
+ # Proxies all undefined method to the API handler
33
+ # associated with the connection.
34
+ #
35
+ def method_missing(method, *args)
36
+ unless args.empty?
37
+ @api.send(method, args)
38
+ else
39
+ @api.send(method)
40
+ end
41
+ end
42
+ end
43
+
44
+ # The ResponseWrapper is used to present a consistant way
45
+ # for the various API classes to process messages returned
46
+ # by the API server.
47
+ #
48
+ # If you write your own ConnectionMethod subclass, ensure that
49
+ # your send_request method returns a ResponseWrapper correctly
50
+ # set with the correct values for headers and body.
51
+ #
52
+ class ResponseWrapper
53
+ attr_reader :headers, :body
54
+ def initialize(headers, body)
55
+ @headers = headers
56
+ @body = body
57
+ end
58
+
59
+ def has_error?
60
+ !headers[:error].nil?
61
+ end
62
+ end
63
+
64
+ # NetHttpConnection is the default method to connect to the
65
+ # FreeAgent API. It uses the Standard Ruby library net/http
66
+ # to create an SSL connection to the FreeAgent server specified
67
+ # by +@freeagent_url+ and authenticates your request with the
68
+ # ApiAuthentication subclass you pass thorugh as +authenticator+.
69
+ #
70
+ # The last last optional value takes a API Handler class, which
71
+ # defaults to the standard one which ships with this gem.
72
+ #
73
+ class NetHttpConnection < ConnectionMethod
74
+
75
+ @@method_map = {
76
+ 'GET' => Net::HTTP::Get,
77
+ 'POST' => Net::HTTP::Post,
78
+ 'PUT' => Net::HTTP::Put,
79
+ 'DELETE' => Net::HTTP::Delete
80
+ }
81
+
82
+ # Sends the +request+ to +@freeagent_url+ over HTTPS. The class
83
+ # instance variable +@@method_map+ maps each HTTP verb required
84
+ # to the correct class for instantiation.
85
+ #
86
+ def send_request(request)
87
+ https = Net::HTTP.new(@freeagent_url, Net::HTTP.https_default_port)
88
+ https.use_ssl = true
89
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
90
+ req = @@method_map[request.method].new(request.path)
91
+ req['content-type'] = 'application/xml'
92
+ req['accept'] = 'application/xml'
93
+ authenticator.authenticate_for req
94
+ resp = nil
95
+ https.start do |http|
96
+ resp = http.request(req)
97
+ end
98
+ if resp.code == request.expected_status
99
+ wrap_response(resp)
100
+ else
101
+ ResponseWrapper.new({ :error => resp.code, :status => resp.code }, resp.body)
102
+ end
103
+ end
104
+
105
+ # Wraps the response from net/http in a ResponseWrapper object
106
+ # so the API classes are able to work with it to do their work.
107
+ #
108
+ def wrap_response(response)
109
+ headers = {}
110
+ response.each_header { |k,v| headers[k] = v }
111
+ ResponseWrapper.new(headers, response.body)
112
+ end
113
+
114
+ end
115
+
116
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gemagent
3
+ version: !ruby/object:Gem::Version
4
+ hash: 961915968
5
+ prerelease: 6
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ - pre
11
+ version: 0.0.1.pre
12
+ platform: ruby
13
+ authors:
14
+ - Ryan Stenhouse
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-04-29 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: " GemAgent lets users of FreeAgent Central's online accounting software\n to interact with the API simply and cleanly by only using functionality\n provided by Ruby's Standard Library.\n"
24
+ email: ryan@ryanstenhouse.eu
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - lib/api_classes.rb
33
+ - lib/api_handler.rb
34
+ - lib/authentication.rb
35
+ - lib/connection.rb
36
+ - ./CONTRIBUTORS
37
+ - ./example/example.rb
38
+ - ./gemagent.gemspec
39
+ - ./gemagent.rb
40
+ - ./HACKING
41
+ - ./lib/api_classes.rb
42
+ - ./lib/api_handler.rb
43
+ - ./lib/authentication.rb
44
+ - ./lib/connection.rb
45
+ - ./LICENCE
46
+ - ./README.md
47
+ - gemagent.rb
48
+ - README.md
49
+ - HACKING
50
+ - LICENCE
51
+ - CONTRIBUTORS
52
+ - gemagent.gemspec
53
+ has_rdoc: true
54
+ homepage: http://ryanstenhouse.eu
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options: []
59
+
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 63
68
+ segments:
69
+ - 1
70
+ - 8
71
+ - 4
72
+ version: 1.8.4
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 27
79
+ segments:
80
+ - 1
81
+ - 3
82
+ - 0
83
+ version: 1.3.0
84
+ requirements: []
85
+
86
+ rubyforge_project: gemagemt
87
+ rubygems_version: 1.6.1
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: GemAgent is a clean and light way to interact with the FreeAgent API.
91
+ test_files: []
92
+