erp_tech_svcs 3.1.0 → 3.1.1
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.
- data/app/models/group.rb +17 -3
- data/app/models/user.rb +40 -10
- data/lib/erp_tech_svcs/extensions/active_record/has_capability_accessors.rb +10 -4
- data/lib/erp_tech_svcs/extensions/active_record/protected_with_capabilities.rb +53 -28
- data/lib/erp_tech_svcs/utils/compass_access_negotiator.rb +5 -3
- data/lib/erp_tech_svcs/version.rb +1 -1
- data/lib/tasks/erp_tech_svcs_tasks.rake +2 -2
- data/spec/lib/erp_tech_svcs/extensions/active_record/has_roles_spec.rb +8 -3
- data/spec/spec_helper.rb +3 -1
- metadata +2 -8
data/app/models/group.rb
CHANGED
@@ -140,15 +140,29 @@ class Group < ActiveRecord::Base
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def role_class_capabilities
|
143
|
-
|
143
|
+
scope_type = ScopeType.find_by_internal_identifier('class')
|
144
|
+
Capability.joins(:capability_type).joins(:capability_accessors).
|
145
|
+
where(:capability_accessors => { :capability_accessor_record_type => "SecurityRole" }).
|
146
|
+
where("capability_accessor_record_id IN (#{roles.select('security_roles.id').to_sql})").
|
147
|
+
where(:scope_type_id => scope_type.id)
|
144
148
|
end
|
145
149
|
|
146
150
|
def all_class_capabilities
|
147
|
-
|
151
|
+
scope_type = ScopeType.find_by_internal_identifier('class')
|
152
|
+
Capability.joins(:capability_type).joins(:capability_accessors).
|
153
|
+
where("(capability_accessors.capability_accessor_record_type = 'Group' AND
|
154
|
+
capability_accessor_record_id = (#{self.id})) OR
|
155
|
+
(capability_accessors.capability_accessor_record_type = 'SecurityRole' AND
|
156
|
+
capability_accessor_record_id IN (#{roles.select('security_roles.id').to_sql}))").
|
157
|
+
where(:scope_type_id => scope_type.id)
|
158
|
+
end
|
159
|
+
|
160
|
+
def all_uniq_class_capabilities
|
161
|
+
all_class_capabilities.all.uniq
|
148
162
|
end
|
149
163
|
|
150
164
|
def class_capabilities_to_hash
|
151
|
-
|
165
|
+
all_uniq_class_capabilities.map {|capability|
|
152
166
|
{ :capability_type_iid => capability.capability_type.internal_identifier,
|
153
167
|
:capability_resource_type => capability.capability_resource_type
|
154
168
|
}
|
data/app/models/user.rb
CHANGED
@@ -46,7 +46,7 @@ class User < ActiveRecord::Base
|
|
46
46
|
passed_roles.flatten!
|
47
47
|
passed_roles.each do |role|
|
48
48
|
role_iid = role.is_a?(SecurityRole) ? role.internal_identifier : role.to_s
|
49
|
-
|
49
|
+
all_uniq_roles.each do |this_role|
|
50
50
|
result = true if (this_role.internal_identifier == role_iid)
|
51
51
|
break if result
|
52
52
|
end
|
@@ -103,40 +103,70 @@ class User < ActiveRecord::Base
|
|
103
103
|
|
104
104
|
# roles assigned to the groups this user belongs to
|
105
105
|
def group_roles
|
106
|
-
|
106
|
+
SecurityRole.joins(:parties).
|
107
|
+
where(:parties => {:business_party_type => 'Group'}).
|
108
|
+
where("parties.business_party_id IN (#{groups.select('groups.id').to_sql})")
|
107
109
|
end
|
108
110
|
|
109
111
|
# composite roles for this user
|
110
112
|
def all_roles
|
111
|
-
(
|
113
|
+
SecurityRole.joins(:parties).joins("LEFT JOIN users ON parties.id=users.party_id").
|
114
|
+
where("(parties.business_party_type='Group' AND
|
115
|
+
parties.business_party_id IN (#{groups.select('groups.id').to_sql})) OR
|
116
|
+
(users.id=#{self.id})")
|
117
|
+
end
|
118
|
+
|
119
|
+
def all_uniq_roles
|
120
|
+
all_roles.all.uniq
|
112
121
|
end
|
113
122
|
|
114
123
|
def group_capabilities
|
115
|
-
|
124
|
+
Capability.joins(:capability_type).joins(:capability_accessors).
|
125
|
+
where(:capability_accessors => { :capability_accessor_record_type => "Group" }).
|
126
|
+
where("capability_accessor_record_id IN (#{groups.select('groups.id').to_sql})")
|
116
127
|
end
|
117
128
|
|
118
129
|
def role_capabilities
|
119
|
-
|
130
|
+
Capability.joins(:capability_type).joins(:capability_accessors).
|
131
|
+
where(:capability_accessors => { :capability_accessor_record_type => "SecurityRole" }).
|
132
|
+
where("capability_accessor_record_id IN (#{all_roles.select('security_roles.id').to_sql})")
|
120
133
|
end
|
121
134
|
|
122
135
|
def all_capabilities
|
123
|
-
(
|
136
|
+
Capability.joins(:capability_type).joins(:capability_accessors).
|
137
|
+
where("(capability_accessors.capability_accessor_record_type = 'Group' AND
|
138
|
+
capability_accessor_record_id IN (#{groups.select('groups.id').to_sql})) OR
|
139
|
+
(capability_accessors.capability_accessor_record_type = 'SecurityRole' AND
|
140
|
+
capability_accessor_record_id IN (#{all_roles.select('security_roles.id').to_sql})) OR
|
141
|
+
(capability_accessors.capability_accessor_record_type = 'User' AND
|
142
|
+
capability_accessor_record_id = #{self.id})")
|
143
|
+
end
|
144
|
+
|
145
|
+
def all_uniq_capabilities
|
146
|
+
all_capabilities.all.uniq
|
124
147
|
end
|
125
148
|
|
126
149
|
def group_class_capabilities
|
127
|
-
|
150
|
+
scope_type = ScopeType.find_by_internal_identifier('class')
|
151
|
+
group_capabilities.where(:scope_type_id => scope_type.id)
|
128
152
|
end
|
129
153
|
|
130
154
|
def role_class_capabilities
|
131
|
-
|
155
|
+
scope_type = ScopeType.find_by_internal_identifier('class')
|
156
|
+
role_capabilities.where(:scope_type_id => scope_type.id)
|
132
157
|
end
|
133
158
|
|
134
159
|
def all_class_capabilities
|
135
|
-
|
160
|
+
scope_type = ScopeType.find_by_internal_identifier('class')
|
161
|
+
all_capabilities.where(:scope_type_id => scope_type.id)
|
162
|
+
end
|
163
|
+
|
164
|
+
def all_uniq_class_capabilities
|
165
|
+
all_class_capabilities.all.uniq
|
136
166
|
end
|
137
167
|
|
138
168
|
def class_capabilities_to_hash
|
139
|
-
|
169
|
+
all_uniq_class_capabilities.map {|capability|
|
140
170
|
{ :capability_type_iid => capability.capability_type.internal_identifier,
|
141
171
|
:capability_resource_type => capability.capability_resource_type
|
142
172
|
}
|
@@ -77,7 +77,8 @@ module ErpTechSvcs
|
|
77
77
|
|
78
78
|
# pass in (capability_type_iid, klass) or (capability) object
|
79
79
|
def add_capability(*capability)
|
80
|
-
|
80
|
+
capability_type_iid = capability.first.is_a?(Symbol) ? capability.first.to_s : capability.first
|
81
|
+
capability = capability_type_iid.is_a?(String) ? get_or_create_capability(capability_type_iid, capability.second) : capability.first
|
81
82
|
ca = CapabilityAccessor.find_or_create_by_capability_accessor_record_type_and_capability_accessor_record_id_and_capability_id(get_superclass, self.id, capability.id)
|
82
83
|
self.reload
|
83
84
|
ca
|
@@ -89,8 +90,12 @@ module ErpTechSvcs
|
|
89
90
|
|
90
91
|
def get_or_create_capability(capability_type_iid, klass)
|
91
92
|
capability_type = convert_capability_type(capability_type_iid)
|
92
|
-
|
93
|
-
|
93
|
+
if klass.is_a?(String)
|
94
|
+
scope_type = ScopeType.find_by_internal_identifier('class')
|
95
|
+
Capability.find_or_create_by_capability_resource_type_and_capability_type_id_and_scope_type_id(klass, capability_type.id, scope_type.id)
|
96
|
+
else
|
97
|
+
klass.add_capability(capability_type_iid) # create instance capability
|
98
|
+
end
|
94
99
|
end
|
95
100
|
|
96
101
|
def get_capability(capability_type_iid, klass)
|
@@ -101,7 +106,8 @@ module ErpTechSvcs
|
|
101
106
|
|
102
107
|
# pass in (capability_type_iid, klass) or (capability) object
|
103
108
|
def remove_capability(*capability)
|
104
|
-
|
109
|
+
capability_type_iid = capability.first.is_a?(Symbol) ? capability.first.to_s : capability.first
|
110
|
+
capability = capability_type_iid.is_a?(String) ? get_or_create_capability(capability_type_iid, capability.second) : capability.first
|
105
111
|
ca = capability_accessors.where(:capability_accessor_record_type => get_superclass, :capability_accessor_record_id => self.id, :capability_id => capability.id).first
|
106
112
|
ca.destroy unless ca.nil?
|
107
113
|
self.reload
|
@@ -9,15 +9,24 @@ module ErpTechSvcs
|
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
|
12
|
-
def protected_with_capabilities
|
12
|
+
def protected_with_capabilities(options = {})
|
13
13
|
extend ProtectedByCapabilities::SingletonMethods
|
14
14
|
include ProtectedByCapabilities::InstanceMethods
|
15
|
-
|
16
|
-
has_many :capabilities, :as => :capability_resource
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
#
|
16
|
+
has_many :capabilities, :as => :capability_resource
|
17
|
+
|
18
|
+
# protect all instance of this class by default
|
19
|
+
class_attribute :protect_all_instances
|
20
|
+
self.protect_all_instances = (options[:protect_all_instances].nil? ? false : options[:protect_all_instances])
|
21
|
+
|
22
|
+
# Get records filtered via query scope capabilities
|
23
|
+
# By default Compass AE treats query scopes as restrictions
|
24
|
+
# A user will see all records unless the user has a capability accessor with a query scope
|
25
|
+
# If you set :protect_all_instances => true it is honored via with_user_security & with_instance_security but NOT with_query_security
|
26
|
+
# arguments: user, capability_type_iids
|
27
|
+
# capability_type_iids is optional and can be a single string or an array of strings
|
28
|
+
# Example: which files can this user download? FileAsset.with_query_security(user, 'download').all
|
29
|
+
# Example: which website sections can this user either view or edit? WebsiteSection.with_query_security(user, ['view','edit']).all
|
21
30
|
scope :with_query_security, lambda{|*args|
|
22
31
|
raise ArgumentError if args.empty? || args.size > 2
|
23
32
|
user = args.first
|
@@ -25,11 +34,11 @@ module ErpTechSvcs
|
|
25
34
|
capability_type_iids = [capability_type_iids] if capability_type_iids.is_a?(String)
|
26
35
|
|
27
36
|
scope_type = ScopeType.find_by_internal_identifier('query')
|
28
|
-
granted_capabilities = user.all_capabilities.
|
37
|
+
granted_capabilities = user.all_capabilities.where(:scope_type_id => scope_type.id).where(:capability_resource_type => self.name)
|
29
38
|
|
30
39
|
unless capability_type_iids.empty?
|
31
40
|
capability_type_ids = capability_type_iids.collect{|type| convert_capability_type(type).id }
|
32
|
-
granted_capabilities = granted_capabilities.
|
41
|
+
granted_capabilities = granted_capabilities.where("capability_type_id IN (?)", capability_type_ids.join(','))
|
33
42
|
end
|
34
43
|
|
35
44
|
query = nil
|
@@ -39,34 +48,45 @@ module ErpTechSvcs
|
|
39
48
|
query
|
40
49
|
}
|
41
50
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
group(columns.collect{|c| "#{self.table_name}.#{c.name}" })
|
46
|
-
query = (denied_capabilities.empty? ? query.where("c.id IS NULL OR c.id = c.id") : query.where("c.id IS NULL OR c.id NOT IN (?)", denied_capabilities.collect{|c| c.id }))
|
47
|
-
query
|
48
|
-
}
|
49
|
-
|
50
|
-
# get records for this model that the given user has access to
|
51
|
+
# Get records for this model permitted via instance capabilities
|
52
|
+
# If :protect_all_instances => true return only instances user has explicitly been granted access to
|
53
|
+
# If :protect_all_instances => false return instances without capabilities or that user is granted access to (default)
|
51
54
|
# arguments: user, capability_type_iids
|
52
55
|
# capability_type_iids is optional and can be a single string or an array of strings
|
53
|
-
# Example: which files can this user download? FileAsset.
|
54
|
-
# Example: which website sections can this user either view or edit? WebsiteSection.
|
55
|
-
scope :
|
56
|
+
# Example: which files can this user download? FileAsset.with_instance_security(user, 'download').all
|
57
|
+
# Example: which website sections can this user either view or edit? WebsiteSection.with_instance_security(user, ['view','edit']).all
|
58
|
+
scope :with_instance_security, lambda{|*args|
|
56
59
|
raise ArgumentError if args.empty? || args.size > 2
|
57
60
|
user = args.first
|
58
61
|
capability_type_iids = args.second || []
|
59
62
|
capability_type_iids = [capability_type_iids] if capability_type_iids.is_a?(String)
|
60
63
|
|
61
64
|
scope_type = ScopeType.find_by_internal_identifier('instance')
|
62
|
-
granted_capabilities = user.all_capabilities.
|
65
|
+
granted_capabilities = user.all_capabilities.where(:scope_type_id => scope_type.id).where(:capability_resource_type => self.name)
|
63
66
|
|
64
67
|
unless capability_type_iids.empty?
|
65
68
|
capability_type_ids = capability_type_iids.collect{|type| convert_capability_type(type).id }
|
66
|
-
granted_capabilities = granted_capabilities.
|
69
|
+
granted_capabilities = granted_capabilities.where("capability_type_id IN (#{capability_type_ids.join(',')})")
|
67
70
|
end
|
68
|
-
|
69
|
-
|
71
|
+
|
72
|
+
denied_capabilities = instance_capabilities.select('capabilities.id').where("capabilities.id NOT IN (#{granted_capabilities.select('capabilities.id').to_sql})")
|
73
|
+
deny_count = denied_capabilities.count
|
74
|
+
|
75
|
+
join_type = (self.protect_all_instances ? 'JOIN' : 'LEFT JOIN')
|
76
|
+
query = joins("#{join_type} capabilities AS c ON c.capability_resource_id = #{self.table_name}.id AND c.capability_resource_type = '#{self.name}'").
|
77
|
+
group(columns.collect{|c| "#{self.table_name}.#{c.name}" })
|
78
|
+
query = (deny_count == 0 ? query.where("c.id IS NULL OR c.id = c.id") : query.where("c.id IS NULL OR c.id NOT IN (#{denied_capabilities.to_sql})"))
|
79
|
+
query
|
80
|
+
}
|
81
|
+
|
82
|
+
# Get records for this model that the given user has access to
|
83
|
+
# arguments: user, capability_type_iids
|
84
|
+
# capability_type_iids is optional and can be a single string or an array of strings
|
85
|
+
# Example: which files can this user download? FileAsset.with_user_security(user, 'download').all
|
86
|
+
# Example: which website sections can this user either view or edit? WebsiteSection.with_user_security(user, ['view','edit']).all
|
87
|
+
scope :with_user_security, lambda{|*args|
|
88
|
+
raise ArgumentError if args.empty? || args.size > 2
|
89
|
+
with_instance_security(*args).with_query_security(*args)
|
70
90
|
}
|
71
91
|
end
|
72
92
|
end
|
@@ -102,9 +122,9 @@ module ErpTechSvcs
|
|
102
122
|
capabilities.where(:scope_type_id => scope_type.id)
|
103
123
|
end
|
104
124
|
|
105
|
-
#
|
125
|
+
# return unique roles on capabilities for this model
|
106
126
|
def capability_roles
|
107
|
-
|
127
|
+
SecurityRole.joins(:capability_accessors => :capability).where(:capability_accessors => {:capabilities => {:capability_resource_type => get_superclass(self.name) }}).all.uniq
|
108
128
|
end
|
109
129
|
|
110
130
|
# add a class level capability (capability_resource_id will be NULL)
|
@@ -147,6 +167,11 @@ module ErpTechSvcs
|
|
147
167
|
|
148
168
|
module InstanceMethods
|
149
169
|
|
170
|
+
# convenience method to access class method
|
171
|
+
def protect_all_instances
|
172
|
+
self.class.protect_all_instances
|
173
|
+
end
|
174
|
+
|
150
175
|
def add_capability(capability_type_iid)
|
151
176
|
capability_type = convert_capability_type(capability_type_iid)
|
152
177
|
scope_type = ScopeType.find_by_internal_identifier('instance')
|
@@ -165,11 +190,11 @@ module ErpTechSvcs
|
|
165
190
|
end
|
166
191
|
|
167
192
|
def protected_with_capability?(capability_type_iid)
|
168
|
-
!get_capability(capability_type_iid).nil?
|
193
|
+
!get_capability(capability_type_iid).nil? or protect_all_instances
|
169
194
|
end
|
170
195
|
|
171
196
|
def allow_access?(user, capability_type_iid)
|
172
|
-
if !self.protected_with_capability?(capability_type_iid.to_s) or (user and user.has_capability?(capability_type_iid.to_s, self))
|
197
|
+
if (!self.protect_all_instances and !self.protected_with_capability?(capability_type_iid.to_s)) or (user and user.has_capability?(capability_type_iid.to_s, self))
|
173
198
|
return true
|
174
199
|
else
|
175
200
|
return false
|
@@ -13,15 +13,17 @@ module ErpTechSvcs
|
|
13
13
|
where(:capability_resource_type => klass).
|
14
14
|
where(:scope_type_id => scope_type.id).
|
15
15
|
where(:capability_types => {:internal_identifier => capability_type_iid}).first
|
16
|
+
return nil if capability.nil? # capability not found so return nil
|
16
17
|
else
|
17
18
|
scope_type = ScopeType.find_by_internal_identifier('instance')
|
18
19
|
capability = klass.capabilities.joins(:capability_type).
|
19
20
|
where(:scope_type_id => scope_type.id).
|
20
21
|
where(:capability_types => {:internal_identifier => capability_type_iid}).first
|
21
|
-
|
22
|
+
# if capability not found, we see if all instances are protected
|
23
|
+
# if all instance are protected, return false, otherwise true
|
24
|
+
return !klass.protect_all_instances if capability.nil?
|
22
25
|
end
|
23
|
-
|
24
|
-
result.nil? ? false : true
|
26
|
+
all_capabilities.include?(capability)
|
25
27
|
end
|
26
28
|
|
27
29
|
# pass in (capability_type_iid, class name or any class instance, a block of code)
|
@@ -8,8 +8,8 @@ namespace :erp_tech_svcs do
|
|
8
8
|
|
9
9
|
#sync shared
|
10
10
|
puts "Syncing Shared Assets..."
|
11
|
-
file_support.sync(File.join(file_support.root, '/images'), CompassAeInstance.
|
12
|
-
file_support.sync(File.join(file_support.root, '/files'), CompassAeInstance.
|
11
|
+
file_support.sync(File.join(file_support.root, '/images'), CompassAeInstance.find_by_internal_identifier('base'))
|
12
|
+
file_support.sync(File.join(file_support.root, '/files'), CompassAeInstance.find_by_internal_identifier('base'))
|
13
13
|
puts "Complete"
|
14
14
|
|
15
15
|
#sync websites
|
@@ -4,17 +4,20 @@ describe ErpTechSvcs::Extensions::ActiveRecord::HasSecurityRoles do
|
|
4
4
|
before(:all) do
|
5
5
|
@user = FactoryGirl.create(:user)
|
6
6
|
@user_2 = FactoryGirl.create(:user)
|
7
|
-
|
8
|
-
@
|
9
|
-
@
|
7
|
+
|
8
|
+
@admin_role = SecurityRole.find_or_create_by_description_and_internal_identifier(:description => 'Admin', :internal_identifier => 'admin')
|
9
|
+
@employee_role = SecurityRole.find_or_create_by_description_and_internal_identifier(:description => 'Employee', :internal_identifier => 'employee')
|
10
|
+
@manager_role = SecurityRole.find_or_create_by_description_and_internal_identifier(:description => 'Manager', :internal_identifier => 'manager')
|
10
11
|
end
|
11
12
|
|
12
13
|
it "should allow you to add a role" do
|
13
14
|
@user.add_role(@admin_role)
|
15
|
+
@user.remove_all_roles
|
14
16
|
end
|
15
17
|
|
16
18
|
it "should allow you to add multiple roles by Role instance or iid" do
|
17
19
|
@user.add_roles(@admin_role, 'manager')
|
20
|
+
@user.remove_all_roles
|
18
21
|
end
|
19
22
|
|
20
23
|
it "should allow you to add multiple roles by array or arguments" do
|
@@ -35,11 +38,13 @@ describe ErpTechSvcs::Extensions::ActiveRecord::HasSecurityRoles do
|
|
35
38
|
end
|
36
39
|
|
37
40
|
it "should allow you to remove a role" do
|
41
|
+
@user.add_role(@admin_role)
|
38
42
|
@user.remove_role(@admin_role)
|
39
43
|
@user.has_role?(@admin_role).should eq false
|
40
44
|
end
|
41
45
|
|
42
46
|
it "should allow you to remove multiple roles by Role instance or iid" do
|
47
|
+
@user.add_roles(@admin_role, 'manager')
|
43
48
|
@user.remove_roles(@employee_role, 'manager')
|
44
49
|
@user.has_role?(@employee_role).should eq false
|
45
50
|
@user.has_role?('manager').should eq false
|
data/spec/spec_helper.rb
CHANGED
@@ -20,6 +20,8 @@ Spork.prefork do
|
|
20
20
|
require File.expand_path(DUMMY_APP_ROOT + "/config/environment.rb", __FILE__)
|
21
21
|
|
22
22
|
ActiveRecord::Base.configurations = YAML::load(IO.read(DUMMY_APP_ROOT + "/config/database.yml"))
|
23
|
+
`rake db:drop RAILS_ENV=spec`
|
24
|
+
`rake db:create RAILS_ENV=spec`
|
23
25
|
ActiveRecord::Base.establish_connection(ENV["DB"] || "spec")
|
24
26
|
ActiveRecord::Migration.verbose = false
|
25
27
|
|
@@ -43,12 +45,12 @@ Spork.each_run do
|
|
43
45
|
#We have to execute the migrations from dummy app directory
|
44
46
|
Dir.chdir DUMMY_APP_ROOT
|
45
47
|
`rake db:drop RAILS_ENV=spec`
|
48
|
+
`rake db:create RAILS_ENV=spec`
|
46
49
|
Dir.chdir ENGINE_RAILS_ROOT
|
47
50
|
|
48
51
|
#We have to execute the migratiapp:compass_ae:install:data_migrationsons from dummy app directory
|
49
52
|
Dir.chdir DUMMY_APP_ROOT
|
50
53
|
|
51
|
-
|
52
54
|
`rake compass_ae:install:migrations RAILS_ENV=spec`
|
53
55
|
`rake compass_ae:install:data_migrations RAILS_ENV=spec`
|
54
56
|
`rake db:migrate RAILS_ENV=spec`
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: erp_tech_svcs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: erp_base_erp_svcs
|
@@ -305,18 +305,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
305
305
|
- - ! '>='
|
306
306
|
- !ruby/object:Gem::Version
|
307
307
|
version: '0'
|
308
|
-
segments:
|
309
|
-
- 0
|
310
|
-
hash: 697401427352755655
|
311
308
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
312
309
|
none: false
|
313
310
|
requirements:
|
314
311
|
- - ! '>='
|
315
312
|
- !ruby/object:Gem::Version
|
316
313
|
version: '0'
|
317
|
-
segments:
|
318
|
-
- 0
|
319
|
-
hash: 697401427352755655
|
320
314
|
requirements: []
|
321
315
|
rubyforge_project:
|
322
316
|
rubygems_version: 1.8.24
|