moonrope 1.4.1 → 2.0.0

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +9 -0
  3. data/Gemfile.lock +47 -0
  4. data/MIT-LICENCE +20 -0
  5. data/README.md +24 -0
  6. data/bin/moonrope +28 -0
  7. data/docs/authentication.md +114 -0
  8. data/docs/controllers.md +106 -0
  9. data/docs/exceptions.md +27 -0
  10. data/docs/introduction.md +29 -0
  11. data/docs/structures.md +214 -0
  12. data/example/authentication.rb +50 -0
  13. data/example/controllers/meta_controller.rb +14 -0
  14. data/example/controllers/users_controller.rb +92 -0
  15. data/example/structures/pet_structure.rb +12 -0
  16. data/example/structures/user_structure.rb +35 -0
  17. data/html/assets/lock.svg +3 -0
  18. data/html/assets/reset.css +101 -0
  19. data/html/assets/style.css +348 -0
  20. data/html/assets/tool.svg +4 -0
  21. data/html/assets/try.js +151 -0
  22. data/html/authenticators/default.html +191 -0
  23. data/html/controllers/meta/version.html +144 -0
  24. data/html/controllers/meta.html +73 -0
  25. data/html/controllers/users/create.html +341 -0
  26. data/html/controllers/users/list.html +348 -0
  27. data/html/controllers/users/show.html +261 -0
  28. data/html/controllers/users/update.html +387 -0
  29. data/html/controllers/users.html +93 -0
  30. data/html/index.html +166 -0
  31. data/html/moonrope.txt +0 -0
  32. data/html/structures/pet.html +176 -0
  33. data/html/structures/user.html +338 -0
  34. data/lib/moonrope/action.rb +165 -37
  35. data/lib/moonrope/authenticator.rb +39 -0
  36. data/lib/moonrope/base.rb +24 -6
  37. data/lib/moonrope/controller.rb +4 -2
  38. data/lib/moonrope/doc_context.rb +94 -0
  39. data/lib/moonrope/doc_server.rb +123 -0
  40. data/lib/moonrope/dsl/action_dsl.rb +159 -9
  41. data/lib/moonrope/dsl/authenticator_dsl.rb +31 -0
  42. data/lib/moonrope/dsl/base_dsl.rb +21 -18
  43. data/lib/moonrope/dsl/controller_dsl.rb +60 -9
  44. data/lib/moonrope/dsl/filterable_dsl.rb +27 -0
  45. data/lib/moonrope/dsl/structure_dsl.rb +27 -2
  46. data/lib/moonrope/errors.rb +3 -0
  47. data/lib/moonrope/eval_environment.rb +82 -3
  48. data/lib/moonrope/eval_helpers/filter_helper.rb +82 -0
  49. data/lib/moonrope/eval_helpers.rb +28 -5
  50. data/lib/moonrope/guard.rb +35 -0
  51. data/lib/moonrope/html_generator.rb +65 -0
  52. data/lib/moonrope/param_set.rb +11 -1
  53. data/lib/moonrope/rack_middleware.rb +1 -1
  54. data/lib/moonrope/railtie.rb +31 -14
  55. data/lib/moonrope/request.rb +25 -14
  56. data/lib/moonrope/structure.rb +74 -11
  57. data/lib/moonrope/structure_attribute.rb +15 -0
  58. data/lib/moonrope/version.rb +1 -1
  59. data/lib/moonrope.rb +5 -4
  60. data/moonrope.gemspec +21 -0
  61. data/spec/spec_helper.rb +32 -0
  62. data/spec/specs/action_spec.rb +455 -0
  63. data/spec/specs/base_spec.rb +29 -0
  64. data/spec/specs/controller_spec.rb +31 -0
  65. data/spec/specs/param_set_spec.rb +31 -0
  66. data/templates/basic/_action_form.erb +77 -0
  67. data/templates/basic/_errors_table.erb +32 -0
  68. data/templates/basic/_structure_attributes_list.erb +55 -0
  69. data/templates/basic/action.erb +168 -0
  70. data/templates/basic/assets/lock.svg +3 -0
  71. data/templates/basic/assets/reset.css +101 -0
  72. data/templates/basic/assets/style.css +348 -0
  73. data/templates/basic/assets/tool.svg +4 -0
  74. data/templates/basic/assets/try.js +151 -0
  75. data/templates/basic/authenticator.erb +51 -0
  76. data/templates/basic/controller.erb +20 -0
  77. data/templates/basic/index.erb +114 -0
  78. data/templates/basic/layout.erb +46 -0
  79. data/templates/basic/structure.erb +23 -0
  80. data/test/test_helper.rb +81 -0
  81. data/test/tests/action_access_test.rb +63 -0
  82. data/test/tests/actions_test.rb +524 -0
  83. data/test/tests/authenticators_test.rb +87 -0
  84. data/test/tests/base_test.rb +35 -0
  85. data/test/tests/controllers_test.rb +49 -0
  86. data/test/tests/eval_environment_test.rb +136 -0
  87. data/test/tests/evel_helpers_test.rb +60 -0
  88. data/test/tests/examples_test.rb +11 -0
  89. data/test/tests/helpers_test.rb +97 -0
  90. data/test/tests/param_set_test.rb +44 -0
  91. data/test/tests/rack_middleware_test.rb +109 -0
  92. data/test/tests/request_test.rb +232 -0
  93. data/test/tests/structures_param_extensions_test.rb +159 -0
  94. data/test/tests/structures_test.rb +335 -0
  95. metadata +82 -48
