fat_free_crm 0.15.0.beta.2 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fat_free_crm might be problematic. Click here for more details.

Files changed (225) hide show
  1. checksums.yaml +4 -4
  2. data/.docker/nginx/sites-enabled/ffcrm.conf +8 -0
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +4 -1
  5. data/.rubocop_todo.yml +190 -89
  6. data/.travis.yml +10 -3
  7. data/CHANGELOG.md +27 -0
  8. data/{CONTRIBUTORS → CONTRIBUTORS.md} +2 -1
  9. data/Dockerfile +15 -13
  10. data/Gemfile +7 -4
  11. data/Gemfile.lock +200 -167
  12. data/README.md +4 -2
  13. data/app/assets/javascripts/crm_sortable.js.coffee +5 -0
  14. data/app/assets/javascripts/timeago.js.coffee +5 -0
  15. data/app/assets/stylesheets/about.css.scss +5 -0
  16. data/app/assets/stylesheets/common.scss +2 -1
  17. data/app/controllers/admin/fields_controller.rb +1 -1
  18. data/app/controllers/admin/groups_controller.rb +5 -1
  19. data/app/controllers/admin/tags_controller.rb +1 -1
  20. data/app/controllers/admin/users_controller.rb +10 -6
  21. data/app/controllers/application_controller.rb +13 -13
  22. data/app/controllers/authentications_controller.rb +2 -2
  23. data/app/controllers/comments_controller.rb +3 -2
  24. data/app/controllers/entities/contacts_controller.rb +9 -7
  25. data/app/controllers/entities/opportunities_controller.rb +1 -1
  26. data/app/controllers/entities_controller.rb +4 -4
  27. data/app/controllers/home_controller.rb +9 -9
  28. data/app/controllers/passwords_controller.rb +1 -1
  29. data/app/controllers/tasks_controller.rb +2 -1
  30. data/app/controllers/users_controller.rb +4 -2
  31. data/app/helpers/application_helper.rb +9 -9
  32. data/app/helpers/javascript_helper.rb +5 -0
  33. data/app/helpers/opportunities_helper.rb +1 -1
  34. data/app/helpers/remote_link_pagination_helper.rb +5 -0
  35. data/app/inputs/date_pair_input.rb +1 -1
  36. data/app/models/entities/account.rb +2 -2
  37. data/app/models/entities/account_contact.rb +1 -1
  38. data/app/models/entities/campaign.rb +3 -3
  39. data/app/models/entities/contact.rb +3 -3
  40. data/app/models/entities/lead.rb +2 -2
  41. data/app/models/entities/opportunity.rb +3 -3
  42. data/app/models/fields/custom_field.rb +1 -1
  43. data/app/models/fields/custom_field_pair.rb +2 -2
  44. data/app/models/fields/field.rb +1 -1
  45. data/app/models/polymorphic/address.rb +2 -2
  46. data/app/models/polymorphic/avatar.rb +4 -2
  47. data/app/models/polymorphic/email.rb +8 -6
  48. data/app/models/polymorphic/task.rb +3 -1
  49. data/app/models/polymorphic/version.rb +3 -3
  50. data/app/models/users/ability.rb +1 -1
  51. data/app/models/users/permission.rb +2 -0
  52. data/app/models/users/user.rb +2 -2
  53. data/app/views/accounts/index.js.haml +1 -1
  54. data/app/views/admin/fields/_sort_by.html.haml +1 -1
  55. data/app/views/admin/users/_user.html.haml +1 -1
  56. data/app/views/campaigns/index.js.haml +1 -1
  57. data/app/views/contacts/index.js.haml +1 -1
  58. data/app/views/entities/_basic_search.html.haml +1 -1
  59. data/app/views/home/_duration_menu.html.haml +1 -1
  60. data/app/views/home/_events_menu.html.haml +1 -1
  61. data/app/views/home/_users_menu.html.haml +1 -1
  62. data/app/views/layouts/application.html.haml +1 -1
  63. data/app/views/leads/index.js.haml +1 -1
  64. data/app/views/opportunities/index.js.haml +1 -1
  65. data/app/views/shared/_naming.html.haml +1 -1
  66. data/app/views/users/_languages.html.haml +1 -1
  67. data/config/application.rb +2 -3
  68. data/config/boot.rb +2 -0
  69. data/config/deploy.example.rb +1 -1
  70. data/config/environments/development.rb +2 -0
  71. data/config/environments/production.rb +1 -1
  72. data/config/environments/test.rb +2 -2
  73. data/config/initializers/assets.rb +6 -1
  74. data/config/initializers/backtrace_silencers.rb +5 -0
  75. data/config/initializers/constants.rb +1 -1
  76. data/config/initializers/cookies_serializer.rb +5 -0
  77. data/config/initializers/custom_field_ransack_translations.rb +5 -0
  78. data/config/initializers/filter_parameter_logging.rb +5 -0
  79. data/config/initializers/inflections.rb +5 -0
  80. data/config/initializers/paper_trail.rb +5 -0
  81. data/config/initializers/ransack.rb +3 -3
  82. data/config/initializers/session_store.rb +5 -0
  83. data/config/initializers/wrap_parameters.rb +5 -0
  84. data/config/locales/et.yml +207 -0
  85. data/config/locales/et_fat_free_crm.yml +928 -0
  86. data/config/locales/pt-BR_ransack.yml +81 -0
  87. data/config/locales/th.rb +1 -1
  88. data/config/routes.rb +18 -18
  89. data/db/migrate/20100928030598_create_sessions.rb +1 -1
  90. data/db/migrate/20100928030599_create_users.rb +2 -2
  91. data/db/migrate/20100928030600_create_openid_tables.rb +1 -1
  92. data/db/migrate/20100928030601_create_accounts.rb +2 -2
  93. data/db/migrate/20100928030602_create_permissions.rb +1 -1
  94. data/db/migrate/20100928030603_create_settings.rb +1 -1
  95. data/db/migrate/20100928030604_create_preferences.rb +2 -2
  96. data/db/migrate/20100928030605_create_campaigns.rb +2 -2
  97. data/db/migrate/20100928030606_create_leads.rb +2 -2
  98. data/db/migrate/20100928030607_create_contacts.rb +2 -2
  99. data/db/migrate/20100928030608_create_opportunities.rb +2 -2
  100. data/db/migrate/20100928030609_create_account_contacts.rb +1 -1
  101. data/db/migrate/20100928030610_create_account_opportunities.rb +1 -1
  102. data/db/migrate/20100928030611_create_contact_opportunities.rb +1 -1
  103. data/db/migrate/20100928030612_create_tasks.rb +2 -2
  104. data/db/migrate/20100928030613_create_comments.rb +1 -1
  105. data/db/migrate/20100928030614_create_activities.rb +1 -1
  106. data/db/migrate/20100928030615_create_avatars.rb +1 -1
  107. data/db/migrate/20100928030616_rename_remember_token.rb +1 -1
  108. data/db/migrate/20100928030617_drop_openid_tables.rb +1 -1
  109. data/db/migrate/20100928030618_add_admin_to_users.rb +1 -1
  110. data/db/migrate/20100928030619_add_suspended_to_users.rb +1 -1
  111. data/db/migrate/20100928030620_remove_uuid.rb +2 -2
  112. data/db/migrate/20100928030621_add_email_to_accounts.rb +1 -1
  113. data/db/migrate/20100928030622_add_background_info_to_models.rb +1 -1
  114. data/db/migrate/20100928030623_create_addresses.rb +2 -2
  115. data/db/migrate/20100928030624_add_index_on_permissions.rb +3 -3
  116. data/db/migrate/20100928030625_create_emails.rb +2 -2
  117. data/db/migrate/20100928030626_add_state_to_timeline_objects.rb +1 -1
  118. data/db/migrate/20100928030627_acts_as_taggable_on_migration.rb +2 -2
  119. data/db/migrate/20101221123456_add_single_access_token_to_users.rb +1 -1
  120. data/db/migrate/20101221345678_add_rating_and_category_to_accounts.rb +1 -1
  121. data/db/migrate/20110719082054_add_skype_to_contacts_and_leads.rb +1 -1
  122. data/db/migrate/20111101083437_create_fields.rb +1 -1
  123. data/db/migrate/20111101090312_create_field_groups.rb +1 -1
  124. data/db/migrate/20111116091952_add_field_groups_tag_id.rb +1 -1
  125. data/db/migrate/20111117041311_change_fields_collection_to_text.rb +1 -1
  126. data/db/migrate/20111201030535_add_field_groups_klass_name.rb +2 -2
  127. data/db/migrate/20120121054235_create_lists.rb +1 -1
  128. data/db/migrate/20120216031616_create_versions.rb +3 -3
  129. data/db/migrate/20120216042541_is_paranoid_to_paper_trail.rb +1 -1
  130. data/db/migrate/20120220233724_add_versions_object_changes.rb +1 -1
  131. data/db/migrate/20120224073107_remove_default_value_and_clear_settings.rb +1 -1
  132. data/db/migrate/20120309070209_add_versions_related.rb +1 -1
  133. data/db/migrate/20120314080441_add_subscribed_users_to_entities.rb +2 -2
  134. data/db/migrate/20120316045804_activities_to_versions.rb +1 -1
  135. data/db/migrate/20120405080727_change_subscribed_users_to_set.rb +1 -1
  136. data/db/migrate/20120405080742_change_further_subscribed_users_to_set.rb +2 -2
  137. data/db/migrate/20120406082136_create_groups.rb +2 -2
  138. data/db/migrate/20120413034923_add_index_on_versions_item_type.rb +1 -1
  139. data/db/migrate/20120510025219_add_not_null_constraints_for_timestamp_columns.rb +3 -3
  140. data/db/migrate/20120528102124_increase_length_of_version_events.rb +1 -1
  141. data/db/migrate/20120801032706_add_pair_id_to_fields.rb +1 -1
  142. data/db/migrate/20121003063155_add_settings_to_custom_fields.rb +1 -1
  143. data/db/migrate/20121221033947_fix_country_mapping.rb +1 -1
  144. data/db/migrate/20131207033244_add_user_id_to_lists.rb +1 -1
  145. data/db/migrate/20140916011927_add_created_at_index_on_versions.rb +1 -1
  146. data/db/migrate/20140916012922_add_indexes_to_model_associations.rb +3 -3
  147. data/db/migrate/20141126031837_increase_email_to254_chars.rb +1 -1
  148. data/db/migrate/20141230021159_add_transaction_id_column_to_versions.rb +1 -1
  149. data/db/migrate/20141230205453_add_missing_unique_indices.acts_as_taggable_on_engine.rb +4 -4
  150. data/db/migrate/20141230205454_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +1 -1
  151. data/db/migrate/20141230205455_add_missing_taggable_index.acts_as_taggable_on_engine.rb +3 -3
  152. data/db/migrate/20150123060900_convert_radio_to_radio_buttons.rb +1 -1
  153. data/db/migrate/20150227123054_remove_last_request_at_from_users.rb +1 -1
  154. data/db/migrate/20150427131956_create_index_related_type.rb +3 -3
  155. data/db/migrate/20160511053730_add_account_contacts_index.rb +2 -2
  156. data/docker-compose.yml +17 -13
  157. data/fat_free_crm.gemspec +4 -6
  158. data/lib/development_tasks/license.rake +12 -9
  159. data/lib/fat_free_crm/callback.rb +4 -4
  160. data/lib/fat_free_crm/engine.rb +2 -2
  161. data/lib/fat_free_crm/exportable.rb +2 -2
  162. data/lib/fat_free_crm/fields.rb +2 -4
  163. data/lib/fat_free_crm/gem_ext.rb +0 -1
  164. data/lib/fat_free_crm/gem_ext/rake/task.rb +2 -0
  165. data/lib/fat_free_crm/mail_processor/base.rb +4 -4
  166. data/lib/fat_free_crm/mail_processor/dropbox.rb +1 -1
  167. data/lib/fat_free_crm/permissions.rb +5 -5
  168. data/lib/fat_free_crm/sortable.rb +1 -1
  169. data/lib/fat_free_crm/version.rb +1 -1
  170. data/lib/gravatar_image_tag.rb +1 -0
  171. data/lib/tasks/ffcrm/demo.rake +2 -2
  172. data/spec/controllers/admin/users_controller_spec.rb +25 -25
  173. data/spec/controllers/authentications_controller_spec.rb +9 -9
  174. data/spec/controllers/comments_controller_spec.rb +15 -15
  175. data/spec/controllers/emails_controller_spec.rb +2 -2
  176. data/spec/controllers/entities/accounts_controller_spec.rb +46 -46
  177. data/spec/controllers/entities/campaigns_controller_spec.rb +46 -46
  178. data/spec/controllers/entities/contacts_controller_spec.rb +55 -55
  179. data/spec/controllers/entities/leads_controller_spec.rb +85 -85
  180. data/spec/controllers/entities/opportunities_controller_spec.rb +74 -74
  181. data/spec/controllers/home_controller_spec.rb +11 -11
  182. data/spec/controllers/passwords_controller_spec.rb +2 -2
  183. data/spec/controllers/tasks_controller_spec.rb +37 -37
  184. data/spec/controllers/users_controller_spec.rb +31 -31
  185. data/spec/factories/campaign_factories.rb +1 -1
  186. data/spec/factories/contact_factories.rb +1 -1
  187. data/spec/factories/field_factories.rb +1 -1
  188. data/spec/factories/lead_factories.rb +2 -2
  189. data/spec/factories/opportunity_factories.rb +3 -3
  190. data/spec/factories/shared_factories.rb +1 -1
  191. data/spec/factories/task_factories.rb +1 -1
  192. data/spec/features/support/browser.rb +9 -1
  193. data/spec/lib/fields_spec.rb +2 -2
  194. data/spec/lib/permissions_spec.rb +38 -6
  195. data/spec/lib/view_factory_spec.rb +2 -2
  196. data/spec/models/fields/custom_field_spec.rb +3 -3
  197. data/spec/models/observers/entity_observer_spec.rb +1 -1
  198. data/spec/models/polymorphic/version_spec.rb +11 -11
  199. data/spec/models/users/abilities/user_ability_spec.rb +8 -3
  200. data/spec/models/users/permission_spec.rb +8 -0
  201. data/spec/models/users/user_spec.rb +1 -1
  202. data/spec/shared/controllers.rb +10 -10
  203. data/spec/spec_helper.rb +1 -1
  204. data/spec/views/accounts/index.haml_spec.rb +1 -1
  205. data/spec/views/accounts/update.js.haml_spec.rb +2 -2
  206. data/spec/views/admin/users/update.js.haml_spec.rb +2 -2
  207. data/spec/views/application/auto_complete.haml_spec.rb +1 -1
  208. data/spec/views/campaigns/index.haml_spec.rb +1 -1
  209. data/spec/views/campaigns/update.js.haml_spec.rb +2 -2
  210. data/spec/views/contacts/index.haml_spec.rb +1 -1
  211. data/spec/views/contacts/update.js.haml_spec.rb +2 -2
  212. data/spec/views/home/options.js.haml_spec.rb +1 -1
  213. data/spec/views/leads/index.haml_spec.rb +1 -1
  214. data/spec/views/leads/promote.js.haml_spec.rb +2 -2
  215. data/spec/views/leads/update.js.haml_spec.rb +2 -2
  216. data/spec/views/opportunities/index.haml_spec.rb +1 -1
  217. data/spec/views/opportunities/update.js.haml_spec.rb +1 -1
  218. data/spec/views/tasks/_edit.haml_spec.rb +2 -2
  219. data/spec/views/tasks/create.js.haml_spec.rb +2 -2
  220. data/spec/views/tasks/edit.js.haml_spec.rb +1 -1
  221. data/spec/views/users/change_password.js.haml_spec.rb +2 -2
  222. data/spec/views/users/update.js.haml_spec.rb +2 -2
  223. data/spec/views/users/upload_avatar.js.haml_spec.rb +2 -2
  224. metadata +17 -20
  225. data/lib/fat_free_crm/gem_ext/active_record/schema_dumper.rb +0 -27
