corral_acl 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +7 -0
- data/corral.gemspec +17 -0
- data/doc/Ability.html +257 -0
- data/doc/Corral/Ability.html +802 -0
- data/doc/Corral/AccessDenied.html +146 -0
- data/doc/Corral/AuthorizationNotPerformed.html +145 -0
- data/doc/Corral/ControllerAdditions/ClassMethods.html +277 -0
- data/doc/Corral/ControllerAdditions.html +513 -0
- data/doc/Corral/Error.html +141 -0
- data/doc/Corral/Generators/AbilityGenerator.html +195 -0
- data/doc/Corral/Generators.html +117 -0
- data/doc/Corral/NullRule.html +226 -0
- data/doc/Corral/SubjectRule.html +406 -0
- data/doc/Corral.html +131 -0
- data/doc/_index.html +194 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +474 -0
- data/doc/doc/_index.html +87 -0
- data/doc/doc/class_list.html +51 -0
- data/doc/doc/css/common.css +1 -0
- data/doc/doc/css/full_list.css +58 -0
- data/doc/doc/css/style.css +474 -0
- data/doc/doc/file_list.html +51 -0
- data/doc/doc/frames.html +17 -0
- data/doc/doc/index.html +87 -0
- data/doc/doc/js/app.js +243 -0
- data/doc/doc/js/full_list.js +216 -0
- data/doc/doc/js/jquery.js +4 -0
- data/doc/doc/method_list.html +51 -0
- data/doc/doc/top-level-namespace.html +102 -0
- data/doc/file.README.html +82 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +82 -0
- data/doc/js/app.js +243 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +211 -0
- data/doc/top-level-namespace.html +114 -0
- data/lib/corral/ability.rb +85 -0
- data/lib/corral/controller_additions.rb +76 -0
- data/lib/corral/exceptions.rb +10 -0
- data/lib/corral/rule.rb +45 -0
- data/lib/corral/version.rb +3 -0
- data/lib/corral.rb +5 -0
- data/lib/generators/corral/ability/USAGE +4 -0
- data/lib/generators/corral/ability/ability_generator.rb +11 -0
- data/lib/generators/corral/ability/templates/ability.rb +25 -0
- data/spec/corral/ability_spec.rb +26 -0
- data/spec/spec_helper.rb +97 -0
- metadata +101 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
module Corral
|
2
|
+
module Ability
|
3
|
+
# Check whether the object can perform an action on a subject.
|
4
|
+
#
|
5
|
+
# @overload can?(action, subject)
|
6
|
+
# @param action [Symbol] The action, represented as a symbol.
|
7
|
+
# @param subject [Object] The subject.
|
8
|
+
# @overload can?(action, subject, args)
|
9
|
+
# @param action [Symbol] The action, represented as a symbol.
|
10
|
+
# @param subject [Object] The subject.
|
11
|
+
# @param args [Hash] Variable arguments for more granular matching.
|
12
|
+
# @return [Boolean] True or false.
|
13
|
+
def can?(action, subject, *args)
|
14
|
+
return true if @allow_anything
|
15
|
+
lookup_rule(subject).authorized?(action, subject, args)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Inverse of #can?.
|
19
|
+
#
|
20
|
+
# @see #can?
|
21
|
+
def cannot?(*args)
|
22
|
+
not can?(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Adds a granting-access rule.
|
26
|
+
#
|
27
|
+
# @param action [Symbol] The action, represented as a symbol.
|
28
|
+
# @param subject [Object] The subject.
|
29
|
+
# @param block [Hash] Variable arguments for more granular matching.
|
30
|
+
def can(action, subject, &block)
|
31
|
+
rule_for(subject).add_grant(action, block)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Inverse of #can.
|
35
|
+
#
|
36
|
+
# @see #can
|
37
|
+
def cannot(action, subject, &block)
|
38
|
+
rule_for(subject).add_deny(action, block)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Allow the object to perform any action on any subject.
|
42
|
+
# This overrides any #cannot rules.
|
43
|
+
#
|
44
|
+
def allow_anything!
|
45
|
+
@allow_anything = true
|
46
|
+
end
|
47
|
+
|
48
|
+
# Check whether the object has authorization to perform the
|
49
|
+
# action it intends to on the subject. Raise AccessDenied
|
50
|
+
# if it doesn't.
|
51
|
+
#
|
52
|
+
# @param action [Symbol] The intended action.
|
53
|
+
# @param subject [Object] The subject of the action.
|
54
|
+
# @raise [AccessDenied] if the object does not have permission.
|
55
|
+
def authorize!(action, subject, *args)
|
56
|
+
raise AccessDenied if cannot?(action, subject, *args)
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
# Subjects hash.
|
62
|
+
def subjects
|
63
|
+
@subjects ||= {}
|
64
|
+
end
|
65
|
+
|
66
|
+
# Find or create a new rule for the specified subject.
|
67
|
+
#
|
68
|
+
# @param subject [Object] The subject.
|
69
|
+
def rule_for(subject)
|
70
|
+
subjects[subject] ||= SubjectRule.new
|
71
|
+
end
|
72
|
+
|
73
|
+
# Lookup a rule for a particular subject.
|
74
|
+
#
|
75
|
+
# @param subject [Object] The subject.
|
76
|
+
def lookup_rule(subject)
|
77
|
+
case subject
|
78
|
+
when Symbol, Class
|
79
|
+
r = subjects[subject] || subjects[:all] || NullRule
|
80
|
+
else
|
81
|
+
subjects[subject.class] || NullRule
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Corral
|
2
|
+
module ControllerAdditions
|
3
|
+
module ClassMethods
|
4
|
+
# Add this to a controller to ensure it performs authorization through +authorized+! or +authorize_resource+ call.
|
5
|
+
# If neither of these authorization methods are called, a Corral::AuthorizationNotPerformed exception will be raised.
|
6
|
+
# This can be placed in ApplicationController to ensure all controller actions do authorization.
|
7
|
+
def check_authorization(options = {})
|
8
|
+
self.after_filter(options.slice(:only, :except)) do |controller|
|
9
|
+
next if controller.instance_variable_defined?(:@_authorized)
|
10
|
+
next if options[:if] && !controller.send(options[:if])
|
11
|
+
next if options[:unless] && controller.send(options[:unless])
|
12
|
+
raise AuthorizationNotPerformed, "This action failed the check_authorization because it did not authorize a resource. Add skip_authorization_check to bypass this check."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Call this in the class of a controller to skip the check_authorization behavior on the actions.
|
17
|
+
# Any arguments are passed to the +before_filter+ called.
|
18
|
+
def skip_authorization_check(*args)
|
19
|
+
self.before_filter(*args) do |controller|
|
20
|
+
controller.instance_variable_set(:@_authorized, true)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.included(base)
|
26
|
+
base.extend ClassMethods
|
27
|
+
base.helper_method :can?, :cannot?, :current_ability if base.respond_to? :helper_method
|
28
|
+
end
|
29
|
+
|
30
|
+
# Raises a Corral::AccessDenied exception if the current_ability cannot
|
31
|
+
# perform the given action. This is usually called in a controller action or
|
32
|
+
# before filter to perform the authorization.
|
33
|
+
#
|
34
|
+
# A :message option can be passed to specify a different message.
|
35
|
+
#
|
36
|
+
# You can rescue from the exception in the controller to customize how unauthorized
|
37
|
+
# access is displayed to the user.
|
38
|
+
#
|
39
|
+
# See the load_and_authorize_resource method to automatically add the authorize! behavior
|
40
|
+
# to the default RESTful actions.
|
41
|
+
def authorize!(*args)
|
42
|
+
@_authorized = true
|
43
|
+
current_ability.authorize!(*args)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Creates and returns the current user's ability and caches it. If you
|
47
|
+
# want to override how the Ability is defined then this is the place.
|
48
|
+
# Just define the method in the controller to change behavior.
|
49
|
+
#
|
50
|
+
# Notice it is important to memoize the ability object so it is not
|
51
|
+
# recreated every time.
|
52
|
+
def current_ability
|
53
|
+
@current_ability ||= ::Ability.new(current_user)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Use in the controller or view to check the user's permission for a given action
|
57
|
+
# and object.
|
58
|
+
#
|
59
|
+
# This simply calls "can?" on the current_ability. See Ability#can?.
|
60
|
+
def can?(*args)
|
61
|
+
current_ability.can?(*args)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Convenience method which works the same as "can?" but returns the opposite value.
|
65
|
+
#
|
66
|
+
def cannot?(*args)
|
67
|
+
current_ability.cannot?(*args)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if defined? ActionController::Base
|
73
|
+
ActionController::Base.class_eval do
|
74
|
+
include Corral::ControllerAdditions
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Corral
|
2
|
+
# A general exception
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
# Raised when using check_authorization without calling authorize!
|
6
|
+
class AuthorizationNotPerformed < Error; end
|
7
|
+
|
8
|
+
# This error is raised when a user isn't allowed to access a given controller action.
|
9
|
+
class AccessDenied < Error; end
|
10
|
+
end
|
data/lib/corral/rule.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Corral
|
2
|
+
# Rule class representing actions doable on a subject.
|
3
|
+
# @!visibility private
|
4
|
+
class SubjectRule
|
5
|
+
def initialize
|
6
|
+
@actions = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
# Add a granting ACL for a particular action.
|
10
|
+
#
|
11
|
+
# @param action [symbol] The action.
|
12
|
+
# @param block An optional block for granularity.
|
13
|
+
def add_grant(action, block)
|
14
|
+
@actions[action] = (block || true)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Add a denying ACL for a particular action.
|
18
|
+
#
|
19
|
+
# @param action [symbol] The action.
|
20
|
+
# @param block An optional block for granularity.
|
21
|
+
def add_deny(action, block)
|
22
|
+
@actions[action] = (block || false)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return whether or not an object can perform a particular action on a subject
|
26
|
+
# @param action [Symbol] The action.
|
27
|
+
# @param subject [Object] The subject.
|
28
|
+
# @param args [Hash] Variable arguments for more granular matching.
|
29
|
+
# @return [Boolean] True or false.
|
30
|
+
def authorized?(action, subject, args)
|
31
|
+
block = @actions[:manage] || @actions[action]
|
32
|
+
return false unless block
|
33
|
+
return true if block == true
|
34
|
+
return !!block.call(*[subject, *args])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Fake rule representing nothing matched a subject when looking up its ability.
|
39
|
+
# @!visibility private
|
40
|
+
class NullRule # :nodoc:
|
41
|
+
def self.authorized?(*)
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/corral.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Ability
|
2
|
+
include Corral::Ability
|
3
|
+
|
4
|
+
def initialize(user)
|
5
|
+
# Define abilities for the passed in user here. For example:
|
6
|
+
#
|
7
|
+
# user ||= User.new # guest user (not logged in)
|
8
|
+
# if user.admin?
|
9
|
+
# allow_anything!
|
10
|
+
# else
|
11
|
+
# can :read, Post
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# The first argument to `can` is the action you are giving the user
|
15
|
+
# permission to do.
|
16
|
+
# If you pass :manage it will apply to every action. Other common actions
|
17
|
+
# here are :read, :create, :update and :destroy.
|
18
|
+
#
|
19
|
+
# The second argument is the resource the user can perform the action on.
|
20
|
+
# Pass a Ruby class of the resource.
|
21
|
+
#
|
22
|
+
# can :update, Article
|
23
|
+
#
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Corral::Ability do
|
4
|
+
before :each do
|
5
|
+
(@ability = double).extend Corral::Ability
|
6
|
+
end
|
7
|
+
|
8
|
+
it "is able to do anything" do
|
9
|
+
@ability.allow_anything!
|
10
|
+
expect(@ability.can?(:manage, String)).to be true
|
11
|
+
expect(@ability.cannot?(:manage, String)).to be false
|
12
|
+
end
|
13
|
+
|
14
|
+
it "is able to perform a specific action on everything" do
|
15
|
+
@ability.can(:read, :all)
|
16
|
+
expect(@ability.can?(:read, String)).to be true
|
17
|
+
expect(@ability.can?(:write, String)).to be false
|
18
|
+
end
|
19
|
+
|
20
|
+
it "cannot do something it has been told it cannot do" do
|
21
|
+
@ability.can(:read, :all)
|
22
|
+
expect(@ability.can?(:read, :this)).to be true
|
23
|
+
@ability.cannot(:read, :this)
|
24
|
+
expect(@ability.can?(:read, :this)).to be false
|
25
|
+
end
|
26
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'corral'
|
2
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
3
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
4
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
5
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
6
|
+
# files.
|
7
|
+
#
|
8
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
9
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
10
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
11
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
12
|
+
# a separate helper file that requires the additional dependencies and performs
|
13
|
+
# the additional setup, and require it from the spec files that actually need
|
14
|
+
# it.
|
15
|
+
#
|
16
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
17
|
+
# users commonly want.
|
18
|
+
#
|
19
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
20
|
+
RSpec.configure do |config|
|
21
|
+
# rspec-expectations config goes here. You can use an alternate
|
22
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
23
|
+
# assertions if you prefer.
|
24
|
+
config.expect_with :rspec do |expectations|
|
25
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
26
|
+
# and `failure_message` of custom matchers include text for helper methods
|
27
|
+
# defined using `chain`, e.g.:
|
28
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
29
|
+
# # => "be bigger than 2 and smaller than 4"
|
30
|
+
# ...rather than:
|
31
|
+
# # => "be bigger than 2"
|
32
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
33
|
+
end
|
34
|
+
|
35
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
36
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
37
|
+
config.mock_with :rspec do |mocks|
|
38
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
39
|
+
# a real object. This is generally recommended, and will default to
|
40
|
+
# `true` in RSpec 4.
|
41
|
+
mocks.verify_partial_doubles = true
|
42
|
+
end
|
43
|
+
|
44
|
+
# The settings below are suggested to provide a good initial experience
|
45
|
+
# with RSpec, but feel free to customize to your heart's content.
|
46
|
+
=begin
|
47
|
+
# These two settings work together to allow you to limit a spec run
|
48
|
+
# to individual examples or groups you care about by tagging them with
|
49
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
50
|
+
# get run.
|
51
|
+
config.filter_run :focus
|
52
|
+
config.run_all_when_everything_filtered = true
|
53
|
+
|
54
|
+
# Allows RSpec to persist some state between runs in order to support
|
55
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
56
|
+
# you configure your source control system to ignore this file.
|
57
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
58
|
+
|
59
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
60
|
+
# recommended. For more details, see:
|
61
|
+
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
|
62
|
+
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
63
|
+
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
|
64
|
+
config.disable_monkey_patching!
|
65
|
+
|
66
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
67
|
+
# be too noisy due to issues in dependencies.
|
68
|
+
config.warnings = true
|
69
|
+
|
70
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
71
|
+
# file, and it's useful to allow more verbose output when running an
|
72
|
+
# individual spec file.
|
73
|
+
if config.files_to_run.one?
|
74
|
+
# Use the documentation formatter for detailed output,
|
75
|
+
# unless a formatter has already been configured
|
76
|
+
# (e.g. via a command-line flag).
|
77
|
+
config.default_formatter = 'doc'
|
78
|
+
end
|
79
|
+
|
80
|
+
# Print the 10 slowest examples and example groups at the
|
81
|
+
# end of the spec run, to help surface which specs are running
|
82
|
+
# particularly slow.
|
83
|
+
config.profile_examples = 10
|
84
|
+
|
85
|
+
# Run specs in random order to surface order dependencies. If you find an
|
86
|
+
# order dependency and want to debug it, you can fix the order by providing
|
87
|
+
# the seed, which is printed after each run.
|
88
|
+
# --seed 1234
|
89
|
+
config.order = :random
|
90
|
+
|
91
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
92
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
93
|
+
# test failures related to randomization by passing the same `--seed` value
|
94
|
+
# as the one that triggered the failure.
|
95
|
+
Kernel.srand config.seed
|
96
|
+
=end
|
97
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: corral_acl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Arcaire
|
8
|
+
- Liam White
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-07-06 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Yet another authorization solution.
|
15
|
+
email: "/dev/null"
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- ".rspec"
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- corral.gemspec
|
26
|
+
- doc/Ability.html
|
27
|
+
- doc/Corral.html
|
28
|
+
- doc/Corral/Ability.html
|
29
|
+
- doc/Corral/AccessDenied.html
|
30
|
+
- doc/Corral/AuthorizationNotPerformed.html
|
31
|
+
- doc/Corral/ControllerAdditions.html
|
32
|
+
- doc/Corral/ControllerAdditions/ClassMethods.html
|
33
|
+
- doc/Corral/Error.html
|
34
|
+
- doc/Corral/Generators.html
|
35
|
+
- doc/Corral/Generators/AbilityGenerator.html
|
36
|
+
- doc/Corral/NullRule.html
|
37
|
+
- doc/Corral/SubjectRule.html
|
38
|
+
- doc/_index.html
|
39
|
+
- doc/class_list.html
|
40
|
+
- doc/css/common.css
|
41
|
+
- doc/css/full_list.css
|
42
|
+
- doc/css/style.css
|
43
|
+
- doc/doc/_index.html
|
44
|
+
- doc/doc/class_list.html
|
45
|
+
- doc/doc/css/common.css
|
46
|
+
- doc/doc/css/full_list.css
|
47
|
+
- doc/doc/css/style.css
|
48
|
+
- doc/doc/file_list.html
|
49
|
+
- doc/doc/frames.html
|
50
|
+
- doc/doc/index.html
|
51
|
+
- doc/doc/js/app.js
|
52
|
+
- doc/doc/js/full_list.js
|
53
|
+
- doc/doc/js/jquery.js
|
54
|
+
- doc/doc/method_list.html
|
55
|
+
- doc/doc/top-level-namespace.html
|
56
|
+
- doc/file.README.html
|
57
|
+
- doc/file_list.html
|
58
|
+
- doc/frames.html
|
59
|
+
- doc/index.html
|
60
|
+
- doc/js/app.js
|
61
|
+
- doc/js/full_list.js
|
62
|
+
- doc/js/jquery.js
|
63
|
+
- doc/method_list.html
|
64
|
+
- doc/top-level-namespace.html
|
65
|
+
- lib/corral.rb
|
66
|
+
- lib/corral/ability.rb
|
67
|
+
- lib/corral/controller_additions.rb
|
68
|
+
- lib/corral/exceptions.rb
|
69
|
+
- lib/corral/rule.rb
|
70
|
+
- lib/corral/version.rb
|
71
|
+
- lib/generators/corral/ability/USAGE
|
72
|
+
- lib/generators/corral/ability/ability_generator.rb
|
73
|
+
- lib/generators/corral/ability/templates/ability.rb
|
74
|
+
- spec/corral/ability_spec.rb
|
75
|
+
- spec/spec_helper.rb
|
76
|
+
homepage:
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.5.1
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: Extremely simple authorization solution.
|
100
|
+
test_files: []
|
101
|
+
has_rdoc:
|