erp_tech_svcs 3.0.10 → 3.0.11

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.
Files changed (38) hide show
  1. data/app/models/attribute_type.rb +1 -1
  2. data/app/models/capability.rb +54 -2
  3. data/app/models/capability_accessor.rb +4 -0
  4. data/app/models/extensions/party.rb +1 -0
  5. data/app/models/file_asset.rb +15 -5
  6. data/app/models/group.rb +149 -0
  7. data/app/models/scope_type.rb +5 -0
  8. data/app/models/security_role.rb +46 -0
  9. data/app/models/user.rb +99 -5
  10. data/db/data_migrations/20110109173616_create_capability_scope_types.rb +14 -0
  11. data/db/data_migrations/20121116155018_create_group_relationship_and_role_types.rb +19 -0
  12. data/db/data_migrations/20121130212146_note_capabilities.rb +23 -0
  13. data/db/migrate/20080805000010_base_tech_services.rb +44 -31
  14. data/db/migrate/20121116151510_create_groups.rb +18 -0
  15. data/db/migrate/20121126171612_upgrade_security.rb +53 -0
  16. data/db/migrate/20121126173506_upgrade_security2.rb +274 -0
  17. data/lib/erp_tech_svcs/engine.rb +7 -7
  18. data/lib/erp_tech_svcs/extensions/active_record/base.rb +17 -0
  19. data/lib/erp_tech_svcs/extensions/active_record/has_capability_accessors.rb +131 -0
  20. data/lib/erp_tech_svcs/extensions/active_record/has_file_assets.rb +9 -1
  21. data/lib/erp_tech_svcs/extensions/active_record/has_security_roles.rb +89 -0
  22. data/lib/erp_tech_svcs/extensions/active_record/protected_with_capabilities.rb +203 -0
  23. data/lib/erp_tech_svcs/extensions.rb +4 -2
  24. data/lib/erp_tech_svcs/file_support/manager.rb +1 -1
  25. data/lib/erp_tech_svcs/file_support/s3_manager.rb +3 -3
  26. data/lib/erp_tech_svcs/utils/compass_access_negotiator.rb +29 -24
  27. data/lib/erp_tech_svcs/version.rb +1 -1
  28. data/spec/lib/erp_tech_svcs/extensions/active_record/has_roles_spec.rb +4 -5
  29. data/spec/models/role_spec.rb +2 -2
  30. data/spec/models/secured_model_spec.rb +1 -1
  31. data/spec/models/user_spec.rb +2 -2
  32. metadata +137 -129
  33. data/app/models/capable_model.rb +0 -4
  34. data/app/models/role.rb +0 -17
  35. data/app/models/secured_model.rb +0 -15
  36. data/db/data_migrations/20120109173616_create_download_capability_type.rb +0 -13
  37. data/lib/erp_tech_svcs/extensions/active_record/has_capabilities.rb +0 -152
  38. data/lib/erp_tech_svcs/extensions/active_record/has_roles.rb +0 -130
@@ -1,7 +1,7 @@
1
1
  class AttributeType < ActiveRecord::Base
2
2
  has_many :attribute_values, :dependent => :destroy
3
3
 
4
- validates_uniqueness_of :internal_identifier
4
+ validates_uniqueness_of :internal_identifier, :case_sensitive => false
5
5
  validates :description, :presence => true
6
6
 
7
7
  before_save :update_iid
@@ -1,8 +1,60 @@
1
1
  class Capability < ActiveRecord::Base
2
- has_roles
3
2
 
3
+ belongs_to :scope_type
4
4
  belongs_to :capability_type
5
- has_and_belongs_to_many :capable_models
5
+ belongs_to :capability_resource, :polymorphic => true
6
+ has_many :capability_accessors, :dependent => :destroy
6
7
 
7
8
  alias :type :capability_type
