cant_cant_cant 0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +86 -0
- data/Rakefile +34 -0
- data/lib/cant_cant_cant/version.rb +3 -0
- data/lib/cant_cant_cant.rb +76 -0
- data/lib/generators/cant_cant_cant/install/install_generator.rb +33 -0
- data/lib/generators/cant_cant_cant/install/templates/config.yml +12 -0
- data/lib/generators/cant_cant_cant/install/templates/initializer.rb +17 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a444a3ec5b00cf225f6af59760d9d263122b1114
|
4
|
+
data.tar.gz: 12325af0887c6d17735fc232a183530bf0dc3b2f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 782820cfc64752416cc5f4ff36a37a45465c0eacff61f120bcd1abefb73ccf97039d3c2fbaafe608cd0032ea0590ef77d0c11f10e85fc46bd99b86192ecb343f
|
7
|
+
data.tar.gz: ffab247b6a21bd60d729cf4fc6176de998b1d155613b77a03a3f7b08217ae479ba1f0ae0298436c6e84b26ec0ade132a5d5b4d844cd9394637154602fa7fa6be
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Shou Ya
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# CantCantCant
|
2
|
+
|
3
|
+
[](https://travis-ci.org/shouya/cant_cant_cant)
|
4
|
+
|
5
|
+
I want an authentication to:
|
6
|
+
|
7
|
+
- be light weight and simple, working in a controllable way;
|
8
|
+
- be role based, where roles and users are multiple-to-multiple relation;
|
9
|
+
- apply on controller actions;
|
10
|
+
- have access control in a single configuration file;
|
11
|
+
- be able to export a list of permissions for roles
|
12
|
+
|
13
|
+
So CanCan[Can] just can't satisfy my requirement. And then CantCantCant is the wheel invented for above purposes.
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add the following line to your `Gemfile` and execute `bundle`.
|
18
|
+
|
19
|
+
gem 'cant_cant_cant'
|
20
|
+
|
21
|
+
Then run:
|
22
|
+
|
23
|
+
$ rails generate cant_cant_cant:install
|
24
|
+
|
25
|
+
to generate the config and the initializer.
|
26
|
+
|
27
|
+
To get authentication works, you have to adjust `config/cant_cant_cant.yml` for your own need.
|
28
|
+
|
29
|
+
After all you need to tell CantCantCant how to acquire your current role(s). Modify the code in `config/initializers/cant_cant_cant.rb`.
|
30
|
+
|
31
|
+
CantCantCant will raise an exception on unauthorized access. In order to handle the error yourself, take a look on the related code in `config/initializers/cant_cant_cant.rb`.
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
You're done. There is no need to configure more in any of your controllers.
|
36
|
+
|
37
|
+
Note that live reloading is not supported yet; it means you'll need to restart your server after modifying your actions/controllers/config to take effect.
|
38
|
+
|
39
|
+
If you need to acquire a list of actions that given roles have access to, just call `CantCantCant.permissions_for(roles)`.
|
40
|
+
|
41
|
+
|
42
|
+
## Configuration
|
43
|
+
|
44
|
+
The configuration is located in `config/cant_cant_cant.yml`. The path to configuration file can be modified in the initializer.
|
45
|
+
|
46
|
+
The configuration is a YAML document that looks like:
|
47
|
+
|
48
|
+
```yaml
|
49
|
+
user: &default_permissions
|
50
|
+
test#public: allow
|
51
|
+
test#admin_only: deny
|
52
|
+
test#no_access: deny
|
53
|
+
|
54
|
+
admin:
|
55
|
+
<<: *default_permissions
|
56
|
+
test#admin_only: allow
|
57
|
+
```
|
58
|
+
|
59
|
+
## Initializer
|
60
|
+
|
61
|
+
You can adjust the initializer as you want, the only thing to notice is that you need to call `CantCantCant.initialize` before making any request, otherwise the authentication won't take effect.
|
62
|
+
|
63
|
+
CantCantCant need a `current_roles` method, you should implement it by your own according to the template, either in the initializer or in your own `ApplicationController`. You can also handle the `PermissionDenied` exception in the same way.
|
64
|
+
|
65
|
+
Using `rails generate cant_cant_cant:install`, the template will be generated for you in the initializer.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class ActionController::Base
|
69
|
+
# Write your own handler
|
70
|
+
rescue_from CantCantCant::PermissionDenied do
|
71
|
+
render plain: 'permission denied', status: 403
|
72
|
+
end
|
73
|
+
|
74
|
+
# Write your own method to return the roles for current user
|
75
|
+
def current_roles
|
76
|
+
return [] unless defined? current_user
|
77
|
+
return [] if current_user.empty?
|
78
|
+
|
79
|
+
current_user.roles
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
## License
|
85
|
+
|
86
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'CantCantCant'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module CantCantCant
|
4
|
+
PermissionDenied = Class.new(RuntimeError)
|
5
|
+
InvalidControllerOrAction = Class.new(RuntimeError)
|
6
|
+
InvalidConfiguration = Class.new(RuntimeError)
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def initialize(config)
|
10
|
+
@config_file = config
|
11
|
+
@cache = {}
|
12
|
+
|
13
|
+
inject_actions
|
14
|
+
end
|
15
|
+
|
16
|
+
def inject_actions
|
17
|
+
validate_config
|
18
|
+
|
19
|
+
permission_table.values.map(&:keys).flatten.uniq.each do |param|
|
20
|
+
inject_action(param)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def allow?(param, roles)
|
25
|
+
permissions_for(roles).include? param
|
26
|
+
end
|
27
|
+
|
28
|
+
def permissions_for(roles)
|
29
|
+
@cache[roles.sort.join(',')] ||=
|
30
|
+
permission_table
|
31
|
+
.values_at(*roles)
|
32
|
+
.select(&:present?)
|
33
|
+
.map { |x| x.keep_if { |_, v| v == 'allow' }.keys }
|
34
|
+
.flatten
|
35
|
+
.uniq
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def permission_table
|
41
|
+
@permission_table ||= YAML.load_file(@config_file).freeze
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_controller(param)
|
45
|
+
controller, action = param.split('#')
|
46
|
+
raise if controller.blank? || action.blank?
|
47
|
+
|
48
|
+
controller = (controller.classify + 'Controller').constantize
|
49
|
+
raise unless action.in? controller.instance_methods(false).map(&:to_s)
|
50
|
+
|
51
|
+
[controller, action]
|
52
|
+
rescue RuntimeError, NameError
|
53
|
+
raise InvalidControllerOrAction, param
|
54
|
+
end
|
55
|
+
|
56
|
+
def inject_action(param)
|
57
|
+
controller, action = extract_controller(param)
|
58
|
+
controller.class_eval do
|
59
|
+
before_action(only: [action]) do
|
60
|
+
next true if CantCantCant.allow?(param, current_roles)
|
61
|
+
raise PermissionDenied, param
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_config
|
67
|
+
permission_table.each do |_, perms|
|
68
|
+
perms.each do |param, access|
|
69
|
+
next unless access.blank?
|
70
|
+
next unless access.in? %w(allow deny)
|
71
|
+
raise InvalidConfiguration, param
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module CantCantCant::Generators
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
desc 'Generate CantCantCant configuration file and initializer'
|
6
|
+
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
def create_config_file
|
10
|
+
template 'config.yml', 'config/cant_cant_cant.yml'
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_initializer_file
|
14
|
+
template 'initializer.rb', 'config/initializers/cant_cant_cant.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def user_params
|
20
|
+
routes = Rails.application.routes.routes.to_a.reject(&:internal)
|
21
|
+
routes.map(&:defaults).reject(&:empty?).uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def user_permission_table
|
25
|
+
map = {}
|
26
|
+
user_params.each do |p|
|
27
|
+
key = "#{p[:controller]}##{p[:action]}"
|
28
|
+
map[key] = :deny
|
29
|
+
end
|
30
|
+
map
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This configuration file is initialized using `rails g cantcantcant:install`
|
2
|
+
|
3
|
+
# The default permission is generated by scanning all non-internal routes
|
4
|
+
user: &default_permissions
|
5
|
+
<%- user_permission_table.each do |k,v| -%>
|
6
|
+
<%=k%>: <%=v%>
|
7
|
+
<%- end -%>
|
8
|
+
|
9
|
+
admin:
|
10
|
+
<<: *default_permissions
|
11
|
+
# Specify your permission rules below
|
12
|
+
# admin#rm_rf: allow
|
@@ -0,0 +1,17 @@
|
|
1
|
+
config = File.join(Rails.root, 'config/cant_cant_cant.yml')
|
2
|
+
CantCantCant.initialize(config)
|
3
|
+
|
4
|
+
class ActionController::Base
|
5
|
+
# Write your own handler
|
6
|
+
rescue_from CantCantCant::PermissionDenied do
|
7
|
+
render plain: 'permission denied', status: 403
|
8
|
+
end
|
9
|
+
|
10
|
+
# Write your own method to return the roles for current user
|
11
|
+
def current_roles
|
12
|
+
return [] unless defined? current_user
|
13
|
+
return [] if current_user.empty?
|
14
|
+
|
15
|
+
current_user.roles
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cant_cant_cant
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Shou Ya
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: CanCan[Can] just can't satisfy me
|
56
|
+
email:
|
57
|
+
- github@lain.li
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- lib/cant_cant_cant.rb
|
66
|
+
- lib/cant_cant_cant/version.rb
|
67
|
+
- lib/generators/cant_cant_cant/install/install_generator.rb
|
68
|
+
- lib/generators/cant_cant_cant/install/templates/config.yml
|
69
|
+
- lib/generators/cant_cant_cant/install/templates/initializer.rb
|
70
|
+
homepage: https://github.com/shouya/cantcantcant
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.5.1
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: CanCan[Can] just can't satisfy me
|
94
|
+
test_files: []
|