moonrope 1.4.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,338 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>User Structure - API Documentation</title>
5
+ <link href='https://fonts.googleapis.com/css?family=Lato:400,700,900' rel='stylesheet' type='text/css'>
6
+ <link href='https://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>
7
+ <link rel="stylesheet" href="../assets/reset.css">
8
+ <link rel="stylesheet" href="../assets/style.css">
9
+ </head>
10
+ <body>
11
+ <section class='sidebarBackground'></section>
12
+ <section class="sidebar">
13
+ <nav>
14
+ <ul>
15
+ <li>
16
+ <a href='../index.html' class="">
17
+ Home
18
+ </a>
19
+ </li>
20
+
21
+ <li>
22
+ <a href='../authenticators/default.html' class="">
23
+ Authentication
24
+ </a>
25
+ </li>
26
+
27
+
28
+ <li>
29
+ <a href='../controllers/meta.html' class="">
30
+ Meta API
31
+ </a>
32
+ </li>
33
+
34
+ <li>
35
+ <a href='../controllers/users.html' class="">
36
+ Users API
37
+ </a>
38
+ </li>
39
+
40
+ </ul>
41
+ </nav>
42
+ </section>
43
+ <section class='content'>
44
+
45
+
46
+ <h1>User Structure</h1>
47
+
48
+ <h2>Base Attributes</h2>
49
+ <table class='table paramTable'>
50
+ <thead>
51
+ <tr>
52
+ <th width="45%">Attribute</th>
53
+ <th width="20%">Type</th>
54
+ <th width="35%">Example</th>
55
+ </tr>
56
+ </thead>
57
+
58
+ <tr>
59
+ <td>
60
+ <p>
61
+ <span class='paramTable__name'>id</span>
62
+ </p>
63
+
64
+ <p class='paramTable__description'>The user's internal system ID</p>
65
+
66
+
67
+
68
+
69
+ </td>
70
+ <td>Integer</td>
71
+ <td>
72
+
73
+ 123
74
+
75
+ </td>
76
+ </tr>
77
+
78
+ <tr>
79
+ <td>
80
+ <p>
81
+ <span class='paramTable__name'>username</span>
82
+ </p>
83
+
84
+ <p class='paramTable__description'>The user's unique username</p>
85
+
86
+
87
+
88
+
89
+ </td>
90
+ <td>String</td>
91
+ <td>
92
+
93
+ adamcooke
94
+
95
+ </td>
96
+ </tr>
97
+
98
+ <tr>
99
+ <td>
100
+ <p>
101
+ <span class='paramTable__name'>name.first</span>
102
+ </p>
103
+
104
+ <p class='paramTable__description'>The user's first name</p>
105
+
106
+
107
+
108
+
109
+ </td>
110
+ <td>String</td>
111
+ <td>
112
+
113
+ Adam
114
+
115
+ </td>
116
+ </tr>
117
+
118
+ <tr>
119
+ <td>
120
+ <p>
121
+ <span class='paramTable__name'>name.last</span>
122
+ </p>
123
+
124
+ <p class='paramTable__description'>The user's last name</p>
125
+
126
+
127
+
128
+
129
+ </td>
130
+ <td>String</td>
131
+ <td>
132
+
133
+ Cooke
134
+
135
+ </td>
136
+ </tr>
137
+
138
+
139
+
140
+ </table>
141
+
142
+
143
+
144
+
145
+ <h2>Extended Attributes</h2>
146
+ <table class='table paramTable'>
147
+ <thead>
148
+ <tr>
149
+ <th width="45%">Attribute</th>
150
+ <th width="20%">Type</th>
151
+ <th width="35%">Example</th>
152
+ </tr>
153
+ </thead>
154
+
155
+ <tr>
156
+ <td>
157
+ <p>
158
+ <span class='paramTable__name'>admin</span>
159
+ </p>
160
+
161
+ <p class='paramTable__description'>Is this user an administrator?</p>
162
+
163
+
164
+
165
+
166
+ </td>
167
+ <td>Boolean</td>
168
+ <td>
169
+
170
+ false
171
+
172
+ </td>
173
+ </tr>
174
+
175
+ <tr>
176
+ <td>
177
+ <p>
178
+ <span class='paramTable__name'>created_at</span>
179
+ </p>
180
+
181
+ <p class='paramTable__description'>The timestamp the user was created</p>
182
+
183
+
184
+
185
+
186
+ </td>
187
+ <td>Timestamp</td>
188
+ <td>
189
+
190
+ 2016-12-25 09:42:00 +0000
191
+
192
+ </td>
193
+ </tr>
194
+
195
+ <tr>
196
+ <td>
197
+ <p>
198
+ <span class='paramTable__name'>updated_at</span>
199
+ </p>
200
+
201
+ <p class='paramTable__description'>The timestamp the user was updated</p>
202
+
203
+
204
+
205
+
206
+ </td>
207
+ <td>Timestamp</td>
208
+ <td>
209
+
210
+ 2016-12-25 09:42:00 +0000
211
+
212
+ </td>
213
+ </tr>
214
+
215
+ <tr>
216
+ <td>
217
+ <p>
218
+ <span class='paramTable__name'>support_pin</span>
219
+ </p>
220
+
221
+ <p class='paramTable__description'>The PIN this user needs to use to access support</p>
222
+
223
+
224
+
225
+
226
+ <ul class='paramTable__restrictedList'>
227
+
228
+ <li>Can only be accessed by API users with admin access</li>
229
+
230
+ </ul>
231
+
232
+ </td>
233
+ <td>String</td>
234
+ <td>
235
+
236
+ 4953
237
+
238
+ </td>
239
+ </tr>
240
+
241
+ <tr>
242
+ <td>
243
+ <p>
244
+ <span class='paramTable__name'>mask</span>
245
+ </p>
246
+
247
+ <p class='paramTable__description'>The unique mask that represents this user</p>
248
+
249
+
250
+
251
+
252
+ <ul class='paramTable__restrictedList'>
253
+
254
+ <li>Must not be authenticated (no auth headers provided).</li>
255
+
256
+ </ul>
257
+
258
+ </td>
259
+ <td>String</td>
260
+ <td>
261
+
262
+ abc123abc123
263
+
264
+ </td>
265
+ </tr>
266
+
267
+
268
+
269
+ </table>
270
+
271
+
272
+
273
+
274
+ <h2>Expansions</h2>
275
+ <p class='text'>
276
+ Expansions are embedded structures of other objects that are related to the structure
277
+ that you're viewing. Which expansions are returned by a specific action are shown on that
278
+ action's documentation however some actions allow you to choose which expansions are
279
+ returned.
280
+ </p>
281
+ <table class='table paramTable'>
282
+ <thead>
283
+ <tr>
284
+ <th width="45%">Attribute</th>
285
+ <th width="20%">Type</th>
286
+ <th width="35%">Example</th>
287
+ </tr>
288
+ </thead>
289
+
290
+ <tr>
291
+ <td>
292
+ <p>
293
+ <span class='paramTable__name'>pets</span>
294
+ </p>
295
+
296
+ <p class='paramTable__description'>All pets that belong to this user</p>
297
+
298
+
299
+
300
+
301
+ </td>
302
+ <td>Array</td>
303
+ <td>
304
+
305
+ <a class='link' href="../structures/pet.html">Pet structure</a>
306
+
307
+ </td>
308
+ </tr>
309
+
310
+
311
+
312
+
313
+ <tr>
314
+ <td>
315
+ <p>
316
+ <span class='paramTable__name'>balance</span>
317
+ </p>
318
+
319
+ <p class='paramTable__description'>The user's balance</p>
320
+
321
+ </td>
322
+ <td>Float</td>
323
+ <td>12.5</td>
324
+ </tr>
325
+
326
+
327
+ </table>
328
+
329
+
330
+
331
+ </section>
332
+ <footer class='footer'>
333
+ <p>Generated by Moonrope at 12:43 on Monday 22 February 2016 for d3c499</p>
334
+ </footer>
335
+ <script src='https://code.jquery.com/jquery-1.12.0.min.js'></script>
336
+ <script src='../assets/try.js'></script>
337
+ </body>
338
+ </html>
@@ -1,3 +1,6 @@
1
+ require 'moonrope/dsl/action_dsl'
2
+ require 'moonrope/action_result'
3
+
1
4
  module Moonrope
