monarchy 0.3.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c41ca61cf044e6e4c4ae5a3a2230c6495e662005
4
- data.tar.gz: 283d4f647c876b35712a7ff094bd5bcf4e4cfe9d
3
+ metadata.gz: 7dfc2d0fdc01fa14cb113bb0d1cf87533af6e849
4
+ data.tar.gz: 6ca7712af3dfbe53c0f309432415471bb1f70cf8
5
5
  SHA512:
6
- metadata.gz: d79f2aac6d3ebb18b1a361a7ed26c0ae3156d2876de19b4b4a447862e7f05fae6bb29b9d47c8be3d5c17e7eb998350cf286b380588bcfd0ce3c8a1cbab58a471
7
- data.tar.gz: d2f3d22b828220881e0f39b55798f6ec686d87bf44ef463b8033570eee9177dfa62f8d24c590ebc65c0a5249563e338ded43fc7733a6b5d1c17e938c56941237
6
+ metadata.gz: defd04040f7ece731b35b84ee04000f72cb08be7cceef9d63ba043d61b77459e8a11cdee5f15cbdcece69f1898ce3709c3e127816040159997bf49a96be01a16
7
+ data.tar.gz: fb7b2313b86d63b912b8741038fe245dbf6847ecccce9d681db5575ba370a7f1661bbc5658c6fdeadbdbc650e23e08c809c89db894f49a5a17e51a8247f9ee94
data/Gemfile CHANGED
@@ -24,6 +24,7 @@ group :development, :test do
24
24
  gem 'factory_girl_rails', '4.7.0'
25
25
  gem 'ffaker', '2.2.0'
26
26
  gem 'database_cleaner', '1.5.3'
27
+ gem 'tqdm', '0.3.0'
27
28
  end
28
29
 
29
30
  gem 'simplecov', '0.11.2', require: false, group: :test
data/Gemfile.lock CHANGED
@@ -1,54 +1,55 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- monarchy (0.3.0)
4
+ monarchy (0.3.1)
5
5
  active_record_union (= 1.1.1)
6
6
  closure_tree (= 6.0.0)
7
7
  configurations (= 2.2.0)
8
8
  rails (~> 4.2, >= 4.2.4)
9
+ tqdm (= 0.3.0)
9
10
 
10
11
  GEM
11
12
  remote: https://rubygems.org/
12
13
  specs:
13
- actionmailer (4.2.6)
14
- actionpack (= 4.2.6)
15
- actionview (= 4.2.6)
16
- activejob (= 4.2.6)
14
+ actionmailer (4.2.7)
15
+ actionpack (= 4.2.7)
16
+ actionview (= 4.2.7)
17
+ activejob (= 4.2.7)
17
18
  mail (~> 2.5, >= 2.5.4)
18
19
  rails-dom-testing (~> 1.0, >= 1.0.5)
19
- actionpack (4.2.6)
20
- actionview (= 4.2.6)
21
- activesupport (= 4.2.6)
20
+ actionpack (4.2.7)
21
+ actionview (= 4.2.7)
22
+ activesupport (= 4.2.7)
22
23
  rack (~> 1.6)
23
24
  rack-test (~> 0.6.2)
24
25
  rails-dom-testing (~> 1.0, >= 1.0.5)
25
26
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
26
- actionview (4.2.6)
27
- activesupport (= 4.2.6)
27
+ actionview (4.2.7)
28
+ activesupport (= 4.2.7)
28
29
  builder (~> 3.1)
29
30
  erubis (~> 2.7.0)
30
31
  rails-dom-testing (~> 1.0, >= 1.0.5)
31
32
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
32
33
  active_record_union (1.1.1)
33
34
  activerecord (>= 4.0)
34
- activejob (4.2.6)
35
- activesupport (= 4.2.6)
35
+ activejob (4.2.7)
36
+ activesupport (= 4.2.7)
36
37
  globalid (>= 0.3.0)
37
- activemodel (4.2.6)
38
- activesupport (= 4.2.6)
38
+ activemodel (4.2.7)
39
+ activesupport (= 4.2.7)
39
40
  builder (~> 3.1)
40
- activerecord (4.2.6)
41
- activemodel (= 4.2.6)
42
- activesupport (= 4.2.6)
41
+ activerecord (4.2.7)
42
+ activemodel (= 4.2.7)
43
+ activesupport (= 4.2.7)
43
44
  arel (~> 6.0)
44
- activesupport (4.2.6)
45
+ activesupport (4.2.7)
45
46
  i18n (~> 0.7)
