middle 0.0.0 → 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.
@@ -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