rrba 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ class rrba
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # Error -- rrba -- 04.02.2005 -- rwaltert@ywesee.com
3
+
4
+ module RRBA
5
+ class AuthenticationError < RuntimeError; end
6
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ # Server -- rrba -- 10.11.2004 -- hwyss@ywesee.com
3
+
4
+ require 'rrba/user'
5
+ require 'rrba/error'
6
+ require 'openssl'
7
+ require 'digest/md5'
8
+
9
+ module RRBA
10
+ class Server
11
+ attr_writer :root, :anonymous
12
+ def initialize
13
+ @users = []
14
+ end
15
+ def add_user(user)
16
+ id = user.unique_id
17
+ if(@users.any? { |usr| usr.unique_id == id })
18
+ raise "Duplicate ID #{id}"
19
+ end
20
+ @users.push(user).last
21
+ end
22
+ def authenticate(id=nil, &block)
23
+ challenge = Digest::MD5.hexdigest(rand(2**32).to_s)[0,20]
24
+ signature = block.call(challenge)
25
+ if(@anonymous && signature == :anonymous)
26
+ return @anonymous.new_session
27
+ end
28
+ if(@root && @root.authenticate(challenge, signature))
29
+ return @root.new_session
30
+ end
31
+ begin
32
+ if(id)
33
+ if((user = user(id)) \
34
+ && user.authenticate(challenge, signature))
35
+ return user.new_session
36
+ end
37
+ else
38
+ @users.each { |user|
39
+ if(user.authenticate(challenge, signature))
40
+ return user.new_session
41
+ end
42
+ }
43
+ end
44
+ rescue RuntimeError
45
+ end
46
+ raise AuthenticationError, 'Authentication failed'
47
+ end
48
+ def user(id)
49
+ @users.select { |user|
50
+ user.unique_id == id
51
+ }.first or raise "Unknown User: #{id}"
52
+ end
53
+ def unique_ids
54
+ @users.collect { |user|
55
+ user.unique_id
56
+ }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # User -- rrba -- 01.11.2004 -- hwyss@ywesee.com
3
+
4
+ module RRBA
5
+ class User
6
+ attr_reader :name, :email, :short_name, :unique_id, :public_key
7
+ def initialize(unique_id)
8
+ @unique_id = unique_id or raise "Invalid ID #{unique_id}"
9
+ end
10
+ def authenticate(challenge, signature)
11
+ # enable lazy initializing
12
+ # (for subclasses that can be persisted)
13
+ public_key.sysverify(challenge, signature)
14
+ end
15
+ def email=(email)
16
+ email = email.to_s.strip
17
+ raise "Invalid Email #{email}" if(email.empty?)
18
+ @email = email
19
+ end
20
+ def name=(name)
21
+ name = name.to_s.strip
22
+ raise "Invalid Username #{name}" if(name.empty?)
23
+ @name = name
24
+ end
25
+ def new_session
26
+ raise NotImplementedError,
27
+ "no predefined behavior for RRBA::User#new_session"
28
+ end
29
+ def public_key=(key)
30
+ @public_key = key.public_key
31
+ end
32
+ def short_name=(short_name)
33
+ short_name = short_name.to_s.strip
34
+ raise "Invalid Short Name #{short_name}" if(short_name.empty?)
35
+ @short_name = short_name
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,149 @@
1
+ # Ruby/Mock version 1.0
2
+ #
3
+ # A class for conveniently building mock objects in RUnit test cases.
4
+ # Copyright (c) 2001 Nat Pryce, all rights reserved
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
+
19
+ require 'runit/error'
20
+
21
+
22
+ class Mock
23
+ # Creates a new, named mock object. The name is reported in exceptions
24
+ # thrown by the mock object when method invocations are incorrect.
25
+ #
26
+ def initialize( mock_name = self.to_s )
27
+ @mock_calls = []
28
+ @next_call = 0
29
+ @name = mock_name
30
+ end
31
+
32
+ # Mock the next method call to be made to this mock object.
33
+ #
34
+ # A mock method is defined by the method name (a symbol) and a block
35
+ # that defines the arity of the method and the mocked behaviour for
36
+ # this call. The mocked behaviour should assert preconditions and
37
+ # return a value. Mocked behaviour should rarely be any more complex
38
+ # than that. If it is, that's probably an indication that the tests
39
+ # need some restructuring or that the tested code needs refactoring.
40
+ #
41
+ # If no block is given and preconditions have been defined for the named
42
+ # method, a block is created for the mocked methodthat has the same arity
43
+ # as the precondition and returns self.
44
+ #
45
+ def __next( name, &test )
46
+ if test == nil
47
+ if respond_to?( Mock.__pre(name) )
48
+ test = proc { |*args| self }
49
+ else
50
+ raise "no block given for mocked method #{name}"
51
+ end
52
+ end
53
+ @mock_calls.push( [name,test] )
54
+ end
55
+
56
+ # Call this at the end of a test to ensure that all scheduled calls
57
+ # have been made to the mock
58
+ #
59
+ def __verify
60
+ if @next_call != @mock_calls.length
61
+ raise RUNIT::AssertionFailedError,
62
+ "not all expected method calls were made to #{@name}",
63
+ caller
64
+ end
65
+ end
66
+
67
+
68
+ private
69
+ # Dispatches aribtrary method calls to the next mocked behaviour
70
+ #
71
+ def method_missing( name, *args )
72
+ __mock_call( name, args, (block_given? ? proc : nil) )
73
+ end
74
+
75
+ # Implements a method call using the next mocked behaviour and asserts
76
+ # that the expected method is called with the expected number of
77
+ # arguments.
78
+ #
79
+ def __mock_call( name, args, block )
80
+ if @next_call >= @mock_calls.length
81
+ raise RUNIT::AssertionFailedError,
82
+ "unexpected call to #{name} method of #{@name}",
83
+ caller(2)
84
+ end
85
+
86
+ expected_name,body = @mock_calls[@next_call]
87
+ @next_call += 1
88
+
89
+ if name != expected_name
90
+ raise RUNIT::AssertionFailedError,
91
+ "wrong method called on #{@name}; " +
92
+ "expected #{expected_name}, was #{name}",
93
+ caller(2)
94
+ end
95
+
96
+ args_length = args.length + (block ? 1 : 0)
97
+
98
+ if body.arity < 0
99
+ if (body.arity+1).abs > args_length
100
+ raise RUNIT::AssertionFailedError,
101
+ "too few arguments to #{name} method of #{@name}; " +
102
+ "require #{(body.arity+1).abs}, got #{args.length}",
103
+ caller(2)
104
+ end
105
+ else
106
+ if body.arity != args_length
107
+ raise RUNIT::AssertionFailedError,
108
+ "wrong number of arguments to " +
109
+ "#{name} method of #{@name}; " +
110
+ "require #{body.arity}, got #{args.length}",
111
+ caller(2)
112
+ end
113
+ end
114
+
115
+ if respond_to? Mock.__pre(name)
116
+ if block
117
+ precondition_ok = __send__( Mock.__pre(name), *args, &block )
118
+ else
119
+ precondition_ok = __send__( Mock.__pre(name), *args )
120
+ end
121
+
122
+ if not precondition_ok
123
+ raise RUNIT::AssertionFailedError,
124
+ "precondition of #{name} method violated",
125
+ caller(2)
126
+ end
127
+ end
128
+
129
+ if block
130
+ instance_eval { body.call( block, *args ) }
131
+ else
132
+ instance_eval { body.call( *args ) }
133
+ end
134
+ end
135
+
136
+ # The name of a precondition for a method
137
+ def Mock.__pre( method )
138
+ "__pre_#{method.to_i}".intern
139
+ end
140
+
141
+
142
+ def Mock.method_added( name )
143
+ unless(/^__pre_/.match(name.to_s))
144
+ pre = self.__pre(name)
145
+ alias_method( pre, name )
146
+ undef_method(name)
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # -- rdpm -- 21.01.2005 -- hwyss@ywesee.com
3
+
4
+ require 'odba'
5
+
6
+ module ODBA
7
+ module Persistable
8
+ attr_reader :odba_store_called
9
+ def odba_store
10
+ @odba_store_called = true
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # suite.rb -- rrba -- 20.11.2002 -- hwyss@ywesee.com
3
+
4
+ $: << File.expand_path(File.dirname(__FILE__))
5
+
6
+ Dir.foreach(File.dirname(__FILE__)) { |file|
7
+ require file if /^test_.*\.rb$/o.match(file)
8
+ }
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env ruby
2
+ # TestServer -- rdpm -- 10.11.2004 -- hwyss@ywesee.com
3
+
4
+ $: << File.expand_path('../lib', File.dirname(__FILE__))
5
+ $: << File.dirname(__FILE__)
6
+
7
+ require 'test/unit'
8
+ require 'mock'
9
+ require 'fileutils'
10
+ require 'rrba/server'
11
+
12
+ module RRBA
13
+ class TestServer < Test::Unit::TestCase
14
+ def setup
15
+ @server = Server.new
16
+ @datadir = File.expand_path('data', File.dirname(__FILE__))
17
+ end
18
+ def test_add_user
19
+ user = User.new(345)
20
+ users = @server.instance_variable_get('@users')
21
+ @server.add_user(user)
22
+ assert_equal(user, @server.user(345))
23
+ end
24
+ def test_add_user__duplicate_id
25
+ user = User.new(345)
26
+ users = @server.instance_variable_get('@users')
27
+ @server.add_user(user)
28
+ assert_equal(user, @server.user(345))
29
+ assert_equal(345, user.unique_id)
30
+ user = User.new(345)
31
+ assert_raises(RuntimeError) {
32
+ @server.add_user(user)
33
+ }
34
+ end
35
+ def test_authenticate__failure
36
+ user1 = Mock.new('User1')
37
+ user2 = Mock.new('User2')
38
+ user3 = Mock.new('User3')
39
+ user1.__next(:authenticate) { |chal, sig|
40
+ assert_equal(20, chal.size)
41
+ assert_equal('client-signature', sig)
42
+ false
43
+ }
44
+ user2.__next(:authenticate) { |chal, sig|
45
+ assert_equal(20, chal.size)
46
+ assert_equal('client-signature', sig)
47
+ false
48
+ }
49
+ user3.__next(:authenticate) { |chal, sig|
50
+ assert_equal(20, chal.size)
51
+ assert_equal('client-signature', sig)
52
+ false
53
+ }
54
+ users = [
55
+ user1,
56
+ user2,
57
+ user3,
58
+ ]
59
+ @server.instance_variable_set('@users', users)
60
+ user = nil
61
+ assert_raises(AuthenticationError) {
62
+ user = @server.authenticate { |challenge|
63
+ assert_equal(20, challenge.size)
64
+ 'client-signature'
65
+ }
66
+ }
67
+ assert_nil(user)
68
+ end
69
+ def test_authenticate__success
70
+ user1 = Mock.new('User1')
71
+ user2 = Mock.new('User2')
72
+ user3 = Mock.new('User3')
73
+ user1.__next(:authenticate) { |challenge, sig|
74
+ assert_equal('client-signature', sig)
75
+ false
76
+ }
77
+ user2.__next(:authenticate) { |challenge, sig|
78
+ assert_equal('client-signature', sig)
79
+ true
80
+ }
81
+ user3.__next(:authenticate) { |challenge, sig|
82
+ assert_equal('client-signature', sig)
83
+ false
84
+ }
85
+ users = [
86
+ user1,
87
+ user2,
88
+ user3,
89
+ ]
90
+ session = Mock.new('Session')
91
+ user2.__next(:new_session) { session }
92
+ @server.instance_variable_set('@users', users)
93
+ sess = @server.authenticate { |challenge, sig|
94
+ assert_equal(20, challenge.size)
95
+ 'client-signature'
96
+ }
97
+ assert_equal(session, sess)
98
+ user2.__verify
99
+ end
100
+ def test_authenticate__root
101
+ root = Mock.new('Root')
102
+ user2 = Mock.new('User2')
103
+ user3 = Mock.new('User3')
104
+ root.__next(:authenticate) { |challenge, sig|
105
+ assert_equal('client-signature', sig)
106
+ true
107
+ }
108
+ users = [
109
+ user2,
110
+ user3,
111
+ ]
112
+ session = Mock.new('Session')
113
+ root.__next(:new_session) { session }
114
+ @server.instance_variable_set('@root', root)
115
+ @server.instance_variable_set('@users', users)
116
+ sess = @server.authenticate { |challenge, sig|
117
+ 'client-signature'
118
+ }
119
+ assert_equal(session, sess)
120
+ root.__verify
121
+ end
122
+ def test_authenticate__anonymous
123
+ root = Mock.new('Root')
124
+ user2 = Mock.new('User2')
125
+ user3 = Mock.new('User3')
126
+ anonymous = Mock.new('Anonymous')
127
+ users = [
128
+ user2,
129
+ user3,
130
+ ]
131
+ session = Mock.new('Session')
132
+ anonymous.__next(:new_session) { session }
133
+ @server.root = root
134
+ @server.anonymous = anonymous
135
+ @server.instance_variable_set('@users', users)
136
+ sess = @server.authenticate { |challenge, sig|
137
+ :anonymous
138
+ }
139
+ assert_equal(session, sess)
140
+ root.__verify
141
+ end
142
+ def test_authenticate__by_id
143
+ user1 = Mock.new('User1')
144
+ user2 = Mock.new('User2')
145
+ user3 = Mock.new('User3')
146
+ user1.__next(:unique_id) { 'user1' }
147
+ user2.__next(:unique_id) { 'user2' }
148
+ user3.__next(:unique_id) { 'user3' }
149
+ user2.__next(:authenticate) { |challenge, sig|
150
+ assert_equal('client-signature', sig)
151
+ true
152
+ }
153
+ users = [
154
+ user1,
155
+ user2,
156
+ user3,
157
+ ]
158
+ session = Mock.new('Session')
159
+ user2.__next(:new_session) { session }
160
+ @server.instance_variable_set('@users', users)
161
+ sess = @server.authenticate('user2') { |challenge, sig|
162
+ assert_equal(20, challenge.size)
163
+ 'client-signature'
164
+ }
165
+ assert_equal(session, sess)
166
+ user2.__verify
167
+ end
168
+ def test_unique_ids
169
+ user = Mock.new('user')
170
+ user2 = Mock.new('user2')
171
+ user.__next(:unique_id) { 'rwaltert' }
172
+ user2.__next(:unique_id) { 'hwyss' }
173
+ users = [user, user2]
174
+ @server.instance_variable_set('@users', users)
175
+ assert_equal(["rwaltert", 'hwyss'], @server.unique_ids)
176
+ end
177
+ end
178
+ end