2
5
  class Action
3
6
 
@@ -13,14 +16,35 @@ module Moonrope
13
16
  # @return [Hash] the params available for the action
14
17
  attr_reader :params
15
18
 
19
+ # @return [String] the title of the action
20
+ attr_accessor :title
21
+
16
22
  # @return [String] the description of the action
17
23
  attr_accessor :description
18
24
 
19
- # @return [Proc] the access check condition for the action
20
- attr_accessor :access
25
+ # @return [Array] the actual action blocks for the action
26
+ attr_accessor :actions
27
+
28
+ # @return [Symbol] the name of the authenticator for this action
29
+ attr_accessor :authenticator
30
+
31
+ # @return [Symbol] the name of the access rule for this action
32
+ attr_accessor :access_rule
33
+
34
+ # @return [Hash] the errors which can be retuend by this action
35
+ attr_accessor :errors
36
+
37
+ # @return [Hash] details of what will be returned on success
38
+ attr_accessor :returns
39
+
40
+ # @return [Bool] whether or not the action should be documented
41
+ attr_accessor :doc
42
+
43
+ # @return [Array] additional traits that have been applied to this action
44
+ attr_reader :traits
21
45
 
22
- # @return [Proc] the action for the action
23
- attr_accessor :action
46
+ # @return [Hash] a hash of filters that are applied
47
+ attr_reader :filters
24
48
 
