kojac 0.9.1 → 0.11.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 +6 -14
- data/.gitignore +4 -0
- data/Gemfile +1 -1
- data/app/assets/javascripts/kojac.js +393 -125
- data/app/assets/javascripts/kojac_canjs.js +34 -34
- data/app/assets/javascripts/kojac_ember.js +110 -152
- data/app/controllers/{kojac_controller.rb → kojac_base_controller.rb} +18 -11
- data/app/policies/kojac_base_policy.rb +114 -0
- data/app/serializers/kojac_base_serializer.rb +35 -0
- data/kojac.gemspec +12 -10
- data/lib/kojac/app_serialize.rb +31 -29
- data/lib/kojac/concentric.rb +152 -0
- data/lib/kojac/kojac_policy.rb +70 -0
- data/lib/kojac/kojac_rails.rb +200 -49
- data/lib/kojac/version.rb +1 -1
- data/spec/can_cache_spec.js +19 -19
- data/spec/demo/.gitignore +16 -0
- data/spec/demo/.ruby-gemset +1 -0
- data/spec/demo/.ruby-version +1 -0
- data/spec/demo/Gemfile +59 -0
- data/spec/demo/Gemfile.lock +153 -0
- data/spec/demo/README.rdoc +15 -248
- data/spec/demo/Rakefile +25 -1
- data/spec/demo/app/{mailers/.gitkeep → assets/images/.keep} +0 -0
- data/spec/demo/app/assets/javascripts/application.js +3 -3
- data/spec/demo/app/controllers/application_controller.rb +6 -1
- data/spec/demo/app/{models/.gitkeep → controllers/concerns/.keep} +0 -0
- data/spec/demo/app/controllers/users_controller.rb +5 -0
- data/spec/demo/{lib/assets/.gitkeep → app/mailers/.keep} +0 -0
- data/spec/demo/{log/.gitkeep → app/models/.keep} +0 -0
- data/spec/demo/app/models/concerns/.keep +0 -0
- data/spec/demo/app/models/user.rb +36 -0
- data/spec/demo/app/policies/user_policy.rb +42 -0
- data/spec/demo/bin/bundle +3 -0
- data/spec/demo/bin/rails +4 -0
- data/spec/demo/bin/rake +4 -0
- data/spec/demo/config.ru +1 -1
- data/spec/demo/config/application.rb +14 -46
- data/spec/demo/config/application.yml +4 -0
- data/spec/demo/config/boot.rb +3 -9
- data/spec/demo/config/database.yml +6 -6
- data/spec/demo/config/environment.rb +4 -2
- data/spec/demo/config/environments/development.rb +11 -19
- data/spec/demo/config/environments/production.rb +40 -27
- data/spec/demo/config/environments/test.rb +13 -14
- data/spec/demo/config/initializers/concentric_config.rb +9 -0
- data/spec/demo/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/demo/config/initializers/inflections.rb +6 -5
- data/spec/demo/config/initializers/initialize_kojac.rb +16 -0
- data/spec/demo/config/initializers/secret_token.rb +7 -2
- data/spec/demo/config/initializers/session_store.rb +0 -5
- data/spec/demo/config/initializers/wrap_parameters.rb +6 -6
- data/spec/demo/config/locales/en.yml +20 -2
- data/spec/demo/config/routes.rb +24 -24
- data/spec/demo/db/migrate/20131212034312_add_user.rb +14 -0
- data/spec/demo/db/migrate/20140107085351_add_owner_id.rb +5 -0
- data/spec/demo/db/schema.rb +28 -0
- data/spec/demo/db/seeds.rb +7 -0
- data/spec/demo/lib/assets/.keep +0 -0
- data/spec/demo/lib/tasks/.keep +0 -0
- data/spec/demo/log/.keep +0 -0
- data/spec/demo/public/404.html +43 -11
- data/spec/demo/public/422.html +43 -11
- data/spec/demo/public/500.html +43 -11
- data/spec/demo/public/robots.txt +5 -0
- data/spec/demo/spec/controllers/allowed_fields_spec.rb +171 -0
- data/spec/demo/spec/factories/users.rb +9 -0
- data/spec/demo/spec/features/concentric_spec.rb +63 -0
- data/spec/demo/spec/features/serialization_spec.rb +86 -0
- data/spec/demo/spec/spec_helper.rb +133 -0
- data/spec/demo/spec/spec_utils.rb +42 -0
- data/spec/demo/vendor/assets/javascripts/.keep +0 -0
- data/spec/demo/vendor/assets/stylesheets/.keep +0 -0
- data/spec/ember_factory_spec.js +1 -1
- data/spec/ember_model_spec.js +13 -3
- data/spec/ember_tojsono_spec.js +105 -0
- data/spec/error_handling_spec.js +90 -0
- data/spec/external/underscore_plus.js +318 -9
- data/spec/kojac_caching_spec.js +3 -1
- data/spec/kojac_ember_cache_spec.js +9 -0
- data/spec/kojac_mock_spec.js +4 -4
- data/spec/kojac_operations_spec.js +4 -4
- data/spec/local_provider_spec.js +184 -0
- data/spec/model_ring_spec.rb +2 -2
- data/spec/operation_include_spec.js +2 -2
- data/spec/run.html +34 -24
- data/spec/type_conversion_spec.js +38 -0
- data/vendor/assets/javascripts/jstorage.js +950 -0
- metadata +115 -129
- data/Gemfile.lock +0 -157
- data/app/serializers/default_kojac_serializer.rb +0 -10
- data/lib/kojac/ring_strong_parameters.rb +0 -195
- data/spec/.DS_Store +0 -0
- data/spec/demo/script/rails +0 -6
- data/spec/external/.DS_Store +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
class KojacBasePolicy
|
|
2
|
+
attr_reader :user, :record, :op
|
|
3
|
+
|
|
4
|
+
def initialize(user, record, op=nil)
|
|
5
|
+
raise Pundit::NotAuthorizedError, "must be logged in" unless user
|
|
6
|
+
@user = user
|
|
7
|
+
@record = record
|
|
8
|
+
@op = op
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def unauthorized!(aMessage=nil)
|
|
12
|
+
raise Pundit::NotAuthorizedError, aMessage||"You are not authorized to perform this action"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#def self.write_op_filter(aCurrentUser,aSafeFields,aSourceFields)
|
|
16
|
+
# ring = aCurrentUser.ring
|
|
17
|
+
# has_owner = !!self.column_names.include?('owner_id')
|
|
18
|
+
# has_dealership = !!self.column_names.include?('dealership_id')
|
|
19
|
+
# # default to user
|
|
20
|
+
# if ring <= SALES_RING
|
|
21
|
+
# aSafeFields['owner_id'] ||= aCurrentUser.owner_id if has_owner
|
|
22
|
+
# aSafeFields['dealership_id'] ||= aCurrentUser.dealership_id if has_dealership
|
|
23
|
+
# end
|
|
24
|
+
# if ring > SYSADMIN_RING
|
|
25
|
+
# unauthorized! if aSafeFields['owner_id'] != aCurrentUser.owner_id if has_owner
|
|
26
|
+
# end
|
|
27
|
+
# if ring > OWNER_ADMIN_RING
|
|
28
|
+
# unauthorized! if aSafeFields['dealership_id'] != aCurrentUser.dealership_id if has_dealership
|
|
29
|
+
# end
|
|
30
|
+
#end
|
|
31
|
+
|
|
32
|
+
def query_ring
|
|
33
|
+
user.ring
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# kojac methods
|
|
37
|
+
def read?
|
|
38
|
+
record.class.ring_can?(query_ring,:read)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def write?
|
|
42
|
+
record.class.ring_can?(query_ring,:write)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# rails methods
|
|
46
|
+
def index?
|
|
47
|
+
record.class.ring_can?(query_ring,:read)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def show?
|
|
51
|
+
record.class.ring_can?(query_ring,:read)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def create?
|
|
55
|
+
record.class.ring_can?(query_ring,:create)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def new?
|
|
59
|
+
record.class.ring_can?(query_ring,:create)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def update?
|
|
63
|
+
record.class.ring_can?(query_ring,:write)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def edit?
|
|
67
|
+
record.class.ring_can?(query_ring,:write)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def destroy?
|
|
71
|
+
record.class.ring_can?(query_ring,:destroy)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def scope
|
|
75
|
+
Pundit.policy_scope!(user, record.class)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def permitted_attributes(aAbility=nil)
|
|
79
|
+
raise "ability not given" unless (@op && @op[:verb]) || aAbility
|
|
80
|
+
if !aAbility && @op
|
|
81
|
+
aAbility = case @op[:verb]
|
|
82
|
+
when 'CREATE'
|
|
83
|
+
when 'UPDATE'
|
|
84
|
+
:write
|
|
85
|
+
when 'READ'
|
|
86
|
+
:read
|
|
87
|
+
when 'ADD'
|
|
88
|
+
:add
|
|
89
|
+
when 'REMOVE'
|
|
90
|
+
:remove
|
|
91
|
+
when 'CREATE_ON'
|
|
92
|
+
:create_on
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
cls = record.is_a?(Class) ? record : record.class
|
|
96
|
+
cls.permitted(query_ring,aAbility)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def permitted_fields(aAbility=nil)
|
|
100
|
+
result = permitted_attributes(aAbility)
|
|
101
|
+
cls = record.is_a?(Class) ? record : record.class
|
|
102
|
+
result.delete_if { |f| cls.reflections.has_key? f }
|
|
103
|
+
result
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def permitted_associations(aAbility=nil)
|
|
107
|
+
result = permitted_attributes(aAbility)
|
|
108
|
+
cls = record.is_a?(Class) ? record : record.class
|
|
109
|
+
result.delete_if { |f| !cls.reflections.has_key? f }
|
|
110
|
+
result
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class KojacBaseSerializer < ActiveModel::Serializer
|
|
2
|
+
|
|
3
|
+
self.root = false
|
|
4
|
+
|
|
5
|
+
def initialize(object, options={})
|
|
6
|
+
super(object,options)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
SERIALIZABLE_TYPES = [NilClass,FalseClass,TrueClass,Fixnum,Bignum,String,Symbol,Hash,Array]
|
|
10
|
+
|
|
11
|
+
def attributes
|
|
12
|
+
attrs = nil
|
|
13
|
+
source = if policy = Kojac::policy(scope,object)
|
|
14
|
+
attrs = policy.permitted_attributes(:read).map(&:to_s)
|
|
15
|
+
object.attributes
|
|
16
|
+
elsif object.respond_to? :attributes
|
|
17
|
+
object.attributes
|
|
18
|
+
elsif object.is_a? Hash
|
|
19
|
+
object
|
|
20
|
+
end
|
|
21
|
+
result = {}
|
|
22
|
+
source.each do |k,v|
|
|
23
|
+
k_s = k.to_s
|
|
24
|
+
next if attrs && !attrs.include?(k_s)
|
|
25
|
+
if SERIALIZABLE_TYPES.include? v.class
|
|
26
|
+
result[k_s] = v
|
|
27
|
+
else
|
|
28
|
+
result[k_s] = KojacUtils.to_jsono(v,scope: scope)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
result
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
alias_method :serializable_object, :serializable_hash
|
|
35
|
+
end
|
data/kojac.gemspec
CHANGED
|
@@ -21,15 +21,17 @@ Gem::Specification.new do |s|
|
|
|
21
21
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
22
22
|
s.require_paths = ["lib"]
|
|
23
23
|
|
|
24
|
-
s.
|
|
25
|
-
s.
|
|
26
|
-
s.
|
|
24
|
+
s.add_runtime_dependency "buzztools", '~> 0.0.5'
|
|
25
|
+
s.add_runtime_dependency "underscore_plus", '~> 0.9.1'
|
|
26
|
+
s.add_runtime_dependency "pundit", '~> 0.2.3'
|
|
27
|
+
s.add_runtime_dependency "active_model_serializers", '= 0.9.0.alpha1'
|
|
27
28
|
|
|
28
|
-
s.
|
|
29
|
-
s.
|
|
30
|
-
s.add_development_dependency "
|
|
31
|
-
s.add_development_dependency "
|
|
32
|
-
s.add_development_dependency "
|
|
33
|
-
s.add_development_dependency "
|
|
34
|
-
s.add_development_dependency "
|
|
29
|
+
#s.add_runtime_dependency "jquery-rails"
|
|
30
|
+
#s.add_runtime_dependency "rails", ">= 3.1"
|
|
31
|
+
# s.add_development_dependency "rspec-rails"
|
|
32
|
+
# s.add_development_dependency "canjs-rails"
|
|
33
|
+
# s.add_development_dependency "ember-rails"
|
|
34
|
+
# s.add_development_dependency "jquery-rails"
|
|
35
|
+
# s.add_development_dependency "capybara"
|
|
36
|
+
# s.add_development_dependency "sqlite3"
|
|
35
37
|
end
|
data/lib/kojac/app_serialize.rb
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
when
|
|
11
|
-
when
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
sz_class =
|
|
20
|
-
sz_class
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
end
|
|
1
|
+
## http://matthewrobertson.org/blog/2013/08/06/active-record-serializers-from-scratch/
|
|
2
|
+
#
|
|
3
|
+
#if Rails::VERSION::STRING.split('.').first.to_i < 4
|
|
4
|
+
# require 'active_record/serializer_override'
|
|
5
|
+
#end
|
|
6
|
+
#
|
|
7
|
+
#def app_serialize(aObject,aScope)
|
|
8
|
+
# result = case aObject.class
|
|
9
|
+
# when Fixnum then aObject.to_s
|
|
10
|
+
# when Bignum then aObject.to_s
|
|
11
|
+
# when Array
|
|
12
|
+
# sz_class = ActiveModel::ArraySerializer
|
|
13
|
+
# sz_class.new(aObject).to_json(:scope => aScope, :root => false)
|
|
14
|
+
# when String then aObject
|
|
15
|
+
# when FalseClass then 'false'
|
|
16
|
+
# when TrueClass then 'true'
|
|
17
|
+
# when Symbol then aObject.to_s
|
|
18
|
+
# #when Hash
|
|
19
|
+
# #sz_class = ActiveModel::Serializer
|
|
20
|
+
# #sz_class.new(aObject).to_json(:scope => aScope, :root => false)
|
|
21
|
+
# else
|
|
22
|
+
# sz_class = aObject.respond_to?(:active_model_serializer) && aObject.send(:active_model_serializer)
|
|
23
|
+
# sz_class = DefaultKojacSerializer if !sz_class && aObject.is_a?(ActiveModel)
|
|
24
|
+
# if sz_class
|
|
25
|
+
# sz_class.new(aObject).to_json(:scope => aScope, :root => false)
|
|
26
|
+
# else
|
|
27
|
+
# aObject.to_json
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
# result
|
|
31
|
+
#end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#concentric
|
|
2
|
+
#
|
|
3
|
+
#Assists implementation of ring level security (http://en.wikipedia.org/wiki/Ring_(computer_security)) with Rails 4 (or Rails 3 with gem) Strong Parameters.
|
|
4
|
+
#
|
|
5
|
+
#Ring Level Security is a simpler alternative to Role Based Security. Rings are arranged in a concentric hierarchy from most-privileged innermost Ring 0 to the least privileged highest ring number. Users have their own ring level which gives them access to that ring and below.
|
|
6
|
+
#
|
|
7
|
+
#For example, a sysadmin could have Ring 0, a website manager ring 1, a customer ring 2, and anonymous users ring 3. A customer would have all the capabilities of anonymous users, and more. Likewise, a website manager has all the capabilities of a customer, and more etc.
|
|
8
|
+
#
|
|
9
|
+
#This inheritance of capabilities of outer rings, and the simple assigning of users to rings, makes security rules less repetitive and easier to write and maintain, minimising dangerous mistakes.
|
|
10
|
+
#
|
|
11
|
+
#This gem does not affect or replace or prevent the standard strong parameters methods from being used in parallel, it merely generates arguments for the standard strong parameters methods.
|
|
12
|
+
#
|
|
13
|
+
#
|
|
14
|
+
#
|
|
15
|
+
#BASIC_FIELDS = [:name, :address]
|
|
16
|
+
#
|
|
17
|
+
#class Deal
|
|
18
|
+
# ring 1, :write, BASIC_FIELDS
|
|
19
|
+
# ring 1, :write, :phone
|
|
20
|
+
# ring 1, :delete
|
|
21
|
+
# ring 2, :read, BASIC_FIELDS
|
|
22
|
+
#end
|
|
23
|
+
#
|
|
24
|
+
#
|
|
25
|
+
#class DealsController
|
|
26
|
+
#
|
|
27
|
+
# def update
|
|
28
|
+
# ring_fields(:write,model)
|
|
29
|
+
# if ring_can(:write,model,:name)
|
|
30
|
+
# if ring_can(:delete,model)
|
|
31
|
+
# model.update(params.permit( ring_fields(:write,model) ))
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
#end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Concentric
|
|
39
|
+
|
|
40
|
+
cattr_accessor :config
|
|
41
|
+
|
|
42
|
+
def self.lookup_ring(aRingName)
|
|
43
|
+
return nil if !aRingName
|
|
44
|
+
return aRingName if aRingName.is_a?(Fixnum)
|
|
45
|
+
if ring_names = Concentric.config[:ring_names]
|
|
46
|
+
return ring_names[aRingName.to_sym]
|
|
47
|
+
else
|
|
48
|
+
return nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.ring_name(aRing)
|
|
53
|
+
ring_names = Concentric.config[:ring_names]
|
|
54
|
+
ring_names.key(aRing)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.ring_text(aRing)
|
|
58
|
+
return 'none' if !aRing
|
|
59
|
+
ring_name(aRing).to_s.humanize
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# see http://yehudakatz.com/2009/11/12/better-ruby-idioms/ re class and instance methods and modules
|
|
65
|
+
|
|
66
|
+
module Concentric::Model
|
|
67
|
+
|
|
68
|
+
def self.included(aClass)
|
|
69
|
+
aClass.cattr_accessor :rings_abilities
|
|
70
|
+
aClass.rings_abilities = [] # [1] => {read: [:name,:address], delete: true}
|
|
71
|
+
aClass.send :extend, ClassMethods
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
module ClassMethods
|
|
75
|
+
|
|
76
|
+
# supports different formats :
|
|
77
|
+
# ring :sales, :write => [:name,:address] ie. sales can write the name and address fields
|
|
78
|
+
# ring :sales, :read ie. sales can read this model
|
|
79
|
+
# ring :sales, [:read, :create, :destroy] ie. sales can read, create and destroy this model
|
|
80
|
+
def ring(aRing,aAbilities)
|
|
81
|
+
#aRing.each {|r| ring(r,aAbilities)} and return if aRing.is_a? Array shouldn't need this because of ring system
|
|
82
|
+
aRing = Concentric.lookup_ring(aRing)
|
|
83
|
+
raise "aRing must be a number or a symbol defined in Concentric.config.ring_names" if !aRing.is_a?(Fixnum)
|
|
84
|
+
raise "aAbilities must be a Hash" unless aAbilities.is_a? Hash # eg. :write => [:name,:address]
|
|
85
|
+
|
|
86
|
+
ring_rec = self.rings_abilities[aRing]
|
|
87
|
+
aAbilities.each do |abilities,fields|
|
|
88
|
+
abilities = [abilities] unless abilities.is_a?(Array)
|
|
89
|
+
fields = [fields] unless fields.is_a?(Array)
|
|
90
|
+
next if fields.empty?
|
|
91
|
+
abilities.each do |a|
|
|
92
|
+
a = a.to_sym
|
|
93
|
+
ring_rec ||= {}
|
|
94
|
+
if fields==[:this]
|
|
95
|
+
ring_rec[a] = true unless ring_rec[a].to_nil
|
|
96
|
+
else
|
|
97
|
+
ring_fields = ring_rec[a]
|
|
98
|
+
ring_fields = [] unless ring_fields.is_a? Array
|
|
99
|
+
ring_fields = ring_fields + fields.map(&:to_sym)
|
|
100
|
+
ring_fields.uniq!
|
|
101
|
+
ring_fields.sort!
|
|
102
|
+
ring_rec[a] = ring_fields
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
self.rings_abilities[aRing] = ring_rec
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# returns properties that this ring can use this ability on
|
|
110
|
+
def permitted(aRing,aAbility)
|
|
111
|
+
aRing = Concentric.lookup_ring(aRing)
|
|
112
|
+
raise "aRing must be a number or a symbol defined in Concentric.config.ring_names" if !aRing.is_a?(Fixnum)
|
|
113
|
+
return [] unless aRing and rings_abilities = self.respond_to?(:rings_abilities) && self.rings_abilities.to_nil
|
|
114
|
+
|
|
115
|
+
fields = []
|
|
116
|
+
aRing.upto(rings_abilities.length-1) do |i|
|
|
117
|
+
next unless ring_rec = rings_abilities[i]
|
|
118
|
+
if af = ring_rec[aAbility.to_sym]
|
|
119
|
+
next if af==true
|
|
120
|
+
fields += af if af.is_a?(Array)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
fields.uniq!
|
|
124
|
+
fields.sort!
|
|
125
|
+
fields
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Query
|
|
129
|
+
def ring_can?(aRing,aAbility,aFields=nil)
|
|
130
|
+
if aFields
|
|
131
|
+
pf = permitted(aRing,aAbility)
|
|
132
|
+
if aFields.is_a? Array
|
|
133
|
+
return (aFields - pf).empty?
|
|
134
|
+
else
|
|
135
|
+
return pf.include? aFields
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
aRing = Concentric.lookup_ring(aRing)
|
|
140
|
+
return [] unless aRing and rings_abilities = self.respond_to?(:rings_abilities).to_nil && self.rings_abilities
|
|
141
|
+
|
|
142
|
+
aRing.upto(rings_abilities.length-1) do |i|
|
|
143
|
+
next unless ring_rec = rings_abilities[i]
|
|
144
|
+
return true if ring_rec[aAbility.to_sym].to_nil
|
|
145
|
+
end
|
|
146
|
+
return false
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
end
|
|
152
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#require "pundit/version"
|
|
2
|
+
require "pundit/policy_finder"
|
|
3
|
+
#require "active_support/concern"
|
|
4
|
+
#require "active_support/core_ext/string/inflections"
|
|
5
|
+
#require "active_support/core_ext/object/blank"
|
|
6
|
+
|
|
7
|
+
module Kojac
|
|
8
|
+
#class NotAuthorizedError < StandardError; end
|
|
9
|
+
#class NotDefinedError < StandardError; end
|
|
10
|
+
|
|
11
|
+
extend ActiveSupport::Concern
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
def policy_scope(user, scope, op=nil)
|
|
15
|
+
policy = Pundit::PolicyFinder.new(scope).scope
|
|
16
|
+
policy.new(user, scope, op).resolve if policy
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def policy_scope!(user, scope, op=nil)
|
|
20
|
+
Pundit::PolicyFinder.new(scope).scope!.new(user, scope, op).resolve
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def policy(user, record, op=nil)
|
|
24
|
+
scope = Pundit::PolicyFinder.new(record).policy
|
|
25
|
+
scope.new(user, record, op) if scope
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def policy!(user, record, op=nil)
|
|
29
|
+
Pundit::PolicyFinder.new(record).policy!.new(user, record, op)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
included do
|
|
34
|
+
if respond_to?(:helper_method)
|
|
35
|
+
helper_method :policy_scope
|
|
36
|
+
helper_method :policy
|
|
37
|
+
end
|
|
38
|
+
if respond_to?(:hide_action)
|
|
39
|
+
hide_action :authorize
|
|
40
|
+
hide_action :verify_authorized
|
|
41
|
+
hide_action :verify_policy_scoped
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def verify_authorized
|
|
46
|
+
raise NotAuthorizedError unless @_policy_authorized
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def verify_policy_scoped
|
|
50
|
+
raise NotAuthorizedError unless @_policy_scoped
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def authorize(record, query=nil)
|
|
54
|
+
query ||= params[:action].to_s + "?"
|
|
55
|
+
@_policy_authorized = true
|
|
56
|
+
unless policy(record).public_send(query)
|
|
57
|
+
raise NotAuthorizedError, "not allowed to #{query} this #{record}"
|
|
58
|
+
end
|
|
59
|
+
true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def policy_scope(scope)
|
|
63
|
+
@_policy_scoped = true
|
|
64
|
+
Pundit::Pundit.policy_scope!(current_user, scope, op)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def policy(record)
|
|
68
|
+
Pundit::Pundit.policy!(current_user, record, op)
|
|
69
|
+
end
|
|
70
|
+
end
|