@@ -9,7 +9,7 @@ FactoryGirl.define do
9
9
  name { FFaker::Lorem.sentence[0, 64] }
10
10
  assigned_to nil
11
11
  access "Public"
12
- status { %w(planned started completed planned started completed on_hold called_off).sample }
12
+ status { %w[planned started completed planned started completed on_hold called_off].sample }
13
13
  budget { rand(500) }
14
14
  target_leads { rand(200) }
15
15
  target_conversion { rand(20) }
@@ -14,7 +14,7 @@ FactoryGirl.define do
14
14
  access "Public"
15
15
  title { FactoryGirl.generate(:title) }
16
16
  department { FFaker::Name.name + " Dept." }
17
- source { %w(campaign cold_call conference online referral self web word_of_mouth other).sample }
17
+ source { %w[campaign cold_call conference online referral self web word_of_mouth other].sample }
18
18
  email { FFaker::Internet.email }
19
19
  alt_email { FFaker::Internet.email }
20
20
  phone { FFaker::PhoneNumber.phone_number }
@@ -5,7 +5,7 @@
5
5
  #------------------------------------------------------------------------------
6
6
  FactoryGirl.define do
7
7
  sequence :klass_name do |_x|
8
- %w(Contact Account Opportunity Lead Campaign).sample
8
+ %w[Contact Account Opportunity Lead Campaign].sample
9
9
  end