25
49
  #
26
50
  # Initialize a new action
@@ -33,6 +57,10 @@ module Moonrope
33
57
  @controller = controller
34
58
  @name = name
35
59
  @params = {}
60
+ @errors = {}
61
+ @traits = []
62
+ @actions = []
63
+ @filters = {}
36
64
  @dsl = Moonrope::DSL::ActionDSL.new(self)
37
65
  @dsl.instance_eval(&block) if block_given?
38
66
  end
@@ -49,6 +77,32 @@ module Moonrope
49
77
  end
50
78
  end
51
79
 
80
+ #
81
+ # Return the authenticator that should be used when executing this action
82
+ #
83
+ # @return [Moonrope::Authenticator]
84
+ #
85
+ def authenticator_to_use
86
+ @authenticator_to_use ||= begin
87
+ if @authenticator
88
+ @controller.base.authenticators[@authenticator] || :not_found
89
+ elsif @controller.authenticator
90
+ @controller.base.authenticators[@controller.authenticator] || :not_found
91
+ else
92
+ @controller.base.authenticators[:default] || :none
93
+ end
94
+ end
95
+ end
96
+
97
+ #
98
+ # Return the access rule to use for this action#
99
+ #
100
+ # @return [Symbol]
101
+ #
102
+ def access_rule_to_use
103
+ @access_rule_to_use ||= access_rule || @controller.access_rule || :default
104
+ end
105
+
52
106
  #
53
107
  # Execute a block of code and catch approprite Moonrope errors and return
54
108
  # a result.
@@ -86,7 +140,7 @@ module Moonrope
86
140
  if request.is_a?(EvalEnvironment)
87
141
  eval_environment = request
88
142
  else
89
- eval_environment = EvalEnvironment.new(@controller.base, request)
143
+ eval_environment = EvalEnvironment.new(@controller.base, request, self)
90
144
  end
91
145
 
92
146
  #
@@ -95,12 +149,6 @@ module Moonrope
95
149
  #
96
150
  eval_environment.default_params = self.default_params
97
151
 
98
- #
99
- # Set the current action to the eval environment so it knows what action
100
- # invoked this.
101
- #
102
- eval_environment.action = self
103
-
104
152
  convert_errors_to_action_result do
105
153
  #
106
154
  # Validate the parameters
@@ -115,7 +163,10 @@ module Moonrope
115
163
  end
116
164
 
117
165
  # Run the actual action
118
- response = eval_environment.instance_eval(&action)
166
+ response = nil
167
+ actions.each do |action|
168
+ response = eval_environment.instance_exec(response, &action)
169
+ end
119
170
 
120
171
  # Calculate the length of time this request takes
121
172
  time_to_run = Time.now - start_time
@@ -144,34 +195,25 @@ module Moonrope
144
195
  if request.is_a?(EvalEnvironment)
145
196
  eval_environment = request
146
197
  else
147
- eval_environment = EvalEnvironment.new(@controller.base, request)
198
+ eval_environment = EvalEnvironment.new(@controller.base, request, self)
148
199
  end
149
200
 
150
- access_condition = self.access || @controller.access || @controller.base.default_access
151
-
152
- if eval_environment.auth
153
- # If there's no authentication object, access is permitted otherwise
154
- # we'll do the normal testing.
155
- if access_condition.is_a?(Proc)
156
- !!eval_environment.instance_exec(self, &access_condition)
157
- elsif access_condition.is_a?(Symbol)
158
- !!(eval_environment.auth.respond_to?(access_condition) && eval_environment.auth.send(access_condition))
159
- elsif access_condition.is_a?(Hash) && access_condition[:must_be] && access_condition[:with]
160
- !!(eval_environment.auth.is_a?(access_condition[:must_be]) &&
161
- eval_environment.auth.respond_to?(access_condition[:with]) &&
162
- eval_environment.auth.send(access_condition[:with])
163
- )
164
- elsif access_condition.is_a?(Hash) && access_condition[:must_be]
165
- !!(eval_environment.auth.is_a?(access_condition[:must_be]))
166
- elsif access_condition == true
167
- true
201
+ if authenticator_to_use.is_a?(Moonrope::Authenticator)
202
+ if rule = authenticator_to_use.rules[access_rule_to_use]
203
+ eval_environment.instance_exec(self, &rule[:block]) == true
168
204
  else
