shamu 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afa18618f6ec75e4163bbc06c2ac89d60b5729d6
4
- data.tar.gz: 0d3fc88e85d907868e82a98d8b877c326eacb4b9
3
+ metadata.gz: e6619b53b0ccf99f395e9ef5687a3eb9cd2fd661
4
+ data.tar.gz: 425daaaa1d330ffeb4ec885a59e9b0c63e5e1548
5
5
  SHA512:
6
- metadata.gz: 405509ea9020934875f4d74015c62b4733511b948c81caa617e67c94ffb3512dffd2264a8f8dcfcccd8277a2835eb142c6a84fb6edf090f6ed8dfdbd9aa8becf
7
- data.tar.gz: af3f05ab6ac199ae75d9716d430ff3270eab6fc156f74a709ad87be0d70d7042fbcc8865cb5f660cdc60d1494657854b76a8c7e6fc10a2c0039ab98402cd6f35
6
+ metadata.gz: 6f1cad8cd5b39cbfe4b186d4dfbb5b4c4f1c5e549dabb829cc801d708516fb15be7e16b8da1f9e1829203ae1d4b695ac6acb8f943767910f716591deb93fc659
7
+ data.tar.gz: 9cccb625e79e236cc7829cf86db880f0a0ac814847b305137c7e33d222e63ca507c0e373c243c9472d40159e503f65fb5169fb4c1d9e5bd684a6def1aac54662
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.0
1
+ 2.3.1
data/Gemfile CHANGED
@@ -14,7 +14,7 @@ group :test do
14
14
 
15
15
  gem "sqlite3", "~> 1.3.11"
16
16
  gem "guard", "~> 2.12.8"
17
- gem "rubocop"
17
+ gem "rubocop", "~> 0.39.0"
18
18
  gem "guard-rubocop"
19
19
  gem "spring"
20
20
  gem "guard-rspec"
