shaf 1.5.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/iana_link_relations.csv.gz +0 -0
- data/lib/shaf.rb +6 -0
- data/lib/shaf/alps/attribute_serializer.rb +41 -0
- data/lib/shaf/alps/json_serializer.rb +50 -0
- data/lib/shaf/alps/relation_serializer.rb +70 -0
- data/lib/shaf/api_doc/link_relations.rb +77 -0
- data/lib/shaf/app.rb +12 -5
- data/lib/shaf/authenticator.rb +56 -0
- data/lib/shaf/authenticator/base.rb +161 -0
- data/lib/shaf/authenticator/basic_auth.rb +25 -0
- data/lib/shaf/authenticator/challenge.rb +32 -0
- data/lib/shaf/authenticator/parameter.rb +31 -0
- data/lib/shaf/authenticator/request.rb +17 -0
- data/lib/shaf/command/console.rb +1 -1
- data/lib/shaf/command/generate.rb +5 -2
- data/lib/shaf/command/new.rb +20 -7
- data/lib/shaf/command/templates/Gemfile.erb +1 -0
- data/{templates/config/settings.yml → lib/shaf/command/templates/config/settings.yml.erb} +1 -5
- data/lib/shaf/errors.rb +11 -0
- data/lib/shaf/extensions.rb +3 -3
- data/lib/shaf/extensions/api_routes.rb +60 -0
- data/lib/shaf/extensions/authorize.rb +11 -9
- data/lib/shaf/extensions/log.rb +1 -1
- data/lib/shaf/extensions/resource_uris.rb +139 -63
- data/lib/shaf/extensions/symbolic_routes.rb +22 -19
- data/lib/shaf/formable.rb +1 -2
- data/lib/shaf/formable/form.rb +1 -1
- data/lib/shaf/generator.rb +2 -0
- data/lib/shaf/generator/base.rb +2 -3
- data/lib/shaf/generator/controller.rb +11 -7
- data/lib/shaf/generator/doc.rb +17 -0
- data/lib/shaf/generator/forms.rb +1 -0
- data/lib/shaf/generator/helper.rb +2 -1
- data/lib/shaf/generator/migration/base.rb +7 -3
- data/lib/shaf/generator/migration/type.rb +4 -26
- data/lib/shaf/generator/migration/types.rb +45 -16
- data/lib/shaf/generator/model.rb +1 -2
- data/lib/shaf/generator/profile.rb +52 -0
- data/lib/shaf/generator/serializer.rb +38 -73
- data/lib/shaf/generator/templates/api/policy.rb.erb +2 -2
- data/lib/shaf/generator/templates/api/profile.rb.erb +16 -0
- data/lib/shaf/generator/templates/api/serializer.rb.erb +2 -2
- data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +1 -2
- data/lib/shaf/generator/templates/spec/serializer_spec.rb.erb +5 -5
- data/lib/shaf/helpers.rb +4 -0
- data/lib/shaf/helpers/authentication.rb +79 -0
- data/lib/shaf/helpers/cache_control.rb +1 -2
- data/lib/shaf/helpers/json_html.rb +58 -18
- data/lib/shaf/helpers/payload.rb +27 -41
- data/lib/shaf/helpers/vary.rb +8 -0
- data/lib/shaf/logger.rb +12 -0
- data/lib/shaf/parser.rb +65 -0
- data/lib/shaf/parser/base.rb +44 -0
- data/lib/shaf/parser/form_data.rb +15 -0
- data/lib/shaf/parser/json.rb +26 -0
- data/lib/shaf/profile.rb +110 -0
- data/lib/shaf/profile/attribute.rb +29 -0
- data/lib/shaf/profile/evaluator.rb +46 -0
- data/lib/shaf/profile/relation.rb +29 -0
- data/lib/shaf/profile/unique_id.rb +58 -0
- data/lib/shaf/profiles.rb +42 -0
- data/lib/shaf/profiles/shaf_basic.rb +20 -0
- data/lib/shaf/profiles/shaf_error.rb +48 -0
- data/lib/shaf/profiles/shaf_form.rb +109 -0
- data/lib/shaf/responder.rb +41 -2
- data/lib/shaf/responder/alps_json.rb +25 -0
- data/lib/shaf/responder/base.rb +20 -17
- data/lib/shaf/responder/hal.rb +62 -7
- data/lib/shaf/responder/html.rb +65 -9
- data/lib/shaf/responder/problem_json.rb +1 -1
- data/lib/shaf/serializer.rb +31 -0
- data/lib/shaf/settings.rb +25 -12
- data/lib/shaf/spec.rb +1 -0
- data/lib/shaf/spec/authenticator.rb +13 -0
- data/lib/shaf/spec/base.rb +1 -1
- data/lib/shaf/spec/http_method_utils.rb +1 -1
- data/lib/shaf/spec/integration_spec.rb +25 -13
- data/lib/shaf/spec/payload_utils.rb +2 -2
- data/lib/shaf/supported_http_methods.rb +15 -0
- data/lib/shaf/tasks/api_doc_task.rb +24 -3
- data/lib/shaf/tasks/routes_task.rb +14 -17
- data/lib/shaf/upgrade/manifest.rb +11 -2
- data/lib/shaf/upgrade/package.rb +78 -49
- data/lib/shaf/upgrade/version.rb +11 -10
- data/lib/shaf/utils.rb +19 -5
- data/lib/shaf/version.rb +3 -1
- data/lib/shaf/yard.rb +34 -0
- data/lib/shaf/yard/attribute_method_handler.rb +19 -0
- data/lib/shaf/yard/attribute_object.rb +30 -0
- data/lib/shaf/yard/base_method_handler.rb +30 -0
- data/lib/shaf/yard/link_method_handler.rb +39 -0
- data/lib/shaf/yard/link_object.rb +60 -0
- data/lib/shaf/yard/nested_attributes.rb +37 -0
- data/lib/shaf/yard/parser.rb +64 -0
- data/lib/shaf/yard/profile_method_handler.rb +51 -0
- data/lib/shaf/yard/profile_object.rb +21 -0
- data/lib/shaf/yard/resource_object.rb +55 -0
- data/lib/shaf/yard/serializer_handler.rb +27 -0
- data/templates/api/controllers/base_controller.rb +0 -10
- data/templates/api/controllers/docs_controller.rb +5 -3
- data/templates/api/controllers/root_controller.rb +7 -1
- data/templates/api/policies/base_policy.rb +2 -0
- data/templates/api/serializers/base_serializer.rb +1 -3
- data/templates/api/serializers/error_serializer.rb +1 -5
- data/templates/api/serializers/form_serializer.rb +1 -5
- data/templates/api/serializers/validation_error_serializer.rb +1 -5
- data/templates/config.ru +1 -1
- data/templates/config/bootstrap.rb +1 -2
- data/templates/config/directories.rb +52 -44
- data/templates/config/helpers.rb +1 -1
- data/templates/config/initializers.rb +52 -8
- data/templates/config/initializers/authentication.rb +18 -0
- data/templates/config/initializers/db_migrations.rb +2 -2
- data/templates/config/initializers/logging.rb +2 -2
- data/templates/frontend/assets/css/main.css +33 -1
- data/templates/frontend/views/headers.erb +20 -0
- data/templates/frontend/views/layout.erb +7 -1
- data/templates/frontend/views/payload.erb +1 -0
- data/templates/spec/spec_helper.rb +2 -0
- data/upgrades/0.5.0.tar.gz +0 -0
- data/upgrades/1.0.4.tar.gz +0 -0
- data/upgrades/1.1.0.tar.gz +0 -0
- data/upgrades/1.6.0.tar.gz +0 -0
- data/upgrades/1.6.1.tar.gz +0 -0
- data/upgrades/2.0.0.tar.gz +0 -0
- data/yard_templates/api_doc/doc_index/html/body.erb +3 -0
- data/yard_templates/api_doc/doc_index/setup.rb +8 -0
- data/yard_templates/api_doc/html/css/api-doc.css +222 -0
- data/yard_templates/api_doc/html/favicon.ico +0 -0
- data/yard_templates/api_doc/html/js/switch_tab.js +17 -0
- data/yard_templates/api_doc/html/setup.rb +59 -0
- data/yard_templates/api_doc/layout/html/footer.erb +3 -0
- data/yard_templates/api_doc/layout/html/header.erb +7 -0
- data/yard_templates/api_doc/layout/html/layout.erb +13 -0
- data/yard_templates/api_doc/layout/setup.rb +24 -0
- data/yard_templates/api_doc/profile/html/attributes.erb +10 -0
- data/yard_templates/api_doc/profile/html/profile.erb +6 -0
- data/yard_templates/api_doc/profile/html/relations.erb +10 -0
- data/yard_templates/api_doc/profile/setup.rb +38 -0
- data/yard_templates/api_doc/profile_attribute/html/attribute.erb +23 -0
- data/yard_templates/api_doc/profile_attribute/setup.rb +21 -0
- data/yard_templates/api_doc/profile_relation/html/relation.erb +37 -0
- data/yard_templates/api_doc/profile_relation/setup.rb +41 -0
- data/yard_templates/api_doc/resource/html/attributes.erb +10 -0
- data/yard_templates/api_doc/resource/html/profile.erb +14 -0
- data/yard_templates/api_doc/resource/html/relations.erb +10 -0
- data/yard_templates/api_doc/resource/html/resource.erb +5 -0
- data/yard_templates/api_doc/resource/setup.rb +56 -0
- data/yard_templates/api_doc/resource_attribute/html/attribute.erb +23 -0
- data/yard_templates/api_doc/resource_attribute/setup.rb +20 -0
- data/yard_templates/api_doc/resource_relation/html/relation.erb +47 -0
- data/yard_templates/api_doc/resource_relation/setup.rb +80 -0
- data/yard_templates/api_doc/setup.rb +31 -0
- data/yard_templates/api_doc/sidebar/html/profile_list.erb +8 -0
- data/yard_templates/api_doc/sidebar/html/search.erb +7 -0
- data/yard_templates/api_doc/sidebar/html/serializer_list.erb +8 -0
- data/yard_templates/api_doc/sidebar/html/sidebar.erb +13 -0
- data/yard_templates/api_doc/sidebar/setup.rb +56 -0
- metadata +140 -30
- metadata.gz.sig +1 -2
- data/lib/shaf/extensions/current_user.rb +0 -48
- data/lib/shaf/responder/hal_serializable.rb +0 -54
@@ -0,0 +1,16 @@
|
|
1
|
+
module Profiles
|
2
|
+
class <%= profile_class_name %> < Shaf::Profile
|
3
|
+
name '<%= profile_name %>'
|
4
|
+
|
5
|
+
doc 'FIXME: replace this with a description of the <%= profile_name %> profile'
|
6
|
+
|
7
|
+
use :delete, from: Shaf::Profiles::ShafBasic
|
8
|
+
|
9
|
+
<% attributes.each do |name, type| %>
|
10
|
+
attribute :<%= name %>,
|
11
|
+
type: '<%= type %>',
|
12
|
+
doc: 'FIXME: Write documentation for <%= name %>'
|
13
|
+
|
14
|
+
<% end %>
|
15
|
+
end
|
16
|
+
end
|
@@ -6,9 +6,9 @@ class <%= class_name %> < BaseSerializer
|
|
6
6
|
model <%= model_class_name %>
|
7
7
|
policy <%= policy_class_name %>
|
8
8
|
|
9
|
-
<%=
|
9
|
+
<%= print(profile_with_doc) %>
|
10
10
|
|
11
|
-
<%= print_nested(
|
11
|
+
<%= print_nested(attributes_with_doc) %>
|
12
12
|
|
13
13
|
<%= print_nested(links_with_doc) %>
|
14
14
|
|
@@ -14,8 +14,7 @@ describe <%= model_class_name %>, type: :integration do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "lists all <%= plural_name %>" do
|
17
|
-
<%= model_class_name %>.create
|
18
|
-
<%= model_class_name %>.create
|
17
|
+
2.times { <%= model_class_name %>.create }
|
19
18
|
|
20
19
|
get <%= plural_name %>_uri
|
21
20
|
_(status).must_equal 200
|
@@ -15,8 +15,8 @@ describe <%= class_name %> do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it "serializes attributes" do
|
18
|
-
<%
|
19
|
-
_(attributes.keys).must_include(
|
18
|
+
<% attribute_names.each do |attr| -%>
|
19
|
+
_(attributes.keys).must_include(:<%= attr %>)
|
20
20
|
<% end -%>
|
21
21
|
end
|
22
22
|
|
@@ -33,13 +33,13 @@ describe <%= class_name %> do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "serializes attributes" do
|
36
|
-
<%
|
37
|
-
_(attributes.keys).must_include(
|
36
|
+
<% attribute_names.each do |attr| -%>
|
37
|
+
_(attributes.keys).must_include(:<%= attr %>)
|
38
38
|
<% end -%>
|
39
39
|
end
|
40
40
|
|
41
41
|
it "serializes links" do
|
42
|
-
<%
|
42
|
+
<% link_relations.each do |rel| -%>
|
43
43
|
_(link_rels).must_include(:'<%= rel %>')
|
44
44
|
<% end -%>
|
45
45
|
end
|
data/lib/shaf/helpers.rb
CHANGED
@@ -3,6 +3,8 @@ require 'shaf/helpers/json_html'
|
|
3
3
|
require 'shaf/helpers/paginate'
|
4
4
|
require 'shaf/helpers/payload'
|
5
5
|
require 'shaf/helpers/http_header'
|
6
|
+
require 'shaf/helpers/authentication'
|
7
|
+
require 'shaf/helpers/vary'
|
6
8
|
|
7
9
|
module Shaf
|
8
10
|
def self.helpers
|
@@ -12,6 +14,8 @@ module Shaf
|
|
12
14
|
Paginate,
|
13
15
|
Payload,
|
14
16
|
HttpHeader,
|
17
|
+
Authentication,
|
18
|
+
Vary,
|
15
19
|
]
|
16
20
|
end
|
17
21
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require 'shaf/authenticator'
|
5
|
+
require 'shaf/errors'
|
6
|
+
|
7
|
+
module Shaf
|
8
|
+
module Authentication
|
9
|
+
class NoChallengesError < Error
|
10
|
+
def initialize(realm)
|
11
|
+
super("No Authentication challenges for realm: #{realm.inspect}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class RealmChangedError < Error
|
16
|
+
def initialize(from:, to:)
|
17
|
+
super <<~ERR
|
18
|
+
Realm was changed from "#{from}" to "#{to}". This is not allowed!
|
19
|
+
Each request corresponds to a certain realm and cannot be changed.
|
20
|
+
This is probably caused by a call to `current_user` using the
|
21
|
+
default realm (from `Shaf::Settings.default_authentication_realm`)
|
22
|
+
and then using `#authenticate realm: 'some_other_realm'
|
23
|
+
ERR
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def www_authenticate(realm: Settings.default_authentication_realm)
|
28
|
+
challenges = Authenticator.challenges_for(realm: realm)
|
29
|
+
raise NoChallengesError.new(realm) if challenges.empty?
|
30
|
+
|
31
|
+
headers 'WWW-Authenticate' => challenges.map(&:to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
def authenticate(realm: Settings.default_authentication_realm)
|
35
|
+
if defined?(@current_realm) && @current_realm&.to_s != realm&.to_s
|
36
|
+
raise RealmChangedError.new(from: @current_realm , to: realm)
|
37
|
+
else
|
38
|
+
@current_realm = realm
|
39
|
+
end
|
40
|
+
|
41
|
+
current_user.tap do |user|
|
42
|
+
www_authenticate(realm: realm) unless user
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def authenticate!(realm: Settings.default_authentication_realm)
|
47
|
+
user = authenticate(realm: realm)
|
48
|
+
return user if user
|
49
|
+
|
50
|
+
msg = +"Unauthorized action"
|
51
|
+
msg << " (Realm: #{realm})" if realm
|
52
|
+
raise Shaf::Errors::UnauthorizedError, msg
|
53
|
+
end
|
54
|
+
alias current_user! authenticate!
|
55
|
+
|
56
|
+
def authenticated?
|
57
|
+
!current_user.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
def current_user
|
61
|
+
unless defined? @current_realm
|
62
|
+
if Settings.key? :default_authentication_realm
|
63
|
+
@current_realm = Settings.default_authentication_realm
|
64
|
+
else
|
65
|
+
Shaf.logger.info <<~MSG
|
66
|
+
No realm has been provided!
|
67
|
+
Authentication/authorization cannot be performed. Did you perhaps
|
68
|
+
forget to configure a realm in
|
69
|
+
`Settings.default_authentication_realm` or provide it when calling
|
70
|
+
`#authenticate!` (or `#authenticate!`)
|
71
|
+
MSG
|
72
|
+
return
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
@current_user ||= Authenticator.user(request.env, realm: @current_realm)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Shaf
|
2
2
|
module CacheControl
|
3
3
|
def cache_control(*args, **kwargs)
|
4
|
-
return unless Shaf::Settings.http_cache
|
5
4
|
__rewrite_max_age(kwargs)
|
6
5
|
super(*args, **kwargs)
|
7
6
|
end
|
@@ -11,7 +10,7 @@ module Shaf
|
|
11
10
|
def __rewrite_max_age(kwargs)
|
12
11
|
max_age = kwargs.delete(:http_cache_max_age)
|
13
12
|
if max_age.is_a? Symbol
|
14
|
-
key = "http_cache_max_age_#{max_age}"
|
13
|
+
key = :"http_cache_max_age_#{max_age}"
|
15
14
|
max_age = Settings.respond_to?(key) ? Settings.send(key) : 86_400
|
16
15
|
end
|
17
16
|
kwargs[:max_age] ||= max_age
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shaf
|
2
4
|
module JsonHtml
|
5
|
+
STRUCTURAL_PATTERN = /^[\[\]\{\}:,]$/.freeze
|
3
6
|
|
4
7
|
def json2html(json)
|
5
8
|
as_html JSON.parse(json)
|
@@ -18,7 +21,7 @@ module Shaf
|
|
18
21
|
when Hash
|
19
22
|
html_hash(obj, indent, pre_indent)
|
20
23
|
else
|
21
|
-
html_scalar(obj,
|
24
|
+
html_scalar(obj, pre_indent)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
@@ -28,41 +31,78 @@ module Shaf
|
|
28
31
|
end
|
29
32
|
|
30
33
|
<<~EOS.chomp
|
31
|
-
#{pre_indent}
|
32
|
-
#{array_of_strings.join(
|
33
|
-
#{indentation(indent)}
|
34
|
+
#{pre_indent}#{span '['}
|
35
|
+
#{array_of_strings.join(item_separator)}
|
36
|
+
#{indentation(indent)}#{span ']'}
|
34
37
|
EOS
|
35
38
|
end
|
36
39
|
|
37
40
|
def html_hash(h, indent, pre_indent)
|
38
41
|
<<~EOS.chomp
|
39
|
-
#{pre_indent}
|
40
|
-
#{h.map { |k,v| sub_hash(k,v, indent + 1) }.join(
|
41
|
-
#{indentation(indent)}
|
42
|
+
#{pre_indent}#{span '{'}
|
43
|
+
#{h.map { |k,v| sub_hash(k,v, indent + 1) }.join(item_separator)}#{item_separator}
|
44
|
+
#{indentation(indent)}#{span '}'}
|
42
45
|
EOS
|
43
46
|
end
|
44
47
|
|
45
|
-
def html_scalar(s,
|
46
|
-
|
47
|
-
format "%s%s%s%s", pre_indent, q, s, q
|
48
|
+
def html_scalar(s, pre_indent)
|
49
|
+
format '%s%s', pre_indent, span(s)
|
48
50
|
end
|
49
51
|
|
50
52
|
def sub_hash(key, value, indent)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
left_side = format '%s%s%s ', indentation(indent), quoted(key), span(':')
|
54
|
+
left_side +
|
55
|
+
if key.to_s == 'href'
|
56
|
+
link(value)
|
57
|
+
else
|
58
|
+
to_html(value, indent: indent)
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
62
|
def indentation(i)
|
59
63
|
" " * i
|
60
64
|
end
|
61
65
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
66
|
+
def quoted(obj)
|
67
|
+
case obj
|
68
|
+
when STRUCTURAL_PATTERN
|
69
|
+
obj
|
70
|
+
when String, Symbol
|
71
|
+
format '"%s"', obj
|
72
|
+
when NilClass
|
73
|
+
'null'
|
74
|
+
else
|
75
|
+
obj
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def link(href)
|
80
|
+
format '<a href="%s">%s</a>', href, quoted(href)
|
65
81
|
end
|
66
82
|
|
83
|
+
def span(value)
|
84
|
+
clazz = span_class(value)
|
85
|
+
value = quoted(value)
|
86
|
+
format '<span class="%s">%s</span>', clazz, value
|
87
|
+
end
|
88
|
+
|
89
|
+
def span_class(obj)
|
90
|
+
case obj
|
91
|
+
when TrueClass, FalseClass
|
92
|
+
'boolean'
|
93
|
+
when NilClass
|
94
|
+
'null'
|
95
|
+
when Numeric
|
96
|
+
'number'
|
97
|
+
when STRUCTURAL_PATTERN
|
98
|
+
'structural'
|
99
|
+
else
|
100
|
+
'string'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def item_separator
|
105
|
+
"#{span ','}\n"
|
106
|
+
end
|
67
107
|
end
|
68
108
|
end
|
data/lib/shaf/helpers/payload.rb
CHANGED
@@ -2,49 +2,32 @@
|
|
2
2
|
|
3
3
|
require 'set'
|
4
4
|
require 'shaf/responder'
|
5
|
+
require 'shaf/parser'
|
6
|
+
require 'shaf/errors'
|
5
7
|
|
6
8
|
module Shaf
|
7
9
|
module Payload
|
8
|
-
|
10
|
+
NO_VALUE = Object.new.freeze
|
9
11
|
|
10
12
|
private
|
11
13
|
|
12
14
|
def payload
|
13
|
-
@payload
|
14
|
-
|
15
|
-
|
16
|
-
def read_input
|
17
|
-
request.body.rewind unless request.body.pos.zero?
|
18
|
-
request.body.read
|
19
|
-
ensure
|
20
|
-
request.body.rewind
|
15
|
+
return @payload if defined? @payload
|
16
|
+
@payload = parse_payload
|
21
17
|
end
|
22
18
|
|
23
19
|
def parse_payload
|
24
|
-
|
25
|
-
return params.reject { |key, _| EXCLUDED_FORM_PARAMS.include? key }
|
26
|
-
end
|
27
|
-
|
28
|
-
input = read_input
|
29
|
-
return {} if input.empty?
|
20
|
+
return unless Parser.input? request
|
30
21
|
|
31
|
-
|
22
|
+
parser = Parser.for(request)
|
23
|
+
raise Errors::UnsupportedMediaTypeError.new(request: request) unless parser
|
32
24
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
rescue StandardError => e
|
25
|
+
log.debug "Parsing input using: #{parser.class}"
|
26
|
+
parser.call
|
27
|
+
rescue Parser::Error => e
|
37
28
|
raise Errors::BadRequestError, "Failed to parse input payload: #{e.message}"
|
38
29
|
end
|
39
30
|
|
40
|
-
def suported_media_type?
|
41
|
-
request.env['CONTENT_TYPE'].match? %r{\Aapplication/(hal\+)?json}
|
42
|
-
end
|
43
|
-
|
44
|
-
def raise_unsupported_media_type_error(request)
|
45
|
-
raise Errors::UnsupportedMediaTypeError.new(request: request)
|
46
|
-
end
|
47
|
-
|
48
31
|
def safe_params(*fields)
|
49
32
|
return {} unless payload
|
50
33
|
|
@@ -57,12 +40,8 @@ module Shaf
|
|
57
40
|
end
|
58
41
|
end
|
59
42
|
|
60
|
-
def
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
def profile(value = nil)
|
65
|
-
return @profile unless value
|
43
|
+
def profile(value = NO_VALUE)
|
44
|
+
return @profile if value == NO_VALUE
|
66
45
|
@profile = value
|
67
46
|
end
|
68
47
|
|
@@ -72,6 +51,7 @@ module Shaf
|
|
72
51
|
status: status,
|
73
52
|
serializer: serializer,
|
74
53
|
collection: true,
|
54
|
+
preload: preload,
|
75
55
|
**kwargs
|
76
56
|
)
|
77
57
|
end
|
@@ -80,14 +60,12 @@ module Shaf
|
|
80
60
|
status ||= resource.respond_to?(:http_status) ? resource.http_status : 200
|
81
61
|
status(status)
|
82
62
|
|
83
|
-
kwargs.merge!(
|
84
|
-
|
85
|
-
serializer: serializer,
|
86
|
-
collection: collection
|
87
|
-
)
|
63
|
+
kwargs.merge!(serializer: serializer, collection: collection)
|
64
|
+
kwargs[:profile] ||= profile
|
88
65
|
|
89
66
|
log.info "#{request.request_method} #{request.path_info} => #{status}"
|
90
|
-
|
67
|
+
responder = Responder.for(request, resource)
|
68
|
+
payload = responder.call(self, resource, preload: preload, **kwargs)
|
91
69
|
add_cache_headers(payload, kwargs)
|
92
70
|
payload
|
93
71
|
rescue StandardError => err
|
@@ -95,6 +73,8 @@ module Shaf
|
|
95
73
|
if status == 500
|
96
74
|
content_type mime_type(:json)
|
97
75
|
body JSON.generate(failure: err.message)
|
76
|
+
elsif err.is_a? Errors::ServerError
|
77
|
+
respond_with(err)
|
98
78
|
else
|
99
79
|
respond_with(Errors::ServerError.new(err.message))
|
100
80
|
end
|
@@ -102,10 +82,16 @@ module Shaf
|
|
102
82
|
|
103
83
|
def add_cache_headers(payload, kwargs)
|
104
84
|
return unless kwargs.delete(:http_cache) { Settings.http_cache }
|
85
|
+
|
86
|
+
chksum, kind = etag_for(payload)
|
87
|
+
etag(chksum, kind: kind) if chksum
|
88
|
+
end
|
89
|
+
|
90
|
+
def etag_for(payload)
|
105
91
|
return if payload.nil? || payload.empty?
|
106
92
|
|
107
93
|
sha1 = Digest::SHA1.hexdigest payload
|
108
|
-
|
94
|
+
[sha1, :weak] # Weak or Strong??
|
109
95
|
end
|
110
96
|
end
|
111
97
|
end
|