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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -24
  3. data/app/controllers/api/v1/audit_log_items_controller.rb +33 -0
  4. data/app/controllers/api/v1/audit_logs_controller.rb +32 -0
  5. data/app/controllers/api/v1/capabilities_controller.rb +160 -0
  6. data/app/controllers/api/v1/file_assets_controller.rb +40 -0
  7. data/app/controllers/api/v1/groups_controller.rb +236 -0
  8. data/app/controllers/api/v1/security_roles_controller.rb +276 -0
  9. data/app/controllers/api/v1/users_controller.rb +262 -0
  10. data/app/controllers/erp_tech_svcs/session_controller.rb +8 -5
  11. data/app/controllers/erp_tech_svcs/user_controller.rb +14 -15
  12. data/app/mailers/user_mailer.rb +8 -5
  13. data/app/models/audit_log.rb +111 -36
  14. data/app/models/audit_log_item.rb +30 -0
  15. data/app/models/audit_log_item_type.rb +1 -0
  16. data/app/models/audit_log_type.rb +19 -0
  17. data/app/models/capability.rb +22 -6
  18. data/app/models/extensions/tracked_status_type.rb +3 -0
  19. data/app/models/file_asset.rb +245 -20
  20. data/app/models/file_asset_holder.rb +20 -0
  21. data/app/models/group.rb +38 -25
  22. data/app/models/notification.rb +32 -13
  23. data/app/models/notification_type.rb +13 -0
  24. data/app/models/security_role.rb +17 -4
  25. data/app/models/user.rb +116 -29
  26. data/app/validators/password_strength_validator.rb +1 -1
  27. data/app/views/user_mailer/activation_needed_email.html.erb +293 -15
  28. data/app/views/user_mailer/reset_password_email.html.erb +268 -13
  29. data/config/initializers/logger.rb +19 -0
  30. data/config/initializers/sorcery.rb +2 -0
  31. data/config/initializers/wickedpdf.rb +4 -0
  32. data/config/routes.rb +64 -0
  33. data/db/data_migrations/20110802200222_schedule_delete_expired_sessions_job.rb +1 -5
  34. data/db/data_migrations/20150819140550_create_job_tracker_for_notification.rb +14 -0
  35. data/db/migrate/20080805000010_base_tech_services.rb +99 -39
  36. data/db/migrate/20150414151421_add_nested_set_columns_to_security_role.rb +13 -0
  37. data/db/migrate/20150609003216_update_user_for_sorcery.rb +11 -0
  38. data/db/migrate/20150819135108_add_custom_fields_to_notifications.rb +5 -0
  39. data/db/migrate/20160122155402_add_description_to_file_asset.rb +13 -0
  40. data/db/migrate/20160310163060_add_created_by_updated_by_to_erp_tech_svcs.rb +35 -0
  41. data/db/migrate/20160313161611_add_tenant_id_to_audit_log.rb +16 -0
  42. data/lib/erp_tech_svcs.rb +6 -10
  43. data/lib/erp_tech_svcs/config.rb +7 -2
  44. data/lib/erp_tech_svcs/delayed_jobs/delete_expired_sessions_job.rb +49 -0
  45. data/lib/erp_tech_svcs/delayed_jobs/notification_job.rb +50 -0
  46. data/lib/erp_tech_svcs/engine.rb +0 -1
  47. data/lib/erp_tech_svcs/erp_tech_svcs_audit_log.rb +12 -6
  48. data/lib/erp_tech_svcs/extensions.rb +0 -1
  49. data/lib/erp_tech_svcs/extensions/active_record/has_capability_accessors.rb +57 -29
  50. data/lib/erp_tech_svcs/extensions/active_record/has_file_assets.rb +57 -31
  51. data/lib/erp_tech_svcs/extensions/active_record/has_security_roles.rb +12 -4
  52. data/lib/erp_tech_svcs/extensions/active_record/is_json.rb +22 -15
  53. data/lib/erp_tech_svcs/extensions/active_record/scoped_by.rb +16 -13
  54. data/lib/erp_tech_svcs/extensions/compass_ae/erp_base_erp_svcs/controllers/api/parties_controller.rb +15 -0
  55. data/lib/erp_tech_svcs/file_support.rb +1 -0
  56. data/lib/erp_tech_svcs/file_support/file_system_manager.rb +77 -44
  57. data/lib/erp_tech_svcs/file_support/manager.rb +12 -3
  58. data/lib/erp_tech_svcs/file_support/railties/compass_ae_resolver.rb +49 -0
  59. data/lib/erp_tech_svcs/file_support/s3_manager.rb +73 -51
  60. data/lib/erp_tech_svcs/utils/compass_access_negotiator.rb +11 -2
  61. data/lib/erp_tech_svcs/utils/default_nested_set_methods.rb +238 -46
  62. data/lib/erp_tech_svcs/version.rb +1 -1
  63. data/lib/tasks/erp_tech_svcs_tasks.rake +43 -5
  64. metadata +73 -42
  65. data/app/models/user_defined_data.rb +0 -6
  66. data/app/models/user_defined_field.rb +0 -8
  67. data/config/initializers/pdfkit.rb +0 -18
  68. data/db/data_migrations/20121130212146_note_capabilities.rb +0 -23
  69. data/db/migrate/20121116151510_create_groups.rb +0 -18
  70. data/db/migrate/20121126171612_upgrade_security.rb +0 -53
  71. data/db/migrate/20121126173506_upgrade_security2.rb +0 -274
  72. data/db/migrate/20130410135419_add_queue_to_delayed_jobs.rb +0 -13
  73. data/db/migrate/20130610163240_create_notifications.rb +0 -37
  74. data/db/migrate/20130725212647_add_party_id_idx_to_users.rb +0 -9
  75. data/db/migrate/20131113213843_add_audit_log_item_old_value.rb +0 -13
  76. data/db/migrate/20131113213844_add_erp_tech_svcs_missing_indexes.rb +0 -31
  77. data/db/migrate/20131129203603_add_user_defined_fields.rb +0 -43
  78. data/db/migrate/20141013060204_add_custom_fields_to_notifications.rb +0 -12
  79. data/db/migrate/20141108182427_add_scoped_by_to_file_assets.rb +0 -14
  80. data/lib/erp_tech_svcs/extensions/active_record/has_user_defined_data.rb +0 -147
  81. data/lib/erp_tech_svcs/sessions/delete_expired_sessions_job.rb +0 -47
  82. data/lib/erp_tech_svcs/sessions/delete_expired_sessions_service.rb +0 -15
  83. data/lib/erp_tech_svcs/utils/compass_logger.rb +0 -87