10
10
 
11
11
  sequence(:field_position) { |x| x }
@@ -13,8 +13,8 @@ FactoryGirl.define do
13
13
  access "Public"
14
14
  company { FFaker::Company.name }
15
15
  title { FactoryGirl.generate(:title) }
16
- source { %w(campaign cold_call conference online referral self web word_of_mouth other).sample }
17
- status { %w(new contacted converted rejected).sample }
16
+ source { %w[campaign cold_call conference online referral self web word_of_mouth other].sample }
17
+ status { %w[new contacted converted rejected].sample }
18
18
  rating 1
19
19
  referred_by { FFaker::Name.name }
20
20
  do_not_call false
@@ -5,11 +5,11 @@
5
5
  #------------------------------------------------------------------------------
6
6
  FactoryGirl.define do
7
7
  sequence :opportunity_status do |_s|
8
- %w(prospecting analysis presentation proposal negotiation final_review won lost).sample
8
+ %w[prospecting analysis presentation proposal negotiation final_review won lost].sample
9
9
  end
10
10
 
11
11
  sequence :opportunity_open_status do |_s|
12
- %w(prospecting analysis presentation proposal negotiation final_review).sample
12
+ %w[prospecting analysis presentation proposal negotiation final_review].sample
13
13
  end
14
14
 