@@ -0,0 +1,218 @@
1
+ require "loofah"
2
+
3
+ module Shamu
4
+ module Attributes
5
+
6
+ # Adds an HTML sanitation option to attributes. When present, string values
7
+ # will be sanitized when the attribute is read.
8
+ #
9
+ # The raw unfiltered value is always available as `#{ attribute }_raw`.
10
+ module HtmlSanitation
11
+ extend ActiveSupport::Concern
12
+
13
+ # The standard HTML sanitation filter methods.
14
+ STANDARD_FILTER_METHODS = [
15
+ :none, # Don't allow any HTML
16
+ :simple, # Allow very simple HTML. See {#simple_html_sanitize}.
17
+ :body, # Allow subset useful for body copy. See
18
+ # {#body_html_sanitize}.
19
+ :safe, # Allow a broad subset of HTML tags and attributes. See
20
+ # {#safe_html_sanitize}.
21
+ :allow # Allow all HTML.
22
+ ].freeze
23
+
24
+ # Tags safe for simple text.
25
+ SIMPLE_TAGS = %w( B I STRONG EM ).freeze
26
+
27
+ # Tags safe for body text.
28
+ BODY_TAGS = %w( B BR CODE DIV EM H2 H3 H4 H5 H6 HR I LI OL P PRE SPAN STRONG U UL ).freeze
29
+
30
+ # Tags that are not safe.
31
+ UNSAFE_TAGS = %w( FORM SCRIPT IFRAME FRAME ).freeze
32
+
33
+ class_methods do
34
+ # (see Attributes.attribute)
35
+ # @param [Symbol,#call] html sanitation options. Acceptable values are
36
+ #
37
+ # - `:none` strip all HTML. The default.
38
+ # - `:simple` simple formatting suitable for most places. See
39
+ # {#simple_html_sanitize} for details.
40
+ # - `:body` basic formatting for 'body' text. See
41
+ # {#body_html_sanitize} for details.
42
+ # - `:allow` permit any HTML tag.
43
+ # - Any other symbol is assumed to be a method on the entity that will
44
+ # be called to filter the html.
45
+ # - `#call` anything that responds to `#call` that takes a single
46
+ # argument of the raw string and returns the sanitized HTML.
47
+ def attribute( name, *args, **options, &block )
48
+ super.tap do
49
+ define_html_sanitized_attribute_reader( name, options[ :html ] ) if options.key?( :html )
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def define_attribute_reader( name, as: nil, ** )
56
+ super
57
+
58
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
59
+ def #{ name }_raw # def attribute_raw
60
+ return @#{ name } if defined? @#{ name } # return @attribute if defined? @attribute
61
+ @#{ name } = fetch_#{ name } # @attribute = fetch_attribute
62
+ end # end
63
+ RUBY
64
+ end
65
+
66
+ def define_html_sanitized_attribute_reader( name, method )
67
+ method ||= :none
68
+
69
+ filter_method = resolve_html_filter_method( name, method )
70
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
71
+ def #{ name } # def attribute
72
+ return @#{ name }_html_sanitized if defined? @#{ name }_html_sanitized # return @attribute_html_sanitized if defined? @attribute_html_sanitized
73
+ @#{ name }_html_sanitized = #{ filter_method }( #{ name }_raw ) # @attribute_html_sanitized = simple_html_sanitized( attribute_raw )
74
+ end # end
75
+ RUBY
76
+ end
77
+
78
+ def resolve_html_filter_method( name, method )
79
+ if STANDARD_FILTER_METHODS.include?( method )
80
+ "#{ method }_html_sanitize"
81
+ elsif method.is_a?( Symbol )
82
+ method
83
+ else
84
+ filter_method = "custom_#{ name }_html_sanitize"
85
+ define_method filter_method, &method
86
+ filter_method
87
+ end
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ # @!visibility public
94
+ #
95
+ # Remove all HTML from the value.
96
+ #
97
+ # @param [String] value to sanitize.
98
+ # @return [String] the sanitized value.
99
+ def none_html_sanitize( value )
100
+ return value unless value.is_a?( String )
101
+
102
+ Loofah.fragment( value ).scrub!( NoneScrubber.new ).to_s
103
+ end
104
+
105
+ # @!visibility public
106
+ #
107
+ # Remove all but the simplest html tags <B>, <I>, <STRONG>, <EM>.
108
+ #
109
+ # @param [String] value to sanitize.
110
+ # @return [String] the sanitized value.
111
+ def simple_html_sanitize( value )
112
+ return value unless value.is_a?( String )
113
+
114
+ Loofah.fragment( value ).scrub!( SimpleScrubber.new ).to_s
115
+ end
116
+
117
+ # @!visibility public
118
+ #
119
+ # Remove all but a limited subset of common tags useful for body copy
120
+ # text. See {BODY_TAGS}.
121
+ #
122
+ # @param [String] value to sanitize.
123
+ # @return [String] the sanitized value.
124
+ def body_html_sanitize( value )
125
+ return value unless value.is_a?( String )
126
+
127
+ Loofah.fragment( value ).scrub!( BodyScrubber.new ).to_s
128
+ end
129
+
130
+ # @!visibility public
131
+ #
132
+ # Remove all HTML from the value.
133
+ #
134
+ # @param [String] value to sanitize.
135
+ # @return [String] the sanitized value.
136
+ def safe_html_sanitize( value )
137
+ return value unless value.is_a?( String )
138
+
139
+ Loofah.fragment( value )
140
+ .scrub!( SafeScrubber.new )
141
+ .scrub!( :no_follow )
142
+ .to_s
143
+ end
144
+
145
+ # @!visibility public
146
+ #
147
+ # Does not perform any sanitization of the value.
148
+ #
149
+ # @param [String] value to sanitize.
150
+ # @return [String] the sanitized value.
151
+ def allow_html_sanitize( value )
152
+ return value unless value.is_a?( String )
153
+
154
+ Loofah.fragment( value ).scrub!( :no_follow ).to_s
155
+ end
156
+
157
+ class NoneScrubber < Loofah::Scrubber
158
+ def initialize
159
+ @direction = :bottom_up
160
+ end
161
+
162
+ def scrub( node )
163
+ if node.text?
164
+ Loofah::Scrubber::CONTINUE
165
+ else
166
+ node.before node.children
167
+ node.remove
168
+ end
169
+ end
170
+ end
171
+
172
+ class PermitScrubber < Loofah::Scrubber
173
+ def initialize
174
+ @direction = :bottom_up
175
+ end
176
+
177
+ def scrub( node )
178
+ if node.type == Nokogiri::XML::Node::ELEMENT_NODE
179
+ if allowed_element?( node.name )
180
+ Loofah::HTML5::Scrub.scrub_attributes node
181
+ else
182
+ node.before node.children unless unsafe_element?( node.name )
183
+ node.remove
184
+ end
185
+ end
186
+
187
+ Loofah::Scrubber::CONTINUE
188
+ end
189
+
190
+ def allowed_element?( name )
191
+ end
192
+
193
+ def unsafe_element?( name )
194
+ UNSAFE_TAGS.include?( name.upcase )
195
+ end
196
+ end
197
+
198
+ class SimpleScrubber < PermitScrubber
199
+ def allowed_element?( name )
200
+ SIMPLE_TAGS.include?( name.upcase )
201
+ end
202
+ end
203
+
204
+ class BodyScrubber < PermitScrubber
205
+ def allowed_element?( name )
206
+ BODY_TAGS.include?( name.upcase )
207
+ end
208
+ end
209
+
210
+ class SafeScrubber < PermitScrubber
211
+ def allowed_element?( name )
212
+ !unsafe_element?( name )
213
+ end
214
+ end
215
+
216
+ end
217
+ end
218
+ end
@@ -12,6 +12,7 @@ module Shamu
12
12
  # - {Attributes::FluidAssignment}