46
47
  json (~> 1.7, >= 1.7.7)
47
48
  minitest (~> 5.1)
48
49
  thread_safe (~> 0.3, >= 0.3.4)
49
50
  tzinfo (~> 1.1)
50
51
  arel (6.0.3)
51
- ast (2.2.0)
52
+ ast (2.3.0)
52
53
  builder (3.2.2)
53
54
  closure_tree (6.0.0)
54
55
  activerecord (>= 4.1.0)
@@ -66,7 +67,7 @@ GEM
66
67
  factory_girl (~> 4.7.0)
67
68
  railties (>= 3.0.0)
68
69
  ffaker (2.2.0)
69
- globalid (0.3.6)
70
+ globalid (0.3.7)
70
71
  activesupport (>= 4.1.0)
71
72
  i18n (0.7.0)
72
73
  json (1.8.3)
@@ -78,14 +79,16 @@ GEM
78
79
  mime-types (3.1)
79
80
  mime-types-data (~> 3.2015)
80
81
  mime-types-data (3.2016.0521)
81
- mini_portile2 (2.0.0)
82
+ mini_portile2 (2.1.0)
82
83
  minitest (5.9.0)
83
- nokogiri (1.6.7.2)
84
- mini_portile2 (~> 2.0.0.rc2)
85
- parser (2.3.1.0)
84
+ nokogiri (1.6.8)
85
+ mini_portile2 (~> 2.1.0)
86
+ pkg-config (~> 1.1.7)
87
+ parser (2.3.1.2)
86
88
  ast (~> 2.2)
89
+ pkg-config (1.1.7)
87
90
  powerpack (0.1.1)
88
- pry (0.10.3)
91
+ pry (0.10.4)
89
92
  coderay (~> 1.1.0)
90
93
  method_source (~> 0.8.1)
91
94
  slop (~> 3.4)
@@ -94,16 +97,16 @@ GEM
94
97
  rack (1.6.4)
95
98
  rack-test (0.6.3)
96
99
  rack (>= 1.0)
97
- rails (4.2.6)
98
- actionmailer (= 4.2.6)
99
- actionpack (= 4.2.6)
100
- actionview (= 4.2.6)
101
- activejob (= 4.2.6)
102
- activemodel (= 4.2.6)
103
- activerecord (= 4.2.6)
104
- activesupport (= 4.2.6)
100
+ rails (4.2.7)
101
+ actionmailer (= 4.2.7)
102
+ actionpack (= 4.2.7)
103
+ actionview (= 4.2.7)
104
+ activejob (= 4.2.7)
105
+ activemodel (= 4.2.7)
106
+ activerecord (= 4.2.7)
107
+ activesupport (= 4.2.7)
105
108
  bundler (>= 1.3.0, < 2.0)
106
- railties (= 4.2.6)
109
+ railties (= 4.2.7)
107
110
  sprockets-rails
108
111
  rails-deprecated_sanitizer (1.0.3)
109
112
  activesupport (>= 4.2.0.alpha)
@@ -113,13 +116,13 @@ GEM
113
116
  rails-deprecated_sanitizer (>= 1.0.1)
114
117
  rails-html-sanitizer (1.0.3)
115
118
  loofah (~> 2.0)
116
- railties (4.2.6)
117
- actionpack (= 4.2.6)
118
- activesupport (= 4.2.6)
119
+ railties (4.2.7)
120
+ actionpack (= 4.2.7)
121
+ activesupport (= 4.2.7)
119
122
  rake (>= 0.8.7)
120
123
  thor (>= 0.18.1, < 2.0)
121
124
  rainbow (2.1.0)
122
- rake (11.1.2)
125
+ rake (11.2.2)
123
126
  rspec (3.4.0)
124
127
  rspec-core (~> 3.4.0)
125
128
  rspec-expectations (~> 3.4.0)
@@ -156,19 +159,20 @@ GEM
156
159
  simplecov-html (~> 0.10.0)
157
160
  simplecov-html (0.10.0)
158
161
  slop (3.6.0)
159
- sprockets (3.6.0)
162
+ sprockets (3.7.0)
160
163
  concurrent-ruby (~> 1.0)
161
164
  rack (> 1, < 3)
162
- sprockets-rails (3.0.4)
165
+ sprockets-rails (3.1.1)
163
166
  actionpack (>= 4.0)
164
167
  activesupport (>= 4.0)
165
168
  sprockets (>= 3.0.0)
166
169
  sqlite3 (1.3.11)
