erp_tech_svcs 4.0.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -0,0 +1,276 @@
1
+ module Api
2
+ module V1
3
+ class SecurityRolesController < BaseController
4
+
5
+ def index
6
+ query = params[:query]
7
+ parent_iids = params[:parent]
8
+ include_admin = params[:include_admin]
9
+
10
+ security_roles = []
11
+
12
+ if parent_iids
13
+ parent = nil
14
+
15
+ # if the parent param is a comma separated string then
16
+ # there are multiple parents
17
+ parent_iids.split(',').each do |parent_iid|
18
+ parent = nil
19
+
20
+ # if the parent param is a colon separated string then
21
+ # the parent is nested from left to right
22
+ parent_iid.split(':').each do |nested_parent_iid|
23
+ if parent
24
+ parent = parent.children.where('internal_identifier = ?', nested_parent_iid).first
25
+ else
26
+ parent = SecurityRole.where('internal_identifier = ?', nested_parent_iid).first
27
+ end
28
+ end
29
+
30
+ security_roles = security_roles.concat parent.children
31
+ end
32
+
33
+ security_roles = SecurityRole.where(id: security_roles.collect(&:id))
34
+ elsif params[:user_id].present?
35
+ security_roles = User.find(params[:user_id]).party.security_roles
36
+ else
37
+ security_roles = nil
38
+ end
39
+
40
+ respond_to do |format|
41
+ format.tree do
42
+ nodes = [].tap do |nodes|
43
+ unless security_roles
44
+ security_roles = SecurityRole.roots
45
+ end
46
+
47
+ security_roles.all.each do |security_role|
48
+ nodes.push(security_role.to_tree_hash)
49
+ end
50
+ end
51
+
52
+ if include_admin
53
+ nodes.unshift SecurityRole.iid('admin').to_tree_hash
54
+ end
55
+
56
+ render :json => {success: true, security_roles: nodes}
57
+ end
58
+ format.json do
59
+ sort_hash = params[:sort].blank? ? {} : Hash.symbolize_keys(JSON.parse(params[:sort]).first)
60
+ sort = sort_hash[:property] || 'description'
61
+ dir = sort_hash[:direction] || 'ASC'
62
+ limit = params[:limit]
63
+ start = params[:start]
64
+
65
+ unless security_roles
66
+ security_roles = SecurityRole
67
+ end
68
+
69
+ if query
70
+ security_role_tbl = SecurityRole.arel_table
71
+ statement = security_roles.where(security_role_tbl[:description].matches("%#{query}%")
72
+ .or(security_role_tbl[:internal_identifier].matches("%#{query}%")))
73
+
74
+ total_count = statement.count
75
+ security_roles = statement.order("#{sort} #{dir}")
76
+ else
77
+ total_count = security_roles.count
78
+ security_roles = security_roles.order("#{sort} #{dir}")
79
+ end
80
+
81
+ if limit and start
82
+ security_roles = security_roles.limit(limit).offset(start)
83
+ end
84
+
85
+ if include_admin
86
+ security_roles = security_roles.all
87
+ security_roles.unshift SecurityRole.iid('admin')
88
+ end
89
+
90
+ render :json => {
91
+ success: true, total_count: total_count,
92
+ security_roles: security_roles.collect do |security_role|
93
+ security_role.to_data_hash
94
+ end
95
+ }
96
+ end
97
+ end
98
+ end
99
+
100
+ def available
101
+ type = params[:type]
102
+ id = params[:id]
103
+
104
+ sort = (params[:sort] || 'description').downcase
105
+ dir = (params[:dir] || 'asc').downcase
106
+ query_filter = params[:query_filter].strip rescue nil
107
+
108
+ statement = id.blank? ? SecurityRole : type.constantize.find(id).roles_not
109
+ statement = (params[:query_filter].blank? ? statement : statement.where("UPPER(security_roles.description) LIKE UPPER('%#{query_filter}%')"))
110
+ available = statement.paginate(:page => page, :per_page => per_page, :order => "#{sort} #{dir}")
111
+
112
+ render :json => {:total_count => statement.count, :security_roles => available.map { |security_role| security_role.to_data_hash }}
113
+ end
114
+
115
+ def selected
116
+ type = params[:type]
117
+ id = params[:id]
118
+
119
+ sort = (params[:sort] || 'description').downcase
120
+ dir = (params[:dir] || 'asc').downcase
121
+ query_filter = params[:query_filter].strip rescue nil
122
+
123
+ statement = id.blank? ? SecurityRole : type.constantize.find(id).roles
124
+ statement = (params[:query_filter].blank? ? statement : statement.where("UPPER(security_roles.description) LIKE UPPER('%#{query_filter}%')"))
125
+ selected = statement.paginate(:page => page, :per_page => per_page, :order => "#{sort} #{dir}")
126
+
127
+ render :json => {:total_count => statement.count, :security_roles => selected.map { |security_role| security_role.to_data_hash }}
128
+ end
129
+
130
+ def add
131
+ begin
132
+ type = params[:type]
133
+ id = params[:id]
134
+ security_role_ids = JSON.parse(params[:security_role_ids])
135
+
136
+ assign_to = type.constantize.find(id)
137
+ security_role_ids.each do |role_id|
138
+ role = SecurityRole.find(role_id)
139
+ case type
140
+ when 'User'
141
+ assign_to.add_role(role)
142
+ when 'Group'
143
+ assign_to.add_role(role)
144
+ when 'Capability'
145
+ role.add_capability(assign_to)
146
+ end
147
+ end
148
+
149
+ render :json => {:success => true, :message => 'Security Roles(s) Added'}
150
+ rescue => ex
151
+ Rails.logger.error ex.message
152
+ Rails.logger.error ex.backtrace.join("\n")
153
+
154
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
155
+
156
+ render :json => {:success => false, :message => ex.message}
157
+ end
158
+ end
159
+
160
+ def remove
161
+ begin
162
+ type = params[:type]
163
+ id = params[:id]
164
+ security_role_ids = JSON.parse(params[:security_role_ids])
165
+
166
+ assign_to = type.constantize.find(id)
167
+ security_role_ids.each do |role_id|
168
+ role = SecurityRole.find(role_id)
169
+ case type
170
+ when 'User'
171
+ assign_to.remove_role(role)
172
+ when 'Group'
173
+ assign_to.remove_role(role)
174
+ when 'Capability'
175
+ role.remove_capability(assign_to)
176
+ end
177
+ end
178
+
179
+ render :json => {:success => true, :message => 'Security Roles(s) Removed'}
180
+ rescue => ex
181
+ Rails.logger.error ex.message
182
+ Rails.logger.error ex.backtrace.join("\n")
183
+
184
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
185
+
186
+ render :json => {:success => false, :message => ex.message}
187
+ end
188
+ end
189
+
190
+ def create
191
+ begin
192
+ ActiveRecord::Base.connection.transaction do
193
+ security_role = SecurityRole.create!(description: params[:description].strip,
194
+ internal_identifier: params[:internal_identifier].strip)
195
+
196
+
197
+ if params[:parent]
198
+ security_role.move_to_child_of(SecurityRole.iid(params[:parent]))
199
+ end
200
+
201
+ render :json => {
202
+ success: true,
203
+ security_role: security_role.to_data_hash,
204
+ message: 'Role created successfully'
205
+ }
206
+ end
207
+ rescue ActiveRecord::RecordInvalid => invalid
208
+ Rails.logger.error invalid.record.errors
209
+
210
+ message = "<ul>"
211
+ invalid.record.errors.collect do |e, m|
212
+ message << "<li>#{e} #{m}</li>"
213
+ end
214
+ message << "</ul>"
215
+
216
+ render :json => {:success => false, :message => message}
217
+ rescue StandardError => ex
218
+ Rails.logger.error ex.message
219
+ Rails.logger.error ex.backtrace.join("\n")
220
+
221
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
222
+
223
+ render :json => {:success => false, :message => 'Error creating Security Role'}
224
+ end
225
+ end
226
+
227
+ def update
228
+ begin
229
+ ActiveRecord::Base.connection.transaction do
230
+ security_role = SecurityRole.find(params[:id])
231
+ security_role.description = params[:description].strip
232
+ security_role.internal_identifier = params[:internal_identifier].strip
233
+
234
+ security_role.save!
235
+
236
+ render json: {success: true, security_role: security_role.to_data_hash}
237
+ end
238
+ rescue ActiveRecord::RecordInvalid => invalid
239
+ Rails.logger.error invalid.record.errors
240
+
241
+ message = "<ul>"
242
+ invalid.record.errors.collect do |e, m|
243
+ message << "<li>#{e} #{m}</li>"
244
+ end
245
+ message << "</ul>"
246
+
247
+ render :json => {:success => false, :message => message}
248
+ rescue StandardError => ex
249
+ Rails.logger.error ex.message
250
+ Rails.logger.error ex.backtrace.join("\n")
251
+
252
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
253
+
254
+ render :json => {:success => false, :message => 'Error updating Security Role'}
255
+ end
256
+ end
257
+
258
+ def destroy
259
+ security_role = SecurityRole.find(params[:id])
260
+
261
+ render json: {success: security_role.destroy}
262
+ end
263
+
264
+
265
+ def page
266
+ offset = params[:start].to_f
267
+ offset > 0 ? (offset / params[:limit].to_f).to_i + 1 : 1
268
+ end
269
+
270
+ def per_page
271
+ params[:limit].nil? ? 10 : params[:limit].to_i
272
+ end
273
+
274
+ end # SecurityRolesController
275
+ end # V1
276
+ end # Api
@@ -0,0 +1,262 @@
1
+ module Api
2
+ module V1
3
+ class UsersController < BaseController
4
+
5
+ def index
6
+ username = params[:username]
7
+ sort_hash = params[:sort].blank? ? {} : Hash.symbolize_keys(JSON.parse(params[:sort]).first)
8
+ sort = sort_hash[:property] || 'username'
9
+ dir = sort_hash[:direction] || 'ASC'
10
+ limit = params[:limit] || 25
11
+ start = params[:start] || 0
12
+
13
+ # scope users by dba_organization and any of its children dba_orgs
14
+ dba_organization = current_user.party.dba_organization
15
+ dba_org_ids = dba_organization.child_dba_organizations.collect(&:id)
16
+ dba_org_ids.push(dba_organization.id)
17
+ dba_org_ids.uniq!
18
+
19
+ users = User.joins(:party).joins("inner join party_relationships as dba_reln on
20
+ (dba_reln.party_id_from = parties.id
21
+ and
22
+ dba_reln.party_id_to in (#{dba_org_ids.join(',')})
23
+ and
24
+ dba_reln.role_type_id_to = #{RoleType.iid('dba_org').id}
25
+ )")
26
+
27
+ # TODO update for more advance searching
28
+ if params[:query_filter].present?
29
+ username = params[:query_filter].strip
30
+ end
31
+
32
+ if username.blank?
33
+ total_count = users.uniq.count
34
+ users = users.order("#{sort} #{dir}").offset(start).limit(limit)
35
+ else
36
+ users = users.where('username like ? or email like ?', "%#{username}%", "%#{username}%")
37
+ total_count = users.uniq.count
38
+ users = users.order("#{sort} #{dir}").offset(start).limit(limit)
39
+ end
40
+
41
+ render :json => {total_count: total_count, users: users.uniq.collect(&:to_data_hash)}
42
+ end
43
+
44
+ def create
45
+ begin
46
+ ActiveRecord::Base.connection.transaction do
47
+ current_user.with_capability(:create, 'User') do
48
+
49
+ user = User.new(
50
+ :email => params[:email],
51
+ :username => params[:username],
52
+ :password => params[:password],
53
+ :password_confirmation => params[:password_confirmation]
54
+ )
55
+
56
+ # set this to tell activation where to redirect_to for login and temp password
57
+ login_url = params[:login_url] || '/erp_app/login'
58
+
59
+ # if a website was selected then set it so we can use the any templates in that website
60
+ unless params['website_id'].blank?
61
+ user.add_instance_attribute(:website_id, params['website_id'])
62
+ end
63
+
64
+ #set this to tell activation where to redirect_to for login and temp password
65
+ user.add_instance_attribute(:login_url, login_url)
66
+ user.add_instance_attribute(:temp_password, params[:password])
67
+
68
+ if params[:auto_activate] == 'yes'
69
+ user.skip_activation_email = true
70
+ end
71
+
72
+ user.save!
73
+ if params[:auto_activate] == 'yes'
74
+ user.activate!
75
+ end
76
+
77
+ if params[:party_id]
78
+ user.party = Party.find(params[:party_id])
79
+ user.save!
80
+ else
81
+ individual = Individual.create(:gender => params[:gender],
82
+ :current_first_name => params[:first_name],
83
+ :current_last_name => params[:last_name])
84
+ user.party = individual.party
85
+ user.save
86
+
87
+ user.party.created_by_party = current_user.party
88
+ user.party.save!
89
+
90
+ # add employee role to party
91
+ party = individual.party
92
+ party.add_role_type(RoleType.find_or_create('employee', 'Employee'))
93
+
94
+ # associate the new party to the dba_organization of the user creating this user
95
+ relationship_type = RelationshipType.find_or_create(RoleType.find_or_create('dba_org', 'Doing Business As Organization'),
96
+ RoleType.find_or_create('employee', 'Employee'))
97
+ party.create_relationship(relationship_type.description,
98
+ current_user.party.dba_organization.id,
99
+ relationship_type)
100
+ end
101
+
102
+ render :json => {:success => true, user: user.to_data_hash}
103
+ end
104
+ end
105
+ rescue ErpTechSvcs::Utils::CompassAccessNegotiator::Errors::UserDoesNotHaveCapability => ex
106
+ render :json => {:success => false, :message => ex.message, :user => nil}
107
+ rescue ActiveRecord::RecordInvalid => invalid
108
+ Rails.logger.error invalid.record.errors
109
+
110
+ message = "<ul>"
111
+ invalid.record.errors.collect do |e, m|
112
+ message << "<li>#{e} #{m}</li>"
113
+ end
114
+ message << "</ul>"
115
+
116
+ render :json => {:success => false, :message => message, :user => nil}
117
+ rescue StandardError => ex
118
+ Rails.logger.error ex.message
119
+ Rails.logger.error ex.backtrace.join("\n")
120
+
121
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
122
+
123
+ render :json => {:success => false, :message => 'Error creating user', :user => nil}
124
+ end
125
+ end
126
+
127
+ def update
128
+ begin
129
+ ActiveRecord::Base.transaction do
130
+
131
+ if params[:id]
132
+ user = User.find(params[:id])
133
+ party = user.party
134
+ else
135
+ user = current_user
136
+ party = user.party
137
+ end
138
+
139
+ if params[:password].present?
140
+ user.password = params[:password].strip
141
+ if params[:password_confirmation].present?
142
+ user.password_confirmation = params[:password_confirmation].strip
143
+ else
144
+ user.password_confirmation = params[:password].strip
145
+ end
146
+ end
147
+
148
+ if params[:username].present?
149
+ user.username = params[:username].strip
150
+ end
151
+
152
+ if params[:status]
153
+ user.activation_state = params[:status]
154
+ end
155
+
156
+ if params[:email].present?
157
+ user.email = params[:email].strip
158
+ end
159
+
160
+ user.save!
161
+
162
+ business_party = party.business_party
163
+
164
+ # update business party information
165
+ if params[:first_name].present?
166
+ business_party.current_first_name = params[:first_name].strip
167
+ end
168
+
169
+ if params[:last_name].present?
170
+ business_party.current_last_name = params[:last_name].strip
171
+ end
172
+
173
+ user.party.updated_by_party = current_user.party
174
+ user.party.save!
175
+
176
+ render :json => {:success => true, :message => 'User updated', :user => user.to_data_hash}
177
+
178
+ end
179
+ rescue ActiveRecord::RecordInvalid => invalid
180
+ Rails.logger.error invalid.record.errors
181
+
182
+ render :json => {:success => false, :message => invalid.record.errors.full_messages, :user => nil}
183
+ rescue StandardError => ex
184
+ Rails.logger.error ex.message
185
+ Rails.logger.error ex.backtrace.join("\n")
186
+
187
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
188
+
189
+ render :json => {:success => false, :message => 'Error updating user', :user => nil}
190
+ end
191
+
192
+ end
193
+
194
+ def reset_password
195
+ begin
196
+ user = User.find(params[:id])
197
+
198
+ user.add_instance_attribute(:reset_password_url, (params[:reset_password_url] || '/erp_app/reset_password'))
199
+ user.add_instance_attribute(:domain, params[:domain])
200
+ user.deliver_reset_password_instructions!
201
+ message = "Password has been reset. An email has been sent with further instructions to #{user.email}."
202
+ success = true
203
+ render :json => {:success => success, :message => message}
204
+ rescue => ex
205
+ Rails.logger.error ex.message
206
+ Rails.logger.error ex.backtrace.join("\n")
207
+
208
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
209
+
210
+ render :json => {:success => false, :message => 'Could not reset password'}
211
+ end
212
+ end
213
+
214
+ def destroy
215
+ user = User.find(params[:id])
216
+
217
+ # get the party as it will also destroy the user
218
+ party = user.party
219
+ party.destroy
220
+
221
+ render :json => {:success => true}
222
+ end
223
+
224
+ def effective_security
225
+ user = User.find(params[:id])
226
+
227
+ render :json => {:success => true, :capabilities => user.class_capabilities_to_hash}
228
+ end
229
+
230
+ def update_security
231
+ begin
232
+ ActiveRecord::Base.transaction do
233
+ user = User.find(params[:id])
234
+
235
+ user.remove_all_security_roles
236
+ user.add_security_roles(params[:security_role_iids].split(','))
237
+
238
+ user.remove_all_groups
239
+ user.add_groups(params[:group_ids].split(',').map{|group_id| Group.find(group_id)})
240
+
241
+ user.remove_all_capabilities
242
+ user.add_capabilities(params[:capability_ids].split(',').map{|capability_id| Capability.find(capability_id)})
243
+
244
+ render json: {success: true}
245
+ end
246
+ rescue ActiveRecord::RecordInvalid => invalid
247
+ Rails.logger.error invalid.record.errors
248
+
249
+ render :json => {:success => false, :message => invalid.record.errors.full_messages, :user => nil}
250
+ rescue StandardError => ex
251
+ Rails.logger.error ex.message
252
+ Rails.logger.error ex.backtrace.join("\n")
253
+
254
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
255
+
256
+ render :json => {:success => false, :message => 'Error updating security', :user => nil}
257
+ end
258
+ end
259
+
260
+ end # UsersController
261
+ end # V1
262
+ end # Api