15
15
  factory :opportunity do
@@ -19,7 +19,7 @@ FactoryGirl.define do
19
19
  assigned_to nil
20
20
  name { FFaker::Lorem.sentence[0, 64] }
21
21
  access "Public"
22
- source { %w(campaign cold_call conference online referral self web word_of_mouth other).sample }
22
+ source { %w[campaign cold_call conference online referral self web word_of_mouth other].sample }
23
23
  stage { FactoryGirl.generate(:opportunity_status) }
24
24
  probability { rand(50) }
25
25
  amount { rand(1000) }
@@ -50,7 +50,7 @@ FactoryGirl.define do
50
50
  zipcode { FFaker::AddressUS.zip_code }
51
51
  country { FFaker::AddressUK.country }
52
52
  full_address { FactoryGirl.generate(:address) }
53
- address_type { %w(Business Billing Shipping).sample }
53
+ address_type { %w[Business Billing Shipping].sample }
54
54
  updated_at { FactoryGirl.generate(:time) }
55
55
  created_at { FactoryGirl.generate(:time) }
56
56
  deleted_at nil
@@ -11,7 +11,7 @@ FactoryGirl.define do
11
11
  completed_by nil
12
12
  name { FFaker::Lorem.sentence[0, 64] }
13
13
  priority nil
14
- category { %w(call email follow_up lunch meeting money presentation trip).sample }
14
+ category { %w[call email follow_up lunch meeting money presentation trip].sample }
15
15
  bucket "due_asap"
16
16
  due_at { FactoryGirl.generate(:time) }
17
17
  background_info { FFaker::Lorem.paragraph[0, 255] }
@@ -8,7 +8,15 @@
8
8
  #
9
9
  if ENV['BROWSER'] == 'chrome'
10
10
  Capybara.register_driver :selenium do |app|
