conduct 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0c9b3822ec5762a6ba425318b04d4ef94fb03a26
4
+ data.tar.gz: 7d0cb343c896041219c9af3d2d8134a960768679
5
+ SHA512:
6
+ metadata.gz: d531afe236c05a3c67807d40214f87476c1b68f87688c89a12893955f7119c3c1d9c8c79c7acf7b76df298519072f977dcb4d5418be084cdfae598cf380063b0
7
+ data.tar.gz: 38e593631fab7e38528b586c24fce7fd72fb6e52e1ade4473868dcff69ddbd25523f0eaff3c7ed23e8d0b66a18ca5726ada1fa82634f7432fb1016b41cfcd146
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Bryan Goines
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.
@@ -0,0 +1,91 @@
1
+ Conduct - A lightweight authorization
2
+ ---
3
+
4
+ This is work in progress. README will be updated/improved when this is completed.
5
+
6
+
7
+ ### Examples:
8
+
9
+ **app/abilities/post_ability.rb**
10
+
11
+ ```ruby
12
+ module PostAbility
13
+
14
+ include Conduct
15
+
16
+ can :write, Post do |post|
17
+ current_user.present? && post.new_record?
18
+ end
19
+
20
+ can :read, Post do |post|
21
+ post.user == current_user
22
+ end
23
+
24
+ end
25
+
26
+ ```
27
+
28
+ **app/abilities/ability.rb**
29
+
30
+ ```ruby
31
+ class Ability
32
+
33
+ include Conduct
34
+
35
+ define_action create: [:new, :create]
36
+ define_action read: [:index, :show]
37
+ define_action update: [:edit, :update]
38
+ define_action delete: [:destroy]
39
+
40
+ define_action manage: [:create, :read, :update, :delete]
41
+
42
+ can :manage, :all do
43
+ current_user.present? && current_user.admin?
44
+ end
45
+
46
+ include PostAbility
47
+
48
+ can :comment, Post, :create_comment?
49
+
50
+ can :create, Comment, do |comment|
51
+ false
52
+ end
53
+
54
+ def create_comment?(post)
55
+ can? :create, post.comments.new
56
+ end
57
+
58
+ end
59
+
60
+ ```
61
+
62
+ **app/controllers/posts_controller.rb**
63
+
64
+ ```ruby
65
+ class PostsController < ApplicationController
66
+ before_filter :authorize_ability! only: [:new, :create]
67
+
68
+ def index
69
+ if authorize_ability
70
+ @posts = @user.posts
71
+ else
72
+ @posts = @user.posts.public
73
+ end
74
+ end
75
+
76
+ def edit
77
+ redirect_to root_url unless can?(:update, @post)
78
+ end
79
+
80
+ ...
81
+
82
+ end
83
+ ```
84
+
85
+ **app/views/posts/index.html.erb**
86
+
87
+ ```ruby
88
+ <% if can?(:create, @post) %>
89
+ <%= link_to "New Post", new_post_path %>
90
+ <% end %>
91
+ ```
@@ -0,0 +1,132 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+
3
+ unless defined?(ActiveSupport)
4
+ require 'active_support/concern'
5
+ require 'active_support/core_ext/array'
6
+ end
7
+
8
+ require 'conduct/rule'
9
+
10
+ module Conduct
11
+ extend ActiveSupport::Concern
12
+
13
+ module ClassMethods
14
+
15
+ attr_accessor :current_user
16
+
17
+ def current_user
18
+ @@current_user
19
+ end
20
+
21
+ def current_user=(user)
22
+ @@current_user = user
23
+ end
24
+
25
+ def rules
26
+ @@rules ||= {}
27
+ end
28
+
29
+ def actions
30
+ @@actions ||= {}
31
+ end
32
+
33
+ def define_action(*args)
34
+ options = args.extract_options!
35
+ options.each do |key, value|
36
+ actions[key] = value
37
+ end
38
+ end
39
+
40
+ def can(action, subject, *args, &block)
41
+ options = args.extract_options!
42
+ block = args.pop if args.last.kind_of?(Proc)
43
+ if defined_action_exists?(action)
44
+ collection = fetch_action_from_collection(action)
45
+ collection.each { |name| define_rule(name, subject, options, &block) }
46
+ end
47
+ define_rule(action, subject, options, &block)
48
+ end
49
+
50
+ private
51
+
52
+ def define_rule(action, subject, options, &block)
53
+ if defined_action_exists?(action)
54
+ add_rule_for_defined_action(action, subject, options, &block)
55
+ end
56
+ if action.is_a?(Array)
57
+ action.each do |name|
58
+ rule = Rule.new(name, subject, options, &block)
59
+ add_rule(rule.name, rule)
60
+ end
61
+ else
62
+ rule = Rule.new(action, subject, options, &block)
63
+ add_rule(rule.name, rule)
64
+ end
65
+ end
66
+
67
+ def add_rule(name, rule)
68
+ rules[name] = rule unless rule_exists?(rule.name)
69
+ end
70
+
71
+ def add_rule_for_defined_action(action, subject, options, &block)
72
+ collection = fetch_action_from_collection(action)
73
+ collection.each do |name|
74
+ rule = Rule.new(name, subject, options, &block)
75
+ add_rule(rule.name, rule)
76
+ end
77
+ end
78
+
79
+ def rule_exists?(name)
80
+ rules[name].present?
81
+ end
82
+
83
+ def defined_action_exists?(action)
84
+ actions[action].present?
85
+ end
86
+
87
+ def fetch_action_from_collection(action)
88
+ list = actions[action]
89
+ fail 'Please define action as collection' unless list.is_a?(Array)
90
+ list
91
+ end
92
+
93
+ end
94
+
95
+ attr_reader :current_user
96
+
97
+ def initialize(user)
98
+ @current_user = self.class.current_user = user
99
+ end
100
+
101
+ def rules
102
+ @rules ||= self.class.rules
103
+ end
104
+
105
+ def can?(action, subject, options = {})
106
+ name = build_name_for(action, subject)
107
+ rule = rules[name] || rules["#{action}_all"]
108
+ return false unless rule
109
+ rule.result(subject, options)
110
+ end
111
+
112
+ def cannot?(*args)
113
+ !can?(*args)
114
+ end
115
+
116
+ private
117
+
118
+ def build_name_for(action, subject)
119
+ subject = find_class(subject)
120
+ "#{action}_#{subject.to_s.downcase}"
121
+ end
122
+
123
+ def find_class(subject)
124
+ return subject.model_name if subject.respond_to?(:model_name)
125
+ return subject.class.model_name if subject.class.respond_to?(:model_name)
126
+ return find_class(subject.first) if subject.is_a?(Array)
127
+ subject.is_a?(Class) ? subject : subject.class
128
+ end
129
+
130
+ end
131
+
132
+ require 'conduct/rails' if defined?(Rails)
@@ -0,0 +1,53 @@
1
+ module Conduct
2
+ module Rails
3
+ module Helpers
4
+
5
+ def ability_object(user)
6
+ @ability ||= Ability.new(user)
7
+ end
8
+
9
+ def current_ability
10
+ @ability ||= Ability.new(current_user)
11
+ end
12
+
13
+ def can?(*args)
14
+ current_ability.can?(*args)
15
+ end
16
+
17
+ def cannot?(*args)
18
+ current_ability.cannot?(*args)
19
+ end
20
+
21
+ # if authorize_ability
22
+ # @posts = current_user.posts
23
+ # else
24
+ # @posts = @user.posts.public
25
+ # end
26
+ def authorize_ability
27
+ return unless defined?(controller_name) || params[:action].present?
28
+ klass = _classify_controller_name
29
+ current_ability.can?(params[:action], klass.new)
30
+ end
31
+
32
+ # before_action :authorize_ability!
33
+ def authorize_ability!
34
+ fail 'Access Denied' unless authorize_ability
35
+ end
36
+
37
+ private
38
+
39
+ def _classify_controller_name
40
+ controller_name.classify.constantize
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+
47
+ if defined?(ActionController::Base)
48
+ ActionController::Base.class_eval do
49
+ include Conduct::Rails::Helpers
50
+ helper_method :can?, :cannot?, :current_ability, :ability_object
51
+ hide_action :authorize_ability, :authorize_ability!
52
+ end
53
+ end
@@ -0,0 +1,35 @@
1
+ module Conduct
2
+ class Rule
3
+
4
+ attr_accessor :action, :subject, :options, :block
5
+ attr_reader :name, :value
6
+
7
+ def initialize(action, subject, options = {}, &block)
8
+ @action = action
9
+ @subject = subject
10
+ @options = options
11
+ @block = block
12
+ @value = nil
13
+ @name = "#{action}_#{subject.to_s.downcase}"
14
+ end
15
+
16
+ def result(object, opts = {})
17
+ if object.respond_to?(:to_a)
18
+ @value = object.to_a.all? { |obj| block_call(obj, opts) }
19
+ else
20
+ @value = block_call(object, opts)
21
+ end
22
+ fail 'Result value is not a boolean type' unless boolean_value?
23
+ @value
24
+ end
25
+
26
+ def block_call(obj, opts = {})
27
+ opts.any? ? block.call(obj, opts) : block.call(obj)
28
+ end
29
+
30
+ def boolean_value?
31
+ value.kind_of?(TrueClass) || value.kind_of?(FalseClass)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module Conduct
2
+ VERSION = '0.1.14'
3
+ end
@@ -0,0 +1,22 @@
1
+ module Conduct
2
+ module Generators
3
+ class AbilityGenerator < ::Rails::Generators::NamedBase
4
+ source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
5
+
6
+ hook_for :orm
7
+
8
+ desc "Create a new ability"
9
+
10
+ def create_ability
11
+ template 'ability_module.rb', File.join('app/abilities', class_path, "#{file_name}_ability.rb")
12
+ inject_into_file 'app/abilities/ability.rb', after: "include Conduct\n" do
13
+ "\n include #{class_name}Activity\n"
14
+ end
15
+
16
+ end
17
+
18
+
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ module <%= class_name %>Ability
2
+
3
+ include Conduct
4
+
5
+ can :manage, <%= class_name %> do |<%= class_name.downcase %>|
6
+ false
7
+ end
8
+
9
+ end
@@ -0,0 +1,14 @@
1
+ module Conduct
2
+ module Generators
3
+ class InstallGenerator < ::Rails::Generators::Base
4
+ source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
5
+
6
+ desc "Creates an ability to your application"
7
+
8
+ def copy_ability
9
+ template 'ability.rb', 'app/abilities/ability.rb'
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ class Ability
2
+
3
+ include Conduct
4
+
5
+ define_action create: [:new, :create]
6
+ define_action read: [:index, :show]
7
+ define_action update: [:edit, :update]
8
+ define_action delete: [:destroy]
9
+
10
+ define_action manage: [:create, :read, :update, :delete]
11
+
12
+
13
+ can :manage, :all do
14
+ # current_user.admin?
15
+ false
16
+ end
17
+
18
+ #include ExampleAbility
19
+
20
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: conduct
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.14
5
+ platform: ruby
6
+ authors:
7
+ - Bryan Goines
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description:
28
+ email: bryann83@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - LICENSE
34
+ - README.md
35
+ - lib/conduct.rb
36
+ - lib/conduct/rails.rb
37
+ - lib/conduct/rule.rb
38
+ - lib/conduct/version.rb
39
+ - lib/generators/conduct/ability/ability_generator.rb
40
+ - lib/generators/conduct/ability/templates/ability_module.rb
41
+ - lib/generators/conduct/install/install_generator.rb
42
+ - lib/generators/conduct/install/templates/ability.rb
43
+ homepage: https://github.com/bry4n/conduct
44
+ licenses: []
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 2.2.2
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: Simple authorization
66
+ test_files: []