13
13
  # - {Attributes::Validation}
14
14
  # - {Attributes::Equality}
15
+ # - {Attributes::HtmlSanitation}
15
16
  #
16
17
  # @example
17
18
  #
@@ -27,6 +28,7 @@ module Shamu
27
28
  require "shamu/attributes/fluid_assignment"
28
29
  require "shamu/attributes/validation"
29
30
  require "shamu/attributes/equality"
31
+ require "shamu/attributes/html_sanitation"
30
32
 
31
33
  def initialize( *attributes )
32
34
  assign_attributes( attributes.last )
@@ -0,0 +1,24 @@
1
+ module Shamu
2
+ module Entities
3
+
4
+ # Forces all string attributes to be html sanitized.
5
+ module HtmlSanitation
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ include Shamu::Attributes::HtmlSanitation
10
+ extend AttributeMethod
11
+ end
12
+
13
+ module AttributeMethod
14
+ # (see Attributes::HtmlSanitation.attribute)
15
+ def attribute( name, *args, **options, &block )
16
+ options[:html] ||= :none
17
+
18
+ super name, *args, **options, &block
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -7,5 +7,6 @@ module Shamu
7
7
  require "shamu/entities/list_scope"
8
8
  require "shamu/entities/identity_cache"
9
9
  require "shamu/entities/entity_path"
10
+ require "shamu/entities/html_sanitation"
10
11
  end
11
12
  end
@@ -17,7 +17,7 @@ en:
17
17
  access_denied: You are not permitted to do that.
18
18
  incomplete_setup: Security has been enabled but is not yet configured.
19
19
  no_actiev_record_policy_checks: Don't check for policy on ActiveRecord resources. Check their projected Entity instead.
20
-
20
+ no_policy_impersonation: Impersonation is not supported by this principal.
21
21
  events:
22
22
  errors:
23
23
  unknown_runner: Unknown runner. Each process should offer a consitent but unique runner_id.
@@ -0,0 +1,19 @@
1
+ module Shamu
2
+ module Security
3
+
4
+ # ...
5
+ class DelegatePrincipal < Principal
6
+
7
+ # (see Principal#impersonate)
8
+ def impersonate( user_id )
9
+ fail NoPolicyImpersonationError
10
+ end
11
+
12
+ # (see Principal#service_delegate?)
13
+ def service_delegate?
14
+ true
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -61,5 +61,11 @@ module Shamu
61
61
  end
62
62
  end
63
63
 