167
170
  thor (0.19.1)
168
171
  thread_safe (0.3.5)
172
+ tqdm (0.3.0)
169
173
  tzinfo (1.2.2)
170
174
  thread_safe (~> 0.1)
171
- unicode-display_width (1.0.5)
175
+ unicode-display_width (1.1.0)
172
176
  with_advisory_lock (3.0.0)
173
177
  activerecord (>= 3.2)
174
178
  thread_safe
@@ -183,16 +187,17 @@ DEPENDENCIES
183
187
  ffaker (= 2.2.0)
184
188
  monarchy!
185
189
  pry-rails (= 0.3.4)
186
- rake (~> 11.1.2)
190
+ rake (~> 11.1)
187
191
  rspec (= 3.4.0)
188
192
  rspec-rails (= 3.4.2)
189
193
  rubocop (= 0.40.0)
190
194
  shoulda-matchers (= 3.1.1)
191
195
  simplecov (= 0.11.2)
192
196
  sqlite3 (= 1.3.11)
197
+ tqdm (= 0.3.0)
193
198
 
194
199
  RUBY VERSION
195
200
  ruby 2.3.0p0
196
201
 
197
202
  BUNDLED WITH
198
- 1.12.1
203
+ 1.12.5
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ class Monarchy::Member < ActiveRecord::Base
3
+ acts_as_member
4
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ class Monarchy::MembersRole < ActiveRecord::Base
3
+ self.table_name = 'monarchy_members_roles'
4
+
5
+ belongs_to :member, class_name: "::#{Monarchy.member_class}"
6
+ belongs_to :role, class_name: "::#{Monarchy.role_class}"
7
+
8
+ validates :role_id, uniqueness: { scope: :member_id }
9
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ class Monarchy::Role < ActiveRecord::Base
3
+ acts_as_role
4
+ end
@@ -10,12 +10,9 @@ module Monarchy
10
10
 
11
11
  def setup_monarchy
12
12
  template 'config.rb', 'config/initializers/monarchy.rb'
13
- template 'models/user.rb', 'app/models/user.rb'
14
- template 'models/hierarchy.rb', 'app/models/monarchy/hierarchy.rb'
15
13
 
16
14
  migration_template 'migrations/hierarchy.rb', 'db/migrate/monarchy_create_hierarchies.rb'
17
15
  migration_template 'migrations/membership.rb', 'db/migrate/monarchy_create_memberships.rb'
18
- migration_template 'migrations/user.rb', 'db/migrate/monarchy_create_users.rb'
19
16
  end
20
17
 
21
18
  def self.next_migration_number(dirname)
@@ -2,4 +2,11 @@ Monarchy.configure do |config|
2
2
  config.default_role.name = :guest
3
3
  config.default_role.level = 0
4
4
  config.default_role.inherited = false
5
+
6
+ config.member_class_name = 'Monarchy::Member'
7
+ config.role_class_name = 'Monarchy::Role'
8
+ # config.user_class_name = 'User'
9
+
10
+ # config.member_force_revoke = true
11
+ # config.restricted_role_names = ['member']
5
12
  end
@@ -9,18 +9,30 @@ class MonarchyCreateMemberships < ActiveRecord::Migration
9
9
  create_table :monarchy_roles do |t|
10
10
  t.string :name, null: false
11
11
  t.integer :level, default: 0, null: false
12
+ t.integer :inherited_role_id
12
13
  t.boolean :inherited, default: false, null: false
13
14
  t.timestamps null: false
14
15
  end
15
16
 
16
- add_index :monarchy_roles, :name, unique: true
17
-
18
17
  create_table :monarchy_members_roles do |t|
19
18
  t.belongs_to :role
20
19
  t.belongs_to :member
21
20
  t.timestamps null: false
22
21
  end
23
22
 
23
+ add_index :monarchy_hierarchies, :parent_id
24
+ add_index :monarchy_hierarchies, :resource_id
25
+
26
+ add_index :monarchy_members, :hierarchy_id
27
+ add_index :monarchy_members, :user_id
28
+
29
+ add_index :monarchy_roles, :level
30
+ add_index :monarchy_roles, :inherited
31
+ add_index :monarchy_roles, :inherited_role_id
32
+ add_index :monarchy_roles, :name, unique: true
33
+
24
34
  add_index :monarchy_members_roles, [:role_id, :member_id], unique: true
35
+ add_index :monarchy_members_roles, :member_id
36
+ add_index :monarchy_members_roles, :role_id
25
37
  end
26
38
  end