11
- Capybara::Selenium::Driver.new(app, browser: :chrome)
11
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(chromeOptions: { args: ['no-sandbox', 'headless', 'disable-gpu'] })
12
+ Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
13
+ end
14
+ else
15
+ Capybara.register_driver :selenium do |app|
16
+ options = Selenium::WebDriver::Firefox::Options.new
17
+ options.args << '--headless'
18
+ capabilities = Selenium::WebDriver::Remote::Capabilities.firefox(marionette: false)
19
+ Capybara::Selenium::Driver.new(app, browser: :firefox, options: options, desired_capabilities: capabilities)
12
20
  end
13
21
  end
14
22
 
@@ -36,7 +36,7 @@ describe 'FatFreeCRM::Fields' do
36
36
 
37
37
  describe "field_groups" do
38
38
  it "should call FieldGroup" do
39
- expect(ActiveRecord::Base.connection).to receive(:table_exists?).with('field_groups').and_return(true)
39
+ expect(ActiveRecord::Base.connection).to receive(:data_source_exists?).with('field_groups').and_return(true)
40
40
  dummy_scope = double
41
41
  expect(dummy_scope).to receive(:order).with(:position)
42
42
  expect(FieldGroup).to receive(:where).and_return(dummy_scope)
@@ -44,7 +44,7 @@ describe 'FatFreeCRM::Fields' do
44
44
  end
45
45
 
46
46
  it "should not call FieldGroup if table doesn't exist (migrations not yet run)" do
47
- expect(ActiveRecord::Base.connection).to receive(:table_exists?).with('field_groups').and_return(false)
47
+ expect(ActiveRecord::Base.connection).to receive(:data_source_exists?).with('field_groups').and_return(false)
48
48
  expect(Foo.new.field_groups).to eq([])
49
49
  end
50
50
  end
@@ -30,19 +30,22 @@ describe FatFreeCRM::Permissions do
30
30
 
31
31
  it "should assign permissions to the object" do
32
32
  expect(@entity.permissions.size).to eq(0)
33
- @entity.update_attribute(:user_ids, %w(1 2 3))
33
+ @entity.user_ids = %w[1 2 3]
34
+ @entity.save!
34
35
  expect(@entity.permissions.where(user_id: [1, 2, 3]).size).to eq(3)
35
36
  end
36
37
 
37
38
  it "should handle [] permissions" do
38
- @entity.update_attribute(:user_ids, [])
39
+ @entity.user_ids = []
40
+ @entity.save!
39
41
  expect(@entity.permissions.size).to eq(0)
40
42
  end
41
43
 
42
44
  it "should replace existing permissions" do
43
45
  @entity.permissions << FactoryGirl.create(:permission, user_id: 1, asset: @entity)
44
46
  @entity.permissions << FactoryGirl.create(:permission, user_id: 2, asset: @entity)
45
- @entity.update_attribute(:user_ids, %w(2 3))
47
+ @entity.user_ids = %w[2 3]
48
+ @entity.save!
46
49
  expect(@entity.permissions.size).to eq(2)
47
50
  expect(@entity.permissions.where(user_id: [1]).size).to eq(0)
48
51
  expect(@entity.permissions.where(user_id: [2]).size).to eq(1)
@@ -56,12 +59,14 @@ describe FatFreeCRM::Permissions do
56
59
  end
57
60
  it "should assign permissions to the object" do
58
61
  expect(@entity.permissions.size).to eq(0)
59
- @entity.update_attribute(:group_ids, %w(1 2 3))
62
+ @entity.group_ids = %w[1 2 3]
63
+ @entity.save!
60
64
  expect(@entity.permissions.where(group_id: [1, 2, 3]).size).to eq(3)
61
65
  end
62
66
 
63
67
  it "should handle [] permissions" do
64
- @entity.update_attribute(:group_ids, [])
68
+ @entity.group_ids = []
69
+ @entity.save!
65
70
  expect(@entity.permissions.size).to eq(0)
66
71
  end
67
72
 
@@ -69,7 +74,8 @@ describe FatFreeCRM::Permissions do
69
74
  @entity.permissions << FactoryGirl.build(:permission, group_id: 1, user_id: nil, asset: @entity)
70
75
  @entity.permissions << FactoryGirl.build(:permission, group_id: 2, user_id: nil, asset: @entity)
71
76
  expect(@entity.permissions.size).to eq(2)
72
- @entity.update_attribute(:group_ids, ['3'])
77
+ @entity.group_ids = ['3']
78
+ @entity.save!
73
79
  expect(@entity.permissions.size).to eq(1)
74
80
  expect(@entity.permissions.where(group_id: [1, 2]).size).to eq(0)
75
81
  expect(@entity.permissions.where(group_id: [3]).size).to eq(1)
@@ -131,4 +137,30 @@ describe FatFreeCRM::Permissions do
131
137
  entity.save_with_model_permissions(model)
132
138
  end
133
139
  end