@@ -0,0 +1,136 @@
1
+ class EvalEnvironmentTest < Test::Unit::TestCase
2
+
3
+ def setup
4
+ @auth_user = User.new(:name => 'Admin User')
5
+ @request = FakeRequest.new(:params => {'page' => '1'}, :version => 2, :identity => @auth_user)
6
+ @environment = Moonrope::EvalEnvironment.new(Moonrope::Base.new, @request, nil, :accessor1 => 'Hello')
7
+ end
8
+
9
+ def test_version
10
+ assert_equal 2, @environment.version
11
+ end
12
+
13
+ def test_params
14
+ assert @environment.params.is_a?(Moonrope::ParamSet)
15
+ assert_equal '1', @environment.params.page
16
+ end
17
+
18
+ def test_accessors
19
+ assert_equal 'Hello', @environment.accessor1
20
+ end
21
+
22
+ def test_identity_access
23
+ assert_equal @auth_user, @environment.identity
24
+ end
25
+
26
+ def test_setting_headers
27
+ @environment.set_header 'Header1', 'A'
28
+ assert_equal 'A', @environment.headers['Header1']
29
+ @environment.set_header 'Header2', 'B'
30
+ assert_equal 'B', @environment.headers['Header2']
31
+ end
32
+
33
+ def test_setting_flags
34
+ @environment.set_flag 'Flag1', 'A'
35
+ assert_equal 'A', @environment.flags['Flag1']
36
+ @environment.set_flag 'Flag2', 'B'
37
+ assert_equal 'B', @environment.flags['Flag2']
38
+ end
39
+
40
+ def test_structure_access
41
+ user_structure = Moonrope::Structure.new(@environment.base, :user) do
42
+ basic { {:id => o.id} }
43
+ end
44
+ structure = @environment.structure(user_structure, User.new)
45
+ assert structure.is_a?(Hash), "structure was not a Hash, was a #{structure.class}"
46
+ end
47
+
48
+ def test_structure_access_with_auto_determination
49
+ user_structure = @environment.base.dsl.structure(:user) do
50
+ basic { {:id => o.id} }
51
+ end
52
+ structure = @environment.structure(UserWithUnderscore.new)
53
+ assert structure.is_a?(Hash), "structure was not a Hash, was a #{structure.class}"
54
+ end
55
+
56
+ def test_structure_for
57
+ user_structure = @environment.base.dsl.structure(:user) do
58
+ basic { {:id => o.id} }
59
+ end
60
+ structure = @environment.structure_for(:user)
61
+ assert_equal structure, user_structure
62
+ end
63
+
64
+ def test_has_structure_for
65
+ user_structure = @environment.base.dsl.structure(:user) do
66
+ basic { {:id => o.id} }
67
+ end
68
+ assert_equal false, @environment.has_structure_for?(:blah)
69
+ assert_equal true, @environment.has_structure_for?(:user)
70
+ end
71
+
72
+ def test_copy_attributes_from_param_set_to_an_object
73
+ base = Moonrope::Base.new
74
+ controller = Moonrope::Controller.new(base, :users) do
75
+ action :save do
76
+ param :username do |object, value|
77
+ object.username = "#{value}!"
78
+ end
79
+ param :id
80
+ end
81
+ end
82
+
83
+ request = FakeRequest.new(:params => {'id' => 123, 'username' => 'adam'})
84
+ env = Moonrope::EvalEnvironment.new(base, request, controller/:save)
85
+ user = User.new
86
+ env.copy_params_to user, :username, :id
87
+ assert_equal user.id, 123
88
+ assert_equal user.username, "adam!"
89
+ end
90
+
91
+ def test_copy_attributes_from_share
92
+ base = Moonrope::Base.new
93
+ controller = Moonrope::Controller.new(base, :users) do
94
+ shared_action :crud do
95
+ param :username
96
+ param :id
97
+ end
98
+ action :save do
99
+ use :crud
100
+ end
101
+ end
102
+
103
+ request = FakeRequest.new(:params => {'id' => 123, 'username' => 'adam'})
104
+ env = Moonrope::EvalEnvironment.new(base, request, controller/:save)
105
+ user = User.new
106
+ env.copy_params_to user, :from => :crud
107
+ assert_equal user.id, 123
108
+ assert_equal user.username, "adam"
109
+ end
110
+
111
+ def test_copy_attribute_from_shared_action_within_shared_action
112
+ base = Moonrope::Base.new
113
+ controller = Moonrope::Controller.new(base, :users) do
114
+ shared_action :private_code do
115
+ param :private_code
116
+ end
117
+ shared_action :crud do
118
+ param :username
119
+ param :id
120
+ use :private_code
121
+ end
122
+ action :save do
123
+ use :crud
124
+ end
125
+ end
126
+
127
+ request = FakeRequest.new(:params => {'id' => 123, 'username' => 'adam', 'private_code' => 'llama'})
128
+ env = Moonrope::EvalEnvironment.new(base, request, controller/:save)
129
+ user = User.new
130
+ env.copy_params_to user, :from => :crud
131
+ assert_equal user.username, "adam"
132
+ assert_equal user.private_code, "llama"
133
+ end
134
+
135
+ end
136
+
@@ -0,0 +1,60 @@
1
+ class EvalHelpersTest < Test::Unit::TestCase
2
+
3
+ def setup
4
+ @environment = Moonrope::EvalEnvironment.new(Moonrope::Base.new, FakeRequest.new(:params => {'page' => 1}))
5
+ @environment.reset
6
+ end
7
+
8
+ def test_errors
9
+ assert_raises Moonrope::Errors::NotFound do
10
+ @environment.error(:not_found, "Page not found")
11
+ end
12
+
13
+ assert_raises Moonrope::Errors::AccessDenied do
14
+ @environment.error(:access_denied, "User not authenticated")
15
+ end
16
+
17
+ assert_raises Moonrope::Errors::ValidationError do
18
+ @environment.error(:validation_error, [{:field => 'user', :message => 'should not be blank'}])
19
+ end
20
+
21
+ assert_raises Moonrope::Errors::ParameterError do
22
+ @environment.error(:parameter_error, [{:field => 'page', :message => 'should be present'}])
23
+ end
24
+
25
+ assert_raises Moonrope::Errors::RequestError do
26
+ @environment.error(:misc_error, "Unknown issue")
27
+ end
28
+ end
29
+
30
+ def test_paginate
31
+ items = PaginationCollection.new
32
+ result = @environment.paginate(items) { |r| r }
33
+ assert result.is_a?(Array)
34
+ assert @environment.flags[:paginated].is_a?(Hash)
35
+ end
36
+
37
+ class PaginationCollection
38
+ def to_a
39
+ [1,2,3,4,5,6]
40
+ end
41
+
42
+ def page(page)
43
+ self
44
+ end
45
+
46
+ def per(max_per_page)
47
+ self
48
+ end
49
+
50
+ def total_pages
51
+ 2
52
+ end
53
+
54
+ def total_count
55
+ 34
56
+ end
57
+ end
58
+
59
+
60
+ end
@@ -0,0 +1,11 @@
1
+ class ExamplesTest < Test::Unit::TestCase
2
+
3
+ def setup
4
+ @base = Moonrope::Base.load(File.expand_path('../../../example', __FILE__))
5
+ end
6
+
7
+ def test_examples_are_valid
8
+ assert_equal 2, @base.controllers.size
9
+ end
10
+
11
+ end
@@ -0,0 +1,97 @@
1
+ class HelpersTest < Test::Unit::TestCase
2
+
3
+ def test_helper_definitions_and_selection
4
+ base = Moonrope::Base.new do
5
+ # A global helper
6
+ helper :say_hello do |name|
7
+ "Hello #{name}!"
8
+ end
9
+
10
+ # A controller specific helper
11
+ controller :users do
12
+ helper :user_helper do |name|
13
+ "Your name is #{name}!"
14
+ end
15
+
16
+ action :action1 do
17
+ action do
18
+ say_hello('David')
19
+ end
20
+ end
21
+
22
+ action :action2 do
23
+ action do
24
+ user_helper('Michael')
25
+ end
26
+ end
27
+
28
+ action :action3 do
29
+ action do
30
+ animal_helper('Bob')
31
+ end
32
+ end
33
+ end
34
+
35
+ # Another controller
36
+ controller :animals do
37
+ helper :animal_helper do |name|
38
+ "Animal name is #{name}"
39
+ end
40
+ end
41
+ end
42
+
43
+ assert_equal 3, base.helpers.size
44
+ assert_equal Moonrope::Helper, base.helper(:say_hello).class
45
+
46
+ # see if the controller-scoped helper is only available to the cobntroller
47
+ assert_equal nil, base.helper(:user_helper)
48
+ assert_equal nil, base.helper(:user_helper, base / :animals)
49
+ assert_equal Moonrope::Helper, base.helper(:user_helper, base/:users).class
50
+
51
+ # see if running the actuions will allow usage of helpers
52
+ result = (base/:users/:action1).execute
53
+ assert_equal "Hello David!", result.data
54
+
55
+ result = (base/:users/:action2).execute
56
+ assert_equal "Your name is Michael!", result.data
57
+
58
+ assert_raises(NoMethodError) { (base/:users/:action3).execute }
59
+ end
60
+
61
+ def test_unloadable_helpers
62
+ base = Moonrope::Base.new
63
+ base.dsl.instance_eval do
64
+ helper :unloadable_helper, :unloadable => false do
65
+ 666
66
+ end
67
+
68
+ helper :normal_helper do
69
+ 111
70
+ end
71
+ end
72
+ # initially they'll both exist
73
+ assert_equal Moonrope::Helper, base.helper(:unloadable_helper).class
74
+ assert_equal Moonrope::Helper, base.helper(:normal_helper).class
75
+ # unload the base
76
+ base.unload
77
+ # now only the unloadable helper remains
78
+ assert_equal Moonrope::Helper, base.helper(:unloadable_helper).class
79
+ assert_equal nil, base.helper(:normal_helper)
80
+ end
81
+
82
+ def test_ensure_helpers_cant_be_double_loaded
83
+ base = Moonrope::Base.new do
84
+ helper :my_helper do
85
+ 123
86
+ end
87
+ end
88
+
89
+ assert_raises Moonrope::Errors::HelperAlreadyDefined do
90
+ base.dsl.instance_eval do
91
+ helper :my_helper do
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,44 @@
1
+ require 'ostruct'
2
+
3
+ class ParamSetTest < Test::Unit::TestCase
4
+
5
+ def test_param_set
6
+ set = Moonrope::ParamSet.new('fruit' => 'Banana')
7
+ # Test that values which aren't included are nil
8
+ assert_equal nil, set.vegetable
9
+ assert_equal nil, set[:vegetable]
10
+ # Test values can be accessed if they are provided
11
+ assert_equal 'Banana', set.fruit
12
+ assert_equal 'Banana', set[:fruit]
13
+ assert_equal 'Banana', set['fruit']
14
+ end
15
+
16
+ def test_default_params
17
+ set = Moonrope::ParamSet.new('fruit' => 'Banana')
18
+ set._defaults = {'vegetable' => 'Tomato', 'fruit' => 'Apple'}
19
+ # Check that the default is provided
20
+ assert_equal 'Tomato', set.vegetable
21
+ # Check that the fruit default isn't used.
22
+ assert_equal 'Banana', set.fruit
23
+ end
24
+
25
+ def test_nilification
26
+ set = Moonrope::ParamSet.new('fruit' => '')
27
+ assert_equal nil, set.fruit
28
+ assert_equal nil, set[:fruit]
29
+ assert_equal nil, set['fruit']
30
+ end
31
+
32
+ def test_key_presence
33
+ set = Moonrope::ParamSet.new('fruit' => 'Apple')
34
+ set._defaults = {'meat' => 'Beef'}
35
+ assert_equal true, set.has?(:fruit)
36
+ assert_equal true, set.has?(:meat)
37
+ assert_equal false, set.has?(:vegetable)
38
+ end
39
+
40
+ class ParamSetCopyTestThing
41
+ attr_accessor :fruit, :vegetable
42
+ end
43
+
44
+ end
@@ -0,0 +1,109 @@
1
+ class RackMiddlewareTest < Test::Unit::TestCase
2
+
3
+ include Rack::Test::Methods
4
+
5
+ def app
6
+ @app ||= begin
7
+ base = Moonrope::Base.new do
8
+ authenticator :default do
9
+ error "Denied", "No suitable credentials were provided."
10
+ lookup do
11
+ # if there is a x-moonrope-username header, check the auth
12
+ # or raise access denied.
13
+ if request.headers['X-Moonrope-Username']
14
+ if request.headers['X-Moonrope-Username'] == 'user' && request.headers['X-Moonrope-Password'] == 'password'
15
+ User.new(:admin => true)
16
+ else
17
+ error "Denied"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ controller :users do
23
+ action :list do
24
+ # return an empty array
25
+ action { [] }
26
+ end
27
+
28
+ action :echo do
29
+ param :name, :required => true
30
+ action { params.name }
31
+ end
32
+ end
33
+ end
34
+ Moonrope::RackMiddleware.new(nil, base)
35
+ end
36
+ end
37
+
38
+ def test_non_api_requests_404
39
+ get "/"
40
+ assert_equal 404, last_response.status
41
+ end
42
+
43
+ def test_api_request_validation
44
+ get "/api/"
45
+ assert_equal 400, last_response.status
46
+ get "/api/v1"
47
+ assert_equal 400, last_response.status
48
+ get "/api/v1/controller"
49
+ assert_equal 400, last_response.status
50
+ end
51
+
52
+ def test_api_methods
53
+ params = {:page => 1}.to_json
54
+ get "/api/v1/users/list", {:params => params}
55
+ assert_equal 200, last_response.status
56
+ assert response_json = JSON.parse(last_response.body)
57
+ assert_equal 'success', response_json['status']
58
+ assert response_json['data'].is_a?(Array)
59
+ assert_equal 'application/json', last_response.headers['Content-Type']
60
+ assert last_response.headers['Content-Length']
61
+ end
62
+
63
+ def test_params_in_body
64
+ post "/api/v1/users/echo", '{"name":"Adam"}', {'CONTENT_TYPE' => 'application/json'}
65
+ assert_equal 200, last_response.status
66
+ assert response_json = JSON.parse(last_response.body)
67
+ assert_equal 'success', response_json['status']
68
+ assert_equal 'Adam', response_json['data']
69
+ end
70
+
71
+ def test_passing_invalid_json_renders_a_bad_request
72
+ get "/api/v1/users/list", {:params => "{invalidjson}"}
73
+ assert_equal 400, last_response.status
74
+ assert response_json = JSON.parse(last_response.body)
75
+ assert_equal 'invalid-json', response_json['status']
76
+ end
77
+
78
+ def test_authenticated_api_methods
79
+ # correct credential
80
+ get "/api/v1/users/list", {}, auth_headers('user', 'password')
81
+ assert response_json = JSON.parse(last_response.body)
82
+ assert_equal 'success', response_json['status']
83
+ # invalid password
84
+ get "/api/v1/users/list", {}, auth_headers('user-invalid', 'password-invalid')
85
+ assert response_json = JSON.parse(last_response.body)
86
+ assert_equal 'error', response_json['status']
87
+ assert_equal 'Denied', response_json['data']['code']
88
+ end
89
+
90
+ def test_request_callback_is_invoked
91
+ request_count = 0
92
+ app.base.on_request = Proc.new do |base, env|
93
+ request_count += 1
94
+ end
95
+ assert_equal 0, request_count
96
+ get "/api/v1/users/list"
97
+ assert_equal 1, request_count
98
+ get "/api/v1/users/list"
99
+ assert_equal 2, request_count
100
+ end
101
+
102
+
103
+ private
104
+
105
+ def auth_headers(username, password)
106
+ {'HTTP_X_MOONROPE_USERNAME' => username, 'HTTP_X_MOONROPE_PASSWORD' => password}
107
+ end
108
+
109
+ end
@@ -0,0 +1,232 @@
1
+ class RequestTest < Test::Unit::TestCase
2
+
3
+
4
+ def test_validation
5
+ # Create a simple API server with just the users & list controller
6
+ base = Moonrope::Base.new do
7
+ controller :users do
8
+ action :list
9
+ end
10
+ end
11
+
12
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
13
+ assert_equal true, request.valid?
14
+ request = base.request(make_rack_env_hash('/api/v1/missing/unknown'))
15
+ assert_equal false, request.valid?
16
+
17
+ request = base.request(make_rack_env_hash('/api/v1'))
18
+ assert_equal false, request.valid?
19
+ request = base.request(make_rack_env_hash('/api/v1/users'))
20
+ assert_equal false, request.valid?
21
+ end
22
+
23
+ def test_version
24
+ base = Moonrope::Base.new
25
+ request = base.request(make_rack_env_hash('/api/v0/users/list'))
26
+ assert_equal 1, request.version
27
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
28
+ assert_equal 1, request.version
29
+ request = base.request(make_rack_env_hash('/api/v2/users/list'))
30
+ assert_equal 2, request.version
31
+ request = base.request(make_rack_env_hash('/api/v100/users/list'))
32
+ assert_equal 100, request.version
33
+ end
34
+
35
+ def test_controllers_and_actions
36
+ base = Moonrope::Base.new do
37
+ controller :users do
38
+ action :list
39
+ end
40
+ end
41
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
42
+ assert request.controller.is_a?(Moonrope::Controller)
43
+ assert_equal :users, request.controller.name
44
+ assert request.action.is_a?(Moonrope::Action)
45
+ assert_equal :list, request.action.name
46
+ end
47
+
48
+ def test_params_are_accessible
49
+ env = make_rack_env_hash('/api/v1/users/list', {'params' => {'page' => 1}})
50
+ request = Moonrope::Base.new.request(env)
51
+ assert request.params.is_a?(Moonrope::ParamSet)
52
+ assert_equal '1', request.params.page
53
+ end
54
+
55
+ def test_actions_can_be_executed
56
+ base = Moonrope::Base.new do
57
+ controller :users do
58
+ action :list do
59
+ action { true }
60
+ end
61
+ end
62
+ end
63
+
64
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
65
+ assert result = request.execute
66
+ assert result.is_a?(Moonrope::ActionResult), "request.action does not return an ActionResult, was a #{result.class}"
67
+ end
68
+
69
+ def test_headers_are_accessible
70
+ base = Moonrope::Base.new
71
+ env = make_rack_env_hash('/api/v1/users/list', {}, {'HTTP_X_EXAMPLE_HEADER' => 'Hello'})
72
+ request = base.request(env)
73
+ assert_equal 'Hello', request.headers['X-Example-Header']
74
+ end
75
+
76
+ def test_ip_is_accessible
77
+ base = Moonrope::Base.new
78
+ env = make_rack_env_hash('/api/v1/users/list')
79
+ request = base.request(env)
80
+ assert_equal '127.0.0.1', request.ip
81
+ end
82
+
83
+ def test_authenticated_requests
84
+ base = Moonrope::Base.new do
85
+ authenticator :default do
86
+ lookup do
87
+ User.new(:admin => true)
88
+ end
89
+ end
90
+ controller :users do
91
+ action :list do
92
+ action { true }
93
+ end
94
+ end
95
+ end
96
+ # authenticated
97
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
98
+ assert result = request.execute
99
+ assert_equal User, request.identity.class
100
+ assert_equal false, request.anonymous?
101
+ assert_equal true, request.authenticated?
102
+ end
103
+
104
+ def test_authentication_failures
105
+ base = Moonrope::Base.new do
106
+ authenticator :default do
107
+ lookup do
108
+ error :access_denied, "Not permitted"
109
+ end
110
+ end
111
+
112
+ controller :users do
113
+ action :list do
114
+ action { true}
115
+ end
116
+ end
117
+ end
118
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
119
+ assert result = request.execute
120
+ assert_equal "access-denied", result.status
121
+ assert_equal nil, request.identity
122
+ assert_equal true, request.anonymous?
123
+ assert_equal false, request.authenticated?
124
+ end
125
+
126
+ def test_requests_which_authenticator_says_are_anonymous
127
+ base = Moonrope::Base.new do
128
+ authenticator :default do
129
+ lookup { nil }
130
+ end
131
+ controller :users do
132
+ action :list do
133
+ action { true }
134
+ end
135
+ end
136
+ end
137
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
138
+ assert result = request.execute
139
+ assert_equal "success", result.status
140
+ assert_equal nil, request.identity
141
+ assert_equal true, request.anonymous?
142
+ assert_equal false, request.authenticated?
143
+ end
144
+
145
+ def test_trying_to_use_invalid_authenticator_raises_error
146
+ base = Moonrope::Base.new do
147
+ authenticator :default do
148
+ lookup do
149
+ User.new(:admin => true)
150
+ end
151
+ end
152
+ controller :users do
153
+ action :list do
154
+ authenticator :blah
155
+ action { true }
156
+ end
157
+ end
158
+ end
159
+
160
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
161
+ assert_raises Moonrope::Errors::MissingAuthenticator do
162
+ request.execute
163
+ end
164
+ end
165
+
166
+ def test_raising_errors_from_the_authenticator_lookup
167
+ base = Moonrope::Base.new do
168
+ authenticator :default do
169
+ error 'InvalidToken', 'Token provided is invalid', :attributes => {:token => 'The token looked up'}
170
+ lookup do
171
+ error 'InvalidToken', :token => request.headers['X-Example-Header']
172
+ end
173
+ end
174
+ controller :users do
175
+ action :list do
176
+ action { true }
177
+ end
178
+ end
179
+ end
180
+ request = base.request(make_rack_env_hash('/api/v1/users/list', {}, {"HTTP_X_EXAMPLE_HEADER" => "1234567"}))
181
+ assert result = request.execute
182
+ assert_equal "error", result.status
183
+ assert_equal "InvalidToken", result.data[:code]
184
+ assert_equal "1234567", result.data[:token]
185
+ assert_equal "Token provided is invalid", result.data[:message]
186
+ end
187
+
188
+ def test_appropriate_error_is_returned_from_access_checks
189
+ base = Moonrope::Base.new do
190
+ authenticator :default do
191
+ lookup { :admin }
192
+ rule :default, "CustomError", "Must be authenticated as admin user" do
193
+ identity == :anonymous
194
+ end
195
+ end
196
+ controller :users do
197
+ action :list do
198
+ action { true }
199
+ end
200
+ end
201
+ end
202
+ request = base.request(make_rack_env_hash('/api/v1/users/list', {}, {"HTTP_X_EXAMPLE_HEADER" => "1234567"}))
203
+ assert result = request.execute
204
+ assert_equal "error", result.status
205
+ assert_equal "CustomError", result.data[:code]
206
+ assert_equal "Must be authenticated as admin user", result.data[:message]
207
+ end
208
+
209
+ def test_appropriate_error_can_be_returned_from_authenticator_error_hash
210
+ base = Moonrope::Base.new do
211
+ authenticator :default do
212
+ lookup { :admin }
213
+ error "CustomError", "Some custom error message override"
214
+ rule :default, "CustomError", "Must be authenticated as admin user" do
215
+ identity == :anonymous
216
+ end
217
+ end
218
+ controller :users do
219
+ action :list do
220
+ action { true }
221
+ end
222
+ end
223
+ end
224
+ request = base.request(make_rack_env_hash('/api/v1/users/list', {}, {"HTTP_X_EXAMPLE_HEADER" => "1234567"}))
225
+ assert result = request.execute
226
+ assert_equal "error", result.status
227
+ assert_equal "CustomError", result.data[:code]
228
+ assert_equal "Some custom error message override", result.data[:message]
229
+ end
230
+
231
+
232
+ end