@@ -8,7 +8,7 @@ module Monarchy
8
8
  extend Monarchy::ActsAsHierarchy::SupportMethods
9
9
  has_closure_tree dependent: :destroy
10
10
 
11
- has_many :members, class_name: 'Monarchy::Member', dependent: :destroy
11
+ has_many :members, class_name: "::#{Monarchy.member_class}", dependent: :destroy
12
12
  belongs_to :resource, polymorphic: true, dependent: :destroy
13
13
 
14
14
  include_scopes
@@ -40,11 +40,30 @@ module Monarchy
40
40
  end
41
41
 
42
42
  def accessible_leaves(user)
43
- joins('INNER JOIN "monarchy_hierarchy_hierarchies" ON '\
44
- '"monarchy_hierarchies"."id" = "monarchy_hierarchy_hierarchies"."descendant_id"')
45
- .joins('INNER JOIN "monarchy_members" ON '\
46
- '"monarchy_members"."hierarchy_id" = "monarchy_hierarchy_hierarchies"."ancestor_id"')
47
- .where(monarchy_members: { user_id: user.id }).distinct
43
+ descendant_leaves.where('monarchy_hierarchy_hierarchies.descendant_id': descendant_leaves_for_user(user)
44
+ .where('monarchy_roles.name': restricted_role_names)
45
+ .select('monarchy_hierarchy_hierarchies.ancestor_id')).union(
46
+ descendant_leaves
47
+ .where('monarchy_hierarchy_hierarchies.ancestor_id': descendant_leaves_for_user(user)
48
+ .where.not('monarchy_roles.name': restricted_role_names))
49
+ )
50
+ end
51
+
52
+ def restricted_role_names
53
+ Array(Monarchy.configuration.restricted_role_names) + [default_role_name]
54
+ end
55
+
56
+ def default_role_name
57
+ Monarchy.configuration.default_role.name
58
+ end
59
+
60
+ def descendant_leaves_for_user(user)
61
+ descendant_leaves.joins(members: [:roles]).where(monarchy_members: { user_id: user.id })
62
+ end
63
+
64
+ def descendant_leaves
65
+ joins('INNER JOIN "monarchy_hierarchy_hierarchies" ON "monarchy_hierarchies"."id" =' \
66
+ '"monarchy_hierarchy_hierarchies"."descendant_id"')
48
67
  end
49
68
  end
50
69
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+ module Monarchy
3
+ module ActsAsMember
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def acts_as_member
8
+ extend Monarchy::ActsAsMember::SupportMethods
9
+
10
+ self.table_name = 'monarchy_members'
11
+
12
+ delegate :resource, :resource_id, :resource_type, to: :hierarchy
13
+
14
+ include_relationships
15
+ include_validators
16
+ include_callbacks
17
+ include_scopes
18
+
19
+ include Monarchy::ActsAsMember::InstanceMethods
20
+ end
21
+ end
22
+
23
+ module SupportMethods
24
+ def include_scopes
25
+ scope :accessible_for, (lambda do |user|
26
+ where(hierarchy: Monarchy::Hierarchy.accessible_for(user))
27
+ end)
28
+ end
29
+
30
+ def include_callbacks
31
+ before_create :set_default_role
32
+ after_destroy :revoke_access, if: :member_force_revoke?
33
+ end
34
+
35
+ def include_validators
36
+ validates :user_id, uniqueness: { scope: :hierarchy_id }
37
+ validates :user, presence: true
38
+ validate :hierarchy_or_resource
39
+ end
40
+
41
+ def include_relationships
42
+ has_many :members_roles, dependent: :destroy, class_name: 'Monarchy::MembersRole'
43
+ has_many :roles, -> { order(level: :desc) }, through: :members_roles, class_name: "::#{Monarchy.role_class}"
44
+
45
+ belongs_to :user, class_name: "::#{Monarchy.user_class}"
46
+ belongs_to :hierarchy, class_name: 'Monarchy::Hierarchy'
47
+ end
48
+ end
49
+
50
+ module InstanceMethods
51
+ def resource=(resource)
52
+ self.hierarchy = resource.hierarchy unless hierarchy
53
+ end
54
+
55
+ private
56
+
57
+ def revoke_access
58
+ user.revoke_access(resource, resource.hierarchy.descendant_ids)
59
+ end
60
+
61
+ def member_force_revoke?
62
+ Monarchy.configuration.member_force_revoke
63
+ end
64
+
65
+ def set_default_role
66
+ roles = self.roles
67
+ roles << Monarchy.role_class.find_or_create_by(
68
+ name: Monarchy.configuration.default_role.name,
69
+ inherited: Monarchy.configuration.default_role.inherited,
70
+ level: Monarchy.configuration.default_role.level
71
+ )
72
+ self.roles = roles.uniq
73
+ end
74
+
75
+ def hierarchy_or_resource
76
+ errors.add(:base, 'Specify a resource or a hierarchy') unless hierarchy
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ ActiveRecord::Base.send :include, Monarchy::ActsAsMember
@@ -6,13 +6,15 @@ module Monarchy
6
6
  module ClassMethods