140
+
141
+ describe 'remove_permissions' do
142
+ context 'with a new record' do
143
+ before :each do
144
+ @entity = UserWithPermission.new
145
+ end
146
+ it 'should have no relationships to destroy' do
147
+ expect(@entity.remove_permissions).to eq []
148
+ end
149
+ end
150
+
151
+ context 'with an existing record' do
152
+ before :each do
153
+ @entity = UserWithPermission.create
154
+
155
+ @permission1 = Permission.create(user_id: 1, group_id: 1, asset_id: @entity.id, asset_type: 'UserWithPermission')
156
+ @permission2 = Permission.create(user_id: 1, group_id: 2, asset_id: @entity.id, asset_type: 'UserWithPermission')
157
+ end
158
+ it 'should remove the related permissions' do
159
+ current = Permission.all.count
160
+
161
+ expect(@entity.remove_permissions.length).to eq 2
162
+ expect(Permission.all.count).to eq(current - 2)
163
+ end
164
+ end
165
+ end
134
166
  end
@@ -13,7 +13,7 @@ describe FatFreeCRM::ViewFactory do
13
13
 
14
14
  describe "initialization" do
15
15
  before(:each) do
16
- @view_params = { name: 'brief', title: 'Brief View', icon: 'fa-bars', controllers: ['contacts'], actions: %w(show index) }
16
+ @view_params = { name: 'brief', title: 'Brief View', icon: 'fa-bars', controllers: ['contacts'], actions: %w[show index] }
17
17
  end
18
18
 
19
19
  it "should initialize with required parameters" do
@@ -41,7 +41,7 @@ describe FatFreeCRM::ViewFactory do
41
41
 
42
42
  describe "views_for" do
43
43
  before(:each) do
44
- @v1 = FatFreeCRM::ViewFactory.new name: 'brief', title: 'Brief View', controllers: ['contacts'], actions: %w(show index)
44
+ @v1 = FatFreeCRM::ViewFactory.new name: 'brief', title: 'Brief View', controllers: ['contacts'], actions: %w[show index]
45
45
  @v2 = FatFreeCRM::ViewFactory.new name: 'long', title: 'Long View', controllers: ['contacts'], actions: ['show']
46
46
  @v3 = FatFreeCRM::ViewFactory.new name: 'full', title: 'Full View', controllers: ['accounts'], actions: ['show']
47
47
  end
@@ -45,7 +45,7 @@ describe CustomField do
45
45
  c = FactoryGirl.build(:custom_field, label: "Test Field", field_group: field_group)
46
46
 
47
47
  columns = []
48
- %w(cf_test_field cf_test_field_2 cf_test_field_3 cf_test_field_4).each do |field|
48
+ %w[cf_test_field cf_test_field_2 cf_test_field_3 cf_test_field_4].each do |field|
49
49
  expect(c.send(:generate_column_name)).to eq(field)
50
50
  allow(Contact).to receive(:column_names).and_return(columns << field)
51
51
  end
@@ -63,8 +63,8 @@ describe CustomField do
63
63
  end
64
64
 
65
65
  it "should return a safe list of types for the 'as' select options" do
66
- { "email" => %w(check_boxes text string email url tel select radio_buttons),
67
- "integer" => %w(integer float) }.each do |type, expected_arr|
66
+ { "email" => %w[check_boxes text string email url tel select radio_buttons],
67
+ "integer" => %w[integer float] }.each do |type, expected_arr|
68
68
  c = FactoryGirl.build(:custom_field, as: type)
69
69
  opts = c.available_as
70
70
  expect(opts.map(&:first)).to match_array(expected_arr)
@@ -11,7 +11,7 @@ describe EntityObserver do
11
11
  allow(PaperTrail).to receive(:whodunnit).and_return(assigner)
12
12
  end
13
13
 
14
- [:account, :contact, :lead, :opportunity].each do |entity_type|
14
+ %i[account contact lead opportunity].each do |entity_type|
15
15
  describe "on creation of #{entity_type}" do
16
16
  let(:assignee) { FactoryGirl.create(:user) }
17
17
  let(:assigner) { FactoryGirl.create(:user) }
@@ -34,7 +34,7 @@ describe Version, versioning: true do
34
34
  before do
35
35
  @lead = FactoryGirl.create(:lead)
36
36
 
37
- %w(create destroy update view).each do |event|
37
+ %w[create destroy update view].each do |event|
38
38
  FactoryGirl.create(:version, event: event, item: @lead, whodunnit: PaperTrail.whodunnit)
39
39
  FactoryGirl.create(:version, event: event, item: @lead, whodunnit: "1")
40
40
  end
@@ -54,12 +54,12 @@ describe Version, versioning: true do
54
54
 
55
55
  it "should include only destroy events" do
56
56
  @versions = Version.for(current_user).include_events(:destroy)
57
- expect(@versions.pluck(:event).uniq).to eq(%w(destroy))
57
+ expect(@versions.pluck(:event).uniq).to eq(['destroy'])
58
58
  end
59
59
 
60
60
  it "should include create and update events" do
61
61
  @versions = Version.for(current_user).include_events(:create, :update)
62
- expect(@versions.pluck(:event).uniq.sort).to eq(%w(create update))
62
+ expect(@versions.pluck(:event).uniq.sort).to eq(%w[create update])
63
63
  end
64
64
 
65
65
  it "should select all versions for a given user" do
@@ -68,7 +68,7 @@ describe Version, versioning: true do
68
68
  end
69
69
  end
70
70
 
71
- %w(account campaign contact lead opportunity task).each do |item|
71
+ %w[account campaign contact lead opportunity task].each do |item|
72
72
  describe "Create, update, and delete (#{item})" do
73
73
  before :each do
74
74
  @item = FactoryGirl.create(item.to_sym, user: current_user)
