monarchy 0.3.1 → 1.0.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 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