7
7
  def acts_as_resource(options = {})
8
8
  extend Monarchy::ActsAsResource::SupportMethods
9
+ setup_acting
9
10
 
10
11
  parent_as(options[:parent_as]) if options[:parent_as]
11
12
 
12
13
  after_create :ensure_hierarchy
14
+ after_save :assign_parent
13
15
 
14
- has_many :members, through: :hierarchy, class_name: 'Monarchy::Member'
15
- has_many :users, through: :members, class_name: 'User'
16
+ has_many :members, through: :hierarchy, class_name: "::#{Monarchy.member_class}"
17
+ has_many :users, through: :members, class_name: "::#{Monarchy.user_class}"
16
18
  has_one :hierarchy, as: :resource, dependent: :destroy, class_name: 'Monarchy::Hierarchy'
17
19
 
18
20
  include_scopes
@@ -22,24 +24,22 @@ module Monarchy
22
24
  end
23
25
 
24
26
  module SupportMethods
27
+ attr_accessor :parentize, :acting_as_resource
28
+
25
29
  private
26
30
 
27
- def parent_as(name)
28
- define_method "#{name}=" do |value|
29
- self.parent = value
30
- super(value)
31
- end
31
+ def setup_acting
32
+ Monarchy.resource_classes << self
33
+ @acting_as_resource = true
34
+ end
32
35
 
33
- define_method "#{name}_id=" do |id|
34
- class_name = name.to_s.camelize.safe_constantize
35
- self.parent = class_name.find(id)
36
- super(id)
37
- end
36
+ def parent_as(name)
37
+ self.parentize = name
38
38
  end
39
39
 
40
40
  def include_scopes
41
41
  scope :in, (lambda do |resource|
42
- joins(:hierarchy).where(monarchy_hierarchies: { parent_id: resource.hierarchy.self_and_descendant_ids })
42
+ joins(:hierarchy).where(monarchy_hierarchies: { parent_id: resource.hierarchy.self_and_descendants })
43
43
  end)
44
44
 
45
45
  scope :accessible_for, (lambda do |user|
@@ -80,6 +80,11 @@ module Monarchy
80
80
  )
81
81
  end
82
82
 
83
+ def assign_parent(force = false)
84
+ parent = self.class.parentize
85
+ self.parent = send(parent) if parent && (send("#{parent}_id_changed?") || force)
86
+ end
87
+
83
88
  def children_resources
84
89
  c = hierarchy.try(:children)
85
90
  return nil if c.nil?
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ module Monarchy
3
+ module ActsAsRole
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def acts_as_role
8
+ self.table_name = 'monarchy_roles'
9
+
10
+ has_many :members_roles, dependent: :destroy, class_name: 'Monarchy::MembersRole'
11
+ has_many :members, through: :members_roles, class_name: "::#{Monarchy.member_class}"
12
+
13
+ belongs_to :inherited_role, class_name: "::#{Monarchy.role_class}"
14
+
15
+ after_create :default_inherited_role
16
+
17
+ include Monarchy::ActsAsRole::InstanceMethods
18
+ end
19
+ end
20
+
21
+ module InstanceMethods
22
+ private
23
+
24
+ def default_inherited_role
25
+ update(inherited_role_id: id) unless inherited_role
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ ActiveRecord::Base.send :include, Monarchy::ActsAsRole
@@ -5,17 +5,22 @@ module Monarchy
5
5
 
6
6
  module ClassMethods
7
7
  def acts_as_user
8
- has_many :members, class_name: 'Monarchy::Member', dependent: :destroy
8
+ has_many :members, class_name: "::#{Monarchy.member_class}", dependent: :destroy
9
9
  has_many :hierarchies, through: :members, class_name: 'Monarchy::Hierarchy'
10
10
 
