TeleAuth 0.5

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.
Files changed (4) hide show
  1. data/README +106 -0
  2. data/lib/teleauth.rb +251 -0
  3. data/tests/ts_teleauth.rb +54 -0
  4. metadata +41 -0
data/README ADDED
@@ -0,0 +1,106 @@
1
+ == Synopsis
2
+
3
+ Ruby TeleAuth Module.
4
+
5
+ Allows for two-factor authentication within Ruby. Uses the
6
+ TeleAuth[http://www.teleauth.com] service.
7
+
8
+ == Author
9
+
10
+ Mohit Muthanna Cheppudira <mohit AT muthanna DOTcom>
11
+
12
+ == Copyright
13
+
14
+ Copyright (c) 2005 Mohit Muthanna Cheppudira.
15
+ Licensed under the GPL.
16
+
17
+ == Prerequisites
18
+
19
+ To use this module, you will need a TeleAuth API Key. Get yours
20
+ at [http://www.teleauth.com].
21
+
22
+ == Basic Usage
23
+
24
+ The following example calls a user on a specific phone
25
+ number and requests a PIN code.
26
+
27
+ require 'teleauth'
28
+
29
+ conn = TeleAuth::Client.new (
30
+ 'urls' = ['http://teleauth.com/api/auth'],
31
+ 'domain_id' = 'mydomain',
32
+ 'login' = 'dialer',
33
+ 'password' = 'bu4ger'
34
+ )
35
+
36
+ Register a user's phone number.
37
+
38
+ conn.register_phone(
39
+ 'ext_uid' => 'foobar',
40
+ 'phone' => '12332445443'
41
+ )
42
+
43
+ Call user and request PIN code.
44
+
45
+ conn.get_secret( 'ext_uid' => 'foobar' ) { |response|
46
+ puts "PIN code: #{ response['secret'] }"
47
+ }
48
+
49
+
50
+ == TeleAuth API
51
+
52
+ In brief, you can use any API command as a TeleAuth::Client
53
+ method. Arguments are provided as hash parameters. Responses
54
+ are returned as Ruby hashes.
55
+
56
+ Examples:
57
+
58
+ response = conn.validate_user
59
+
60
+ conn.validate_user { |response|
61
+ # do something
62
+ }
63
+
64
+ Register a user's phone number and PIN code.
65
+
66
+ conn.register_phone(
67
+ 'ext_uid' => 'foobar',
68
+ 'phone' => '12332445443',
69
+ 'pin' => '45334',
70
+ )
71
+
72
+ Call the user and validate PIN
73
+
74
+ conn.validate_phone( 'ext_uid' => 'foobar' ) { |response|
75
+ if response['login'] == 'PASS'
76
+ puts "Valid PIN code."
77
+ else
78
+ puts "Authorization failed"
79
+ end
80
+ end
81
+
82
+
83
+ For the TeleAuth API reference, visit http://teleauth.com
84
+
85
+ == Logging, Exceptions and Errors
86
+
87
+ The class raises the TeleAuth::APIError exception if the API command
88
+ failed.
89
+
90
+ If you have multiple URLs, eg. for failover, the module can
91
+ inform you if a failover took place.
92
+
93
+ conn.on_command_fail { |url|
94
+ puts "Failed to connect to #{ url }. Trying next one."
95
+ }
96
+
97
+
98
+ If you need nice debug output, use on_log:
99
+
100
+ con.on_log { |msg|
101
+ $stderr.puts( "LOG: #{ msg }" )
102
+ end
103
+
104
+ == Support
105
+
106
+ Get on the {TeleAuth Mailing List}[http://lists.sourceforge.net/lists/listinfo/teleauth-users]
@@ -0,0 +1,251 @@
1
+ require 'uri'
2
+ require 'yaml'
3
+ require 'net/http'
4
+
5
+ =begin rdoc
6
+
7
+ == Synopsis
8
+
9
+ Ruby TeleAuth Module.
10
+ $Id$
11
+
12
+ Allows for two-factor authentication within Ruby. Uses the
13
+ TeleAuth[http://www.teleauth.com] service.
14
+
15
+ == Author
16
+
17
+ Mohit Muthanna Cheppudira mohit AT muthanna DOT com
18
+
19
+ == Copyright
20
+
21
+ Copyright (c) 2005 Mohit Muthanna Cheppudira.
22
+ Licensed under the GPL.
23
+
24
+ =end
25
+
26
+ module TeleAuth
27
+
28
+ =begin rdoc
29
+ This exception is raised if an API command could
30
+ not be successfully sent to any of the TeleAuth
31
+ URLs.
32
+ =end
33
+
34
+ class APIError < Exception; end
35
+
36
+ =begin rdoc
37
+
38
+ This is the TeleAuth Client Class. Basic usage:
39
+
40
+ The following example calls a user on a specific phone
41
+ number and requests a PIN code.
42
+
43
+ require 'teleauth'
44
+
45
+ conn = TeleAuth::Client.new (
46
+ 'urls' = ['http://teleauth.com/api/auth'],
47
+ 'domain_id' = 'mydomain',
48
+ 'login' = 'dialer',
49
+ 'password' = 'bu4ger'
50
+ )
51
+
52
+ # Register a user's phone number.
53
+ conn.register_phone(
54
+ 'ext_uid' => 'foobar',
55
+ 'phone' => '12332445443'
56
+ )
57
+
58
+ conn.get_secret( 'ext_uid' => 'foobar' ) { |response|
59
+ puts "PIN code: #{ response['secret'] }"
60
+ }
61
+
62
+ =end
63
+
64
+ class Client
65
+
66
+ =begin rdoc
67
+ [auth] A hash that consists of API authentication parameters.
68
+ [urls] An array of API URLs.
69
+ =end
70
+
71
+ attr_accessor :auth, :urls
72
+
73
+ =begin rdoc
74
+ At a minimum, this method requires a list of URLs, and
75
+ the API Key, like so:
76
+
77
+
78
+ conn = TeleAuth::Client.new(
79
+ "urls" => ["http://teleauth.com/apu/auth", "http://backup.teleauth.com/api/auth"],
80
+ "domain_id" => "public.sample",
81
+ "login" => "admin",
82
+ "password" => "p4ss"
83
+ )
84
+
85
+ The URLs are a list of primary and failover API servers. When
86
+ an API command is sent, each of these servers are cycled through
87
+ until one of them works.
88
+ =end
89
+
90
+ def initialize( params = {} )
91
+ if params.has_key?( 'urls' )
92
+ self.urls = params['urls']
93
+
94
+ # Delete this key, as it shouldn't be passed in
95
+ # the API request.
96
+ params.delete( 'urls' )
97
+ else
98
+ self.urls = []
99
+ end
100
+
101
+ @auth = params
102
+ @on_command_fail = proc {}
103
+ @on_log = proc {}
104
+ end
105
+
106
+ =begin rdoc
107
+ Setup a code-block to execute if one of the URLs fail. This could
108
+ be useful for logging, for example. It passes the URL of the API
109
+ server that failed.
110
+
111
+ conn.on_command_fail { |url|
112
+ $stderr.puts "Failed to send command to #{ url }"
113
+ }
114
+ =end
115
+
116
+ def on_command_fail( &block )
117
+ @on_command_fail = block
118
+ end
119
+
120
+ =begin rdoc
121
+ Our logger. Call this and specify a logging routing to receive more
122
+ debug information.
123
+
124
+ conn.on_log { |msg|
125
+ $stderr.puts "LOG: #{ msg }"
126
+ end
127
+ =end
128
+
129
+ def on_log( &block )
130
+ @on_log = block
131
+ end
132
+
133
+ def log( *args )
134
+ @on_log.call( *args )
135
+ end
136
+
137
+ =begin rdoc
138
+ The main communications routine. Establish a connection to the API
139
+ server, and send the command. Private.
140
+ =end
141
+
142
+ def api_send( command_hash )
143
+
144
+ # For each URL...
145
+ @urls.each do |url|
146
+ log( "Trying #{ url }" )
147
+ uri = URI.parse( url )
148
+
149
+ # Make sure it's HTTP/(S) ...
150
+ if uri.scheme == "http"
151
+ response = ""
152
+
153
+ # Build the POST parameters..
154
+ post_params = command_hash.keys.collect { |key|
155
+ key + "=" + command_hash[key]
156
+ }.join( "&" )
157
+
158
+ log( "Sending: #{ post_params }" )
159
+
160
+ begin
161
+ Net::HTTP.start( uri.host ) do |query|
162
+ response = query.post( uri.path, post_params )
163
+ end
164
+
165
+ log( "Response: #{ response.message }" )
166
+
167
+ if response.message == "OK"
168
+ log( "Body: #{ response.body }" )
169
+ return response.body
170
+ else
171
+ # HTTP level failure...
172
+ @on_command_fail.call( url )
173
+ next
174
+ end
175
+ rescue Exception => e
176
+ # Socket level failure...
177
+ @on_command_fail.call( url )
178
+ next
179
+ end
180
+ else
181
+ # Unsupported URI scheme...
182
+ @on_command_fail.call( url )
183
+ end
184
+ end
185
+
186
+ # All failed. Return Nil.
187
+ return nil
188
+ end
189
+
190
+ =begin rdoc
191
+ This method creates a hash with parameters for api_send
192
+ =end
193
+ def send_command( *args )
194
+ # Extract the instance method name
195
+ command = args.shift
196
+
197
+ # No Arguments?
198
+ if (params = args.shift).nil?
199
+ params = Hash.new
200
+ end
201
+
202
+ # Pass the extracted method name as the API command
203
+ command_hash = auth.merge( params ).merge( 'cmd' => command.to_s )
204
+ response = api_send( command_hash )
205
+
206
+ raise APIError if response.nil?
207
+ response
208
+ end
209
+
210
+ =begin rdoc
211
+ Check to see if we have connectivity by sending a "version" API command.
212
+ =end
213
+
214
+ def ping?
215
+ begin
216
+ version
217
+ rescue Exception => e
218
+ return false
219
+ end
220
+
221
+ true
222
+ end
223
+
224
+ =begin rdoc
225
+ This is where the magic happens. Any instance method that is not defined
226
+ reaches here. We just propogate the request to send_command, which
227
+ extracts the method name, and substitutes it for the API command. This
228
+ get's fed to api_send.
229
+
230
+ This function also yields to a code block, so commands can be sent in
231
+ multiple forms:
232
+
233
+ conn.get_user_list { |user_list|
234
+ # ... do something with user_list
235
+ }
236
+
237
+ or
238
+
239
+ user_list = conn.get_user_list
240
+ =end
241
+
242
+ def method_missing( *args )
243
+ response = YAML::load( send_command( *args ) )
244
+ yield response if block_given?
245
+ response
246
+ end
247
+
248
+ protected :api_send, :log
249
+ end
250
+
251
+ end
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # PickAxe magic. Helps run tests from any directory.
4
+ $:.unshift File.join( File.dirname( __FILE__ ), "..", "lib" )
5
+
6
+ require 'teleauth'
7
+ require 'test/unit'
8
+
9
+ include TeleAuth
10
+
11
+ =begin rdoc
12
+ Test class for TeleAuth::Client.
13
+ =end
14
+
15
+ class TestClient < Test::Unit::TestCase
16
+ def setup
17
+
18
+ # Setup API Test parameters here. Make sure
19
+ # you use an invalid URL before a valid one
20
+ # to test failures.
21
+
22
+ @conn = Client.new(
23
+ "urls" => ["http://abc.d/f", "http://teleauth.com/api/auth"],
24
+ "domain_id" => "public.test",
25
+ "login" => "reader",
26
+ "password" => "reader"
27
+ )
28
+ end
29
+
30
+ def teardown
31
+ # Nothing to do...
32
+ end
33
+
34
+ def test_ping
35
+ assert_equal( @conn.ping?, true )
36
+ end
37
+
38
+ def test_commands
39
+ failed = false
40
+ @conn.on_command_fail {
41
+ failed = true
42
+ }
43
+
44
+ # Test both formats of commands...
45
+ assert_equal( @conn.validate_user['result'], 'OK' )
46
+
47
+ @conn.validate_user { |response|
48
+ assert_equal response['result'], 'OK'
49
+ }
50
+
51
+ # The first URL should have failed.
52
+ assert_equal failed, true
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,41 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.10
3
+ specification_version: 1
4
+ name: TeleAuth
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.5"
7
+ date: 2005-08-26
8
+ summary: Ruby library for the TeleAuth authentication system. Requires a TeleAuth API key.
9
+ require_paths:
10
+ - lib
11
+ email: mohit@muthanna.com
12
+ homepage: http://teleauth.com
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: teleauth
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ authors:
28
+ - Mohit Muthanna Cheppudira
29
+ files:
30
+ - lib/teleauth.rb
31
+ - tests/ts_teleauth.rb
32
+ - README
33
+ test_files:
34
+ - tests/ts_teleauth.rb
35
+ rdoc_options: []
36
+ extra_rdoc_files:
37
+ - README
38
+ executables: []
39
+ extensions: []
40
+ requirements: []
41
+ dependencies: []