169
- false
205
+ if access_rule_to_use == :default
206
+ # The default rule on any authenticator will allow everything so we
207
+ # don't need to worry about this not being defined.
208
+ true
209
+ else
210
+ # If an access rule that doesn't exist has been requested, we will
211
+ # raise an internal error.
212
+ raise Moonrope::Errors::MissingAccessRule, "The rule '#{access_rule_to_use}' was not found on '#{authenticator_to_use.name}' authenticator"
213
+ end
170
214
  end
171
215
  else
172
- # No authentication object is available to test with. The result here
173
- # depends on whether or not an access condition has been defined or not.
174
- !access_condition
216
+ true
175
217
  end
176
218
  end
177
219
 
@@ -191,12 +233,98 @@ module Moonrope
191
233
  raise Moonrope::Errors::ParameterError, "`#{name}` parameter is invalid"
192
234
  end
193
235
 
194
- if value[:type] && param_set[name] && !param_set[name].is_a?(value[:type])
195
- raise Moonrope::Errors::ParameterError, "`#{name}` should be a `#{value[:type]}` but is a `#{param_set[name].class}`"
236
+ if value[:options].is_a?(Array) && param_set[name] && !value[:options].include?(param_set[name])
237
+ raise Moonrope::Errors::ParameterError, "`#{name}` must be one of #{value[:options].join(', ')}"
238
+ end
239
+
240
+ if value[:type] && param_set[name]
241
+ if value[:type] == :boolean
242
+ if BOOLEAN_VALUES.include?(param_set[name])
243
+ param_set._set_value(name, TRUE_LIKE_VALUES.include?(param_set[name]))
244
+ else
245
+ raise Moonrope::Errors::ParameterError, "`#{name}` should be a boolean value"
246
+ end
247
+ elsif value[:type].is_a?(Symbol) || value[:type].is_a?(String)
248
+ # Value is a symbol, nothing to do.
249
+ elsif !param_set[name].is_a?(value[:type])
250
+ raise Moonrope::Errors::ParameterError, "`#{name}` should be a `#{value[:type]}` but is a `#{param_set[name].class}`"
251
+ end
196
252
  end
197
253
  end
198
254
  true
199
255
  end
200
256
 
257
+ TRUE_LIKE_VALUES = ['true', '1', 1, true]
258
+ FALSE_LIKE_VALUES = ['false', '0', 0, false]
259
+ BOOLEAN_VALUES = TRUE_LIKE_VALUES + FALSE_LIKE_VALUES
260
+
261
+ #
262
+ # Does this action allow the user to include/exclude full attributes when
263
+ # calling this action?
264
+ #
265
+ def can_change_full?
266
+ if returns && opts = returns[:structure_opts]
267
+ opts[:paramable] == true ||
268
+ (opts[:paramable].is_a?(Hash) && opts[:paramable].has_key?(:full))
269
+ else
270
+ false
271
+ end
272
+ end
273
+
274
+ #
275
+ # Does this action include full attributes by default?
276
+ #
277
+ def includes_full_attributes?
278
+ if returns && opts = returns[:structure_opts]
279
+ (opts[:paramable].is_a?(Hash) && opts[:paramable][:full] == true) ||
280
+ opts[:full] == true
281
+ else
282
+ false
283
+ end
284
+ end
285
+
286
+ #
287
+ # Does this action allow the user to include/exclude expansions when calling
288
+ # this action?
289
+ #
290
+ def can_change_expansions?
291
+ if returns && opts = returns[:structure_opts]
292
+ opts[:paramable] == true ||
293
+ (opts[:paramable].is_a?(Hash) && opts[:paramable].has_key?(:expansions))
294
+ else
295
+ false
296
+ end
297
+ end
298
+
299
+ #
300
+ # Does this action include full attributes by default?
301
+ #
302
+ def includes_expansion?(expansion)
303
+ if returns && opts = returns[:structure_opts]
304
+ (opts[:paramable].is_a?(Hash) && opts[:paramable][:expansions] == true) ||
305
+ opts[:expansions] == true ||
306
+ (opts[:paramable].is_a?(Hash) && opts[:paramable][:expansions].is_a?(Array) && opts[:paramable][:expansions].include?(expansion)) ||
307
+ (opts[:expansions].is_a?(Array) && opts[:expansions].include?(expansion))
308
+ else
309
+ false
310
+ end
311
+ end
312
+
313
+ #
314
+ # Which expansions is the user permitted to include/exclude when calling this
315
+ # action.
316
+ #
317
+ def available_expansions
318
+ if returns && (structure = returns[:structure]) && can_change_expansions?
319
+ if returns[:structure_opts][:paramable].is_a?(Hash) && returns[:structure_opts][:paramable][:expansions].is_a?(Array)
320
+ returns[:structure_opts][:paramable][:expansions]
321
+ else
322
+ @controller.base.structure(structure).all_expansions
323
+ end
324
+ else
325
+ []
326
+ end
327
+ end
328
+
201
329
  end
