middle 0.0.0 → 0.1.0

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: eb995f2195f8cd12d67f972b80da0837f276b4b5
4
+ data.tar.gz: f6235086693ba177f845fa665d948bc16fa3a8e9
5
+ SHA512:
6
+ metadata.gz: d720fd3692af339787bea732de25fcdbcd5fe7cef8f3d2184b4e9031321066af76cebe8f9665b4bfa5623561f943a0852cd27b3315364036795004223eb16bef
7
+ data.tar.gz: d4aa0e17743721ae852ce91b56e0d6db32ce2dc6f8b682072927e8c0449f8bc26aad21f0057da807e939c0d1c46c0e27579322820a7f15e69a5d613b267e061a
@@ -0,0 +1,91 @@
1
+ Middle - simple 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 Middle
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 Middle
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,22 @@
1
+ module Middle
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 Middle\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 Middle
4
+
5
+ can :manage, <%= class_name %> do |<%= class_name.downcase %>|
6
+ false
7
+ end
8
+
9
+ end
@@ -0,0 +1,14 @@
1
+ module Middle
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 Middle
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
@@ -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 'middle/rule'
9
+
10
+ module Middle
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 'middle/rails' if defined?(Rails)
@@ -0,0 +1,53 @@
1
+ module Middle
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 Middle::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 Middle
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 Middle
2
+ VERSION = '0.1.0'
3
+ end
metadata CHANGED
@@ -1,48 +1,66 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middle
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.0.0
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Bryan Goines
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-19 00:00:00.000000000 Z
13
- dependencies: []
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'
14
27
  description:
15
28
  email: bryann83@gmail.com
16
29
  executables: []
17
30
  extensions: []
18
31
  extra_rdoc_files: []
19
32
  files:
20
- - lib/middle.rb
21
33
  - LICENSE
22
- - middle.gemspec
23
- - README
24
- homepage: http://google.com/
34
+ - README.md
35
+ - lib/generators/middle/ability/ability_generator.rb
36
+ - lib/generators/middle/ability/templates/ability_module.rb
37
+ - lib/generators/middle/install/install_generator.rb
38
+ - lib/generators/middle/install/templates/ability.rb
39
+ - lib/middle.rb
40
+ - lib/middle/rails.rb
41
+ - lib/middle/rule.rb
42
+ - lib/middle/version.rb
43
+ homepage: https://github.com/bry4n/middle
25
44
  licenses: []
45
+ metadata: {}
26
46
  post_install_message:
27
47
  rdoc_options: []
28
48
  require_paths:
29
49
  - lib
30
50
  required_ruby_version: !ruby/object:Gem::Requirement
31
51
  requirements:
32
- - - ! '>='
52
+ - - ">="
33
53
  - !ruby/object:Gem::Version
34
54
  version: '0'
35
- none: false
36
55
  required_rubygems_version: !ruby/object:Gem::Requirement
37
56
  requirements:
38
- - - ! '>='
57
+ - - ">="
39
58
  - !ruby/object:Gem::Version
40
59
  version: '0'
41
- none: false
42
60
  requirements: []
43
61
  rubyforge_project:
44
- rubygems_version: 1.8.23
62
+ rubygems_version: 2.2.2
45
63
  signing_key:
46
- specification_version: 3
47
- summary: Under development
64
+ specification_version: 4
65
+ summary: Simple authorization
48
66
  test_files: []
data/README DELETED
File without changes
@@ -1,15 +0,0 @@
1
- $:.unshift File.expand_path('../lib', __FILE__)
2
-
3
- require "rubygems"
4
-
5
- Gem::Specification.new do |gem|
6
- gem.name = "middle"
7
- gem.version = "0.0.0"
8
- gem.author = "Bryan Goines"
9
- gem.summary = "Under development"
10
- gem.email = "bryann83@gmail.com"
11
- gem.homepage = "http://google.com/"
12
-
13
- gem.files = Dir['**/*']
14
-
15
- end