11
+ scope :accessible_for, (lambda do |user|
12
+ where(id: Monarchy::Hierarchy.accessible_for(user)
13
+ .joins(members: [:user]).select(:user_id)).union(where(id: user.id))
14
+ end)
15
+
11
16
  include Monarchy::ActsAsUser::InstanceMethods
12
17
  end
13
18
  end
14
19
 
15
20
  module InstanceMethods
16
21
  def roles_for(resource, inheritence = true)
17
- return [] unless resource.hierarchy
18
- accessible_roles_for(resource, inheritence).group_by(&:level).values.first || []
22
+ return Monarchy.role_class.none unless resource.hierarchy
23
+ accessible_roles_for(resource, inheritence)
19
24
  end
20
25
 
21
26
  def member_for(resource)
@@ -28,9 +33,9 @@ module Monarchy
28
33
  end
29
34
  end
30
35
 
31
- def revoke_access(resource)
32
- self_and_descendant_ids = resource.hierarchy.self_and_descendant_ids
33
- members_for(self_and_descendant_ids).destroy_all
36
+ def revoke_access(resource, hierarchy_ids = nil)
37
+ hierarchy_ids ||= resource.hierarchy.self_and_descendant_ids
38
+ members_for(hierarchy_ids).delete_all
34
39
  end
35
40
 
36
41
  def revoke_role(role_name, resource)
@@ -44,30 +49,35 @@ module Monarchy
44
49
  private
45
50
 
46
51
  def accessible_roles_for(resource, inheritnce)
47
- accessible_roles = inheritnce ? resource_and_inheritence_roles(resource) : resource_roles(resource)
52
+ accessible_roles = if inheritnce
53
+ resource_and_inheritence_roles(resource)
54
+ else
55
+ resource_roles(resource).order('level desc')
56
+ end
57
+
48
58
  accessible_roles.present? ? accessible_roles : descendant_role(resource)
49
59
  end
50
60
 
51
61
  def resource_and_inheritence_roles(resource)
52
- hierarchy_ids = resource.hierarchy.self_and_ancestors_ids
53
- Monarchy::Role.joins(:members)
54
- .where("((monarchy_roles.inherited = 't' "\
55
- "AND monarchy_members.hierarchy_id IN (#{hierarchy_ids.join(',')})) "\
56
- "OR (monarchy_members.hierarchy_id = #{resource.hierarchy.id})) "\
57
- "AND monarchy_members.user_id = #{id}")
58
- .distinct.order(level: :desc)
62
+ hierarchy_ids = resource.hierarchy.ancestors.select(:id)
63
+ Monarchy.role_class.where(id:
64
+ Monarchy.role_class.joins(:members).where('monarchy_members.user_id': id)
65
+ .where('monarchy_roles.inherited': 't', 'monarchy_members.hierarchy_id': hierarchy_ids)
66
+ .select(:inherited_role_id))
67
+ .union(resource_roles(resource))
68
+ .distinct
59
69
  end
60
70
 
61
71
  def resource_roles(resource)
62
- Monarchy::Role.joins(:members)
63
- .where('monarchy_members.hierarchy_id': resource.hierarchy.id, 'monarchy_members.user_id': id)
64
- .distinct.order(level: :desc)
72
+ Monarchy.role_class.joins(:members)
73
+ .where('monarchy_members.hierarchy_id': resource.hierarchy.id, 'monarchy_members.user_id': id)
74
+ .distinct
65
75
  end
66
76
 
67
77
  def descendant_role(resource)
68
78
  descendant_ids = resource.hierarchy.descendant_ids
69
79
  children_access = members_for(descendant_ids).present?
70
- children_access ? [default_role] : []
80
+ children_access ? Monarchy.role_class.where(id: default_role) : Monarchy.role_class.none
71
81
  end
72
82
 
73
83
  def revoking_role(role_name, resource, force = false)
@@ -75,28 +85,29 @@ module Monarchy
75
85
  member_roles = member.members_roles
76
86
 
77
87
  return revoke_access(resource) if last_role?(member_roles, role_name) && force
78
- member_roles.joins(:role).where(monarchy_roles: { name: role_name }).destroy_all
88
+ member_roles.joins(:role).where(monarchy_roles: { name: role_name }).delete_all
79
89
  end
80
90
 
81
91
  def grant_or_create_member(role_name, resource)
82
- role = Monarchy::Role.find_by(name: role_name)
83
- member = member_for(resource)
92
+ role = Monarchy.role_class.find_by(name: role_name)
93
+ raise 'Role does not exist' unless role
84
94
 
95
+ member = member_for(resource)
85
96
  if member
86
97
  Monarchy::MembersRole.create(member: member, role: role)