@@ -122,7 +122,7 @@ describe Version, versioning: true do
122
122
  @task.update(name: 'New Name')
123
123
 
124
124
  versions = Version.where(@conditions)
125
- expect(versions.pluck(:event).sort).to eq(%w(create update)) # but not view
125
+ expect(versions.pluck(:event).sort).to eq(%w[create update]) # but not view
126
126
  end
127
127
  end
128
128
 
@@ -179,7 +179,7 @@ describe Version, versioning: true do
179
179
  @item.update(name: 'New Name')
180
180
 
181
181
  versions = Version.where(item_id: @item.id, item_type: @item.class.name)
182
- expect(versions.pluck(:event).sort).to eq(%w(create update))
182
+ expect(versions.pluck(:event).sort).to eq(%w[create update])
183
183
 
184
184
  visible_versions = Version.visible_to(@user)
185
185
  expect(visible_versions).to eq([])
@@ -190,7 +190,7 @@ describe Version, versioning: true do
190
190
  @item.destroy
191
191
 
192
192
  versions = Version.where(item_id: @item.id, item_type: @item.class.name)
193
- expect(versions.pluck(:event).sort).to eq(%w(create destroy))
193
+ expect(versions.pluck(:event).sort).to eq(%w[create destroy])
194
194
 
195
195
  visible_versions = Version.visible_to(@user)
196
196
  expect(visible_versions).to eq([])
@@ -205,7 +205,7 @@ describe Version, versioning: true do
205
205
  @item.update(name: 'New Name')
206
206
 
207
207
  versions = Version.where(item_id: @item.id, item_type: @item.class.name)
208
- expect(versions.pluck(:event).sort).to eq(%w(create update))
208
+ expect(versions.pluck(:event).sort).to eq(%w[create update])
209
209
 
210
210
  visible_versions = Version.visible_to(@user)
211
211
  expect(visible_versions).to eq([])
@@ -220,7 +220,7 @@ describe Version, versioning: true do
220
220
  @item.destroy
221
221
 
222
222
  versions = Version.where(item_id: @item.id, item_type: @item.class.name)
223
- expect(versions.pluck(:event).sort).to eq(%w(create destroy))
223
+ expect(versions.pluck(:event).sort).to eq(%w[create destroy])
224
224
 
225
225
  visible_versions = Version.visible_to(@user)
226
226
  expect(visible_versions).to eq([])
@@ -235,10 +235,10 @@ describe Version, versioning: true do
235
235
  @item.update(name: 'New Name')
236
236
 
237
237
  versions = Version.where(item_id: @item.id, item_type: @item.class.name)
238
- expect(versions.pluck(:event).sort).to eq(%w(create update))
238
+ expect(versions.pluck(:event).sort).to eq(%w[create update])
239
239
 
240
240
  visible_versions = Version.visible_to(@user)
241
- expect(visible_versions.map(&:event).sort).to eq(%w(create update))
241
+ expect(visible_versions.map(&:event).sort).to eq(%w[create update])
242
242
  end
243
243
  end
244
244
  end
@@ -1,8 +1,13 @@
1
+ # Copyright (c) 2008-2013 Michael Dvorkin and contributors.
2
+ #
3
+ # Fat Free CRM is freely distributable under the terms of MIT license.
4
+ # See MIT-LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
+ #------------------------------------------------------------------------------
1
6
  require 'spec_helper'
2
7
  require 'cancan/matchers'
3
8
 
4
9
  def all_actions
5
- [:index, :show, :create, :update, :destroy, :manage]
10
+ %i[index show create update destroy manage]
6
11
  end
7
12
 
8
13
  describe "User abilities" do
@@ -27,7 +32,7 @@ describe "User abilities" do
27
32
  context "when another user, I" do
28
33
  let(:user) { create :user }
29
34
  let(:can) { [] }
30
- let(:cannot) { [:show, :create, :update, :index, :destroy, :manage] }
35
+ let(:cannot) { %i[show create update index destroy manage] }
31
36
  it do
32
37
  can.each do |do_action|
33
38
  is_expected.to be_able_to(do_action, subject_user)
@@ -43,7 +48,7 @@ describe "User abilities" do
43
48
  context "when anonymous user, I" do
44
49
  let(:user) { nil }
45
50
  let(:can) { [] }
46
- let(:cannot) { [:show, :create, :update, :index, :destroy, :manage] }
51
+ let(:cannot) { %i[show create update index destroy manage] }
47
52
  it do
48
53
  can.each do |do_action|
49
54
  is_expected.to be_able_to(do_action, subject_user)
@@ -45,4 +45,12 @@ describe Permission do
45
45
  expect(p.errors['user_id']).to eq(["can't be blank"])
46
46
  expect(p.errors['group_id']).to eq(["can't be blank"])
47
47
  end
48
+
49
+ it 'should not allow duplicate records with (user_id, group_id, asset_type, asset_ids) the same' do
50
+ permission1 = Permission.create(user_id: 1, group_id: 1, asset_id: 1, asset_type: 'UserWithPermission')
51
+ permission2 = Permission.new(user_id: 1, group_id: 1, asset_id: 1, asset_type: 'UserWithPermission')
52
+
53
+ expect(permission1).to be_valid
54
+ expect(permission2).not_to be_valid
55
+ end
48
56
  end