@@ -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
- path = unless dir_pieces[1] == 'public'
20
- "/download/#{data.instance.name}?path=#{dir_pieces.delete_if { |name| name == data.instance.name }.join('/')}"
21
- else
22
- dir_pieces.delete_at(1) if dir_pieces[1] == 'public'
23
- dir_pieces.join('/')
24
- end
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, :save_dimensions
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
- belongs_to :file_asset_holder, :polymorphic => true
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 = ?', self.directory, self.name).first.nil?
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
- return file_support.bucket.objects[file_path].url_for(:read, options).to_s
294
+ file_support.bucket.objects[file_path].url_for(:read, options).to_s
184
295
  else
185
- return File.join(Rails.root, self.directory, self.name)
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
- f = Paperclip::Geometry.from_file(self.path)
193
- w = f.width.to_i
194
- h = f.height.to_i
195
- update_attribute(:width, w) if width != w
196
- update_attribute(:height, h) if height != h
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
@@ -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 #{join_party_relationships}")
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 #{join_party_relationships}")
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 #{join_party_relationships}").where("party_relationships.id IS NULL")
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
- 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)
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
- where("(capability_accessors.capability_accessor_record_type = 'Group' AND
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
- where(:scope_type_id => scope_type.id)
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.internal_identifier,
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