64
+ # Principal does not support impersonation.
65
+ class NoPolicyImpersonationError < Error
66
+ def initialize( message = :no_policy_impersonation )
67
+ super
68
+ end
69
+ end
64
70
  end
65
71
  end
@@ -67,6 +67,12 @@ module Shamu
67
67
  self.class.new( user_id: user_id, parent_principal: self, remote_ip: remote_ip, elevated: elevated )
68
68
  end
69
69
 
70
+ # @return [Boolean] true if the principal was offered by one service to
71
+ # another and requesting that the downstream service delegate security
72
+ # checks to the calling service.
73
+ def service_delegate?
74
+ end
75
+
70
76
  end
71
77
  end
72
78
  end
@@ -76,6 +76,7 @@ module Shamu
76
76
  # @return [Boolean] true if the service has been asked to delegate
77
77
  # policy checks to the upstream service and
78
78
  def service_policy_delegation?
79
+ security_principal.service_delegate?
79
80
  end
80
81
 
81
82
  end
@@ -70,10 +70,34 @@ module Shamu
70
70
  # end
71
71
  # end
72
72
  def with_request( params, request_class, &block )
73
- request = request_class.coerce( params )
74
- sources = yield( request ) if request.valid?
73
+ with_partial_request params, request_class do |request|
74
+ next unless request.valid?
75
75
 
76
- result request, *sources
76
+ yield request
77
+ end
78
+ end
79
+
80
+ # @!visibility public
81
+ #
82
+ # Behaves the same as {#with_request} but always executes the block even
83
+ # if the params are not yet valid. Allows the block to populate the
84
+ # request with missing information before validating.
85
+ #
86
+ # @param (see #with_request)
87
+ # @return (see #with_request)
88
+ # @see #with_request
89
+ def with_partial_request( params, request_class, &block )
90
+ request = request_class.coerce( params )
91
+ # Make sure the request captures errors even if the block doesn't
92
+ # check
93
+ request.valid?
94
+ sources = yield( request )
95
+
96
+ if sources.is_a?( Result )
97
+ sources
98
+ else
99
+ result request, *Array.wrap( sources )
100
+ end
77
101
  end
78
102
 
79
103
  # Static methods added to {RequestSupport}
@@ -116,9 +116,9 @@ module Shamu
116
116
  # record.
117
117
  # @param [Symbol,#call(record)] match the attribute or a Proc used to
118
118
  # extract the id used to compare records.
119
- # @param [Symbol,#call] coerce a method that can be used to coerce id values
120
- # to the same type (eg :to_i). If not set, automatically uses :to_i
121
- # if match is an 'id' attribute.
119
+ # @param [Symbol,#call] coerce a method that can be used to coerce id
120
+ # values to the same type (eg :to_i). If not set, automatically uses
121
+ # :to_model_id if match is an 'id' attribute.
122
122
  # @yield (see #entity_list)
123
123
  # @yieldparam (see #entity_list)
124
124
  # @yieldreturn (see #entity_list)
@@ -153,7 +153,7 @@ module Shamu
153
153
  def entity_lookup_list( records, ids, null_class, match: :id, coerce: :not_set, &transformer )
154
154
  matcher = entity_lookup_list_matcher( match )
155
155
  coerce = coerce_method( coerce, match )
156
- ids = ids.map( &coerce ) if coerce
156
+ ids = ids.map( &coerce ) if coerce
157
157
 
158
158
  list = entity_list records, &transformer
159
159
  matched = ids.map do |id|
@@ -175,7 +175,7 @@ module Shamu
175
175
 
176
176
  def coerce_method( coerce, match )
177
177
  return coerce unless coerce == :not_set
178
- :to_i if match.is_a?( Symbol ) && match =~ /(^|_)id$/
178
+ :to_model_id if match.is_a?( Symbol ) && match =~ /(^|_)ids?$/
179
179
  end
180
180
 
181
181
  # @!visibility public
@@ -297,6 +297,8 @@ module Shamu
297
297
  # end
298
298
  # end
299
299
  def cached_lookup( ids, match: :id, coerce: :not_set, entity: nil, &lookup )
300
+ coerce = coerce_method( coerce, match )
301
+ ids = ids.map( &coerce ) if coerce
300
302
  cache = cache_for( key: match, coerce: coerce, entity: entity )
