From 80bc8352b7dba987881a66c4db33d78a3b2fdefd Mon Sep 17 00:00:00 2001 From: Christopher Thornton Date: Thu, 31 Aug 2017 16:31:04 -0700 Subject: [PATCH] Add linting for the ACL file --- CHANGES.md | 6 ++++++ lib/rails/auth/acl.rb | 9 +++++++++ lib/rails/auth/version.rb | 2 +- rails-auth.gemspec | 1 + spec/fixtures/example_invalid_acl.yml | 7 +++++++ spec/rails/auth/acl_spec.rb | 13 +++++++++++++ 6 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 spec/fixtures/example_invalid_acl.yml diff --git a/CHANGES.md b/CHANGES.md index 1dac4cd..e8eaf32 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +### 2.2.0 (2017-08-31) + +* [#46](https://github.com/square/rails-auth/pull/46) + Add linting for YAML acl checks (i.e. prevent duplicate keys) + ([@cgthornt]) + ### 2.1.3 (2017-08-04) * [#44](https://github.com/square/rails-auth/pull/44) diff --git a/lib/rails/auth/acl.rb b/lib/rails/auth/acl.rb index e6d7a2f..bad3b61 100644 --- a/lib/rails/auth/acl.rb +++ b/lib/rails/auth/acl.rb @@ -17,6 +17,15 @@ class ACL # @param [String] :yaml serialized YAML to load an ACL from def self.from_yaml(yaml, **args) require "yaml" + require "yamllint" + + linter = YamlLint::Linter.new + linter.check_stream(StringIO.new(yaml)) + if linter.errors? + # Always in the format of {"" => ["msg1", "msg2", ...]} + msg = linter.errors[""].join(", ") + raise ParseError, "ACL lint failed: #{msg}" + end new(YAML.load(yaml), **args) end diff --git a/lib/rails/auth/version.rb b/lib/rails/auth/version.rb index 9b846bb..de5e78b 100644 --- a/lib/rails/auth/version.rb +++ b/lib/rails/auth/version.rb @@ -3,6 +3,6 @@ module Rails # Pluggable authentication and authorization for Rack/Rails module Auth - VERSION = "2.1.3".freeze + VERSION = "2.2.0".freeze end end diff --git a/rails-auth.gemspec b/rails-auth.gemspec index 368f050..a96d4d5 100644 --- a/rails-auth.gemspec +++ b/rails-auth.gemspec @@ -28,6 +28,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = ">= 2.0.0" spec.add_runtime_dependency "rack" + spec.add_runtime_dependency "yamllint", "~> 0.0.9" spec.add_development_dependency "bundler", "~> 1.10" spec.add_development_dependency "rake", "~> 10.0" diff --git a/spec/fixtures/example_invalid_acl.yml b/spec/fixtures/example_invalid_acl.yml new file mode 100644 index 0000000..66958aa --- /dev/null +++ b/spec/fixtures/example_invalid_acl.yml @@ -0,0 +1,7 @@ +--- +- resources: + - method: ALL + method: POST + path: /foo/bar/.* + - path: /foo/bar + path: /bar diff --git a/spec/rails/auth/acl_spec.rb b/spec/rails/auth/acl_spec.rb index 3bde83c..599c864 100644 --- a/spec/rails/auth/acl_spec.rb +++ b/spec/rails/auth/acl_spec.rb @@ -31,4 +31,17 @@ expect(resources.first.path).to eq %r{\A/foo/bar/.*\z} end end + + describe ".from_yaml" do + subject { example_acl } + + context "when given an invalid YAML file" do + let(:example_config) { fixture_path("example_invalid_acl.yml").read } + + it "raises an error" do + expect { subject }.to raise_error Rails::Auth::ParseError, + 'ACL lint failed: The same key is defined more than once: 0.resources.0.method, The same key is defined more than once: 0.resources.1.path' + end + end + end end