@@ -60,7 +60,7 @@ describe User do
60
60
  @user = FactoryGirl.build(:user)
61
61
  end
62
62
 
63
- %w(account campaign lead contact opportunity).each do |asset|
63
+ %w[account campaign lead contact opportunity].each do |asset|
64
64
  it "should not destroy the user if she owns #{asset}" do
65
65
  FactoryGirl.create(asset, user: @user)
66
66
 
@@ -10,13 +10,13 @@ shared_examples "auto complete" do
10
10
  end
11
11
 
12
12
  it "should do the search and find records that match autocomplete query" do
13
- get :auto_complete, auto_complete_query: @query
13
+ get :auto_complete, params: { auto_complete_query: @query }
14
14
  expect(assigns[:query]).to eq(@query)
15
15
  expect(assigns[:auto_complete]).to eq(@auto_complete_matches) # Each controller must define it.
16
16
  end
17
17
 
18
18
  it "should save current autocomplete controller in a session" do
19
- get :auto_complete, auto_complete_query: @query
19
+ get :auto_complete, params: { auto_complete_query: @query }
20
20
 
21
21
  # We don't save Admin/Users autocomplete controller in a session since Users are not
22
22
  # exposed through the Jumpbox.
@@ -26,14 +26,14 @@ shared_examples "auto complete" do
26
26
  end
27
27
 
28
28
  it "should render application/_auto_complete template" do
29
- post :auto_complete, auto_complete_query: @query
29
+ post :auto_complete, params: { auto_complete_query: @query }
30
30
  expect(response).to render_template("application/_auto_complete")
31
31
  end
32
32
  end
33
33
 
34
34
  shared_examples "attach" do
35
35
  it "should attach existing asset to the parent asset of different type" do
36
- xhr :put, :attach, id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id
36
+ put :attach, params: { id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id }, xhr: true
37
37
  expect(@model.send(@attachment.class.name.tableize)).to include(@attachment)
38
38
  expect(assigns[:attachment]).to eq(@attachment)
39
39
  expect(assigns[:attached]).to eq([@attachment])
@@ -53,7 +53,7 @@ shared_examples "attach" do
53
53
  @model.send(@attachment.class.name.tableize) << @attachment
54
54
  end
55
55
 
56
- xhr :put, :attach, id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id
56
+ put :attach, params: { id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id }, xhr: true
57
57
  expect(assigns[:attached]).to eq(nil)
58
58
  expect(response).to render_template("entities/attach")
59
59
  end
@@ -61,14 +61,14 @@ shared_examples "attach" do
61
61
  it "should display flash warning when the model is no longer available" do
62
62
  @model.destroy
63
63
 
64
- xhr :put, :attach, id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id
64
+ put :attach, params: { id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id }, xhr: true
65
65
  expect(flash[:warning]).not_to eq(nil)
66
66
  expect(response.body).to eq("window.location.reload();")
67
67
  end
68
68
  it "should display flash warning when the attachment is no longer available" do
69
69
  @attachment.destroy
70
70
 
71
- xhr :put, :attach, id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id
71
+ put :attach, params: { id: @model.id, assets: @attachment.class.name.tableize, asset_id: @attachment.id }, xhr: true
72
72
  expect(flash[:warning]).not_to eq(nil)
73
73
  expect(response.body).to eq("window.location.reload();")
74
74
  end
@@ -76,7 +76,7 @@ end
76
76
 
77
77
  shared_examples "discard" do
78
78
  it "should discard the attachment without deleting it" do
79
- xhr :post, :discard, id: @model.id, attachment: @attachment.class.name, attachment_id: @attachment.id
79
+ post :discard, params: { id: @model.id, attachment: @attachment.class.name, attachment_id: @attachment.id }, xhr: true
80
80
  expect(assigns[:attachment]).to eq(@attachment.reload) # The attachment should still exist.
81
81
  expect(@model.reload.send(@attachment.class.name.tableize.to_s)).to eq([]) # But no longer associated with the model.
82
82
  expect(assigns[:account]).to eq(@model) if @model.is_a?(Account)
@@ -88,7 +88,7 @@ shared_examples "discard" do
88
88
  it "should display flash warning when the model is no longer available" do
89
89
  @model.destroy
90
90
 
91
- xhr :post, :discard, id: @model.id, attachment: @attachment.class.name, attachment_id: @attachment.id
91
+ post :discard, params: { id: @model.id, attachment: @attachment.class.name, attachment_id: @attachment.id }, xhr: true
92
92
  expect(flash[:warning]).not_to eq(nil)
93
93
  expect(response.body).to eq("window.location.reload();")
94
94
  end
@@ -96,7 +96,7 @@ shared_examples "discard" do
96
96
  it "should display flash warning when the attachment is no longer available" do
97
97
  @attachment.destroy
98
98
 
99
- xhr :post, :discard, id: @model.id, attachment: @attachment.class.name, attachment_id: @attachment.id
99
+ post :discard, params: { id: @model.id, attachment: @attachment.class.name, attachment_id: @attachment.id }, xhr: true
100
100
  expect(flash[:warning]).not_to eq(nil)
101
101
  expect(response.body).to eq("window.location.reload();")
102
102
  end