301
303
  missing_ids = cache.uncached_keys( ids )
302
304
 
data/lib/shamu/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Shamu
3
3
  # The primary version number
4
- VERSION_NUMBER = "0.0.8".freeze
4
+ VERSION_NUMBER = "0.0.9".freeze
5
5
 
6
6
  # Version suffix such as 'beta' or 'alpha'
7
7
  VERSION_SUFFIX = "".freeze
data/shamu.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency "rack", "~> 1"
28
28
  spec.add_dependency "listen", "~> 3"
29
29
  spec.add_dependency "crc32", "~> 1"
30
-
30
+ spec.add_dependency "loofah", "~> 2"
31
31
 
32
32
  spec.add_development_dependency "bundler", "~> 1.6"
33
33
  spec.add_development_dependency "i18n", "~> 0.7"
@@ -0,0 +1,42 @@
1
+ require "spec_helper"
2
+
3
+ module HtmlSanitationSpec
4
+ class Attrs
5
+ include Shamu::Attributes
6
+ include Shamu::Attributes::HtmlSanitation
7
+
8
+ attribute :bio, html: :body
9
+ attribute :name, html: :simple
10
+ attribute :email, html: :none
11
+ end
12
+ end
13
+
14
+ describe Shamu::Attributes::HtmlSanitation do
15
+ context "simple sanitation" do
16
+ let( :entity ) { HtmlSanitationSpec::Attrs.new( name: "<b>Bold</b> <p>Name</p>" ) }
17
+
18
+ it "removes non-simple HTML by default" do
19
+ expect( entity.name ).to eq "<b>Bold</b> Name"
20
+ end
21
+
22
+ it "exposes original value available via raw attribute" do
23
+ expect( entity.name_raw ).to eq "<b>Bold</b> <p>Name</p>"
24
+ end
25
+ end
26
+
27
+ context "none sanitation" do
28
+ let( :entity ) { HtmlSanitationSpec::Attrs.new( email: "<b>Bold</b> <p>Name</p>" ) }
29
+
30
+ it "removes all HTML by default" do
31
+ expect( entity.email ).to eq "Bold Name"
32
+ end
33
+ end
34
+
35
+ context "body sanitation" do
36
+ let( :entity ) { HtmlSanitationSpec::Attrs.new( bio: "<script>alert('Hacked')</script><h2>Title</h2>" ) }
37
+
38
+ it "only removes illegal HTML" do
39
+ expect( entity.bio ).to eq "<h2>Title</h2>"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ module HtmlSanitationSpec
4
+ class Entity < Shamu::Entities::Entity
5
+ include Shamu::Entities::HtmlSanitation
6
+
7
+ attribute :name
8
+ end
9
+ end
10
+
11
+ describe Shamu::Attributes::HtmlSanitation do
12
+ let( :entity ) { HtmlSanitationSpec::Entity.new( name: "<b>Bold</b> <p>Name</p>" ) }
13
+
14
+ it "removes all HTML by default" do
15
+ expect( entity.name ).to eq "Bold Name"
16
+ end
17
+ end
@@ -15,6 +15,12 @@ module RequestSupportSpec
15
15
  end
16
16
  end
17
17
 
18
+ def partial_process( params )
19
+ with_partial_request( params, Request::Change ) do |_|
20
+ request_hook
21
+ end
22
+ end
23
+
18
24
  def request_hook
19
25
  end
20
26
 
@@ -120,6 +126,24 @@ describe Shamu::Services::RequestSupport do
120
126
  end
121
127
  end
122
128
 
129
+ describe "#with_partial_request" do
130
+ let( :request_params ) { { level: 1, amount: 5 } }
131
+ let( :service ) { scorpion.new RequestSupportSpec::Service }
132
+
133
+ it "yields even if params are invalid" do
134
+ request_params.delete :amount
135
+ expect( service ).to receive( :request_hook )
136
+ service.partial_process( request_params )
137
+ end
138
+
139
+ it "reports errors even if block doesn't check" do
140
+ request_params.delete :amount
141
+ result = service.partial_process( request_params )
142
+
143
+ expect( result.request.errors ).not_to be_empty
144
+ end
145
+ end
146
+
123
147
  describe "#request_for" do
