adhearsion 0.8.3 → 0.8.4
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/CHANGELOG +11 -2
- data/EVENTS +1 -1
- data/Rakefile +4 -4
- data/adhearsion.gemspec +8 -4
- data/app_generators/ahn/USAGE +3 -3
- data/app_generators/ahn/ahn_generator.rb +11 -11
- data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +3 -3
- data/app_generators/ahn/templates/components/disabled/restful_rpc/example-client.rb +6 -6
- data/app_generators/ahn/templates/components/disabled/restful_rpc/restful_rpc.rb +16 -16
- data/app_generators/ahn/templates/components/disabled/restful_rpc/spec/restful_rpc_spec.rb +42 -42
- data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.rb +11 -11
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +1 -1
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +6 -6
- data/app_generators/ahn/templates/components/simon_game/simon_game.rb +4 -4
- data/app_generators/ahn/templates/config/startup.rb +31 -16
- data/bin/ahn +3 -3
- data/bin/ahnctl +8 -8
- data/bin/jahn +3 -3
- data/examples/asterisk_manager_interface/standalone.rb +2 -2
- data/lib/adhearsion.rb +4 -2
- data/lib/adhearsion/cli.rb +31 -31
- data/lib/adhearsion/component_manager.rb +39 -39
- data/lib/adhearsion/component_manager/component_tester.rb +14 -14
- data/lib/adhearsion/component_manager/spec_framework.rb +1 -1
- data/lib/adhearsion/events_support.rb +12 -12
- data/lib/adhearsion/foundation/blank_slate.rb +1 -1
- data/lib/adhearsion/foundation/custom_daemonizer.rb +2 -2
- data/lib/adhearsion/foundation/event_socket.rb +26 -26
- data/lib/adhearsion/foundation/future_resource.rb +6 -6
- data/lib/adhearsion/foundation/metaprogramming.rb +2 -2
- data/lib/adhearsion/foundation/numeric.rb +3 -3
- data/lib/adhearsion/foundation/relationship_properties.rb +7 -7
- data/lib/adhearsion/foundation/string.rb +8 -8
- data/lib/adhearsion/foundation/synchronized_hash.rb +8 -8
- data/lib/adhearsion/host_definitions.rb +16 -16
- data/lib/adhearsion/initializer.rb +74 -65
- data/lib/adhearsion/initializer/asterisk.rb +15 -9
- data/lib/adhearsion/initializer/configuration.rb +54 -39
- data/lib/adhearsion/initializer/database.rb +4 -4
- data/lib/adhearsion/initializer/drb.rb +6 -6
- data/lib/adhearsion/initializer/freeswitch.rb +1 -1
- data/lib/adhearsion/initializer/ldap.rb +51 -0
- data/lib/adhearsion/initializer/rails.rb +8 -8
- data/lib/adhearsion/logging.rb +16 -16
- data/lib/adhearsion/tasks/deprecations.rb +12 -12
- data/lib/adhearsion/tasks/generating.rb +2 -2
- data/lib/adhearsion/tasks/testing.rb +7 -7
- data/lib/adhearsion/version.rb +1 -1
- data/lib/adhearsion/voip/asterisk/agi_server.rb +44 -14
- data/lib/adhearsion/voip/asterisk/commands.rb +281 -237
- data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +8 -8
- data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +14 -14
- data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +16 -16
- data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +39 -39
- data/lib/adhearsion/voip/asterisk/config_manager.rb +13 -13
- data/lib/adhearsion/voip/asterisk/manager_interface.rb +91 -87
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +739 -739
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +60 -60
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +16 -16
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +1 -1
- data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +13 -13
- data/lib/adhearsion/voip/asterisk/super_manager.rb +3 -3
- data/lib/adhearsion/voip/call.rb +101 -64
- data/lib/adhearsion/voip/call_routing.rb +9 -9
- data/lib/adhearsion/voip/constants.rb +7 -7
- data/lib/adhearsion/voip/conveniences.rb +1 -1
- data/lib/adhearsion/voip/dial_plan.rb +42 -40
- data/lib/adhearsion/voip/dsl/dialing_dsl.rb +27 -27
- data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +1 -1
- data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +6 -6
- data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +17 -17
- data/lib/adhearsion/voip/dsl/dialplan/parser.rb +7 -7
- data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +2 -2
- data/lib/adhearsion/voip/dsl/numerical_string.rb +3 -3
- data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +7 -7
- data/lib/adhearsion/voip/freeswitch/event_handler.rb +1 -1
- data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +20 -20
- data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +5 -5
- data/lib/adhearsion/voip/freeswitch/oes_server.rb +33 -33
- data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +1 -1
- data/lib/adhearsion/voip/menu_state_machine/matchers.rb +2 -2
- data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +9 -9
- data/lib/theatre.rb +18 -18
- data/lib/theatre/callback_definition_loader.rb +17 -17
- data/lib/theatre/guid.rb +6 -6
- data/lib/theatre/invocation.rb +19 -19
- data/lib/theatre/namespace_manager.rb +28 -28
- metadata +55 -14
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
0.8.4
|
|
2
|
+
- Add configurable argument delimiter for talking to Asterisk. This enables Adhearsion to support Asterisk versions 1.4 (and prior) as well as 1.6 (and later).
|
|
3
|
+
- Fixed using ActiveRecord in Adhearsion components
|
|
4
|
+
- Daemonizing no longer truncates the Adhearsion log file
|
|
5
|
+
- Add support for using ActiveLdap
|
|
6
|
+
- Misc improvements to support Asterisk 1.6 changes
|
|
7
|
+
- Escape commands sent to Asterisk via AGI
|
|
8
|
+
- Manager Events now work when daemonized
|
|
9
|
+
|
|
1
10
|
0.8.3
|
|
2
11
|
- The "uniqueid" call channel variable available in dialplan.rb is now *always* a String
|
|
3
12
|
- Renamed interruptable_play to interruptible_play and made interruptible_play() public instead of protected.
|
|
@@ -10,7 +19,7 @@
|
|
|
10
19
|
- Fixes an inconsequential bug when CTL-C'ing Adhearsion.
|
|
11
20
|
|
|
12
21
|
0.8.1
|
|
13
|
-
- The sandbox component now comes
|
|
22
|
+
- The sandbox component now comes
|
|
14
23
|
- Minor bug fixes
|
|
15
24
|
|
|
16
25
|
0.8.0 rev 2
|
|
@@ -21,4 +30,4 @@ Notes from before 0.8.0:
|
|
|
21
30
|
- Adding a deprecation warning about Fixnum#digit and Fixnum#digits
|
|
22
31
|
- Removed the AMI class and replaced it with the ManagerInterface class.
|
|
23
32
|
- The old AMI high-level instance methods are available in the new ManagerInterface class, but a deprecation warning will be logged each time they're used. When the SuperManager class is implemented, they'll be removed entirely.
|
|
24
|
-
- Moved Theatre into Adhearsion's lib folder.
|
|
33
|
+
- Moved Theatre into Adhearsion's lib folder.
|
data/EVENTS
CHANGED
data/Rakefile
CHANGED
|
@@ -88,13 +88,13 @@ end
|
|
|
88
88
|
|
|
89
89
|
desc "Compares Adhearsion's files with those listed in adhearsion.gemspec"
|
|
90
90
|
task :check_gemspec_files do
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
files_from_gemspec = ADHEARSION_FILES
|
|
93
93
|
files_from_filesystem = Dir.glob(File.dirname(__FILE__) + "/**/*").map do |filename|
|
|
94
94
|
filename[0...Dir.pwd.length] == Dir.pwd ? filename[(Dir.pwd.length+1)..-1] : filename
|
|
95
95
|
end
|
|
96
96
|
files_from_filesystem.reject! { |f| File.directory? f }
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
puts
|
|
99
99
|
puts 'Pipe this command to "grep -v \'spec/\' | grep -v test" to ignore test files'
|
|
100
100
|
puts
|
|
@@ -102,8 +102,8 @@ task :check_gemspec_files do
|
|
|
102
102
|
puts '## Files on filesystem not in the gemspec:'
|
|
103
103
|
puts '##########################################'
|
|
104
104
|
puts((files_from_filesystem - files_from_gemspec).map { |f| " " + f })
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
|
|
106
|
+
|
|
107
107
|
puts '##########################################'
|
|
108
108
|
puts '## Files in gemspec not in the filesystem:'
|
|
109
109
|
puts '##########################################'
|
data/adhearsion.gemspec
CHANGED
|
@@ -51,6 +51,7 @@ ADHEARSION_FILES = %w{
|
|
|
51
51
|
lib/adhearsion/initializer/asterisk.rb
|
|
52
52
|
lib/adhearsion/initializer/configuration.rb
|
|
53
53
|
lib/adhearsion/initializer/database.rb
|
|
54
|
+
lib/adhearsion/initializer/ldap.rb
|
|
54
55
|
lib/adhearsion/initializer/drb.rb
|
|
55
56
|
lib/adhearsion/initializer/freeswitch.rb
|
|
56
57
|
lib/adhearsion/initializer/rails.rb
|
|
@@ -112,18 +113,18 @@ ADHEARSION_FILES = %w{
|
|
|
112
113
|
|
|
113
114
|
Gem::Specification.new do |s|
|
|
114
115
|
s.name = "adhearsion"
|
|
115
|
-
s.version = "0.8.
|
|
116
|
+
s.version = "0.8.4"
|
|
116
117
|
|
|
117
118
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
118
119
|
s.authors = ["Jay Phillips"]
|
|
119
120
|
|
|
120
121
|
s.date = "2008-08-21"
|
|
121
122
|
s.description = "Adhearsion is an open-source telephony development framework"
|
|
122
|
-
s.email = "Jay
|
|
123
|
+
s.email = "Jay&Adhearsion.com"
|
|
123
124
|
s.executables = ["ahn", "ahnctl", "jahn"]
|
|
124
|
-
|
|
125
|
+
|
|
125
126
|
s.files = ADHEARSION_FILES
|
|
126
|
-
|
|
127
|
+
|
|
127
128
|
s.has_rdoc = false
|
|
128
129
|
s.homepage = "http://adhearsion.com"
|
|
129
130
|
s.require_paths = ["lib"]
|
|
@@ -138,12 +139,15 @@ Gem::Specification.new do |s|
|
|
|
138
139
|
if current_version >= 3 then
|
|
139
140
|
s.add_runtime_dependency("rubigen", [">= 1.0.6"])
|
|
140
141
|
s.add_runtime_dependency("log4r", [">= 1.0.5"])
|
|
142
|
+
s.add_runtime_dependency("activesupport", [">= 2.1.0"])
|
|
141
143
|
else
|
|
142
144
|
s.add_dependency("rubigen", [">= 1.0.6"])
|
|
143
145
|
s.add_dependency("log4r", [">= 1.0.5"])
|
|
146
|
+
s.add_dependency("activesupport", [">= 2.1.0"])
|
|
144
147
|
end
|
|
145
148
|
else
|
|
146
149
|
s.add_dependency("rubigen", [">= 1.0.6"])
|
|
147
150
|
s.add_dependency("log4r", [">= 1.0.5"])
|
|
151
|
+
s.add_dependency("activesupport", [">= 2.1.0"])
|
|
148
152
|
end
|
|
149
153
|
end
|
data/app_generators/ahn/USAGE
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
class AhnGenerator < RubiGen::Base
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
|
|
4
4
|
Config::CONFIG['ruby_install_name'])
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
default_options :author => nil
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
attr_reader :name, :component
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
def initialize(runtime_args, runtime_options = {})
|
|
11
11
|
super
|
|
12
12
|
usage if args.empty?
|
|
@@ -23,30 +23,30 @@ class AhnGenerator < RubiGen::Base
|
|
|
23
23
|
BASEDIRS.each { |path| m.directory path }
|
|
24
24
|
|
|
25
25
|
m.file *[".ahnrc"]*2
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
m.file *["components/simon_game/simon_game.rb"]*2
|
|
28
28
|
m.file *["components/ami_remote/ami_remote.rb"]*2
|
|
29
29
|
|
|
30
30
|
m.file *["components/disabled/stomp_gateway/stomp_gateway.rb"]*2
|
|
31
31
|
m.file *["components/disabled/stomp_gateway/stomp_gateway.yml"]*2
|
|
32
32
|
m.file *["components/disabled/stomp_gateway/README.markdown"]*2
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
m.file *["components/disabled/restful_rpc/restful_rpc.rb"]*2
|
|
35
35
|
m.file *["components/disabled/restful_rpc/restful_rpc.yml"]*2
|
|
36
36
|
m.file *["components/disabled/restful_rpc/README.markdown"]*2
|
|
37
37
|
m.file *["components/disabled/restful_rpc/example-client.rb"]*2
|
|
38
38
|
m.file *["components/disabled/restful_rpc/spec/restful_rpc_spec.rb"]*2
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
m.file *["components/disabled/sandbox/sandbox.yml"]*2
|
|
41
41
|
m.file *["components/disabled/sandbox/sandbox.rb"]*2
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
m.file *["config/startup.rb"]*2
|
|
44
44
|
m.file *["dialplan.rb"]*2
|
|
45
45
|
m.file *["events.rb"]*2
|
|
46
46
|
m.file *["README"]*2
|
|
47
47
|
m.file *["Rakefile"]*2
|
|
48
|
-
|
|
49
|
-
# m.dependency "install_rubigen_scripts", [destination_root, 'ahn', 'adhearsion', 'test_spec'],
|
|
48
|
+
|
|
49
|
+
# m.dependency "install_rubigen_scripts", [destination_root, 'ahn', 'adhearsion', 'test_spec'],
|
|
50
50
|
# :shebang => options[:shebang], :collision => :force
|
|
51
51
|
end
|
|
52
52
|
end
|
|
@@ -70,7 +70,7 @@ EOS
|
|
|
70
70
|
# "Default: none") { |options[:author]| }
|
|
71
71
|
opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
|
|
72
72
|
end
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
def extract_options
|
|
75
75
|
# for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
|
|
76
76
|
# Templates can access these value via the attr_reader-generated methods, but not the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
methods_for :rpc do
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
# Simply create proxy methods for the high-level AMI methods
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
[:send_action, :introduce, :originate, :call_into_context, :call_and_exec, :ping].each do |method_name|
|
|
6
6
|
define_method(method_name) do |*args|
|
|
7
7
|
if VoIP::Asterisk.manager_interface
|
|
@@ -11,5 +11,5 @@ methods_for :rpc do
|
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
end
|
|
@@ -5,28 +5,28 @@ require 'json'
|
|
|
5
5
|
# You must have the "rest-client" and "json" gems installed for this file to work.
|
|
6
6
|
|
|
7
7
|
class RESTfulAdhearsion
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
DEFAULT_OPTIONS = {
|
|
10
10
|
# Note: :user and :password are non-existent by default
|
|
11
11
|
:host => "localhost",
|
|
12
12
|
:port => "5000",
|
|
13
13
|
:path_nesting => "/"
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def initialize(options={})
|
|
17
17
|
@options = DEFAULT_OPTIONS.merge options
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
@path_nesting = @options.delete :path_nesting
|
|
20
20
|
@host = @options.delete :host
|
|
21
21
|
@port = @options.delete :port
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
@url_beginning = "http://#{@host}:#{@port}#{@path_nesting}"
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
def method_missing(method_name, *args)
|
|
27
27
|
JSON.parse RestClient::Resource.new(@url_beginning + method_name.to_s, @options).post(args.to_json)
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
Adhearsion = RESTfulAdhearsion.new :host => "localhost", :port => 5000, :user => "jicksta", :password => "roflcopterz"
|
|
@@ -6,9 +6,9 @@ VALID_IP_ADDRESS = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|\*)\.){3}(?:25[0
|
|
|
6
6
|
|
|
7
7
|
def ip_allowed?(ip)
|
|
8
8
|
raise ArgumentError, "#{ip.inspect} is not a valid IP address!" unless ip.kind_of?(String) && ip =~ VALID_IP_ADDRESS
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
octets = ip.split "."
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
case COMPONENTS.restful_rpc["access"]
|
|
13
13
|
when "everyone"
|
|
14
14
|
true
|
|
@@ -37,51 +37,51 @@ end
|
|
|
37
37
|
|
|
38
38
|
RESTFUL_API_HANDLER = lambda do |env|
|
|
39
39
|
json = env["rack.input"].read
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
# Return "Bad Request" HTTP error if the client forgot
|
|
42
42
|
return [400, {}, "You must POST a valid JSON object!"] if json.blank?
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
json = JSON.parse json
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
nesting = COMPONENTS.restful_rpc["path_nesting"]
|
|
47
47
|
path = env["PATH_INFO"]
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
return [404, {}, "This resource does not respond to #{path.inspect}"] unless path[0...nesting.size] == nesting
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
path = path[nesting.size..-1]
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
return [404, {"Content-Type" => "application/json"}, "You cannot nest method names!"] if path.include?("/")
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
rpc_object = Adhearsion::Components.component_manager.extend_object_with(Object.new, :rpc)
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
# TODO: set the content-type and other HTTP headers
|
|
58
58
|
response_object = Array rpc_object.send(path, *json)
|
|
59
59
|
[200, {"Content-Type" => "application/json"}, response_object.to_json]
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
initialization do
|
|
64
64
|
config = COMPONENTS.restful_rpc
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
api = RESTFUL_API_HANDLER
|
|
67
67
|
|
|
68
68
|
port = config["port"] || 5000
|
|
69
69
|
authentication = config["authentication"]
|
|
70
70
|
show_exceptions = config["show_exceptions"]
|
|
71
71
|
handler = Rack::Handler.const_get(config["handler"] || "Mongrel")
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
if authentication
|
|
74
74
|
api = Rack::Auth::Basic.new(api) do |username, password|
|
|
75
75
|
authentication[username] == password
|
|
76
76
|
end
|
|
77
77
|
api.realm = "Adhearsion API"
|
|
78
78
|
end
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
if show_exceptions
|
|
81
81
|
api = Rack::ShowStatus.new(Rack::ShowExceptions.new(api))
|
|
82
82
|
end
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
Thread.new do
|
|
85
|
-
handler.run api, :Port => port
|
|
85
|
+
handler.run api, :Port => port
|
|
86
86
|
end
|
|
87
87
|
end
|
|
@@ -50,61 +50,61 @@ RESTFUL_RPC = ComponentTester.new("restful_rpc", File.dirname(__FILE__) + "/../.
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
describe "The VALID_IP_ADDRESS regular expression" do
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
it "should match only valid IP addresses" do
|
|
55
55
|
valid_ip_addresses = ["192.168.1.98", "10.0.1.200", "255.255.255.0", "123.*.4.*"]
|
|
56
56
|
invalid_ip_addresses = ["10.0.1.1 foo", "bar 255.255.255.0", "0*0*0*0", "1234"]
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
valid_ip_addresses. each { |ip| RESTFUL_RPC::VALID_IP_ADDRESS.should =~ ip }
|
|
59
59
|
invalid_ip_addresses.each { |ip| RESTFUL_RPC::VALID_IP_ADDRESS.should_not =~ ip }
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
describe "The initialization block" do
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
it "should create a new Thread" do
|
|
66
66
|
mock_component_config_with :restful_rpc => {}
|
|
67
67
|
mock(Thread).new { nil }
|
|
68
68
|
RESTFUL_RPC.initialize!
|
|
69
69
|
end
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
it "should run the Rack adapter specified in the configuration" do
|
|
72
72
|
mock(Thread).new.yields
|
|
73
73
|
mock_component_config_with :restful_rpc => {"adapter" => "Mongrel"}
|
|
74
74
|
mock(Rack::Handler::Mongrel).run is_a(Proc), :Port => 5000
|
|
75
75
|
RESTFUL_RPC.initialize!
|
|
76
76
|
end
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
it "should wrap the RESTFUL_API_HANDLER in an Rack::Auth::Basic object if authentication is enabled" do
|
|
79
79
|
mock(Thread).new.yields
|
|
80
80
|
mock_component_config_with :restful_rpc => {"authentication" => {"foo" => "bar"}}
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
proper_authenticator = lambda do |obj|
|
|
83
83
|
request = OpenStruct.new :credentials => ["foo", "bar"]
|
|
84
84
|
obj.is_a?(Rack::Auth::Basic) && obj.send(:valid?, request)
|
|
85
85
|
end
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
mock(Rack::Handler::Mongrel).run(satisfy(&proper_authenticator), :Port => 5000)
|
|
88
88
|
RESTFUL_RPC.initialize!
|
|
89
89
|
end
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
it 'should wrap the RESTFUL_API_HANDLER in ShowStatus and ShowExceptions objects when show_exceptions is enabled' do
|
|
92
92
|
mock(Thread).new.yields
|
|
93
93
|
mock_component_config_with :restful_rpc => {"show_exceptions" => true}
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
mock.proxy(Rack::ShowExceptions).new(is_a(Proc))
|
|
96
96
|
mock.proxy(Rack::ShowStatus).new is_a(Rack::ShowExceptions)
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
mock(Rack::Handler::Mongrel).run is_a(Rack::ShowStatus), :Port => 5000
|
|
99
99
|
RESTFUL_RPC.initialize!
|
|
100
100
|
end
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
describe 'Private helper methods' do
|
|
105
105
|
|
|
106
106
|
describe "the RESTFUL_API_HANDLER lambda" do
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
it "should return a 200 for requests which execute a method that has been defined in the methods_for(:rpc) context" do
|
|
109
109
|
component_manager = Adhearsion::Components::ComponentManager.new('/path/shouldnt/matter')
|
|
110
110
|
|
|
@@ -116,38 +116,38 @@ describe 'Private helper methods' do
|
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
RUBY
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
input = StringIO.new %w[jay phillips].to_json
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
mock_component_config_with :restful_rpc => {"path_nesting" => "/"}
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
env = {"PATH_INFO" => "/testing_123456", "rack.input" => input}
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
response = RESTFUL_RPC::RESTFUL_API_HANDLER.call(env)
|
|
127
127
|
response.should be_kind_of(Array)
|
|
128
128
|
response.should have(3).items
|
|
129
129
|
response.first.should equal(200)
|
|
130
130
|
JSON.parse(response.last).should eql(%w[jay phillips].map(&:reverse).reverse)
|
|
131
131
|
end
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
it "should return a 400 when no data is POSTed" do
|
|
134
134
|
env = {"rack.input" => StringIO.new(""), "REQUEST_URI" => "/foobar"}
|
|
135
135
|
RESTFUL_RPC::RESTFUL_API_HANDLER.call(env).first.should equal(400)
|
|
136
136
|
end
|
|
137
|
-
|
|
137
|
+
|
|
138
138
|
it "should work with a high level test of a successful method invocation" do
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
component_manager = Adhearsion::Components::ComponentManager.new('/path/shouldnt/matter')
|
|
141
141
|
|
|
142
142
|
mock(Adhearsion::Components).component_manager { component_manager }
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
component_manager.load_code '
|
|
145
145
|
methods_for(:rpc) do
|
|
146
146
|
def rofl(one,two)
|
|
147
147
|
"Hai! #{one} #{two}"
|
|
148
148
|
end
|
|
149
149
|
end'
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
env = {
|
|
152
152
|
"CONTENT_LENGTH" => "12",
|
|
153
153
|
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
|
@@ -177,78 +177,78 @@ describe 'Private helper methods' do
|
|
|
177
177
|
"SERVER_PORT" => "5000",
|
|
178
178
|
"SERVER_PROTOCOL" => "HTTP/1.1",
|
|
179
179
|
"SERVER_SOFTWARE" => "WEBrick/1.3.1 (Ruby/1.8.6/2008-03-03)" }
|
|
180
|
-
|
|
180
|
+
|
|
181
181
|
response = RESTFUL_RPC::RESTFUL_API_HANDLER.call(env)
|
|
182
182
|
JSON.parse(response.last).should == ["Hai! o hai!"]
|
|
183
|
-
|
|
183
|
+
|
|
184
184
|
end
|
|
185
|
-
|
|
185
|
+
|
|
186
186
|
it "should contain backtrace information when show_errors is enabled and an exception occurs" do
|
|
187
187
|
mock_component_config_with :restful_api => {"show_errors" => true}
|
|
188
188
|
pending
|
|
189
189
|
end
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
end
|
|
192
|
-
|
|
192
|
+
|
|
193
193
|
describe 'the ip_allowed?() method' do
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
before :each do
|
|
196
196
|
@method = RESTFUL_RPC.helper_method :ip_allowed?
|
|
197
197
|
end
|
|
198
|
-
|
|
198
|
+
|
|
199
199
|
it 'should raise a ConfigurationError if "access" is not one of "everyone", "whitelist" or "blacklist"' do
|
|
200
200
|
good_access_values = %w[everyone whitelist blacklist]
|
|
201
201
|
bad_access_values = %w[foo bar qaz qwerty everone blaclist whitlist]
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
good_access_values.each do |access_value|
|
|
204
204
|
mock_component_config_with :restful_rpc => {"access" => access_value, "whitelist" => [], "blacklist" => []}
|
|
205
205
|
lambda { @method.call("10.0.0.1") }.should_not raise_error
|
|
206
206
|
end
|
|
207
|
-
|
|
207
|
+
|
|
208
208
|
bad_access_values.each do |access_value|
|
|
209
209
|
mock_component_config_with :restful_rpc => {"access" => access_value, "authentication" => false}
|
|
210
210
|
lambda { @method.call("10.0.0.1") }.should raise_error(Adhearsion::Components::ConfigurationError)
|
|
211
211
|
end
|
|
212
212
|
end
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
describe 'whitelists' do
|
|
215
|
-
|
|
215
|
+
|
|
216
216
|
it "should parse *'s as wildcards" do
|
|
217
217
|
mock_component_config_with :restful_rpc => {"access" => "whitelist", "whitelist" => ["10.*.*.*"]}
|
|
218
218
|
@method.call("10.1.2.3").should be_true
|
|
219
219
|
end
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
it "should allow IPs which are explictly specified" do
|
|
222
222
|
mock_component_config_with :restful_rpc => {"access" => "whitelist", "whitelist" => ["4.3.2.1"]}
|
|
223
223
|
@method.call("4.3.2.1").should be_true
|
|
224
224
|
end
|
|
225
|
-
|
|
225
|
+
|
|
226
226
|
it "should not allow IPs which are not explicitly specified" do
|
|
227
227
|
mock_component_config_with :restful_rpc => {"access" => "whitelist", "whitelist" => %w[ 1.2.3.4 4.3.2.1]}
|
|
228
228
|
@method.call("2.2.2.2").should be_false
|
|
229
229
|
end
|
|
230
|
-
|
|
230
|
+
|
|
231
231
|
end
|
|
232
|
-
|
|
232
|
+
|
|
233
233
|
describe 'blacklists' do
|
|
234
|
-
|
|
234
|
+
|
|
235
235
|
it "should parse *'s as wildcards" do
|
|
236
236
|
mock_component_config_with :restful_rpc => {"access" => "blacklist", "blacklist" => ["10.*.*.*"]}
|
|
237
237
|
@method.call("10.1.2.3").should be_false
|
|
238
238
|
end
|
|
239
|
-
|
|
239
|
+
|
|
240
240
|
it "should not allow IPs which are explicitly specified" do
|
|
241
241
|
mock_component_config_with :restful_rpc => {"access" => "blacklist", "blacklist" => ["9.8.7.6", "9.8.7.5"]}
|
|
242
242
|
@method.call("9.8.7.5").should be_false
|
|
243
243
|
end
|
|
244
|
-
|
|
244
|
+
|
|
245
245
|
it "should allow IPs which are not explicitly specified" do
|
|
246
246
|
mock_component_config_with :restful_rpc => {"access" => "blacklist", "blacklist" => ["10.20.30.40"]}
|
|
247
247
|
@method.call("1.1.1.1").should be_true
|
|
248
248
|
end
|
|
249
|
-
|
|
249
|
+
|
|
250
250
|
end
|
|
251
|
-
|
|
251
|
+
|
|
252
252
|
describe '"everyone" access' do
|
|
253
253
|
it "should return true for any IP given, irrespective of the configuration" do
|
|
254
254
|
ip_addresses = %w[100.200.100.200 0.0.0.0 *.0.0.*]
|
|
@@ -257,7 +257,7 @@ describe 'Private helper methods' do
|
|
|
257
257
|
end
|
|
258
258
|
end
|
|
259
259
|
end
|
|
260
|
-
|
|
260
|
+
|
|
261
261
|
end
|
|
262
262
|
|
|
263
263
|
end
|