action_policy 0.3.2 → 0.3.3

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: 998666ad64277112c6ddc44e6db9e0aa81b6bbf32994fb675797bcd8e1f9ca70
4
- data.tar.gz: 5a35c722589841c6b41d6efd1735abe63833db03b9a7aec23e798648a97c5470
3
+ metadata.gz: 782d6e62c1723d8aa9b128cf054d90ace4a52a65467db205a079f898a9e068a8
4
+ data.tar.gz: e581bec4f5a7aaa782229f85aa34d09d7ed27eb19c870dcc9d3982c3271205d8
5
5
  SHA512:
6
- metadata.gz: 03a5594069a5947566708f3b3ad419d79be8931d38c25195f754d1474fa9b2f3bcf5e0f9e520a828d56c1fcfac762929ae4fdcf852c657f4b6bec973c0559e0b
7
- data.tar.gz: e41e88d916fdf0832e7b03cdadcf7f6c1a4814c45e6ca76e12094bbcb03a6ea54146a0e676d079a0813caff31f54c3dfe90d0e917ade8c4261e17ec4d55a4221
6
+ metadata.gz: 8178fe440e7b7b8f1b60a858e503ad65e37eaa3157dca0f48b772a626704f66763392d60a2f18758d9e903d19e687f292c0b261f5c531d81693ee5e1df38472c
7
+ data.tar.gz: 8126f417658773d0deeca4d927881d8a9bf504853d89d58d1d43dd07d6f1328bc355b81bd9f12e7742ce753d20d6c17caf07a0ce2f4fd6df50e2fb0bb70ca034
data/.gitignore CHANGED
@@ -8,3 +8,8 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  Gemfile.local
11
+
12
+ spec/dummy/log/*
13
+ spec/dummy/db/*.sqlite3
14
+ spec/dummy/db/*.sqlite3-journal
15
+ spec/dummy/tmp/
@@ -12,6 +12,7 @@ AllCops:
12
12
  - 'Gemfile'
13
13
  - 'vendor/**/*'
14
14
  - 'gemfiles/**/*'
15
+ - 'lib/generators/**/templates/**/*'
15
16
  DisplayCopNames: true
16
17
  TargetRubyVersion: 2.4
17
18
 
@@ -1,5 +1,29 @@
1
1
  ## master
2
2
 
3
+ ## 0.3.3 (2019-11-27)
4
+
5
+ - Improve pretty print functionality. ([@palkan][])
6
+
7
+ Colorize true/false values.
8
+ Handle multiline expressions and debug statements (i.e., `binding.pry`).
9
+
10
+ - Add Rails generators. ([@nicolas-brousse][])
11
+
12
+ Adds `action_policy:install` and `action_policy:policy MODEL` Rails generators.
13
+
14
+ - Optional authorization target. ([@somenugget][])
15
+
16
+ Allows making authorization context optional:
17
+
18
+ ```ruby
19
+ class OptionalRolePolicy < ActionPolicy::Base
20
+ authorize :role, optional: true
21
+ end
22
+
23
+ policy = OptionalRolePolicy.new
24
+ policy.role #=> nil
25
+ ```
26
+
3
27
  ## 0.3.2 (2019-05-26) 👶
4
28
 
5
29
  - Fixed thread-safety issues with scoping configs. ([@palkan][])
@@ -313,3 +337,5 @@
313
337
  [@brendon]: https://github.com/brendon
314
338
  [@DmitryTsepelev]: https://github.com/DmitryTsepelev
315
339
  [@korolvs]: https://github.com/korolvs
340
+ [@nicolas-brousse]: https://github.com/nicolas-brousse
341
+ [@somenugget]: https://github.com/somenugget
data/README.md CHANGED
@@ -47,6 +47,8 @@ class ApplicationPolicy < ActionPolicy::Base
47
47
  end
48
48
  ```
49
49
 
50
+ This may be done with `rails generate action_policy:install` generator.
51
+
50
52
  Then write a policy for a resource. For example:
51
53
 
52
54
  ```ruby
@@ -64,6 +66,8 @@ class PostPolicy < ApplicationPolicy
64
66
  end
65
67
  ```
66
68
 
69
+ This may be done with `rails generate action_policy:policy Post` generator.
70
+
67
71
  Now you can easily add authorization to your Rails\* controller:
68
72
 
69
73
  ```ruby
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
31
31
 
32
32
  spec.required_ruby_version = ">= 2.4.0"
33
33
 