124
148
  it "returns request" do
125
149
  request = service.request_for( :create )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shamu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Alexander
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-20 00:00:00.000000000 Z
11
+ date: 2016-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: loofah
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: bundler
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -213,6 +227,7 @@ files:
213
227
  - lib/shamu/attributes/assignment.rb
214
228
  - lib/shamu/attributes/equality.rb
215
229
  - lib/shamu/attributes/fluid_assignment.rb
230
+ - lib/shamu/attributes/html_sanitation.rb
216
231
  - lib/shamu/attributes/validation.rb
217
232
  - lib/shamu/auditing.rb
218
233
  - lib/shamu/auditing/README.md
@@ -228,6 +243,7 @@ files:
228
243
  - lib/shamu/entities/active_record_soft_destroy.rb
229
244
  - lib/shamu/entities/entity.rb
230
245
  - lib/shamu/entities/entity_path.rb
246
+ - lib/shamu/entities/html_sanitation.rb
231
247
  - lib/shamu/entities/identity_cache.rb
232
248
  - lib/shamu/entities/list.rb
233
249
  - lib/shamu/entities/list_scope.rb
@@ -311,6 +327,7 @@ files:
311
327
  - lib/shamu/security.rb
312
328
  - lib/shamu/security/README.md
313
329
  - lib/shamu/security/active_record_policy.rb
330
+ - lib/shamu/security/delegate_principal.rb
314
331
  - lib/shamu/security/error.rb
315
332
  - lib/shamu/security/hashed_value.rb
316
333
  - lib/shamu/security/no_policy.rb
@@ -350,6 +367,7 @@ files:
350
367
  - spec/lib/shamu/attributes/assignment_spec.rb
351
368
  - spec/lib/shamu/attributes/equality_spec.rb
352
369
  - spec/lib/shamu/attributes/fluid_assignment_spec.rb
370
+ - spec/lib/shamu/attributes/html_sanitation_spec.rb
353
371
  - spec/lib/shamu/attributes/validation_spec.rb
354
372
  - spec/lib/shamu/attributes_spec.rb
355
373
  - spec/lib/shamu/auditing/logging_auditing_service_spec.rb
@@ -358,6 +376,7 @@ files:
358
376
  - spec/lib/shamu/entities/active_record_spec.rb
359
377
  - spec/lib/shamu/entities/entity_path_spec.rb
360
378
  - spec/lib/shamu/entities/entity_spec.rb
379
+ - spec/lib/shamu/entities/html_sanitation_spec.rb
361
380
  - spec/lib/shamu/entities/identity_cache_spec.rb
362
381
  - spec/lib/shamu/entities/list_scope/dates_spec.rb
363
382
  - spec/lib/shamu/entities/list_scope/paging_spec.rb
@@ -463,6 +482,7 @@ test_files:
463
482
  - spec/lib/shamu/attributes/assignment_spec.rb
464
483
  - spec/lib/shamu/attributes/equality_spec.rb
465
484
  - spec/lib/shamu/attributes/fluid_assignment_spec.rb
485
+ - spec/lib/shamu/attributes/html_sanitation_spec.rb
466
486
  - spec/lib/shamu/attributes/validation_spec.rb
467
487
  - spec/lib/shamu/attributes_spec.rb
468
488
  - spec/lib/shamu/auditing/logging_auditing_service_spec.rb
@@ -471,6 +491,7 @@ test_files:
471
491
  - spec/lib/shamu/entities/active_record_spec.rb
472
492
  - spec/lib/shamu/entities/entity_path_spec.rb
473
493
  - spec/lib/shamu/entities/entity_spec.rb
494
+ - spec/lib/shamu/entities/html_sanitation_spec.rb
474
495
  - spec/lib/shamu/entities/identity_cache_spec.rb
475
496
  - spec/lib/shamu/entities/list_scope/dates_spec.rb
476
497
  - spec/lib/shamu/entities/list_scope/paging_spec.rb