moonrope 1.3.3 → 2.0.2
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.
- checksums.yaml +5 -5
- data/Gemfile +9 -0
- data/Gemfile.lock +47 -0
- data/MIT-LICENCE +20 -0
- data/README.md +24 -0
- data/bin/moonrope +28 -0
- data/docs/authentication.md +114 -0
- data/docs/controllers.md +106 -0
- data/docs/exceptions.md +27 -0
- data/docs/introduction.md +29 -0
- data/docs/structures.md +214 -0
- data/example/authentication.rb +50 -0
- data/example/controllers/meta_controller.rb +14 -0
- data/example/controllers/users_controller.rb +92 -0
- data/example/structures/pet_structure.rb +12 -0
- data/example/structures/user_structure.rb +35 -0
- data/lib/moonrope.rb +5 -4
- data/lib/moonrope/action.rb +170 -40
- data/lib/moonrope/authenticator.rb +42 -0
- data/lib/moonrope/base.rb +67 -6
- data/lib/moonrope/controller.rb +4 -2
- data/lib/moonrope/doc_context.rb +94 -0
- data/lib/moonrope/doc_server.rb +123 -0
- data/lib/moonrope/dsl/action_dsl.rb +159 -9
- data/lib/moonrope/dsl/authenticator_dsl.rb +35 -0
- data/lib/moonrope/dsl/base_dsl.rb +21 -18
- data/lib/moonrope/dsl/controller_dsl.rb +60 -9
- data/lib/moonrope/dsl/filterable_dsl.rb +27 -0
- data/lib/moonrope/dsl/structure_dsl.rb +28 -2
- data/lib/moonrope/errors.rb +13 -0
- data/lib/moonrope/eval_environment.rb +82 -3
- data/lib/moonrope/eval_helpers.rb +47 -8
- data/lib/moonrope/eval_helpers/filter_helper.rb +82 -0
- data/lib/moonrope/guard.rb +35 -0
- data/lib/moonrope/html_generator.rb +65 -0
- data/lib/moonrope/param_set.rb +11 -1
- data/lib/moonrope/rack_middleware.rb +66 -37
- data/lib/moonrope/railtie.rb +31 -14
- data/lib/moonrope/request.rb +43 -15
- data/lib/moonrope/structure.rb +100 -18
- data/lib/moonrope/structure_attribute.rb +39 -0
- data/lib/moonrope/version.rb +1 -1
- data/moonrope.gemspec +21 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/specs/action_spec.rb +455 -0
- data/spec/specs/base_spec.rb +29 -0
- data/spec/specs/controller_spec.rb +31 -0
- data/spec/specs/param_set_spec.rb +31 -0
- data/templates/basic/_action_form.erb +77 -0
- data/templates/basic/_errors_table.erb +32 -0
- data/templates/basic/_structure_attributes_list.erb +55 -0
- data/templates/basic/action.erb +168 -0
- data/templates/basic/assets/lock.svg +3 -0
- data/templates/basic/assets/reset.css +101 -0
- data/templates/basic/assets/style.css +348 -0
- data/templates/basic/assets/tool.svg +4 -0
- data/templates/basic/assets/try.js +157 -0
- data/templates/basic/authenticator.erb +52 -0
- data/templates/basic/controller.erb +20 -0
- data/templates/basic/index.erb +114 -0
- data/templates/basic/layout.erb +46 -0
- data/templates/basic/structure.erb +23 -0
- data/test/test_helper.rb +81 -0
- data/test/tests/action_access_test.rb +63 -0
- data/test/tests/actions_test.rb +524 -0
- data/test/tests/authenticators_test.rb +87 -0
- data/test/tests/base_test.rb +35 -0
- data/test/tests/controllers_test.rb +49 -0
- data/test/tests/eval_environment_test.rb +136 -0
- data/test/tests/evel_helpers_test.rb +60 -0
- data/test/tests/examples_test.rb +11 -0
- data/test/tests/helpers_test.rb +97 -0
- data/test/tests/param_set_test.rb +44 -0
- data/test/tests/rack_middleware_test.rb +131 -0
- data/test/tests/request_test.rb +232 -0
- data/test/tests/structures_param_extensions_test.rb +159 -0
- data/test/tests/structures_test.rb +398 -0
- metadata +71 -56
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
authenticator :default do
|
|
2
|
+
|
|
3
|
+
description <<-DESCRIPTION
|
|
4
|
+
To authenticate to the API, you need to pass an appropriate API token with your
|
|
5
|
+
request. To find out how to obtain an API token, please refer to the Authentication
|
|
6
|
+
API documentaton which outlines the available methods available for this.
|
|
7
|
+
DESCRIPTION
|
|
8
|
+
|
|
9
|
+
header "X-Auth-Application", "The API application which is generated by us and provided to you.", :example => "abc123abc123abc123"
|
|
10
|
+
header "X-Auth-Token", "The API token for the user you wish to authenticate as.", :example => "abc123abc123abc123"
|
|
11
|
+
|
|
12
|
+
error "InvalidApplicationToken", "The application token provided in X-Auth-Application is not valid.", :attributes => {:token => "The token used to find the application"}
|
|
13
|
+
error "InvalidAuthToken", "The auth token provided in X-Auth-Token is not valid.", :attributes => {:token => "The token that was used"}
|
|
14
|
+
error "ExpiredAuthToken", "The auth token provided in X-Auth-Token has expired.", :attributes => {:expired_at => "The time the token expired"}
|
|
15
|
+
|
|
16
|
+
lookup do
|
|
17
|
+
if app_token = header['X-Auth-Application']
|
|
18
|
+
api_application = APIApplication.find_by_token(app_token)
|
|
19
|
+
if api_application.nil?
|
|
20
|
+
error "InvalidApplicationToken", :token => app_token
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if auth_token = header['X-Auth-Token']
|
|
24
|
+
api_token = api_application.api_tokens.find_by_token(auth_token)
|
|
25
|
+
if api_token.nil? || api_token.inactive?
|
|
26
|
+
error "InvalidAuthToken", :token => auth_token
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if api_token.expired?
|
|
30
|
+
error "ExpiredAuthToken", :expired_at => api_token.expired_at
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
api_token
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
rule :default, "NotAuthenticated", "Must be authenticated with a valid user API token." do
|
|
39
|
+
identity.is_a?(APIToken) && identity.user
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
rule :must_be_admin, "MustBeAdmin", "Must be authenticated as a valid admin user." do
|
|
43
|
+
identity.is_a?(APIToken) && identity.user && identity.user.admin?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
rule :anonymous, "MustBeAnonymous", "Must not be authenticated (no auth headers provided)." do
|
|
47
|
+
identity == :anonymous
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
controller :meta do
|
|
2
|
+
|
|
3
|
+
friendly_name "Meta API"
|
|
4
|
+
description <<-DESC
|
|
5
|
+
The meta API provides you with access to information about the API itself.
|
|
6
|
+
DESC
|
|
7
|
+
|
|
8
|
+
action :version do
|
|
9
|
+
description "Return the current software version"
|
|
10
|
+
returns :string, :eg => "v1.2.3"
|
|
11
|
+
action { LlamaCom::VERSION }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
controller :users do
|
|
2
|
+
|
|
3
|
+
friendly_name "Users API"
|
|
4
|
+
description <<-DESC
|
|
5
|
+
The Users API provides full access to manage the users
|
|
6
|
+
which exist on your account.
|
|
7
|
+
DESC
|
|
8
|
+
|
|
9
|
+
action :list do
|
|
10
|
+
title "List all users"
|
|
11
|
+
description "This action will return a list of all users which the authenticated user has access to."
|
|
12
|
+
param :page, "The page number", :default => 1, :type => Integer
|
|
13
|
+
param :per_page, "The number of items to return per page", :default => 30, :type => Integer
|
|
14
|
+
sortable :username, :id, :created_at, :updated_at
|
|
15
|
+
paginated
|
|
16
|
+
filterable do
|
|
17
|
+
attribute :username, :type => String
|
|
18
|
+
attribute :age, :type => Integer
|
|
19
|
+
attribute :admin, :type => :boolean
|
|
20
|
+
end
|
|
21
|
+
returns :array, :structure => :user
|
|
22
|
+
action do
|
|
23
|
+
paginate(User.all) do |user|
|
|
24
|
+
structure user, :return => true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
action :show do
|
|
30
|
+
title "Get unit information"
|
|
31
|
+
param :username, "The user's username", :type => String, :required => true
|
|
32
|
+
returns :hash, :structure => :user, :structure_opts => {:paramable => true}
|
|
33
|
+
error "UserNotFound", "No user was found matching the given username", :attributes => {:username => "The username which was looked up"}
|
|
34
|
+
action do
|
|
35
|
+
if user = User.find_by_username(params.username)
|
|
36
|
+
structure user, :return => true
|
|
37
|
+
else
|
|
38
|
+
error 'UserNotFound', :username => params.username
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
shared_action :properties do
|
|
44
|
+
param :username, "The user's username", :type => String
|
|
45
|
+
param :first_name, "The user's first name", :type => String
|
|
46
|
+
param :last_name, "The user's last name", :type => String
|
|
47
|
+
param :email_address, "The user's e-mail address", :type => String
|
|
48
|
+
param :password, "The user's password", :type => String
|
|
49
|
+
param :admin, "Should this user be an admin?", :type => :boolean do |object, value|
|
|
50
|
+
if identity.admin?
|
|
51
|
+
object.admin = value
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
action :create do
|
|
57
|
+
title "Create a new user"
|
|
58
|
+
description <<-DESCRIPTION
|
|
59
|
+
This action will create a new user with the properties which have been provided.
|
|
60
|
+
DESCRIPTION
|
|
61
|
+
use :properties
|
|
62
|
+
returns :hash, :structure => :user, :structure_opts => {:full => true}
|
|
63
|
+
error "ValidationError", "The details provided were not sufficient to save the user", :attributes => {:errors => "An array of errors for each field"}
|
|
64
|
+
action do
|
|
65
|
+
user = User.new
|
|
66
|
+
if user.save
|
|
67
|
+
structure user, :return => true
|
|
68
|
+
else
|
|
69
|
+
error 'ValidationError', :errors => user.errors
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
action :update do
|
|
75
|
+
title "Update an existing user"
|
|
76
|
+
description "This action will update an existing user with the properties provided."
|
|
77
|
+
param :id, "The ID of the user to update", :type => Integer, :required => true
|
|
78
|
+
use :properties
|
|
79
|
+
returns :hash, :structure => :user, :structure_opts => {:full => true}
|
|
80
|
+
error 'UserNotFound', "The user specified could not be found", :attributes => {:id => "The ID that was looked up"}
|
|
81
|
+
error "ValidationError", "The details provided were not sufficient to save the user", :attributes => {:errors => "An array of errors for each field"}
|
|
82
|
+
action do
|
|
83
|
+
user = User.find_by_id(params.id) || error('UserNotFound', :id => params.id)
|
|
84
|
+
if user.save
|
|
85
|
+
structure user, :return => true
|
|
86
|
+
else
|
|
87
|
+
error 'ValidationError', :errors => user.errors
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
structure :pet do
|
|
2
|
+
|
|
3
|
+
# Uncomment the below line to stop this structure being documented.
|
|
4
|
+
# no_doc!
|
|
5
|
+
|
|
6
|
+
basic :id, "The ID of the pet", :type => Integer, :eg => 148
|
|
7
|
+
basic :name, "The name of the pet", :type => String, :eg => "Fido"
|
|
8
|
+
basic :color, "What color is the pet?", :type => String, :eg => "Green"
|
|
9
|
+
|
|
10
|
+
expansion :user, "The user who owns this pet", :type => Hash, :structure => :user
|
|
11
|
+
|
|
12
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
structure :user do
|
|
2
|
+
|
|
3
|
+
basic :id, "The user's internal system ID", :type => Integer, :eg => 123
|
|
4
|
+
basic :username, "The user's unique username", :type => String, :eg => "adamcooke"
|
|
5
|
+
group :name do
|
|
6
|
+
basic :first, "The user's first name", :type => String, :eg => "Adam", :source_attribute => :first_name
|
|
7
|
+
basic :last, "The user's last name", :type => String, :eg => "Cooke", :source_attribute => :last_name
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
full :admin, "Is this user an administrator?", :type => :boolean
|
|
11
|
+
full :age, "The user's age", :type => Integer, :doc => false
|
|
12
|
+
full :created_at, "The timestamp the user was created", :type => :timestamp
|
|
13
|
+
full :updated_at, "The timestamp the user was updated", :type => :timestamp
|
|
14
|
+
|
|
15
|
+
expansion :pets, "All pets that belong to this user", :structure => :pet, :type => Array
|
|
16
|
+
|
|
17
|
+
expansion :balance, "The user's balance", :type => Float, :eg => 12.50 do
|
|
18
|
+
o.user.balance
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
expansion :hidden, "This is a hidden expansion", :doc => false do
|
|
22
|
+
o.user.hidden
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
condition Proc.new { identity.admin? }, "Can only be accessed by API users with admin access" do
|
|
26
|
+
# This value will only be provided to users who are accesing the API with
|
|
27
|
+
# the permission to view
|
|
28
|
+
full :support_pin, "The PIN this user needs to use to access support", :type => String, :eg => "4953"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
condition :default => :anonymous do
|
|
32
|
+
full :mask, "The unique mask that represents this user", :type => String, :eg => 'abc123abc123'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
data/lib/moonrope.rb
CHANGED
|
@@ -11,7 +11,8 @@ require 'moonrope/dsl/base_dsl'
|
|
|
11
11
|
require 'moonrope/dsl/action_dsl'
|
|
12
12
|
require 'moonrope/dsl/controller_dsl'
|
|
13
13
|
require 'moonrope/dsl/structure_dsl'
|
|
14
|
-
|
|
14
|
+
require 'moonrope/dsl/authenticator_dsl'
|
|
15
|
+
require 'moonrope/authenticator'
|
|
15
16
|
require 'moonrope/errors'
|
|
16
17
|
require 'moonrope/eval_helpers'
|
|
17
18
|
require 'moonrope/eval_environment'
|
|
@@ -26,13 +27,13 @@ require 'moonrope/version'
|
|
|
26
27
|
require 'moonrope/railtie' if defined?(Rails)
|
|
27
28
|
|
|
28
29
|
module Moonrope
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
class << self
|
|
31
32
|
attr_accessor :logger
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
def logger
|
|
34
35
|
@logger ||= Logger.new(STDOUT)
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
|
-
|
|
38
|
+
|
|
38
39
|
end
|
data/lib/moonrope/action.rb
CHANGED
|
@@ -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 [
|
|
20
|
-
attr_accessor :
|
|
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 [
|
|
23
|
-
|
|
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,23 +77,51 @@ 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.
|
|
55
109
|
#
|
|
56
|
-
def convert_errors_to_action_result(&block)
|
|
110
|
+
def convert_errors_to_action_result(start_time = nil, &block)
|
|
57
111
|
begin
|
|
58
112
|
yield block
|
|
59
113
|
rescue => exception
|
|
60
114
|
case exception
|
|
61
115
|
when Moonrope::Errors::RequestError
|
|
62
116
|
result = ActionResult.new(self)
|
|
117
|
+
result.time = start_time ? (Time.now - start_time).round(2) : nil
|
|
63
118
|
result.status = exception.status
|
|
64
119
|
result.data = exception.data
|
|
65
120
|
result
|
|
66
121
|
else
|
|
67
122
|
if error_block = @controller.base.external_errors[exception.class]
|
|
68
123
|
result = ActionResult.new(self)
|
|
124
|
+
result.time = start_time ? (Time.now - start_time).round(2) : nil
|
|
69
125
|
error_block.call(exception, result)
|
|
70
126
|
result
|
|
71
127
|
else
|
|
@@ -86,7 +142,7 @@ module Moonrope
|
|
|
86
142
|
if request.is_a?(EvalEnvironment)
|
|
87
143
|
eval_environment = request
|
|
88
144
|
else
|
|
89
|
-
eval_environment = EvalEnvironment.new(@controller.base, request)
|
|
145
|
+
eval_environment = EvalEnvironment.new(@controller.base, request, self)
|
|
90
146
|
end
|
|
91
147
|
|
|
92
148
|
#
|
|
@@ -95,27 +151,24 @@ module Moonrope
|
|
|
95
151
|
#
|
|
96
152
|
eval_environment.default_params = self.default_params
|
|
97
153
|
|
|
98
|
-
|
|
99
|
-
# Set the current action to the eval environment so it knows what action
|
|
100
|
-
# invoked this.
|
|
101
|
-
#
|
|
102
|
-
eval_environment.action = self
|
|
154
|
+
start_time = Time.now
|
|
103
155
|
|
|
104
|
-
convert_errors_to_action_result do
|
|
156
|
+
convert_errors_to_action_result(start_time) do
|
|
105
157
|
#
|
|
106
158
|
# Validate the parameters
|
|
107
159
|
#
|
|
108
160
|
self.validate_parameters(eval_environment.params)
|
|
109
161
|
|
|
110
|
-
start_time = Time.now
|
|
111
|
-
|
|
112
162
|
# Run before filters
|
|
113
163
|
controller.before_actions_for(name).each do |action|
|
|
114
164
|
eval_environment.instance_eval(&action.block)
|
|
115
165
|
end
|
|
116
166
|
|
|
117
167
|
# Run the actual action
|
|
118
|
-
response =
|
|
168
|
+
response = nil
|
|
169
|
+
actions.each do |action|
|
|
170
|
+
response = eval_environment.instance_exec(response, &action)
|
|
171
|
+
end
|
|
119
172
|
|
|
120
173
|
# Calculate the length of time this request takes
|
|
121
174
|
time_to_run = Time.now - start_time
|
|
@@ -144,34 +197,25 @@ module Moonrope
|
|
|
144
197
|
if request.is_a?(EvalEnvironment)
|
|
145
198
|
eval_environment = request
|
|
146
199
|
else
|
|
147
|
-
eval_environment = EvalEnvironment.new(@controller.base, request)
|
|
200
|
+
eval_environment = EvalEnvironment.new(@controller.base, request, self)
|
|
148
201
|
end
|
|
149
202
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
|
203
|
+
if authenticator_to_use.is_a?(Moonrope::Authenticator)
|
|
204
|
+
if rule = authenticator_to_use.rules[access_rule_to_use]
|
|
205
|
+
eval_environment.instance_exec(self, &rule[:block]) == true
|
|
168
206
|
else
|
|
169
|
-
|
|
207
|
+
if access_rule_to_use == :default
|
|
208
|
+
# The default rule on any authenticator will allow everything so we
|
|
209
|
+
# don't need to worry about this not being defined.
|
|
210
|
+
true
|
|
211
|
+
else
|
|
212
|
+
# If an access rule that doesn't exist has been requested, we will
|
|
213
|
+
# raise an internal error.
|
|
214
|
+
raise Moonrope::Errors::MissingAccessRule, "The rule '#{access_rule_to_use}' was not found on '#{authenticator_to_use.name}' authenticator"
|
|
215
|
+
end
|
|
170
216
|
end
|
|
171
217
|
else
|
|
172
|
-
|
|
173
|
-
# depends on whether or not an access condition has been defined or not.
|
|
174
|
-
!access_condition
|
|
218
|
+
true
|
|
175
219
|
end
|
|
176
220
|
end
|
|
177
221
|
|
|
@@ -191,12 +235,98 @@ module Moonrope
|
|
|
191
235
|
raise Moonrope::Errors::ParameterError, "`#{name}` parameter is invalid"
|
|
192
236
|
end
|
|
193
237
|
|
|
194
|
-
if value[:
|
|
195
|
-
raise Moonrope::Errors::ParameterError, "`#{name}`
|
|
238
|
+
if value[:options].is_a?(Array) && param_set[name] && !value[:options].include?(param_set[name])
|
|
239
|
+
raise Moonrope::Errors::ParameterError, "`#{name}` must be one of #{value[:options].join(', ')}"
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
if value[:type] && param_set[name]
|
|
243
|
+
if value[:type] == :boolean
|
|
244
|
+
if BOOLEAN_VALUES.include?(param_set[name])
|
|
245
|
+
param_set._set_value(name, TRUE_LIKE_VALUES.include?(param_set[name]))
|
|
246
|
+
else
|
|
247
|
+
raise Moonrope::Errors::ParameterError, "`#{name}` should be a boolean value"
|
|
248
|
+
end
|
|
249
|
+
elsif value[:type].is_a?(Symbol) || value[:type].is_a?(String)
|
|
250
|
+
# Value is a symbol, nothing to do.
|
|
251
|
+
elsif !param_set[name].is_a?(value[:type])
|
|
252
|
+
raise Moonrope::Errors::ParameterError, "`#{name}` should be a `#{value[:type]}` but is a `#{param_set[name].class}`"
|
|
253
|
+
end
|
|
196
254
|
end
|
|
197
255
|
end
|
|
198
256
|
true
|
|
199
257
|
end
|
|
200
258
|
|
|
259
|
+
TRUE_LIKE_VALUES = ['true', '1', 1, true]
|
|
260
|
+
FALSE_LIKE_VALUES = ['false', '0', 0, false]
|
|
261
|
+
BOOLEAN_VALUES = TRUE_LIKE_VALUES + FALSE_LIKE_VALUES
|
|
262
|
+
|
|
263
|
+
#
|
|
264
|
+
# Does this action allow the user to include/exclude full attributes when
|
|
265
|
+
# calling this action?
|
|
266
|
+
#
|
|
267
|
+
def can_change_full?
|
|
268
|
+
if returns && opts = returns[:structure_opts]
|
|
269
|
+
opts[:paramable] == true ||
|
|
270
|
+
(opts[:paramable].is_a?(Hash) && opts[:paramable].has_key?(:full))
|
|
271
|
+
else
|
|
272
|
+
false
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
#
|
|
277
|
+
# Does this action include full attributes by default?
|
|
278
|
+
#
|
|
279
|
+
def includes_full_attributes?
|
|
280
|
+
if returns && opts = returns[:structure_opts]
|
|
281
|
+
(opts[:paramable].is_a?(Hash) && opts[:paramable][:full] == true) ||
|
|
282
|
+
opts[:full] == true
|
|
283
|
+
else
|
|
284
|
+
false
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
#
|
|
289
|
+
# Does this action allow the user to include/exclude expansions when calling
|
|
290
|
+
# this action?
|
|
291
|
+
#
|
|
292
|
+
def can_change_expansions?
|
|
293
|
+
if returns && opts = returns[:structure_opts]
|
|
294
|
+
opts[:paramable] == true ||
|
|
295
|
+
(opts[:paramable].is_a?(Hash) && opts[:paramable].has_key?(:expansions))
|
|
296
|
+
else
|
|
297
|
+
false
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
#
|
|
302
|
+
# Does this action include full attributes by default?
|
|
303
|
+
#
|
|
304
|
+
def includes_expansion?(expansion)
|
|
305
|
+
if returns && opts = returns[:structure_opts]
|
|
306
|
+
(opts[:paramable].is_a?(Hash) && opts[:paramable][:expansions] == true) ||
|
|
307
|
+
opts[:expansions] == true ||
|
|
308
|
+
(opts[:paramable].is_a?(Hash) && opts[:paramable][:expansions].is_a?(Array) && opts[:paramable][:expansions].include?(expansion)) ||
|
|
309
|
+
(opts[:expansions].is_a?(Array) && opts[:expansions].include?(expansion))
|
|
310
|
+
else
|
|
311
|
+
false
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
#
|
|
316
|
+
# Which expansions is the user permitted to include/exclude when calling this
|
|
317
|
+
# action.
|
|
318
|
+
#
|
|
319
|
+
def available_expansions
|
|
320
|
+
if returns && (structure = returns[:structure]) && can_change_expansions?
|
|
321
|
+
if returns[:structure_opts][:paramable].is_a?(Hash) && returns[:structure_opts][:paramable][:expansions].is_a?(Array)
|
|
322
|
+
returns[:structure_opts][:paramable][:expansions]
|
|
323
|
+
else
|
|
324
|
+
@controller.base.structure(structure).all_expansions
|
|
325
|
+
end
|
|
326
|
+
else
|
|
327
|
+
[]
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
201
331
|
end
|
|
202
332
|
end
|