moonrope 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +5 -0
- data/lib/moonrope.rb +37 -0
- data/lib/moonrope/action.rb +163 -0
- data/lib/moonrope/action_result.rb +63 -0
- data/lib/moonrope/base.rb +130 -0
- data/lib/moonrope/before_action.rb +24 -0
- data/lib/moonrope/controller.rb +49 -0
- data/lib/moonrope/dsl/action_dsl.rb +70 -0
- data/lib/moonrope/dsl/base_dsl.rb +74 -0
- data/lib/moonrope/dsl/controller_dsl.rb +57 -0
- data/lib/moonrope/dsl/structure_dsl.rb +63 -0
- data/lib/moonrope/dsl/structure_restriction_dsl.rb +27 -0
- data/lib/moonrope/errors.rb +48 -0
- data/lib/moonrope/eval_environment.rb +141 -0
- data/lib/moonrope/eval_helpers.rb +35 -0
- data/lib/moonrope/helper.rb +28 -0
- data/lib/moonrope/param_set.rb +44 -0
- data/lib/moonrope/rack_middleware.rb +73 -0
- data/lib/moonrope/railtie.rb +30 -0
- data/lib/moonrope/request.rb +165 -0
- data/lib/moonrope/structure.rb +83 -0
- data/lib/moonrope/version.rb +3 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 89677af83c79db9270d024635bb4a4cefc8131f6
|
4
|
+
data.tar.gz: 0a4002afcef30a933974d0090c501f276f0bd13d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e4a4fc0d9bd542697910e6c82e72faa41debf0cf2f6497267ab036d681bd28ca9dddd0079bbf0c5e868bca224e6728e46ce398bf7ae3c65e3809ed10b66e7fe
|
7
|
+
data.tar.gz: d974dffc746c61c3a5f5543ca21f22849c82020fe324e90a1e549479b6dcac9a1f096cef8f7a3f7d7b5455819df0db931ca40498e73ceeae9d3a4db7e33dec50
|
data/Rakefile
ADDED
data/lib/moonrope.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require 'moonrope/action'
|
5
|
+
require 'moonrope/action_result'
|
6
|
+
require 'moonrope/base'
|
7
|
+
require 'moonrope/before_action'
|
8
|
+
require 'moonrope/controller'
|
9
|
+
require 'moonrope/dsl/base_dsl'
|
10
|
+
require 'moonrope/dsl/action_dsl'
|
11
|
+
require 'moonrope/dsl/controller_dsl'
|
12
|
+
require 'moonrope/dsl/structure_dsl'
|
13
|
+
require 'moonrope/dsl/structure_restriction_dsl'
|
14
|
+
|
15
|
+
require 'moonrope/errors'
|
16
|
+
require 'moonrope/eval_helpers'
|
17
|
+
require 'moonrope/eval_environment'
|
18
|
+
require 'moonrope/helper'
|
19
|
+
require 'moonrope/param_set'
|
20
|
+
require 'moonrope/rack_middleware'
|
21
|
+
require 'moonrope/request'
|
22
|
+
require 'moonrope/structure'
|
23
|
+
require 'moonrope/version'
|
24
|
+
|
25
|
+
require 'moonrope/railtie' if defined?(Rails)
|
26
|
+
|
27
|
+
module Moonrope
|
28
|
+
|
29
|
+
class << self
|
30
|
+
attr_accessor :logger
|
31
|
+
|
32
|
+
def logger
|
33
|
+
@logger ||= Logger.new(STDOUT)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Moonrope
|
2
|
+
class Action
|
3
|
+
|
4
|
+
# @return [Moonrope::Controller] the associated controller
|
5
|
+
attr_reader :controller
|
6
|
+
|
7
|
+
# @return [Symbol] the name of the action
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
# @return [Moonrope::DSL::Action] the action's DSL
|
11
|
+
attr_reader :dsl
|
12
|
+
|
13
|
+
# @return [Hash] the params available for the action
|
14
|
+
attr_reader :params
|
15
|
+
|
16
|
+
# @return [String] the description of the action
|
17
|
+
attr_accessor :description
|
18
|
+
|
19
|
+
# @return [Proc] the access check condition for the action
|
20
|
+
attr_accessor :access
|
21
|
+
|
22
|
+
# @return [Proc] the action for the action
|
23
|
+
attr_accessor :action
|
24
|
+
|
25
|
+
#
|
26
|
+
# Initialize a new action
|
27
|
+
#
|
28
|
+
# @param controller [Moonrope::Controller] the controller this action belongs to
|
29
|
+
# @param name [Symbol] the name of the action
|
30
|
+
# @yield allows the action to be configured via Moonrope::DSL::ActionDSL
|
31
|
+
#
|
32
|
+
def initialize(controller, name, &block)
|
33
|
+
@controller = controller
|
34
|
+
@name = name
|
35
|
+
@params = {}
|
36
|
+
@dsl = Moonrope::DSL::ActionDSL.new(self)
|
37
|
+
@dsl.instance_eval(&block) if block_given?
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Return a hash of all params for this action which are
|
42
|
+
#
|
43
|
+
# @return [Hash] hash with field names as keys with default values
|
44
|
+
#
|
45
|
+
def default_params
|
46
|
+
@params.inject({}) do |h,(k,v)|
|
47
|
+
h[k.to_s] = v[:default] if v[:default]
|
48
|
+
h
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Executes the action and returns a ActionResult object with the result
|
54
|
+
# of the action.
|
55
|
+
#
|
56
|
+
# @param request [Moonrope::Request or Moonrope::EvalEnvironment]
|
57
|
+
# @return [Moonrope::ActionResult]
|
58
|
+
#
|
59
|
+
def execute(request = nil)
|
60
|
+
if request.is_a?(EvalEnvironment)
|
61
|
+
eval_environment = request
|
62
|
+
else
|
63
|
+
eval_environment = EvalEnvironment.new(@controller.base, request)
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Set this actions default parameters in the eval environment so that
|
68
|
+
# it has access to them.
|
69
|
+
#
|
70
|
+
eval_environment.default_params = self.default_params
|
71
|
+
|
72
|
+
#
|
73
|
+
# Set the current action to the eval environment so it knows what action
|
74
|
+
# invoked this.
|
75
|
+
#
|
76
|
+
eval_environment.action = self
|
77
|
+
|
78
|
+
begin
|
79
|
+
#
|
80
|
+
# Validate the parameters
|
81
|
+
#
|
82
|
+
self.validate_parameters(eval_environment.params)
|
83
|
+
|
84
|
+
start_time = Time.now
|
85
|
+
|
86
|
+
# Run before filters
|
87
|
+
controller.before_actions_for(name).each do |action|
|
88
|
+
eval_environment.instance_eval(&action.block)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Run the actual action
|
92
|
+
response = eval_environment.instance_eval(&action)
|
93
|
+
|
94
|
+
# Calculate the length of time this request takes
|
95
|
+
time_to_run = Time.now - start_time
|
96
|
+
|
97
|
+
# Prepare a action result
|
98
|
+
result = ActionResult.new(self)
|
99
|
+
result.data = response
|
100
|
+
result.status = 'success'
|
101
|
+
result.time = time_to_run.round(2)
|
102
|
+
result.flags = eval_environment.flags
|
103
|
+
result.headers = eval_environment.headers
|
104
|
+
|
105
|
+
# Return the result object
|
106
|
+
result
|
107
|
+
|
108
|
+
rescue Moonrope::Errors::RequestError => e
|
109
|
+
result = ActionResult.new(self)
|
110
|
+
result.status = e.status
|
111
|
+
result.data = e.data
|
112
|
+
result
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Check whether the authenticated user has access to this request.
|
118
|
+
# Accepts a Request or an EvalEnvironment.
|
119
|
+
#
|
120
|
+
# @param request [Moonrope::Request or Moonrope::EvalEnvironment]
|
121
|
+
# @return [Boolean]
|
122
|
+
#
|
123
|
+
def check_access(request = nil)
|
124
|
+
if request.is_a?(EvalEnvironment)
|
125
|
+
eval_environment = request
|
126
|
+
else
|
127
|
+
eval_environment = EvalEnvironment.new(@controller.base, request)
|
128
|
+
end
|
129
|
+
|
130
|
+
if eval_environment.auth && access.is_a?(Proc)
|
131
|
+
!!eval_environment.instance_eval(&access)
|
132
|
+
elsif @controller.base.default_access.is_a?(Proc)
|
133
|
+
!!eval_environment.instance_exec(self, &@controller.base.default_access)
|
134
|
+
else
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Return whether or not the passed ParamSet is valid for this action
|
141
|
+
#
|
142
|
+
# @param param_set [Moonrope::ParamSet] the param set to check
|
143
|
+
# @return [Boolean]
|
144
|
+
#
|
145
|
+
def validate_parameters(param_set)
|
146
|
+
@params.each do |name, value|
|
147
|
+
if value[:required] && param_set[name].nil?
|
148
|
+
raise Moonrope::Errors::ParameterError, "`#{name}` parameter is required but is missing"
|
149
|
+
end
|
150
|
+
|
151
|
+
if value[:regex] && param_set[name] && !(param_set[name].to_s =~ value[:regex])
|
152
|
+
raise Moonrope::Errors::ParameterError, "`#{name}` parameter is invalid"
|
153
|
+
end
|
154
|
+
|
155
|
+
if value[:type] && param_set[name] && !param_set[name].is_a?(value[:type])
|
156
|
+
raise Moonrope::Errors::ParameterError, "`#{name}` should be a `#{value[:type]}` but is a `#{param_set[name].class}`"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
true
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Moonrope
|
2
|
+
class ActionResult
|
3
|
+
|
4
|
+
#
|
5
|
+
# Initialize a new result from a Moonrope::Action.
|
6
|
+
#
|
7
|
+
# @param action [Moonrope::Action] the action which originated this result
|
8
|
+
#
|
9
|
+
def initialize(action)
|
10
|
+
@action = action
|
11
|
+
@headers = {}
|
12
|
+
@time = nil
|
13
|
+
@flags = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Object] the return value from the action
|
17
|
+
attr_accessor :data
|
18
|
+
|
19
|
+
# @return [String] the status of the request
|
20
|
+
attr_accessor :status
|
21
|
+
|
22
|
+
# @return [Hash] headers which have been set in the action
|
23
|
+
attr_accessor :headers
|
24
|
+
|
25
|
+
# @return [Float] the length of time to process the action
|
26
|
+
attr_accessor :time
|
27
|
+
|
28
|
+
# @return [Hash] flags which have been set in the action
|
29
|
+
attr_accessor :flags
|
30
|
+
|
31
|
+
#
|
32
|
+
# Return a Hash representation of this ActionResult without the
|
33
|
+
# headers.
|
34
|
+
#
|
35
|
+
# {
|
36
|
+
# :status => 'success',
|
37
|
+
# :time => 1.32,
|
38
|
+
# :flags => {},
|
39
|
+
# :data => {}
|
40
|
+
# }
|
41
|
+
#
|
42
|
+
# @return [Hash]
|
43
|
+
#
|
44
|
+
def to_hash
|
45
|
+
{
|
46
|
+
:status => self.status,
|
47
|
+
:time => self.time,
|
48
|
+
:flags => self.flags,
|
49
|
+
:data => self.data
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Return the ActionResult's hash with a JSON.
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
#
|
58
|
+
def to_json
|
59
|
+
to_hash.to_json
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Moonrope
|
2
|
+
class Base
|
3
|
+
|
4
|
+
#
|
5
|
+
# Load a set of Moonrope configuration files from a given
|
6
|
+
# directory.
|
7
|
+
#
|
8
|
+
# @param path [String] the path to a directory containing Moonrope files
|
9
|
+
# @return [Moonrope::Base]
|
10
|
+
#
|
11
|
+
def self.load(path)
|
12
|
+
api = self.new
|
13
|
+
api.load(path)
|
14
|
+
api
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Array] the array of defined structures
|
18
|
+
attr_reader :structures
|
19
|
+
|
20
|
+
# @return [Array] the array of defined controllers
|
21
|
+
attr_accessor :controllers
|
22
|
+
|
23
|
+
# @return [Array] the array of defined helpers
|
24
|
+
attr_accessor :helpers
|
25
|
+
|
26
|
+
# @return [Moonrope::DSL::BaseDSL] the base DSL
|
27
|
+
attr_accessor :dsl
|
28
|
+
|
29
|
+
# @return [Proc] the authentictor
|
30
|
+
attr_accessor :authenticator
|
31
|
+
|
32
|
+
# @return [Proc] the default access condition
|
33
|
+
attr_accessor :default_access
|
34
|
+
|
35
|
+
# @return [String] the directory the base was loaded from (if relevant)
|
36
|
+
attr_accessor :loaded_from
|
37
|
+
|
38
|
+
#
|
39
|
+
# Initialize a new instance of the Moonrope::Base
|
40
|
+
#
|
41
|
+
# @yield instance evals the contents within the Base DSL
|
42
|
+
#
|
43
|
+
def initialize(&block)
|
44
|
+
unload
|
45
|
+
@dsl = Moonrope::DSL::BaseDSL.new(self)
|
46
|
+
@dsl.instance_eval(&block) if block_given?
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Reset the whole base to contain no data.
|
51
|
+
#
|
52
|
+
def unload
|
53
|
+
@structures = []
|
54
|
+
@controllers = []
|
55
|
+
@helpers = []
|
56
|
+
@authenticator = nil
|
57
|
+
@default_access = nil
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Reload this whole base API from the path
|
62
|
+
#
|
63
|
+
def load(directory = nil)
|
64
|
+
directory = self.loaded_from if directory.nil?
|
65
|
+
if directory
|
66
|
+
unload
|
67
|
+
Dir["#{directory}/**/*.rb"].each do |filename|
|
68
|
+
self.dsl.instance_eval(File.read(filename), filename)
|
69
|
+
end
|
70
|
+
self.loaded_from = directory
|
71
|
+
self
|
72
|
+
else
|
73
|
+
raise Moonrope::Error, "Can't reload Moonrope::Base as it wasn't required from a directory"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
alias_method :reload, :load
|
78
|
+
|
79
|
+
#
|
80
|
+
# Return a structure of the given name
|
81
|
+
#
|
82
|
+
# @param name [Symbol] the name of the structure
|
83
|
+
# @return [Moonrope::Structure]
|
84
|
+
#
|
85
|
+
def structure(name)
|
86
|
+
structures.select { |s| s.name == name }.first
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :[], :structure
|
90
|
+
|
91
|
+
#
|
92
|
+
# Return a controller of the given name
|
93
|
+
#
|
94
|
+
# @param name [Symbol] the name of the controller
|
95
|
+
# @return [Moonrope::Controller]
|
96
|
+
#
|
97
|
+
def controller(name)
|
98
|
+
controllers.select { |a| a.name == name }.first
|
99
|
+
end
|
100
|
+
|
101
|
+
alias_method :/, :controller
|
102
|
+
|
103
|
+
#
|
104
|
+
# Create a new rack request for this API.
|
105
|
+
#
|
106
|
+
# @return [Moonrope::Request] a new request object
|
107
|
+
#
|
108
|
+
def request(*args)
|
109
|
+
Moonrope::Request.new(self, *args)
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Return a helper for the given name and, potentially controller
|
114
|
+
#
|
115
|
+
# @param name [Symbol] the name of the helper
|
116
|
+
# @param controller [Moonrope::Controller] the controller scope
|
117
|
+
#
|
118
|
+
def helper(name, controller = nil)
|
119
|
+
if controller
|
120
|
+
matched_helpers = @helpers.select do |h|
|
121
|
+
h.name == name.to_sym && (h.controller.nil? || h.controller == controller)
|
122
|
+
end
|
123
|
+
else
|
124
|
+
matched_helpers = @helpers.select { |h| h.name == name.to_sym && h.controller.nil? }
|
125
|
+
end
|
126
|
+
matched_helpers.first
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Moonrope
|
2
|
+
class BeforeAction
|
3
|
+
|
4
|
+
# @return [Array] the names of actions to execute this request on
|
5
|
+
attr_accessor :actions
|
6
|
+
|
7
|
+
# @return [Proc] the block to execute in this action
|
8
|
+
attr_accessor :block
|
9
|
+
|
10
|
+
# @return [Moonrope::Controller] the associated controller
|
11
|
+
attr_reader :controller
|
12
|
+
|
13
|
+
#
|
14
|
+
# Initilize a new BeforeAction
|
15
|
+
#
|
16
|
+
# @param controller [Moonrope::Controller]
|
17
|
+
#
|
18
|
+
def initialize(controller)
|
19
|
+
@controller = controller
|
20
|
+
@actions = []
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Moonrope
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
attr_accessor :name, :actions, :befores
|
5
|
+
attr_reader :base, :dsl
|
6
|
+
|
7
|
+
#
|
8
|
+
# Initalize a new Moonrope::Controller
|
9
|
+
#
|
10
|
+
# @param base [Moonrope::Base] the base
|
11
|
+
# @param name [Symbol] the name of the controller
|
12
|
+
# @yield instance evals the contents within the ControllerDSL
|
13
|
+
#
|
14
|
+
def initialize(base, name, &block)
|
15
|
+
@base = base
|
16
|
+
@name = name
|
17
|
+
@actions = {}
|
18
|
+
@befores = []
|
19
|
+
@dsl = Moonrope::DSL::ControllerDSL.new(self)
|
20
|
+
@dsl.instance_eval(&block) if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Return an array of before actions which must be executed for
|
25
|
+
# the given action.
|
26
|
+
#
|
27
|
+
# @param action [Symbol] the name of the action to return
|
28
|
+
# @return [Array] an array of Moonrope::BeforeAction instances
|
29
|
+
#
|
30
|
+
def before_actions_for(action)
|
31
|
+
@befores.select do |b|
|
32
|
+
b.actions.empty? || b.actions.include?(action)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Lookup and return an action in this controller by name.
|
38
|
+
#
|
39
|
+
# @param action [Symbol] the name of the action
|
40
|
+
# @return [Moonrope::Action] the action
|
41
|
+
#
|
42
|
+
def action(action)
|
43
|
+
actions[action.to_sym]
|
44
|
+
end
|
45
|
+
|
46
|
+
alias_method :/, :action
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|