erp_tech_svcs 4.0.0 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -24
- data/app/controllers/api/v1/audit_log_items_controller.rb +33 -0
- data/app/controllers/api/v1/audit_logs_controller.rb +32 -0
- data/app/controllers/api/v1/capabilities_controller.rb +160 -0
- data/app/controllers/api/v1/file_assets_controller.rb +40 -0
- data/app/controllers/api/v1/groups_controller.rb +236 -0
- data/app/controllers/api/v1/security_roles_controller.rb +276 -0
- data/app/controllers/api/v1/users_controller.rb +262 -0
- data/app/controllers/erp_tech_svcs/session_controller.rb +8 -5
- data/app/controllers/erp_tech_svcs/user_controller.rb +14 -15
- data/app/mailers/user_mailer.rb +8 -5
- data/app/models/audit_log.rb +111 -36
- data/app/models/audit_log_item.rb +30 -0
- data/app/models/audit_log_item_type.rb +1 -0
- data/app/models/audit_log_type.rb +19 -0
- data/app/models/capability.rb +22 -6
- data/app/models/extensions/tracked_status_type.rb +3 -0
- data/app/models/file_asset.rb +245 -20
- data/app/models/file_asset_holder.rb +20 -0
- data/app/models/group.rb +38 -25
- data/app/models/notification.rb +32 -13
- data/app/models/notification_type.rb +13 -0
- data/app/models/security_role.rb +17 -4
- data/app/models/user.rb +116 -29
- data/app/validators/password_strength_validator.rb +1 -1
- data/app/views/user_mailer/activation_needed_email.html.erb +293 -15
- data/app/views/user_mailer/reset_password_email.html.erb +268 -13
- data/config/initializers/logger.rb +19 -0
- data/config/initializers/sorcery.rb +2 -0
- data/config/initializers/wickedpdf.rb +4 -0
- data/config/routes.rb +64 -0
- data/db/data_migrations/20110802200222_schedule_delete_expired_sessions_job.rb +1 -5
- data/db/data_migrations/20150819140550_create_job_tracker_for_notification.rb +14 -0
- data/db/migrate/20080805000010_base_tech_services.rb +99 -39
- data/db/migrate/20150414151421_add_nested_set_columns_to_security_role.rb +13 -0
- data/db/migrate/20150609003216_update_user_for_sorcery.rb +11 -0
- data/db/migrate/20150819135108_add_custom_fields_to_notifications.rb +5 -0
- data/db/migrate/20160122155402_add_description_to_file_asset.rb +13 -0
- data/db/migrate/20160310163060_add_created_by_updated_by_to_erp_tech_svcs.rb +35 -0
- data/db/migrate/20160313161611_add_tenant_id_to_audit_log.rb +16 -0
- data/lib/erp_tech_svcs.rb +6 -10
- data/lib/erp_tech_svcs/config.rb +7 -2
- data/lib/erp_tech_svcs/delayed_jobs/delete_expired_sessions_job.rb +49 -0
- data/lib/erp_tech_svcs/delayed_jobs/notification_job.rb +50 -0
- data/lib/erp_tech_svcs/engine.rb +0 -1
- data/lib/erp_tech_svcs/erp_tech_svcs_audit_log.rb +12 -6
- data/lib/erp_tech_svcs/extensions.rb +0 -1
- data/lib/erp_tech_svcs/extensions/active_record/has_capability_accessors.rb +57 -29
- data/lib/erp_tech_svcs/extensions/active_record/has_file_assets.rb +57 -31
- data/lib/erp_tech_svcs/extensions/active_record/has_security_roles.rb +12 -4
- data/lib/erp_tech_svcs/extensions/active_record/is_json.rb +22 -15
- data/lib/erp_tech_svcs/extensions/active_record/scoped_by.rb +16 -13
- data/lib/erp_tech_svcs/extensions/compass_ae/erp_base_erp_svcs/controllers/api/parties_controller.rb +15 -0
- data/lib/erp_tech_svcs/file_support.rb +1 -0
- data/lib/erp_tech_svcs/file_support/file_system_manager.rb +77 -44
- data/lib/erp_tech_svcs/file_support/manager.rb +12 -3
- data/lib/erp_tech_svcs/file_support/railties/compass_ae_resolver.rb +49 -0
- data/lib/erp_tech_svcs/file_support/s3_manager.rb +73 -51
- data/lib/erp_tech_svcs/utils/compass_access_negotiator.rb +11 -2
- data/lib/erp_tech_svcs/utils/default_nested_set_methods.rb +238 -46
- data/lib/erp_tech_svcs/version.rb +1 -1
- data/lib/tasks/erp_tech_svcs_tasks.rake +43 -5
- metadata +73 -42
- data/app/models/user_defined_data.rb +0 -6
- data/app/models/user_defined_field.rb +0 -8
- data/config/initializers/pdfkit.rb +0 -18
- data/db/data_migrations/20121130212146_note_capabilities.rb +0 -23
- data/db/migrate/20121116151510_create_groups.rb +0 -18
- data/db/migrate/20121126171612_upgrade_security.rb +0 -53
- data/db/migrate/20121126173506_upgrade_security2.rb +0 -274
- data/db/migrate/20130410135419_add_queue_to_delayed_jobs.rb +0 -13
- data/db/migrate/20130610163240_create_notifications.rb +0 -37
- data/db/migrate/20130725212647_add_party_id_idx_to_users.rb +0 -9
- data/db/migrate/20131113213843_add_audit_log_item_old_value.rb +0 -13
- data/db/migrate/20131113213844_add_erp_tech_svcs_missing_indexes.rb +0 -31
- data/db/migrate/20131129203603_add_user_defined_fields.rb +0 -43
- data/db/migrate/20141013060204_add_custom_fields_to_notifications.rb +0 -12
- data/db/migrate/20141108182427_add_scoped_by_to_file_assets.rb +0 -14
- data/lib/erp_tech_svcs/extensions/active_record/has_user_defined_data.rb +0 -147
- data/lib/erp_tech_svcs/sessions/delete_expired_sessions_job.rb +0 -47
- data/lib/erp_tech_svcs/sessions/delete_expired_sessions_service.rb +0 -15
- data/lib/erp_tech_svcs/utils/compass_logger.rb +0 -87
data/app/models/file_asset.rb
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
# create_table :file_assets do |t|
|
2
|
+
# t.string :type
|
3
|
+
# t.string :name
|
4
|
+
# t.string :directory
|
5
|
+
# t.string :data_file_name
|
6
|
+
# t.string :data_content_type
|
7
|
+
# t.integer :data_file_size
|
8
|
+
# t.datetime :data_updated_at
|
9
|
+
# t.text :scoped_by
|
10
|
+
# t.string :width
|
11
|
+
# t.string :height
|
12
|
+
# t.string :description
|
13
|
+
#
|
14
|
+
# t.timestamps
|
15
|
+
# end
|
16
|
+
# add_index :file_assets, :type
|
17
|
+
# add_index :file_assets, [:file_asset_holder_id, :file_asset_holder_type], :name => 'file_asset_holder_idx'
|
18
|
+
# add_index :file_assets, :name
|
19
|
+
# add_index :file_assets, :directory
|
20
|
+
|
1
21
|
require 'fileutils'
|
2
22
|
|
3
23
|
Paperclip.interpolates(:file_path) { |data, style|
|
@@ -16,14 +36,12 @@ Paperclip.interpolates(:file_url) { |data, style|
|
|
16
36
|
when :filesystem
|
17
37
|
#if public is at the front of this path and we are using file_system remove it
|
18
38
|
dir_pieces = url.split('/')
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, path)}"
|
39
|
+
unless dir_pieces[1] == 'public'
|
40
|
+
"/download/#{data.instance.name}?path=#{dir_pieces.delete_if { |name| name == data.instance.name }.join('/')}"
|
41
|
+
else
|
42
|
+
dir_pieces.delete_at(1) if dir_pieces[1] == 'public'
|
43
|
+
dir_pieces.join('/')
|
44
|
+
end
|
27
45
|
when :s3
|
28
46
|
url
|
29
47
|
end
|
@@ -32,6 +50,8 @@ Paperclip.interpolates(:file_url) { |data, style|
|
|
32
50
|
class FileAsset < ActiveRecord::Base
|
33
51
|
attr_protected :created_at, :updated_at
|
34
52
|
|
53
|
+
tracks_created_by_updated_by
|
54
|
+
|
35
55
|
if respond_to?(:class_attribute)
|
36
56
|
class_attribute :file_type
|
37
57
|
class_attribute :valid_extensions
|
@@ -47,12 +67,16 @@ class FileAsset < ActiveRecord::Base
|
|
47
67
|
|
48
68
|
after_create :set_sti
|
49
69
|
# must fire after paperclip's after_save :save_attached_files
|
50
|
-
after_save :set_data_file_name
|
70
|
+
after_save :set_data_file_name
|
71
|
+
|
51
72
|
before_validation(on: :create) do
|
52
73
|
self.check_name_uniqueness
|
53
74
|
end
|
54
75
|
|
55
|
-
|
76
|
+
has_many :file_asset_holders, :dependent => :destroy
|
77
|
+
|
78
|
+
acts_as_taggable
|
79
|
+
|
56
80
|
instantiates_with_sti
|
57
81
|
|
58
82
|
protected_with_capabilities
|
@@ -68,6 +92,7 @@ class FileAsset < ActiveRecord::Base
|
|
68
92
|
:validations => {:extension => lambda { |data, file| validate_extension(data, file) }}
|
69
93
|
|
70
94
|
before_post_process :set_content_type
|
95
|
+
before_save :save_dimensions
|
71
96
|
|
72
97
|
validates_attachment_presence :data
|
73
98
|
validates_attachment_size :data, :less_than => ErpTechSvcs::Config.max_file_size_in_mb.megabytes
|
@@ -80,6 +105,29 @@ class FileAsset < ActiveRecord::Base
|
|
80
105
|
validates_format_of :name, :with => /^\w/
|
81
106
|
|
82
107
|
class << self
|
108
|
+
def adjust_image(data, size=nil)
|
109
|
+
file_support = ErpTechSvcs::FileSupport::FileSystemManager.new
|
110
|
+
name = "#{SecureRandom.uuid}.jpg"
|
111
|
+
path = File.join(Rails.root, 'tmp', name)
|
112
|
+
|
113
|
+
data = StringIO.new(data) if data.is_a?(String)
|
114
|
+
File.open(path, 'wb+') { |f| f.write(data.read) }
|
115
|
+
|
116
|
+
# resize
|
117
|
+
if size
|
118
|
+
Paperclip.run("convert", "#{path} -resize #{size}^ #{path}", :swallow_stderr => false)
|
119
|
+
end
|
120
|
+
|
121
|
+
# rotate
|
122
|
+
Paperclip.run("convert", "#{path} -auto-orient #{path}", :swallow_stderr => false)
|
123
|
+
|
124
|
+
#remove the file after we get the data
|
125
|
+
data = file_support.get_contents(path)[0]
|
126
|
+
FileUtils.rm(path)
|
127
|
+
|
128
|
+
data
|
129
|
+
end
|
130
|
+
|
83
131
|
def acceptable?(name)
|
84
132
|
valid_extensions.include?(File.extname(name))
|
85
133
|
end
|
@@ -115,6 +163,60 @@ class FileAsset < ActiveRecord::Base
|
|
115
163
|
directory = nil if directory == '.'
|
116
164
|
[directory, name]
|
117
165
|
end
|
166
|
+
|
167
|
+
# Filter records
|
168
|
+
#
|
169
|
+
# @param filters [Hash] a hash of filters to be applied,
|
170
|
+
# @param statement [ActiveRecord::Relation] the query being built
|
171
|
+
# @return [ActiveRecord::Relation] the query being built
|
172
|
+
def apply_filters(filters, statement=nil)
|
173
|
+
statement = FileAsset unless statement
|
174
|
+
|
175
|
+
if filters[:file_asset_holder_type].present? && filters[:file_asset_holder_id].present?
|
176
|
+
statement = statement.joins(:file_asset_holders)
|
177
|
+
.where(file_asset_holders: {
|
178
|
+
file_asset_holder_id: filters[:file_asset_holder_id],
|
179
|
+
file_asset_holder_type: filters[:file_asset_holder_type]
|
180
|
+
})
|
181
|
+
end
|
182
|
+
|
183
|
+
statement
|
184
|
+
end
|
185
|
+
|
186
|
+
# scope by dba organization
|
187
|
+
#
|
188
|
+
# @param dba_organization [Party] dba organization to scope by
|
189
|
+
#
|
190
|
+
# @return [ActiveRecord::Relation]
|
191
|
+
def scope_by_dba_organization(dba_organization)
|
192
|
+
scope_by_party(dba_organization, {role_types: [RoleType.iid('dba_org')]})
|
193
|
+
end
|
194
|
+
|
195
|
+
alias scope_by_dba_org scope_by_dba_organization
|
196
|
+
|
197
|
+
# scope by party
|
198
|
+
#
|
199
|
+
# @param party [Integer | Party | Array] either a id of Party record, a Party record, an array of Party records
|
200
|
+
# or an array of Party ids
|
201
|
+
# @param options [Hash] options to apply to this scope
|
202
|
+
# @option options [Array] :role_types role types to include in the scope
|
203
|
+
#
|
204
|
+
# @return [ActiveRecord::Relation]
|
205
|
+
def scope_by_party(party, options={})
|
206
|
+
table_alias = String.random
|
207
|
+
|
208
|
+
if options[:role_types]
|
209
|
+
joins("inner join entity_party_roles as #{table_alias} on #{table_alias}.entity_record_type = 'FileAsset'
|
210
|
+
and #{table_alias}.entity_record_id = file_assets.id and
|
211
|
+
#{table_alias}.role_type_id in (#{RoleType.find_child_role_types(options[:role_types]).collect(&:id).join(',')})
|
212
|
+
and #{table_alias}.party_id in (#{Party.select('id').where(id: party).to_sql})")
|
213
|
+
|
214
|
+
else
|
215
|
+
joins("inner join entity_party_roles as #{table_alias} on #{table_alias}.entity_record_type = 'FileAsset'
|
216
|
+
and #{table_alias}.entity_record_id = file_assets.id
|
217
|
+
and #{table_alias}.party_id in (#{Party.select('id').where(id: party).to_sql})")
|
218
|
+
end
|
219
|
+
end
|
118
220
|
end
|
119
221
|
|
120
222
|
def initialize(attributes = {}, options={})
|
@@ -125,7 +227,7 @@ class FileAsset < ActiveRecord::Base
|
|
125
227
|
base_path ||= data.original_filename if data.respond_to?(:original_filename)
|
126
228
|
|
127
229
|
directory, name = FileAsset.split_path(base_path) if base_path and name.blank?
|
128
|
-
directory.gsub!(Rails.root.to_s, '')
|
230
|
+
directory.gsub!(Rails.root.to_s, '') if directory
|
129
231
|
|
130
232
|
@type ||= FileAsset.type_for(name) if name
|
131
233
|
@type = "TextFile" if @type.nil?
|
@@ -136,9 +238,18 @@ class FileAsset < ActiveRecord::Base
|
|
136
238
|
super attributes.merge(:directory => directory, :name => name, :data => data)
|
137
239
|
end
|
138
240
|
|
241
|
+
def fully_qualified_url
|
242
|
+
case ErpTechSvcs::Config.file_storage
|
243
|
+
when :filesystem
|
244
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, data.url)}"
|
245
|
+
when :s3
|
246
|
+
data.url
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
139
250
|
def check_name_uniqueness
|
140
251
|
# check if name is already taken
|
141
|
-
unless FileAsset.where('directory = ? and name = ?',
|
252
|
+
unless FileAsset.where('directory = ? and name = ?', self.directory, self.name).first.nil?
|
142
253
|
# if it is keeping add incrementing by 1 until we have a good name
|
143
254
|
counter = 0
|
144
255
|
while true
|
@@ -180,20 +291,23 @@ class FileAsset < ActiveRecord::Base
|
|
180
291
|
file_path = File.join(self.directory, self.name).sub(%r{^/}, '')
|
181
292
|
options = {}
|
182
293
|
options[:expires] = ErpTechSvcs::Config.s3_url_expires_in_seconds if self.is_secured?
|
183
|
-
|
294
|
+
file_support.bucket.objects[file_path].url_for(:read, options).to_s
|
184
295
|
else
|
185
|
-
|
296
|
+
File.join(Rails.root, self.directory, self.name)
|
186
297
|
end
|
187
298
|
end
|
188
299
|
|
189
300
|
def save_dimensions
|
190
|
-
if type == 'Image'
|
301
|
+
if @type == 'Image'
|
191
302
|
begin
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
303
|
+
tempfile = data.queued_for_write[:original]
|
304
|
+
unless tempfile.nil?
|
305
|
+
geometry = Paperclip::Geometry.from_file(tempfile)
|
306
|
+
w = geometry.width.to_i
|
307
|
+
h = geometry.height.to_i
|
308
|
+
update_attribute(:width, w) if width != w
|
309
|
+
update_attribute(:height, h) if height != h
|
310
|
+
end
|
197
311
|
rescue => ex
|
198
312
|
Rails.logger.error('Could not save width and height of image. Make sure Image Magick and the identify command are accessible')
|
199
313
|
end
|
@@ -258,11 +372,40 @@ class FileAsset < ActiveRecord::Base
|
|
258
372
|
return result, message
|
259
373
|
end
|
260
374
|
|
375
|
+
def to_s
|
376
|
+
self.description
|
377
|
+
end
|
378
|
+
|
379
|
+
def to_data_hash
|
380
|
+
data = to_hash(only: [:id, :directory, :width, :height, :name, :description])
|
381
|
+
|
382
|
+
data[:url] = self.data.url
|
383
|
+
data[:fully_qualified_url] = self.fully_qualified_url
|
384
|
+
data[:tags] = self.tag_list.join(',')
|
385
|
+
data[:thumbnail_src] = self.thumbnail_src
|
386
|
+
|
387
|
+
data
|
388
|
+
end
|
389
|
+
|
390
|
+
def thumbnail_src
|
391
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, 'assets/default_file.png')}"
|
392
|
+
end
|
393
|
+
|
261
394
|
end
|
262
395
|
|
263
396
|
class Image < FileAsset
|
264
397
|
self.file_type = :image
|
265
398
|
self.valid_extensions = %w(.jpg .JPG .jpeg .JPEG .gif .GIF .png .PNG .ico .ICO .bmp .BMP .tif .tiff .TIF .TIFF)
|
399
|
+
|
400
|
+
def thumbnail_src
|
401
|
+
thumbnail_image = FileAsset.where("data_file_name = ? and directory like '%thumbnail%' and id = ?", self.name, self.id).first
|
402
|
+
|
403
|
+
if thumbnail_image
|
404
|
+
thumbnail_image.fully_qualified_url
|
405
|
+
else
|
406
|
+
self.fully_qualified_url
|
407
|
+
end
|
408
|
+
end
|
266
409
|
end
|
267
410
|
|
268
411
|
class TextFile < FileAsset
|
@@ -278,46 +421,128 @@ class TextFile < FileAsset
|
|
278
421
|
def text
|
279
422
|
@text ||= ::File.read(path) rescue ''
|
280
423
|
end
|
424
|
+
|
425
|
+
def thumbnail_src
|
426
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, 'assets/default_file.png')}"
|
427
|
+
end
|
281
428
|
end
|
282
429
|
|
283
430
|
class Javascript < TextFile
|
284
431
|
self.file_type = :javascript
|
285
432
|
self.content_type = 'text/javascript'
|
286
433
|
self.valid_extensions = %w(.js .JS)
|
434
|
+
|
435
|
+
def thumbnail_src
|
436
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/javascript_file.png')}"
|
437
|
+
end
|
287
438
|
end
|
288
439
|
|
289
440
|
class Stylesheet < TextFile
|
290
441
|
self.file_type = :stylesheet
|
291
442
|
self.content_type = 'text/css'
|
292
443
|
self.valid_extensions = %w(.css .CSS)
|
444
|
+
|
445
|
+
def thumbnail_src
|
446
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/css_file.png')}"
|
447
|
+
end
|
293
448
|
end
|
294
449
|
|
295
450
|
class Template < TextFile
|
296
451
|
self.file_type = :template
|
297
452
|
self.content_type = 'text/plain'
|
298
453
|
self.valid_extensions = %w(.erb .haml .liquid .builder)
|
454
|
+
|
455
|
+
def thumbnail_src
|
456
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, 'assets/tpl_file.png')}"
|
457
|
+
end
|
299
458
|
end
|
300
459
|
|
301
460
|
class HtmlFile < TextFile
|
302
461
|
self.file_type = :html
|
303
462
|
self.content_type = 'text/html'
|
304
463
|
self.valid_extensions = %w(.html .HTML)
|
464
|
+
|
465
|
+
def thumbnail_src
|
466
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/html_file.png')}"
|
467
|
+
end
|
305
468
|
end
|
306
469
|
|
307
470
|
class XmlFile < TextFile
|
308
471
|
self.file_type = :xml
|
309
472
|
self.content_type = 'text/plain'
|
310
473
|
self.valid_extensions = %w(.xml .XML)
|
474
|
+
|
475
|
+
def thumbnail_src
|
476
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/xml_file.png')}"
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
class DocFile < TextFile
|
481
|
+
self.file_type = :doc
|
482
|
+
self.content_type = 'application/msword'
|
483
|
+
self.valid_extensions = %w(.doc .dot)
|
484
|
+
|
485
|
+
def thumbnail_src
|
486
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/doc_file.png')}"
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
class DocxFile < TextFile
|
491
|
+
self.file_type = :docx
|
492
|
+
self.content_type = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
493
|
+
self.valid_extensions = %w(.docx)
|
494
|
+
|
495
|
+
def thumbnail_src
|
496
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/docx_file.png')}"
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
class Xls < TextFile
|
501
|
+
self.file_type = :xls
|
502
|
+
self.content_type = 'application/vnd.ms-excel'
|
503
|
+
self.valid_extensions = %w(.xls .xlt .xla .xlsx)
|
504
|
+
|
505
|
+
def thumbnail_src
|
506
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/xls_file.png')}"
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
class Ppt < TextFile
|
511
|
+
self.file_type = :ppt
|
512
|
+
self.content_type = 'application/vnd.ms-powerpoint'
|
513
|
+
self.valid_extensions = %w(.ppt .pot .pps .ppa)
|
514
|
+
|
515
|
+
def thumbnail_src
|
516
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, 'assets/ppt_file.png')}"
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
class Pptx < TextFile
|
521
|
+
self.file_type = :pptx
|
522
|
+
self.content_type = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
|
523
|
+
self.valid_extensions = %w(.pptx)
|
524
|
+
|
525
|
+
def thumbnail_src
|
526
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, 'assets/pptx_file.png')}"
|
527
|
+
end
|
311
528
|
end
|
312
529
|
|
313
530
|
class Pdf < TextFile
|
314
531
|
self.file_type = :pdf
|
315
532
|
self.content_type = 'application/pdf'
|
316
533
|
self.valid_extensions = %w(.pdf .PDF)
|
534
|
+
|
535
|
+
def thumbnail_src
|
536
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/pdf_file.png')}"
|
537
|
+
end
|
317
538
|
end
|
318
539
|
|
319
540
|
class Swf < FileAsset
|
320
541
|
self.file_type = :swf
|
321
542
|
self.content_type = 'application/x-shockwave-flash'
|
322
543
|
self.valid_extensions = %w(.swf .SWF)
|
544
|
+
|
545
|
+
def thumbnail_src
|
546
|
+
"#{ErpTechSvcs::Config.file_protocol}://#{File.join(ErpTechSvcs::Config.installation_domain, '/assets/shockwave_file.png')}"
|
547
|
+
end
|
323
548
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# create_table :file_asset_holders do |t|
|
2
|
+
# t.references :file_asset
|
3
|
+
# t.references :file_asset_holder, :polymorphic => true
|
4
|
+
# t.text :scoped_by
|
5
|
+
#
|
6
|
+
# t.timestamps
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# add_index :file_asset_holders, :file_asset_id, :name => 'file_asset_holder_file_id_idx'
|
10
|
+
# add_index :file_asset_holders, [:file_asset_holder_id, :file_asset_holder_type], :name => 'file_asset_holder_idx'
|
11
|
+
|
12
|
+
class FileAssetHolder < ActiveRecord::Base
|
13
|
+
attr_protected :created_at, :updated_at
|
14
|
+
|
15
|
+
belongs_to :file_asset
|
16
|
+
belongs_to :file_asset_holder, :polymorphic => true
|
17
|
+
|
18
|
+
# setup scoping
|
19
|
+
add_scoped_by :scoped_by
|
20
|
+
end
|
data/app/models/group.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# unless table_exists?(:groups)
|
2
|
+
# create_table :groups do |t|
|
3
|
+
# t.column :description, :string
|
4
|
+
# t.timestamps
|
5
|
+
# end
|
6
|
+
# end
|
7
|
+
|
1
8
|
# Security Group
|
2
9
|
class Group < ActiveRecord::Base
|
3
10
|
has_capability_accessors
|
@@ -5,7 +12,7 @@ class Group < ActiveRecord::Base
|
|
5
12
|
after_create :create_party
|
6
13
|
after_save :save_party
|
7
14
|
after_destroy :destroy_party_relationships, :destroy_party
|
8
|
-
|
15
|
+
|
9
16
|
has_one :party, :as => :business_party
|
10
17
|
|
11
18
|
attr_accessible :description
|
@@ -46,11 +53,11 @@ class Group < ActiveRecord::Base
|
|
46
53
|
pty = Party.new
|
47
54
|
pty.description = self.description
|
48
55
|
pty.business_party = self
|
49
|
-
|
56
|
+
|
50
57
|
pty.save
|
51
58
|
self.save
|
52
59
|
end
|
53
|
-
|
60
|
+
|
54
61
|
def save_party
|
55
62
|
self.party.description = self.description
|
56
63
|
self.party.save
|
@@ -61,7 +68,7 @@ class Group < ActiveRecord::Base
|
|
61
68
|
self.party.destroy
|
62
69
|
end
|
63
70
|
end
|
64
|
-
|
71
|
+
|
65
72
|
def destroy_party_relationships
|
66
73
|
party_relationships.destroy_all
|
67
74
|
end
|
@@ -71,23 +78,18 @@ class Group < ActiveRecord::Base
|
|
71
78
|
PartyRelationship.where(:party_id_to => self.party.id)
|
72
79
|
end
|
73
80
|
|
74
|
-
def join_party_relationships
|
75
|
-
role_type = RoleType.find_by_internal_identifier('group')
|
76
|
-
"party_relationships ON party_id_to = #{self.party.id} AND party_id_from = parties.id AND role_type_id_to=#{role_type.id}"
|
77
|
-
end
|
78
|
-
|
79
81
|
def members
|
80
|
-
Party.joins("JOIN #{
|
82
|
+
Party.joins("JOIN #{group_member_join}")
|
81
83
|
end
|
82
|
-
|
84
|
+
|
83
85
|
# get users in this group
|
84
86
|
def users
|
85
|
-
User.joins(:party).joins("JOIN #{
|
87
|
+
User.joins(:party).joins("JOIN #{group_member_join}")
|
86
88
|
end
|
87
89
|
|
88
90
|
# get users not in this group
|
89
91
|
def users_not
|
90
|
-
User.joins(:party).joins("LEFT JOIN #{
|
92
|
+
User.joins(:party).joins("LEFT JOIN #{group_member_join}").where("party_relationships.id IS NULL")
|
91
93
|
end
|
92
94
|
|
93
95
|
# add user to group
|
@@ -112,7 +114,7 @@ class Group < ActiveRecord::Base
|
|
112
114
|
rel = get_relationship(a_party).first
|
113
115
|
unless rel.nil?
|
114
116
|
# if so, return relationship
|
115
|
-
return rel
|
117
|
+
return rel
|
116
118
|
else
|
117
119
|
# if not then build party_relationship
|
118
120
|
rt = RelationshipType.find_by_internal_identifier('group_membership')
|
@@ -141,20 +143,20 @@ class Group < ActiveRecord::Base
|
|
141
143
|
|
142
144
|
def role_class_capabilities
|
143
145
|
scope_type = ScopeType.find_by_internal_identifier('class')
|
144
|
-
Capability.joins(:capability_type).joins(:capability_accessors).
|
145
|
-
|
146
|
-
|
147
|
-
|
146
|
+
Capability.includes(:capability_type).joins(:capability_type).joins(:capability_accessors).
|
147
|
+
where(:capability_accessors => { :capability_accessor_record_type => "SecurityRole" }).
|
148
|
+
where("capability_accessor_record_id IN (#{roles.select('security_roles.id').to_sql})").
|
149
|
+
where(:scope_type_id => scope_type.id)
|
148
150
|
end
|
149
151
|
|
150
152
|
def all_class_capabilities
|
151
153
|
scope_type = ScopeType.find_by_internal_identifier('class')
|
152
|
-
Capability.joins(:capability_type).joins(:capability_accessors).
|
153
|
-
|
154
|
+
Capability.includes(:capability_type).joins(:capability_type).joins(:capability_accessors).
|
155
|
+
where("(capability_accessors.capability_accessor_record_type = 'Group' AND
|
154
156
|
capability_accessor_record_id = (#{self.id})) OR
|
155
157
|
(capability_accessors.capability_accessor_record_type = 'SecurityRole' AND
|
156
158
|
capability_accessor_record_id IN (#{roles.select('security_roles.id').to_sql}))").
|
157
|
-
|
159
|
+
where(:scope_type_id => scope_type.id)
|
158
160
|
end
|
159
161
|
|
160
162
|
def all_uniq_class_capabilities
|
@@ -162,11 +164,22 @@ class Group < ActiveRecord::Base
|
|
162
164
|
end
|
163
165
|
|
164
166
|
def class_capabilities_to_hash
|
165
|
-
all_uniq_class_capabilities.map {|capability|
|
166
|
-
{ :capability_type_iid => capability.capability_type.
|
167
|
-
:capability_resource_type => capability.capability_resource_type
|
168
|
-
|
167
|
+
all_uniq_class_capabilities.map {|capability|
|
168
|
+
{ :capability_type_iid => capability.capability_type.description,
|
169
|
+
:capability_resource_type => capability.capability_resource_type
|
170
|
+
}
|
169
171
|
}.compact
|
170
172
|
end
|
171
173
|
|
174
|
+
def to_data_hash
|
175
|
+
self.to_hash(only: [:id, :description, :created_at, :updated_at])
|
176
|
+
end
|
177
|
+
|
178
|
+
protected
|
179
|
+
|
180
|
+
def group_member_join
|
181
|
+
role_type = RoleType.find_by_internal_identifier('group_member')
|
182
|
+
"party_relationships ON party_id_from = #{self.party.id} AND party_id_to = parties.id AND role_type_id_from=#{role_type.id}"
|
183
|
+
end
|
184
|
+
|
172
185
|
end
|