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 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
+ [![Build Status](https://travis-ci.org/shouya/cant_cant_cant.svg?branch=master)](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,3 @@
1
+ module CantCantCant
2
+ VERSION = '0.1.0'
3
+ end
@@ -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: []