202
330
  end
@@ -0,0 +1,39 @@
1
+ require 'moonrope/dsl/authenticator_dsl'
2
+
3
+ module Moonrope
4
+ class Authenticator
5
+
6
+ def initialize(name, &block)
7
+ @name = name
8
+ @headers = {}
9
+ @errors = {}
10
+ @rules = {}
11
+ if block_given?
12
+ dsl = Moonrope::DSL::AuthenticatorDSL.new(self)
13
+ dsl.instance_eval(&block)
14
+ end
15
+ end
16
+
17
+ # @return [Symbol] the name of the authenticator
18
+ attr_reader :name
19
+
20
+ # @return [String] the description for the authenticator
21
+ attr_accessor :description
22
+
23
+ # @return [Proc] the lookup block
24
+ attr_accessor :lookup
25
+
26
+ # @return [Hash] the headers that this authenticator uses
27
+ attr_reader :headers
28
+
29
+ # @return [Hash] the errors this authenticator can raise
30
+ attr_reader :errors
31
+
32
+ # @return [Hash] the rules this authenticator provides
33
+ attr_reader :rules
34
+
35
+ # @return [Bool] whether or not the action should be documented
36
+ attr_accessor :doc
37
+
38
+ end
39
+ end
data/lib/moonrope/base.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'moonrope/dsl/base_dsl'
2
+
1
3
  module Moonrope
2
4
  class Base
3
5
 
@@ -14,6 +16,11 @@ module Moonrope
14
16
  api
15
17
  end
16
18
 
19
+ class << self
20
+ # @return [Moonrope::Base] return a global instance
21
+ attr_accessor :instance
22
+ end
23
+
17
24
  # @return [Array] the array of defined structures
18
25
  attr_reader :structures
19
26
 
@@ -26,11 +33,11 @@ module Moonrope
26
33
  # @return [Moonrope::DSL::BaseDSL] the base DSL
27
34
  attr_accessor :dsl
28
35
 
29
- # @return [Proc] the authentictor
30
- attr_accessor :authenticator
36
+ # @return [Hash] authenticators
37
+ attr_accessor :authenticators
31
38
 
32
- # @return [Proc] the default access condition
33
- attr_accessor :default_access
39
+ # @return [Hash] global shared actions
40
+ attr_accessor :shared_actions
34
41
 
35
42
  # @return [Array] the array of directories to load from (if relevant)
36
43
  attr_accessor :load_directories
@@ -61,7 +68,8 @@ module Moonrope
61
68
  @structures = []
62
69
  @controllers = []
63
70
  @helpers = @helpers.is_a?(Array) ? @helpers.select { |h| h.options[:unloadable] == false } : []
64
- @authenticator = nil
71
+ @authenticators = {}
72
+ @shared_actions = {}
65
73
  @default_access = nil
66
74
  end
67
75
 
@@ -92,7 +100,17 @@ module Moonrope
92
100
  #
93
101
  def load_directory(directory)
94
102
  if File.exist?(directory)
95
- Dir["#{directory}/**/*.rb"].each do |filename|
103
+ @loaded_files = []
104
+ Dir[
105
+ "#{directory}/structures/**/*.rb",
106
+ "#{directory}/shared_actions/**/*.rb",
107
+ "#{directory}/controllers/**/*.rb",
108
+ "#{directory}/helpers/**/*.rb",
109
+ "#{directory}/authenticators/**/*.rb",
110
+ "#{directory}/*.rb",
111
+ ].each do |filename|
112
+ next if @loaded_files.include?(filename)
113
+ @loaded_files << filename
96
114
  self.dsl.instance_eval(File.read(filename), filename)
97
115
  end
98
116
  true