87
98
  else
88
- member = Monarchy::Member.create(user: self, hierarchy: resource.hierarchy, roles: [role])
99
+ member = Monarchy.member_class.create(user: self, hierarchy: resource.hierarchy, roles: [role])
89
100
  end
90
101
 
91
102
  member
92
103
  end
93
104
 
94
105
  def members_for(hierarchy_ids)
95
- Monarchy::Member.where(hierarchy_id: hierarchy_ids, user_id: id)
106
+ Monarchy.member_class.where(hierarchy_id: hierarchy_ids, user_id: id)
96
107
  end
97
108
 
98
109
  def default_role
99
- @default_role ||= Monarchy::Role.find_by(name: Monarchy.configuration.default_role.name)
110
+ @default_role ||= Monarchy.role_class.find_by(name: Monarchy.configuration.default_role.name)
100
111
  end
101
112
 
102
113
  def last_role?(member_roles, role_name = nil)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Monarchy
3
- VERSION = '0.3.1'
3
+ VERSION = '1.0.0'
4
4
  end
data/lib/monarchy.rb CHANGED
@@ -3,16 +3,43 @@ require 'closure_tree'
3
3
  require 'configurations'
4
4
  require 'active_record_union'
5
5
 
6
+ require 'monarchy/acts_as_role'
7
+ require 'monarchy/acts_as_member'
6
8
  require 'monarchy/acts_as_hierarchy'
7
9
  require 'monarchy/acts_as_resource'
8
10
  require 'monarchy/acts_as_user'
9
- require 'monarchy/membership'
10
11
  require 'monarchy/engine'
11
12
 
12
13
  module Monarchy
14
+ cattr_accessor :resource_classes
15
+
16
+ def self.resource_classes
17
+ @resource_classes ||= []
18
+ end
19
+
13
20
  include Configurations
14
21
 
22
+ configuration_defaults do |config|
23
+ config.member_class_name = 'Monarchy::Member'
24
+ config.role_class_name = 'Monarchy::Role'
25
+ config.member_force_revoke = false
26
+ config.restricted_role_names = []
27
+ end
28
+
15
29
  not_configured do |prop|
16
- raise NoMethodError, "#{prop} must be configured"
30
+ raise NoMethodError, "Monarchy requires a #{prop} to be configured"
31
+ end
32
+
33
+ def self.member_class
34
+ Monarchy.configuration.member_class_name.safe_constantize
35
+ end
36
+
37
+ def self.role_class
38
+ Monarchy.configuration.role_class_name.safe_constantize
39
+ end
40
+
41
+ def self.user_class
42
+ klass = Monarchy.configuration.user_class_name.safe_constantize
43
+ klass ? klass : raise(ArgumentError, 'User class has to be initialized or exist!')
17
44
  end
18
45
  end
@@ -1,5 +1,18 @@
1
1
  # frozen_string_literal: true
2
- # desc "Explaining what the task does"
3
- # task :monarchy do
4
- # # Task goes here
5
- # end
2
+ require 'tqdm'
3
+
4
+ task 'monarchy:reparentize' do
5
+ Monarchy.resource_classes.with_progress.each do |klass|
6
+ klass.all.each do |model|
7
+ model.send(:assign_parent, true)
8
+ end
9
+ end
10
+ end
11
+
12
+ task 'monarchy:hierarchization' do
13
+ Monarchy.resource_classes.with_progress.each do |klass|
14
+ klass.all.each do |model|
15
+ model.send(:ensure_hierarchy)
16
+ end
17
+ end
18
+ end
data/monarchy.gemspec CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
29
29
  s.add_dependency 'closure_tree', '6.0.0'
30
30
  s.add_dependency 'configurations', '2.2.0'
31
31
  s.add_dependency 'active_record_union', '1.1.1'
32
+ s.add_dependency 'tqdm', '0.3.0'
32
33
 
33
34
  s.add_development_dependency 'bundler', '~> 1.10'
34
35
  s.add_development_dependency 'rake', '~> 11.1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monarchy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Exelord
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-29 00:00:00.000000000 Z
11
+ date: 2016-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -72,6 +72,20 @@ dependencies:
72
72
  - - '='
73
73
  - !ruby/object:Gem::Version
74
74
  version: 1.1.1
75
+ - !ruby/object:Gem::Dependency
76
+ name: tqdm
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '='
80
+ - !ruby/object:Gem::Version
81
+ version: 0.3.0
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '='
87
+ - !ruby/object:Gem::Version
88
+ version: 0.3.0
75
89
  - !ruby/object:Gem::Dependency
