package_protections 2.5.2 → 3.1.0
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 217ae8f6eee7f084ff39ce7c4cf0bb06a08c361abff49e411d730a3a79592b71
|
4
|
+
data.tar.gz: 21a4eea2876078f531a67d3705e7a0d38c11b3bf87cd265e552bda9e8661638a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1633812b257db230cf9f0244c8dd397197d4feb98f37abcd9906e5660adbfb7985c82fc6758254f99771726d49d3796c2e30438a54bd14a75c9ed3b64dbca1a0
|
7
|
+
data.tar.gz: e1aafb82c4a5a93425cbfc28135bae436b792681f6cbd8257f95e2d51d985a436e80d191313d2959a3e9c37423f970608109bca773a5ffe0ad01af3d6214b6da
|
data/README.md
CHANGED
@@ -56,7 +56,7 @@ This protection only looks at files in `packs/your_pack/app` (it ignores spec fi
|
|
56
56
|
This protection is implemented via Rubocop -- expect to see results for this when running `rubocop` however you normally do. To add to the TODO list, add to `.rubocop_todo.yml`
|
57
57
|
Lastly – this protection can be configured by setting `globally_permitted_namespaces`, e.g.:
|
58
58
|
```ruby
|
59
|
-
|
59
|
+
RuboCop::Packs.configure do |config|
|
60
60
|
config.globally_permitted_namespaces = ['SomeGlobalNamespace']
|
61
61
|
end
|
62
62
|
```
|
@@ -13,14 +13,7 @@ module PackageProtections
|
|
13
13
|
sig { params(original_package: ParsePackwerk::Package).returns(ProtectedPackage) }
|
14
14
|
def self.from(original_package)
|
15
15
|
metadata = original_package.metadata['protections'] || {}
|
16
|
-
|
17
16
|
valid_identifiers = PackageProtections.all.map(&:identifier)
|
18
|
-
invalid_identifiers = metadata.keys - valid_identifiers
|
19
|
-
|
20
|
-
if invalid_identifiers.any?
|
21
|
-
raise IncorrectPublicApiUsageError.new("Invalid configuration for package `#{original_package.name}`. The metadata keys #{invalid_identifiers.inspect} are not valid behaviors under the `protection` metadata namespace. Valid keys are #{valid_identifiers.inspect}. See https://github.com/rubyatscale/package_protections#readme for more info") # rubocop:disable Style/RaiseArgs
|
22
|
-
end
|
23
|
-
|
24
17
|
protections = {}
|
25
18
|
metadata.each_key do |protection_key|
|
26
19
|
protection = PackageProtections.with_identifier(protection_key)
|
@@ -32,18 +25,8 @@ module PackageProtections
|
|
32
25
|
end
|
33
26
|
|
34
27
|
unspecified_protections = valid_identifiers - protections.keys
|
35
|
-
protections_requiring_explicit_configuration = T.let([], T::Array[Identifier])
|
36
28
|
unspecified_protections.each do |protection_key|
|
37
|
-
|
38
|
-
if !protection.default_behavior.fail_never?
|
39
|
-
protections_requiring_explicit_configuration << protection.identifier
|
40
|
-
end
|
41
|
-
protections[protection_key] = protection.default_behavior
|
42
|
-
end
|
43
|
-
|
44
|
-
if protections_requiring_explicit_configuration.any?
|
45
|
-
error = "All protections must explicitly set unless their default behavior is `fail_never`. Missing protections: #{protections_requiring_explicit_configuration.join(', ')}"
|
46
|
-
raise IncorrectPublicApiUsageError, error
|
29
|
+
protections[protection_key] = PackageProtections.with_identifier(protection_key).default_behavior
|
47
30
|
end
|
48
31
|
|
49
32
|
new(
|
@@ -55,13 +38,7 @@ module PackageProtections
|
|
55
38
|
|
56
39
|
sig { params(protection: ProtectionInterface, metadata: T::Hash[T.untyped, T.untyped], package: ParsePackwerk::Package).returns(ViolationBehavior) }
|
57
40
|
def self.get_violation_behavior(protection, metadata, package)
|
58
|
-
|
59
|
-
unmet_preconditions = protection.unmet_preconditions_for_behavior(behavior, package)
|
60
|
-
if !unmet_preconditions.nil?
|
61
|
-
raise IncorrectPublicApiUsageError.new("#{protection.identifier} protection does not have the valid preconditions. #{unmet_preconditions}. See https://github.com/rubyatscale/package_protections#readme for more info") # rubocop:disable Style/RaiseArgs
|
62
|
-
end
|
63
|
-
|
64
|
-
behavior
|
41
|
+
ViolationBehavior.from_raw_value(metadata[protection.identifier])
|
65
42
|
end
|
66
43
|
|
67
44
|
sig { params(key: Identifier).returns(ViolationBehavior) }
|
data/lib/package_protections.rb
CHANGED
@@ -91,6 +91,49 @@ module PackageProtections
|
|
91
91
|
).compact
|
92
92
|
end
|
93
93
|
|
94
|
+
sig do
|
95
|
+
returns(T::Array[String])
|
96
|
+
end
|
97
|
+
def self.validate!
|
98
|
+
errors = T.let([], T::Array[String])
|
99
|
+
valid_identifiers = PackageProtections.all.map(&:identifier)
|
100
|
+
|
101
|
+
ParsePackwerk.all.each do |p|
|
102
|
+
metadata = p.metadata['protections'] || {}
|
103
|
+
|
104
|
+
# Validate that there are no invalid keys
|
105
|
+
invalid_identifiers = metadata.keys - valid_identifiers
|
106
|
+
if invalid_identifiers.any?
|
107
|
+
errors << "Invalid configuration for package `#{p.name}`. The metadata keys #{invalid_identifiers.inspect} are not a valid behavior under the `protection` metadata namespace. Valid keys are #{valid_identifiers.inspect}. See https://github.com/rubyatscale/package_protections#readme for more info"
|
108
|
+
end
|
109
|
+
|
110
|
+
# Validate that all protections requiring configuration have explicit configuration
|
111
|
+
unspecified_protections = valid_identifiers - metadata.keys
|
112
|
+
protections_requiring_explicit_configuration = unspecified_protections.reject do |protection_key|
|
113
|
+
protection = PackageProtections.with_identifier(protection_key)
|
114
|
+
protection.default_behavior.fail_never?
|
115
|
+
end
|
116
|
+
|
117
|
+
protections_requiring_explicit_configuration.each do |protection_identifier|
|
118
|
+
errors << "All protections must explicitly set unless their default behavior is `fail_never`. Missing protection #{protection_identifier} for package #{p.name}."
|
119
|
+
end
|
120
|
+
|
121
|
+
# Validate that all protections have all preconditions met
|
122
|
+
metadata.each do |protection_identifier, value|
|
123
|
+
next if !valid_identifiers.include?(protection_identifier)
|
124
|
+
|
125
|
+
behavior = ViolationBehavior.from_raw_value(value)
|
126
|
+
protection = PackageProtections.with_identifier(protection_identifier)
|
127
|
+
unmet_preconditions = protection.unmet_preconditions_for_behavior(behavior, p)
|
128
|
+
if unmet_preconditions
|
129
|
+
errors << "#{protection_identifier} protection does not have the valid preconditions in #{p.name}. #{unmet_preconditions}. See https://github.com/rubyatscale/package_protections#readme for more info"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
errors
|
135
|
+
end
|
136
|
+
|
94
137
|
#
|
95
138
|
# PackageProtections.set_defaults! sets any unset protections to their default enforcement
|
96
139
|
#
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
34
34
|
enabled: include_packs.any?,
|
35
35
|
metadata: {
|
36
36
|
'IncludePacks' => include_packs,
|
37
|
-
'GloballyPermittedNamespaces' => ::
|
37
|
+
'GloballyPermittedNamespaces' => ::RuboCop::Packs.config.globally_permitted_namespaces
|
38
38
|
}
|
39
39
|
)
|
40
40
|
]
|
@@ -57,23 +57,19 @@ module RuboCop
|
|
57
57
|
|
58
58
|
sig { override.params(behavior: ::PackageProtections::ViolationBehavior, package: ParsePackwerk::Package).returns(T.nilable(String)) }
|
59
59
|
def unmet_preconditions_for_behavior(behavior, package)
|
60
|
-
if
|
61
|
-
|
62
|
-
else
|
63
|
-
# We don't need to validate if the behavior is currentely fail_never
|
64
|
-
return if behavior.fail_never?
|
60
|
+
# We don't need to validate if the behavior is currentely fail_never
|
61
|
+
return if behavior.fail_never?
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
63
|
+
# The reason for this is precondition is the `MultipleNamespacesProtection` assumes this to work properly.
|
64
|
+
# To remove this precondition, we need to modify `MultipleNamespacesProtection` to be more generalized!
|
65
|
+
is_root_package = package.name == ParsePackwerk::ROOT_PACKAGE_NAME
|
66
|
+
in_allowed_directory = ::PackageProtections::EXPECTED_PACK_DIRECTORIES.any? do |expected_package_directory|
|
67
|
+
package.directory.to_s.start_with?(expected_package_directory)
|
68
|
+
end
|
69
|
+
if in_allowed_directory || is_root_package
|
70
|
+
nil
|
71
|
+
else
|
72
|
+
"Package #{package.name} must be located in one of #{::PackageProtections::EXPECTED_PACK_DIRECTORIES.join(', ')} (or be the root) to use this protection"
|
77
73
|
end
|
78
74
|
end
|
79
75
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: package_protections
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gusto Engineers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -232,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
232
232
|
- !ruby/object:Gem::Version
|
233
233
|
version: '0'
|
234
234
|
requirements: []
|
235
|
-
rubygems_version: 3.
|
235
|
+
rubygems_version: 3.1.6
|
236
236
|
signing_key:
|
237
237
|
specification_version: 4
|
238
238
|
summary: Package protections for Rails apps
|