34
+ spec.add_development_dependency "ammeter", "~> 1.1.3"
34
35
  spec.add_development_dependency "bundler", ">= 1.15"
35
36
  spec.add_development_dependency "minitest", "~> 5.0"
36
37
  spec.add_development_dependency "rake", "~> 10.0"
@@ -19,6 +19,7 @@ end
19
19
  Now you must provide `account` during policy initialization. When authorization key is missing or equals to `nil`, `ActionPolicy::AuthorizationContextMissing` error is raised.
20
20
 
21
21
  **NOTE:** if you want to allow passing `nil` as `account` value, you must add `allow_nil: true` option to `authorize`.
22
+ If you want to be able not to pass `account` at all, you must add `optional: true`
22
23
 
23
24
  To do that automatically in your `authorize!` and `allowed_to?` calls, you must also configure authorization context. For example, in your controller:
24
25
 
@@ -1,15 +1,15 @@
1
1
  # GraphQL integration
2
2
 
3
- You can use Action Policy as an authorization library for you [GraphQL Ruby](https://graphql-ruby.org/) application via the [`action_policy-graphql` gem](https://github.com/palkan/action_policy-graphql).
3
+ You can use Action Policy as an authorization library for your [GraphQL Ruby](https://graphql-ruby.org/) application via the [`action_policy-graphql` gem](https://github.com/palkan/action_policy-graphql).
4
4
 
5
5
  This integration provides the following features:
6
6
  - Fields & mutations authorization
7
7
  - List and connections scoping
8
- - [**Exposing permissions/authorization rules in the API**](https://dev.to/evilmartians/exposing-permissions-in-graphql-apis-with-action-policy-1mfh).
8
+ - [**Exposing permissions/authorization rules in the API**](https://evilmartians.com/chronicles/exposing-permissions-in-graphql-apis-with-action-policy).
9
9
 
10
10
  ## Getting Started
11
11
 
12
- First, add `action_policy-graphql` gem to your Gemfile (see [installation instructions](https://github.com/palkan/action_policy-graphql#installation)).
12
+ First, add the `action_policy-graphql` gem to your Gemfile (see [installation instructions](https://github.com/palkan/action_policy-graphql#installation)).
13
13
 
14
14
  Then, include `ActionPolicy::GraphQL::Behaviour` to your base type (or any other type/mutation where you want to use authorization features):
15
15
 
@@ -23,11 +23,16 @@ end
23
23
  class Types::BaseMutation < GraphQL::Schema::Mutation
24
24
  include ActionPolicy::GraphQL::Behaviour
25
25
  end
26
+
27
+ # For using authorization helpers in resolvers
28
+ class Types::BaseResolver < GraphQL::Schema::Resolver
29
+ include ActionPolicy::GraphQL::Behaviour
30
+ end
26
31
  ```
27
32
 
28
33
  ## Authorization Context
29
34
 
30
- By default, Action Policy use `context[:current_user]` as the `user` [authorization context](./authoriation_context.md).
35
+ By default, Action Policy uses `context[:current_user]` as the `user` [authorization context](./authorization_context.md).
31
36
 
32
37
  **NOTE:** see below for more information on what's included into `ActionPolicy::GraphQL::Behaviour`.
33
38
 
@@ -75,6 +80,38 @@ You can also change the default `show?` rule globally:
75
80
  ActionPolicy::GraphQL.default_authorize_rule = :show_graphql_field?
76
81
  ```
77
82
 
83
+ If you want to perform authorization before resolving the field value, you can use `preauthorize: *` option:
84
+
85
+ ```ruby
86
+ field :homes, [Home], null: false, preauthorize: {with: HomePolicy}
87
+
88
+ def homes
89
+ Home.all
90
+ end
91
+ ```
92
+
93
+ The code above is equal to:
94
+
95
+ ```ruby
96
+ field :homes, [Home], null: false
97
+
98
+ def homes
99
+ authorize! "homes", to: :index?, with: HomePolicy
100
+ Home.all
101
+ end
102
+ ```
103
+
104
+ **NOTE:** we pass the field's name as the `record` to the policy rule. We assume that preauthorization rules do not depend on
105
+ the record itself and pass the field's name for debugging purposes only.
106
+
107
+ You can customize the authorization options, e.g. `authorize: {to: :preview?, with: CustomPolicy}`.
108
+
109
+ **NOTE:** unlike `authorize: *` you MUST specify the `with: SomePolicy` option.
110
+ The default authorization rule depends on the type of the field:
111
+
112
+ - for lists we use `index?` (configured by `ActionPolicy::GraphQL.default_preauthorize_list_rule` parameter)
113
+ - for _singleton_ fields we use `show?` (configured by `ActionPolicy::GraphQL.default_preauthorize_node_rule` parameter)
114
+
78
115
  ### Class-level authorization
79
116
 
80
117
  You can use Action Policy in the class-level [authorization hooks](https://graphql-ruby.org/authorization/authorization.html) (`self.authorized?`) like this:
@@ -83,9 +120,10 @@ You can use Action Policy in the class-level [authorization hooks](https://graph
83
120
  class Types::Friendship < Types::BaseObject
84
121
  def self.authorized?(object, context)
85
122
  super &&
86
- object.allowed_to?(
123
+ allowed_to?(
87
124
  :show?,
88
125
  object,
126
+ # NOTE: you must provide context explicitly
89
127
  context: {user: context[:current_user]}
90
128
  )
91
129
  end
@@ -94,7 +132,7 @@ end
94
132
 
95
133
  ## Authorizing Mutations
96
134
 
97
- Mutation is just a Ruby class with a single API method. There is nothing specific in authorizing mutations: from the Action Policy point of view, they are just [_behaviours_](./behaviour.md).
135
+ A mutation is just a Ruby class with a single API method. There is nothing specific in authorizing mutations: from the Action Policy point of view, they are just [_behaviours_](./behaviour.md).
98
136
 
99
137
  If you want to authorize the mutation, you call `authorize!` method. For example:
100
138
 
@@ -166,6 +204,8 @@ class CityType < ::Common::Graphql::Type
166
204
  end
167
205
  ```
168
206
 
207
+ **NOTE:** you cannot use `authorize: *` and `authorized_scope: *` at the same time but you can combine `preauthorize: *` with `authorized_scope: *`.
208
+
169
209
  See the documenation on [scoping](./scoping.md).
170
210
 
171
211
  ## Exposing Authorization Rules
@@ -221,6 +261,16 @@ You can override a custom authorization field prefix (`can_`):
221
261
  ActionPolicy::GraphQL.default_authorization_field_prefix = "allowed_to_"
222
262
  ```
223
263
 
264
+ You can specify a custom field name as well (only for a single rule):
265
+
266
+ ```ruby
267
+ class ProfileType < ::Common::Graphql::Type
268
+ # Adds can_create_post field.
269
+
270
+ expose_authorization_rules :create?, with: PostPolicy, field_name: "can_create_post"
271
+ end
272
+ ```
273
+
224
274
  ## Custom Behaviour
225
275
 
226
276
  Including the default `ActionPolicy::GraphQL::Behaviour` is equal to adding the following to your base class:
@@ -77,4 +77,4 @@ When everything is green, it's time to fully migrate to ActionPolicy:
77
77
  - migrate view helpers (from `policy(..)` to `allowed_to?`, from `policy_scope` to `authorized`)
78
78
  - re-write specs using simple non-DSL syntax (or [Action Policy RSpec syntax](testing#rspec-dsl))
79
79
  - add [authorization tests](testing#testing-authorization) (add `require 'action_policy/rspec'`)
80
- - use [Reasons](), [I18n integration](i18n), [cache](caching) and other Action Policy features!
80
+ - use [Reasons](reasons), [I18n integration](i18n), [cache](caching) and other Action Policy features!
@@ -34,6 +34,10 @@ class ApplicationPolicy < ActionPolicy::Base
34
34
  end
35
35
  ```
36
36
 
37
+ You could use the following command to generate it.
38
+
39
+ $ rails generate action_policy:install
40
+
37
41
  **NOTE:** it is not necessary to inherit from `ActionPolicy::Base`; instead, you can [construct basic policy](custom_policy.md) choosing only the components you need.
38
42
 
39
43
  Rules must be public methods on the class. Using private methods as rules will raise an error.
@@ -87,9 +87,10 @@ The additional details are especially helpful when combined with localization, '
87
87
 
88
88
  ```yml
89
89
  en:
90
- policy:
91
- stage:
92
- show?: "The %{title} stage is not accessible"
90
+ action_policy:
91
+ policy:
92
+ stage:
93
+ show?: "The %{title} stage is not accessible"
93
94
  ```
94
95
 
95
96
  And then when you call `full_messages`:
@@ -85,7 +85,7 @@ end
85
85
  If test failed the exception message includes the result and [failure reasons](reasons) (if any):
86
86
 
87
87
  ```
88
- 1) PostPolucy#show? when post is draft
88
+ 1) PostPolicy#show? when post is draft
89
89
  Failure/Error: ...
90
90
 
91
91
  Expected to fail but succeed:
@@ -96,7 +96,7 @@ If you have [debugging utils](debugging) installed the message also includes the
96
96
  source code of the policy rule:
97
97
 
98
98
  ```
99
- 1) UserPolucy#manage? when post is draft
99
+ 1) UserPolicy#manage? when post is draft
100
100
  Failure/Error: ...
101
101
 
102
102
  Expected to fail but succeed:
@@ -49,11 +49,15 @@ module ActionPolicy
49
49
  @authorization_context = {}
50
50
 
51
51
  self.class.authorization_targets.each do |id, opts|
52
- raise AuthorizationContextMissing, id unless params.key?(id)
52
+ if opts[:optional] == true
53
+ val = params.fetch(id, nil)
54
+ else
55
+ raise AuthorizationContextMissing, id unless params.key?(id)
53
56
 
54
- val = params.fetch(id)
57
+ val = params.fetch(id)
55
58
 
56
- raise AuthorizationContextMissing, id if val.nil? && opts[:allow_nil] != true
59
+ raise AuthorizationContextMissing, id if val.nil? && opts[:allow_nil] != true
60
+ end
57
61
 
58
62
  authorization_context[id] = instance_variable_set("@#{id}", val)
59
63
  end
@@ -90,8 +90,9 @@ module ActionPolicy
90
90
  def with_clean_result # :nodoc:
91
91
  was_result = @result
92
92
  yield
93
- res, @result = @result, was_result
94
- res
93
+ @result
94
+ ensure
95
+ @result = was_result
95
96
  end
96
97
 
97
98
  # Returns a result of applying the specified rule to the specified record.
@@ -43,6 +43,6 @@ RSpec.configure do |config|
43
43
  config.include(
44
44
  ActionPolicy::RSpec::PunditSyntax::PolicyExampleGroup,
45
45
  type: :policy,
46
- example_group: {file_path: %r{spec/policies}}
46
+ file_path: %r{spec/policies}
47
47
  )
48
48
  end
@@ -41,6 +41,9 @@ module ActionPolicy
41
41
  # #=> AND
42
42
  # #=> access_feed? #=> true
43
43
  module PrettyPrint
44
+ TRUE = "\e[32mtrue\e[0m"
45
+ FALSE = "\e[31mfalse\e[0m"
46
+
44
47
  class Visitor
45
48
  attr_reader :lines, :object
46
49
  attr_accessor :indent
@@ -68,10 +71,11 @@ module ActionPolicy
68
71
 
69
72
  def expression_with_result(sexp)
70
73
  expression = Unparser.unparse(sexp)
71
- "#{expression} #=> #{eval_exp(expression)}"
74
+ "#{expression} #=> #{colorize(eval_exp(expression))}"
72
75
  end
73
76
 
74
77
  def eval_exp(exp)
78
+ return "<skipped>" if ignore_exp?(exp)
75
79
  object.instance_eval(exp)
76
80
  rescue => e
77
81
  "Failed: #{e.message}"
@@ -89,13 +93,22 @@ module ActionPolicy
89
93
  visit_node(ast.children[1])
90
94
  end
91
95
 
92
- # Parens
93
96
  def visit_begin(ast)
94
- lines << indented("(")
95
- self.indent += 2
96
- visit_node(ast.children[0])
97
- self.indent -= 2
98
- lines << indented(")")
97
+ # Parens
98
+ if ast.children.size == 1
99
+ lines << indented("(")
100
+ self.indent += 2
101
+ visit_node(ast.children[0])
102
+ self.indent -= 2
103
+ lines << indented(")")
104
+ else
105
+ # Multiple expressions
106
+ ast.children.each do |node|
107
+ visit_node(node)
108
+ # restore indent after each expression
109
+ self.indent -= 2
110
+ end
111
+ end
99
112
  end
100
113
 
101
114
  def visit_missing(ast)
@@ -108,6 +121,18 @@ module ActionPolicy
108
121
  self.indent += 2 if indent.zero?
109
122
  end
110
123
  end
124
+
125
+ # Some lines should not be evaled
126
+ def ignore_exp?(exp)
127
+ exp.match?(/^\s*binding\.(pry|irb)\s*$/)
128
+ end
129
+
130
+ def colorize(val)
131
+ return val unless $stdout.isatty
132
+ return TRUE if val.eql?(true)
133
+ return FALSE if val.eql?(false)
134
+ val
135
+ end
111
136
  end
112
137
 
113
138
  class << self
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionPolicy
4
- VERSION = "0.3.2"
4
+ VERSION = "0.3.3"
5
5
  end
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Generates an application policy for your application.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module ActionPolicy
6
+ module Generators
7
+ class InstallGenerator < ::Rails::Generators::Base
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def copy_application_policy
11
+ template "application_policy.rb", "app/policies/application_policy.rb"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationPolicy < ActionPolicy::Base
2
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generates a policy for a model with the given name.
3
+
4
+ Example:
5
+ rails generate action_policy:policy user
6
+
7
+ This will create:
8
+ app/policies/user_policy.rb
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module ActionPolicy
6
+ module Generators
7
+ class PolicyGenerator < ::Rails::Generators::NamedBase
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ invoke "action_policy:install"
11
+
12
+ def create_policy
13
+ template "policy.rb", File.join("app/policies", class_path, "#{file_name}_policy.rb")
14
+ end
15
+
16
+ hook_for :test_framework
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Policy < ApplicationPolicy
3
+ # See https://actionpolicy.evilmartians.io/#/writing_policies
4
+ #
5
+ # def index?
6
+ # true
7
+ # end
8
+ #
9
+ # def update?
10
+ # # here we can access our context and record
11
+ # user.admin? || (user.id == record.user_id)
12
+ # end
13
+
14
+ # Scoping
15
+ # See https://actionpolicy.evilmartians.io/#/scoping
16
+ #
17
+ # relation_scope do |relation|
18
+ # next relation if user.admin?
19
+ # relation.where(user: user)
20
+ # end
21
+ end
22
+ <% end -%>
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Rspec
6
+ module Generators
7
+ class PolicyGenerator < ::Rails::Generators::NamedBase
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def create_policy_spec
11
+ template "policy_spec.rb", File.join("spec/policies", class_path, "#{file_name}_policy_spec.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require '<%= File.exists?("spec/rails_helper.rb") ? "rails_helper" : "spec_helper" %>'
2
+
3
+ RSpec.describe <%= class_name %>Policy, type: :policy do
4
+ # let(:user) { build_stubbed :user }
5
+ # let(:record) { build_stubbed :post, draft: false }
6
+ # let(:context) { {user: user} }
7
+
8
+ describe_rule :index? do
9
+ pending "add some examples to (or delete) #{__FILE__}"
10
+ end
11
+
12
+ describe_rule :create? do
13
+ pending "add some examples to (or delete) #{__FILE__}"
14
+ end
15
+
16
+ describe_rule :manage? do
17
+ pending "add some examples to (or delete) #{__FILE__}"
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module TestUnit
6
+ module Generators
7
+ class PolicyGenerator < ::Rails::Generators::NamedBase
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def create_policy_test
11
+ template "policy_test.rb", File.join("test/policies", class_path, "#{file_name}_policy_test.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ class <%= class_name %>PolicyTest < ActiveSupport::TestCase
4
+ def test_index
5
+ end
6
+
7
+ def test_create
8
+ end
9
+
10
+ def test_manage
11
+ end
12
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-27 00:00:00.000000000 Z
11
+ date: 2019-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ammeter
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.3
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.3
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -253,6 +267,16 @@ files:
253
267
  - lib/action_policy/utils/pretty_print.rb
254
268
  - lib/action_policy/utils/suggest_message.rb
255
269
  - lib/action_policy/version.rb
270
+ - lib/generators/action_policy/install/USAGE
271
+ - lib/generators/action_policy/install/install_generator.rb
272
+ - lib/generators/action_policy/install/templates/application_policy.rb
273
+ - lib/generators/action_policy/policy/USAGE
274
+ - lib/generators/action_policy/policy/policy_generator.rb
275
+ - lib/generators/action_policy/policy/templates/policy.rb
276
+ - lib/generators/action_policy/rspec/policy_generator.rb
277
+ - lib/generators/action_policy/rspec/templates/policy_spec.rb
278
+ - lib/generators/action_policy/test_unit/policy_generator.rb
279
+ - lib/generators/action_policy/test_unit/templates/policy_test.rb
256
280
  homepage: https://github.com/palkan/action_policy
257
281
  licenses:
258
282
  - MIT
@@ -277,7 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
277
301
  - !ruby/object:Gem::Version
278
302
  version: '0'
279
303
  requirements: []
280
- rubygems_version: 3.0.3
304
+ rubygems_version: 3.0.6
281
305
  signing_key:
282
306
  specification_version: 4
283
307
  summary: Authorization framework for Ruby/Rails application