76
90
  name: bundler
77
91
  requirement: !ruby/object:Gem::Requirement
@@ -133,6 +147,9 @@ files:
133
147
  - README.md
134
148
  - Rakefile
135
149
  - app/models/monarchy/hierarchy.rb
150
+ - app/models/monarchy/member.rb
151
+ - app/models/monarchy/members_role.rb
152
+ - app/models/monarchy/role.rb
136
153
  - bin/console
137
154
  - bin/setup
138
155
  - lib/generators/monarchy/resource_generator.rb
@@ -141,16 +158,14 @@ files:
141
158
  - lib/generators/templates/migrations/hierarchy.rb
142
159
  - lib/generators/templates/migrations/membership.rb
143
160
  - lib/generators/templates/migrations/resource.rb
144
- - lib/generators/templates/migrations/user.rb
145
- - lib/generators/templates/models/hierarchy.rb
146
161
  - lib/generators/templates/models/resource.rb
147
- - lib/generators/templates/models/user.rb
148
162
  - lib/monarchy.rb
149
163
  - lib/monarchy/acts_as_hierarchy.rb
164
+ - lib/monarchy/acts_as_member.rb
150
165
  - lib/monarchy/acts_as_resource.rb
166
+ - lib/monarchy/acts_as_role.rb
151
167
  - lib/monarchy/acts_as_user.rb
152
168
  - lib/monarchy/engine.rb
153
- - lib/monarchy/membership.rb
154
169
  - lib/monarchy/version.rb
155
170
  - lib/tasks/monarchy_tasks.rake
156
171
  - monarchy.gemspec
@@ -1,7 +0,0 @@
1
- class MonarchyCreateUsers < ActiveRecord::Migration
2
- def change
3
- create_table :users do |t|
4
- t.timestamps null: false
5
- end
6
- end
7
- end
@@ -1,4 +0,0 @@
1
- class Monarchy::Hierarchy < ActiveRecord::Base
2
- self.table_name = 'monarchy_hierarchies'
3
- acts_as_hierarchy
4
- end
@@ -1,3 +0,0 @@
1
- class User < ActiveRecord::Base
2
- acts_as_user
3
- end
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
- module Monarchy
3
- class Member < ActiveRecord::Base
4
- self.table_name = 'monarchy_members'
5
-
6
- has_many :members_roles, dependent: :destroy, class_name: 'Monarchy::MembersRole'
7
- has_many :roles, through: :members_roles, class_name: 'Monarchy::Role'
8
-
9
- belongs_to :user
10
- belongs_to :hierarchy, class_name: 'Monarchy::Hierarchy'
11
-
12
- delegate :resource, :resource=, :resource_id, :resource_type, to: :hierarchy
13
-
14
- validates :user_id, uniqueness: { scope: :hierarchy_id }
15
- validates :user, presence: true
16
-
17
- validate :hierarchy_or_resource
18
-
19
- before_create :set_default_role
20
-
21
- scope :accessible_for, (lambda do |user|
22
- where(hierarchy: Monarchy::Hierarchy.accessible_for(user))
23
- end)
24
-
25
- def resource=(resource)
26
- self.hierarchy = resource.hierarchy unless hierarchy
27
- end
28
-
29
- private
30
-
31
- def set_default_role
32
- roles = self.roles
33
- roles << Monarchy::Role.find_or_create_by(
34
- name: Monarchy.configuration.default_role.name,
35
- inherited: Monarchy.configuration.default_role.inherited,
36
- level: Monarchy.configuration.default_role.level
37
- )
38
- self.roles = roles.uniq
39
- end
40
-
41
- def hierarchy_or_resource
42
- errors.add(:base, 'Specify a resource or a hierarchy') unless hierarchy
43
- end
44
- end
45
-
46
- class Role < ActiveRecord::Base
47
- self.table_name = 'monarchy_roles'
48
-
49
- has_many :members_roles, dependent: :destroy, class_name: 'Monarchy::MembersRole'
50
- has_many :members, through: :members_roles, class_name: 'Monarchy::Member'
51
- end
52
-
53
- class MembersRole < ActiveRecord::Base
54
- self.table_name = 'monarchy_members_roles'
55
-
56
- belongs_to :member, class_name: 'Monarchy::Member'
57
- belongs_to :role, class_name: 'Monarchy::Role'
58
-
59
- validates :role_id, uniqueness: { scope: :member_id }
60
- end
61
- end