9
+
10
+ after_create :update_description
11
+
12
+ def update_description
13
+ if description.blank?
14
+ desc = "#{capability_type.description} #{capability_resource_type}"
15
+ case scope_type
16
+ when ScopeType.find_by_internal_identifier('class')
17
+ self.description = "#{desc}"
18
+ when ScopeType.find_by_internal_identifier('instance')
19
+ self.description = "#{desc} Instance"
20
+ when ScopeType.find_by_internal_identifier('query')
21
+ self.description = "#{desc} Scope"
22
+ end
23
+ self.save
24
+ end
25
+ end
26
+
27
+ def roles_not
28
+ SecurityRole.joins("LEFT JOIN capability_accessors ON capability_accessors.capability_id = #{self.id}
29
+ AND capability_accessors.capability_accessor_record_type = 'SecurityRole'
30
+ AND capability_accessors.capability_accessor_record_id = security_roles.id").
31
+ where("capability_accessors.id IS NULL")
32
+ end
33
+
34
+ def roles
35
+ SecurityRole.joins(:capability_accessors).where(:capability_accessors => {:capability_id => self.id })
36
+ end
37
+
38
+ def users_not
39
+ User.joins("LEFT JOIN capability_accessors ON capability_accessors.capability_id = #{self.id}
40
+ AND capability_accessors.capability_accessor_record_type = 'User'
41
+ AND capability_accessors.capability_accessor_record_id = users.id").
42
+ where("capability_accessors.id IS NULL")
43
+ end
44
+
45
+ def users
46
+ User.joins(:capability_accessors).where(:capability_accessors => {:capability_id => self.id })
47
+ end
48
+
49
+ def groups_not
50
+ Group.joins("LEFT JOIN capability_accessors ON capability_accessors.capability_id = #{self.id}
51
+ AND capability_accessors.capability_accessor_record_type = 'Group'
52
+ AND capability_accessors.capability_accessor_record_id = groups.id").
53
+ where("capability_accessors.id IS NULL")
54
+ end
55
+
56
+ def groups
57
+ Group.joins(:capability_accessors).where(:capability_accessors => {:capability_id => self.id })
58
+ end
59
+
8
60
  end
@@ -0,0 +1,4 @@
1
+ class CapabilityAccessor < ActiveRecord::Base
2
+ belongs_to :capability_accessor_record, :polymorphic => true
3
+ belongs_to :capability
4
+ end
@@ -1,3 +1,4 @@
1
1
  Party.class_eval do
2
+ has_security_roles
2
3
  has_one :user, :dependent => :destroy
3
4
  end
@@ -43,7 +43,7 @@ class FileAsset < ActiveRecord::Base
43
43
  belongs_to :file_asset_holder, :polymorphic => true
44
44
  instantiates_with_sti
45
45
 
46
- has_capabilities
46
+ protected_with_capabilities
47
47
 
48
48
  #paperclip
49
49
  has_attached_file :data,
@@ -64,7 +64,7 @@ class FileAsset < ActiveRecord::Base
64
64
  validates_attachment_size :data, :less_than => ErpTechSvcs::Config.max_file_size_in_mb.megabytes
65
65
 
66
66
  validates :name, :presence => {:message => 'Name can not be blank'}
67
- validates_uniqueness_of :name, :scope => [:directory]
67
+ validates_uniqueness_of :name, :scope => [:directory], :case_sensitive => false
68
68
  validates_each :directory, :name do |record, attr, value|
69
69
  record.errors.add attr, 'may not contain consequtive dots' if value =~ /\.\./
70
70
  end
@@ -108,7 +108,7 @@ class FileAsset < ActiveRecord::Base
108
108
  end
109
109
  end
110
110
 
111
- def initialize(attributes = {}, options)
111
+ def initialize(attributes = {}, options={})
112
112
  attributes ||= {}
113
113
 
114
114
  base_path = attributes.delete(:base_path)
@@ -127,6 +127,10 @@ class FileAsset < ActiveRecord::Base
127
127
  super attributes.merge(:directory => directory, :name => name, :data => data)
128
128
  end
129
129
 
130
+ def is_secured?
131
+ self.protected_with_capability?('download')
132
+ end
133
+
130
134
  # compass file download url
131
135
  def url
132
136
  "/download/#{self.name}?#{self.directory}"
@@ -139,7 +143,7 @@ class FileAsset < ActiveRecord::Base
139
143
  if ErpTechSvcs::Config.file_storage == :s3
140
144
  file_path = File.join(self.directory,self.name).sub(%r{^/},'')
141
145
  options = {}
142
- options[:expires] = ErpTechSvcs::Config.s3_url_expires_in_seconds if self.has_capabilities?
146
+ options[:expires] = ErpTechSvcs::Config.s3_url_expires_in_seconds if self.is_secured?
143
147
  return file_support.bucket.objects[file_path].url_for(:read, options).to_s
144
148
  else
145
149
  return File.join(Rails.root, self.directory, self.name)
@@ -187,7 +191,7 @@ class FileAsset < ActiveRecord::Base
187
191
 
188
192
  def get_contents
189
193
  file_support = ErpTechSvcs::FileSupport::Base.new(:storage => ErpTechSvcs::Config.file_storage)
190
- file_support.get_contents(File.join(self.directory,self.data_file_name))
194
+ file_support.get_contents(File.join(file_support.root, self.directory, self.data_file_name))
191
195
  end
192
196
 
193
197
  def move(new_parent_path)
@@ -256,6 +260,12 @@ class HtmlFile < TextFile
256
260
  self.valid_extensions = %w(.html .HTML)
257
261
  end
258
262
 
263
+ class XmlFile < TextFile
264
+ self.file_type = :xml
265
+ self.content_type = 'text/plain'
266
+ self.valid_extensions = %w(.xml .XML)
267
+ end
268
+
259
269
  class Pdf < TextFile
260
270
  self.file_type = :pdf
261
271
  self.content_type = 'application/pdf'
@@ -0,0 +1,149 @@
1
+ # Security Group
2
+ class Group < ActiveRecord::Base
3
+ has_capability_accessors
4
+
5
+ after_create :create_party
6
+ after_save :save_party
7
+ after_destroy :destroy_party_relationships, :destroy_party
8
+
9
+ has_one :party, :as => :business_party
10
+
11
+ validates_uniqueness_of :description, :case_sensitive => false
12
+
13
+ def self.add(description)
14
+ Group.create(:description => description)
15
+ end
16
+
17
+ # roles this group does NOT have
18
+ def roles_not
19
+ party.roles_not
20
+ end
21
+
22
+ # roles this group has
23
+ def roles
24
+ party.security_roles
25
+ end
26
+
27
+ def has_role?(role)
28
+ role = role.is_a?(SecurityRole) ? role : SecurityRole.find_by_internal_identifier(role.to_s)
29
+ all_roles.include?(role)
30
+ end
31
+
32
+ def add_role(role)
33
+ party.add_role(role)
34
+ end
35
+
36
+ def remove_role(role)
37
+ party.remove_role(role)
38
+ end
39
+
40
+ def remove_all_roles
41
+ party.remove_all_roles
42
+ end
43
+
44
+ def create_party
45
+ pty = Party.new
46
+ pty.description = self.description
47
+ pty.business_party = self
48
+
49
+ pty.save
50
+ self.save
51
+ end
52
+
53
+ def save_party
54
+ self.party.description = self.description
55
+ self.party.save
56
+ end
57
+
58
+ def destroy_party
59
+ if self.party
60
+ self.party.destroy
61
+ end
62
+ end
63
+
64
+ def destroy_party_relationships
65
+ party_relationships.destroy_all
66
+ end
67
+
68
+ # group lives on TO side of relationship
69
+ def party_relationships
70
+ PartyRelationship.where(:party_id_to => self.party.id)
71
+ end
72
+
73
+ def join_party_relationships
74
+ role_type = RoleType.find_by_internal_identifier('group')
75
+ "party_relationships ON party_id_to = #{self.party.id} AND party_id_from = parties.id AND role_type_id_to=#{role_type.id}"
76
+ end
77
+
78
+ def members
79
+ Party.joins("JOIN #{join_party_relationships}")
80
+ end
81
+
82
+ # get users in this group
83
+ def users
84
+ User.joins(:party).joins("JOIN #{join_party_relationships}")
85
+ end
86
+
87
+ # get users not in this group
88
+ def users_not
89
+ User.joins(:party).joins("LEFT JOIN #{join_party_relationships}").where("party_relationships.id IS NULL")
90
+ end
91
+
92
+ # add user to group
93
+ def add_user(user)
94
+ add_party(user.party)
95
+ end
96
+
97
+ # remove user from group
98
+ def remove_user(user)
99
+ remove_party(user.party)
100
+ end
101
+
102
+ def get_relationship(a_party)
103
+ role_type = RoleType.find_by_internal_identifier('group')
104
+ PartyRelationship.where(:party_id_to => self.party.id, :party_id_from => a_party.id, :role_type_id_to => role_type.id)
105
+ end
106
+
107
+ # add party to group
108
+ # group lives on TO side of relationship
109
+ def add_party(a_party)
110
+ # check and see if party is already a member of this group
111
+ rel = get_relationship(a_party).first
112
+ unless rel.nil?
113
+ # if so, return relationship
114
+ return rel
115
+ else
116
+ # if not then build party_relationship
117
+ rt = RelationshipType.find_by_internal_identifier('group_membership')
118
+ pr = PartyRelationship.new
119
+ pr.description = rt.description
120
+ pr.relationship_type = rt
121
+ pr.from_role = RoleType.find_by_internal_identifier('group_member')
122
+ pr.to_role = RoleType.find_by_internal_identifier('group')
123
+ pr.from_party = a_party
124
+ pr.to_party = self.party
125
+ pr.save
126
+ return pr
127
+ end
128
+ end
129
+
130
+ # remove party from group
131
+ # group lives on TO side of relationship
132
+ def remove_party(a_party)
133
+ begin
134
+ get_relationship(a_party).first.destroy
135
+ rescue Exception => e
136
+ Rails.logger.error e.message
137
+ return nil
138
+ end
139
+ end
140
+
141
+ def class_capabilities_to_hash
142
+ class_capabilities.map {|capability|
143
+ { :capability_type_iid => capability.capability_type.internal_identifier,
144
+ :capability_resource_type => capability.capability_resource_type
145
+ }
146
+ }.compact
147
+ end
148
+
149
+ end
@@ -0,0 +1,5 @@
1
+ class ScopeType < ActiveRecord::Base
2
+
3
+ has_many :capabilities
4
+
5
+ end
@@ -0,0 +1,46 @@
1
+ class SecurityRole < ActiveRecord::Base
2
+ acts_as_erp_type
3
+ has_capability_accessors
4
+ has_and_belongs_to_many :parties
5
+
6
+ validates :description, :presence => {:message => 'Description cannot be blank'}
7
+ validates :internal_identifier, :presence => {:message => 'Internal identifier cannot be blank'}
8
+ validates_uniqueness_of :internal_identifier, :case_sensitive => false
9
+ validates_length_of :internal_identifier, :within => 3..100
10
+
11
+ def to_xml(options = {})
12
+ default_only = []
13
+ options[:only] = (options[:only] || []) + default_only
14
+ super(options)
15
+ end
16
+
17
+ # creating method because we only want a getter, not a setter for iid
18
+ def iid
19
+ self.internal_identifier
20
+ end
21
+
22
+ def join_parties_security_roles
23
+ "parties_security_roles ON parties_security_roles.party_id=parties.id AND parties_security_roles.security_role_id=#{self.id}"
24
+ end
25
+
26
+ # users with this role
27
+ def users
28
+ User.joins(:party).joins("JOIN #{join_parties_security_roles}")
29
+ end
30
+
31
+ # users without this role
32
+ def users_not
33
+ User.joins(:party).joins("LEFT JOIN #{join_parties_security_roles}").where("parties_security_roles.security_role_id IS NULL")
34
+ end
35
+
36
+ # groups with this role
37
+ def groups
38
+ Group.joins(:party).joins("JOIN #{join_parties_security_roles}")
39
+ end
40
+
41
+ # groups without this role
42
+ def groups_not
43
+ Group.joins(:party).joins("LEFT JOIN #{join_parties_security_roles}").where("parties_security_roles.security_role_id IS NULL")
44
+ end
45
+
46
+ end
data/app/models/user.rb CHANGED
@@ -1,26 +1,25 @@
1
1
  class User < ActiveRecord::Base
2
+ include ErpTechSvcs::Utils::CompassAccessNegotiator
2
3
  include ActiveModel::Validations
3
4
 
4
5
  attr_accessor :password_validator
5
6
 
6
- has_roles
7
- include ErpTechSvcs::Utils::CompassAccessNegotiator
8
-
9
7
  belongs_to :party
10
8
 
11
9
  attr_accessible :email, :password, :password_confirmation
12
10
  authenticates_with_sorcery!
11
+ has_capability_accessors
13
12
 
14
13
  #password validations
15
14
  validates_confirmation_of :password, :message => "should match confirmation", :if => :password
16
15
  validates :password, :presence => true, :password_strength => true, :if => :password
17
16
 
18
17
  #email validations
19
- validates :email, :presence => {:message => 'Email cannot be blank'}, :uniqueness => true
18
+ validates :email, :presence => {:message => 'Email cannot be blank'}, :uniqueness => {:case_sensitive => false}
20
19
  validates_format_of :email, :with => /\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/
21
20
 
22
21
  #username validations
23
- validates :username, :presence => {:message => 'Username cannot be blank'}, :uniqueness => true
22
+ validates :username, :presence => {:message => 'Username cannot be blank'}, :uniqueness => {:case_sensitive => false}
24
23
 
25
24
  #these two methods allow us to assign instance level attributes that are not persisted. These are used for mailers
26
25
  def instance_attributes
@@ -32,4 +31,99 @@ class User < ActiveRecord::Base
32
31
  @instance_attrs[k] = v
33
32
  end
34
33
 
34
+ # roles this user does NOT have
35
+ def roles_not
36
+ party.roles_not
37
+ end
38
+
39
+ # roles this user has
40
+ def roles
41
+ party.security_roles
42
+ end
43
+
44
+ def has_role?(role)
45
+ role = role.is_a?(SecurityRole) ? role : SecurityRole.find_by_internal_identifier(role.to_s)
46
+ all_roles.include?(role)
47
+ end
48
+
49
+ def add_role(role)
50
+ party.add_role(role)
51
+ end
52
+
53
+ def remove_role(role)
54
+ party.remove_role(role)
55
+ end
56
+
57
+ def remove_all_roles
58
+ party.remove_all_roles
59
+ end
60
+
61
+ # user lives on FROM side of relationship
62
+ def group_relationships
63
+ role_type = RoleType.find_by_internal_identifier('group_member')
64
+ PartyRelationship.where(:party_id_from => self.party.id, :role_type_id_from => role_type.id)
65
+ end
66
+
67
+ def join_party_relationships
68
+ role_type = RoleType.find_by_internal_identifier('group_member')
69
+ "party_relationships ON party_id_from = #{self.party.id} AND party_id_to = parties.id AND role_type_id_from=#{role_type.id}"
70
+ end
71
+
72
+ # party records for the groups this user belongs to
73
+ def group_parties
74
+ Party.joins("JOIN #{join_party_relationships}")
75
+ end
76
+
77
+ # groups this user belongs to
78
+ def groups
79
+ Group.joins(:party).joins("JOIN #{join_party_relationships}")
80
+ end
81
+
82
+ # groups this user does NOT belong to
83
+ def groups_not
84
+ Group.joins(:party).joins("LEFT JOIN #{join_party_relationships}").where("party_relationships.id IS NULL")
85
+ end
86
+
87
+ # roles assigned to the groups this user belongs to
88
+ def group_roles
89
+ groups.collect{|g| g.roles }.flatten.uniq
90
+ end
91
+
92
+ # composite roles for this user
93
+ def all_roles
94
+ (group_roles + roles).uniq
95
+ end
96
+
97
+ def group_capabilities
98
+ groups.collect{|r| r.capabilities }.flatten.uniq.compact
99
+ end
100
+
101
+ def role_capabilities
102
+ all_roles.collect{|r| r.capabilities }.flatten.compact
103
+ end
104
+
105
+ def all_capabilities
106
+ (role_capabilities + group_capabilities + capabilities).uniq
107
+ end
108
+
109
+ def group_class_capabilities
110
+ groups.collect{|g| g.class_capabilities }.flatten.uniq.compact
111
+ end
112
+
113
+ def role_class_capabilities
114
+ all_roles.collect{|r| r.class_capabilities }.flatten.uniq.compact
115
+ end
116
+
117
+ def all_class_capabilities
118
+ (role_class_capabilities + group_class_capabilities + class_capabilities).uniq
119
+ end
120
+
121
+ def class_capabilities_to_hash
122
+ all_class_capabilities.map {|capability|
123
+ { :capability_type_iid => capability.capability_type.internal_identifier,
124
+ :capability_resource_type => capability.capability_resource_type
125
+ }
126
+ }.compact
127
+ end
128
+
35
129
  end
@@ -0,0 +1,14 @@
1
+ class CreateCapabilityScopeTypes
2
+
3
+ def self.up
4
+ CapabilityType.create(:internal_identifier => 'download', :description => 'Download') if CapabilityType.where("internal_identifier = 'download'").first.nil?
5
+
6
+ ScopeType.create(:description => 'Instance', :internal_identifier => 'instance') if ScopeType.where("internal_identifier = 'instance'").first.nil?
7
+ ScopeType.create(:description => 'Class', :internal_identifier => 'class') if ScopeType.where("internal_identifier = 'class'").first.nil?
8
+ ScopeType.create(:description => 'Query', :internal_identifier => 'query') if ScopeType.where("internal_identifier = 'query'").first.nil?
9
+ end
10
+
11
+ def self.down
12
+ end
13
+
14
+ end
@@ -0,0 +1,19 @@
1
+ class CreateGroupRelationshipAndRoleTypes
2
+
3
+ def self.up
4
+ #insert data here
5
+ to_role = RoleType.create(:description => 'Security Group', :internal_identifier => 'group')
6
+ from_role = RoleType.create(:description => 'Security Group Member', :internal_identifier => 'group_member')
7
+ RelationshipType.create(:description => 'Security Group Membership',
8
+ :name => 'Group Membership',
9
+ :internal_identifier => 'group_membership',
10
+ :valid_from_role => from_role,
11
+ :valid_to_role => to_role
12
+ )
13
+ end
14
+
15
+ def self.down
16
+ #remove data here
17
+ end
18
+
19
+ end
@@ -0,0 +1,23 @@
1
+ class NoteCapabilities
2
+
3
+ def self.up
4
+ #insert data here
5
+ admin = SecurityRole.find_by_internal_identifier('admin')
6
+ employee = SecurityRole.find_by_internal_identifier('employee')
7
+
8
+ admin.add_capability('create', 'Note')
9
+ admin.add_capability('delete', 'Note')
10
+ admin.add_capability('edit', 'Note')
11
+ admin.add_capability('view', 'Note')
12
+
13
+ employee.add_capability('create', 'Note')
14
+ employee.add_capability('delete', 'Note')
15
+ employee.add_capability('edit', 'Note')
16
+ employee.add_capability('view', 'Note')
17
+ end
18
+
19
+ def self.down
20
+ #remove data here
21
+ end
22
+
23
+ end
@@ -49,9 +49,16 @@ class BaseTechServices < ActiveRecord::Migration
49
49
 
50
50
  end
51
51
 
52
- unless table_exists?(:roles)
52
+ unless table_exists?(:groups)
53
+ create_table :groups do |t|
54
+ t.column :description, :string
55
+ t.timestamps
56
+ end
57
+ end
58
+
59
+ unless table_exists?(:security_roles)
53
60
  # create the roles table
54
- create_table :roles do |t|
61
+ create_table :security_roles do |t|
55
62
  t.column :description, :string
56
63
  t.column :internal_identifier, :string
57
64
  t.column :external_identifier, :string
@@ -139,26 +146,6 @@ class BaseTechServices < ActiveRecord::Migration
139
146
  end
140
147
  end
141
148
 
142
- unless table_exists?(:secured_models)
143
- create_table :secured_models do |t|
144
- t.references :secured_record, :polymorphic => true
145
-
146
- t.timestamps
147
- end
148
- add_index :secured_models, [:secured_record_id, :secured_record_type], :name => 'secured_record_idx'
149
- end
150
-
151
- unless table_exists?(:roles_secured_models)
152
- create_table :roles_secured_models, :id => false do |t|
153
- t.references :secured_model
154
- t.references :role
155
-
156
- t.timestamps
157
- end
158
- add_index :roles_secured_models, :secured_model_id
159
- add_index :roles_secured_models, :role_id
160
- end
161
-
162
149
  unless table_exists?(:file_assets)
163
150
  create_table :file_assets do |t|
164
151
  t.references :file_asset_holder, :polymorphic => true
@@ -219,31 +206,57 @@ class BaseTechServices < ActiveRecord::Migration
219
206
  unless table_exists?(:capabilities)
220
207
  # create the roles table
221
208
  create_table :capabilities do |t|
222
- t.string :resource
209
+ t.string :description
223
210
  t.references :capability_type
211
+ t.string :capability_resource_type
212
+ t.integer :capability_resource_id
213
+ t.integer :scope_type_id
214
+ t.text :scope_query
224
215
  t.timestamps
225
216
  end
226
217
 
227
218
  add_index :capabilities, :capability_type_id
219
+ add_index :capabilities, :scope_type_id
220
+ add_index :capabilities, [:capability_resource_id, :capability_resource_type], :name => 'capability_resource_index'
228
221
  end
229
222
 
230
- unless table_exists?(:capabilities_capable_models)
231
- # create the roles table
232
- create_table :capabilities_capable_models, :id => false do |t|
233
- t.references :capable_model
234
- t.references :capability
223
+ unless table_exists?(:capability_accessors)
224
+ create_table :capability_accessors do |t|
225
+ t.string :capability_accessor_record_type
226
+ t.integer :capability_accessor_record_id
227
+ t.integer :capability_id
228
+ t.timestamps
229
+ end
230
+
231
+ add_index :capability_accessors, :capability_id
232
+ add_index :capability_accessors, [:capability_accessor_record_id, :capability_accessor_record_type], :name => 'capability_accessor_record_index'
233
+ end
234
+
235
+ unless table_exists?(:scope_types)
236
+ create_table :scope_types do |t|
237
+ t.string :description
238
+ t.string :internal_identifier
235
239
  t.timestamps
236
240
  end
237
241
 
238
- add_index :capabilities_capable_models, :capable_model_id
239
- add_index :capabilities_capable_models, :capability_id
242
+ add_index :scope_types, :internal_identifier
243
+ end
244
+
245
+ unless table_exists?(:parties_security_roles)
246
+ create_table :parties_security_roles, :id => false do |t|
247
+ t.integer :party_id
248
+ t.integer :security_role_id
249
+ end
250
+
251
+ add_index :parties_security_roles, :party_id
252
+ add_index :parties_security_roles, :security_role_id
240
253
  end
241
254
 
242
255
  end
243
256
 
244
257
  def self.down
245
258
  # check that each table exists before trying to delete it.
246
- [
259
+ [ :groups,
247
260
  :audit_logs, :sessions, :simple_captcha_data,
248
261
  :capable_models, :capability_types, :capabilities,:capabilities_capable_models,
249
262
  :roles_users, :roles, :audit_log_items, :audit_log_item_types,
@@ -0,0 +1,18 @@
1
+ class CreateGroups < ActiveRecord::Migration
2
+ def self.up
3
+ unless table_exists?(:groups)
4
+ create_table :groups do |t|
5
+ t.column :description, :string
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ [ :groups ].each do |tbl|
13
+ if table_exists?(tbl)
14
+ drop_table tbl
15
+ end
16
+ end
17
+ end
18
+ end