moonrope 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,5 @@
1
+ task :default do
2
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
3
+ $LOAD_PATH.unshift(File.expand_path('../test', __FILE__))
4
+ require 'test_helper'
5
+ end
@@ -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