fat_free_crm 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Capfile +1 -4
  3. data/Gemfile.lock +0 -1
  4. data/README.md +1 -0
  5. data/app/assets/javascripts/lists.js.coffee +1 -2
  6. data/app/controllers/application_controller.rb +27 -25
  7. data/app/controllers/emails_controller.rb +1 -30
  8. data/app/controllers/entities/contacts_controller.rb +1 -1
  9. data/app/controllers/entities/opportunities_controller.rb +1 -1
  10. data/app/controllers/entities_controller.rb +0 -1
  11. data/app/controllers/home_controller.rb +0 -4
  12. data/app/controllers/passwords_controller.rb +3 -3
  13. data/app/controllers/tasks_controller.rb +17 -10
  14. data/app/controllers/users_controller.rb +23 -46
  15. data/app/helpers/application_helper.rb +0 -3
  16. data/app/helpers/campaigns_helper.rb +0 -1
  17. data/app/helpers/leads_helper.rb +0 -11
  18. data/app/helpers/opportunities_helper.rb +0 -1
  19. data/app/helpers/tags_helper.rb +0 -8
  20. data/app/helpers/versions_helper.rb +1 -1
  21. data/app/models/entities/account_contact.rb +1 -1
  22. data/app/models/entities/campaign.rb +3 -3
  23. data/app/models/entities/contact.rb +3 -3
  24. data/app/models/entities/lead.rb +5 -5
  25. data/app/models/entities/opportunity.rb +1 -3
  26. data/app/models/fields/field_group.rb +1 -0
  27. data/app/models/list.rb +2 -1
  28. data/app/models/polymorphic/avatar.rb +1 -1
  29. data/app/models/polymorphic/task.rb +7 -4
  30. data/app/models/setting.rb +0 -3
  31. data/app/models/users/ability.rb +13 -2
  32. data/app/models/users/user.rb +4 -1
  33. data/app/views/home/index.html.haml +0 -4
  34. data/app/views/layouts/application.html.haml +7 -5
  35. data/app/views/leads/_contact.html.haml +0 -3
  36. data/app/views/lists/_personal_sidebar.html.haml +2 -2
  37. data/app/views/lists/_sidebar.html.haml +2 -2
  38. data/config/application.rb +2 -2
  39. data/config/environments/development.rb +2 -0
  40. data/config/environments/production.rb +2 -3
  41. data/config/initializers/secret_token.rb +25 -1
  42. data/config/locales/en-US_fat_free_crm.yml +1 -1
  43. data/config/routes.rb +27 -32
  44. data/config/settings.default.yml +3 -4
  45. data/lib/development_tasks/rspec.rake +1 -5
  46. data/lib/fat_free_crm.rb +11 -1
  47. data/lib/fat_free_crm/fields.rb +1 -1
  48. data/lib/fat_free_crm/gem_ext/rails/text_helper.rb +1 -2
  49. data/lib/fat_free_crm/secret_token_generator.rb +59 -0
  50. data/lib/fat_free_crm/version.rb +1 -1
  51. data/spec/controllers/admin/users_controller_spec.rb +1 -3
  52. data/spec/controllers/home_controller_spec.rb +0 -7
  53. data/spec/controllers/passwords_controller_spec.rb +23 -5
  54. data/spec/controllers/users_controller_spec.rb +45 -17
  55. data/spec/lib/secret_token_generator_spec.rb +55 -0
  56. data/spec/models/users/abilities/user_ability_spec.rb +58 -0
  57. data/spec/routing/emails_routing_spec.rb +13 -14
  58. data/spec/spec_helper.rb +2 -1
  59. metadata +5 -2
@@ -189,7 +189,7 @@ en-US:
189
189
  msg_account_not_approved: Your account has not been approved yet.
190
190
  msg_asset_deleted: ! '%{value} has been deleted.'
191
191
  msg_asset_not_available: This %{value} is no longer available.
192
- msg_asset_not_authorized: You are not authorized to view this %{value}.
192
+ msg_not_authorized: You are not authorized to take this action.
193
193
  msg_assets_not_available: The %{value} are not available.
194
194
  msg_asset_rejected: ! '%{value} has been rejected.'
195
195
  msg_bad_image_file: ^Could't upload or resize the image file you specified.
data/config/routes.rb CHANGED
@@ -21,10 +21,10 @@ Rails.application.routes.draw do
21
21
  match '/home/timezone', :as => :timezone
22
22
  match '/home/redraw', :as => :redraw
23
23
 
24
- resource :authentication
25
- resources :comments, :except => [:new, :show]
26
- resources :emails
27
- resources :passwords
24
+ resource :authentication, :except => [:index, :edit]
25
+ resources :comments, :except => [:new, :show]
26
+ resources :emails, :only => [:destroy]
27
+ resources :passwords, :only => [:new, :create, :edit, :update]
28
28
 
29
29
  resources :accounts, :id => /\d+/ do
30
30
  collection do
@@ -32,17 +32,17 @@ Rails.application.routes.draw do
32
32
  post :filter
33
33
  get :options
34
34
  get :field_group
35
- match :auto_complete
35
+ post :auto_complete
36
36
  post :redraw
37
- get :versions
37
+ get :versions
38
38
  end
39
39
  member do
40
40
  put :attach
41
41
  post :discard
42
42
  post :subscribe
43
43
  post :unsubscribe
44
- get :contacts
45
- get :opportunities
44
+ get :contacts
45
+ get :opportunities
46
46
  end
47
47
  end
48
48
 
@@ -54,15 +54,15 @@ Rails.application.routes.draw do
54
54
  get :field_group
55
55
  post :auto_complete
56
56
  post :redraw
57
- get :versions
57
+ get :versions
58
58
  end
59
59
  member do
60
60
  put :attach
61
61
  post :discard
62
62
  post :subscribe
63
63
  post :unsubscribe
64
- get :leads
65
- get :opportunities
64
+ get :leads
65
+ get :opportunities
66
66
  end
67
67
  end
68
68
 
@@ -74,14 +74,14 @@ Rails.application.routes.draw do
74
74
  get :field_group
75
75
  post :auto_complete
76
76
  post :redraw
77
- get :versions
77
+ get :versions
78
78
  end
79
79
  member do
80
80
  put :attach
81
81
  post :discard
82
82
  post :subscribe
83
83
  post :unsubscribe
84
- get :opportunities
84
+ get :opportunities
85
85
  end
86
86
  end
87
87
 
@@ -93,7 +93,8 @@ Rails.application.routes.draw do
93
93
  get :field_group
94
94
  post :auto_complete
95
95
  post :redraw
96
- get :versions
96
+ get :versions
97
+ get :autocomplete_account_name
97
98
  end
98
99
  member do
99
100
  get :convert
@@ -104,8 +105,6 @@ Rails.application.routes.draw do
104
105
  put :promote
105
106
  put :reject
106
107
  end
107
-
108
- get :autocomplete_account_name, :on => :collection
109
108
  end
110
109
 
111
110
  resources :opportunities, :id => /\d+/ do
@@ -123,7 +122,7 @@ Rails.application.routes.draw do
123
122
  post :discard
124
123
  post :subscribe
125
124
  post :unsubscribe
126
- get :contacts
125
+ get :contacts
127
126
  end
128
127
  end
129
128
 
@@ -133,24 +132,21 @@ Rails.application.routes.draw do
133
132
  post :auto_complete
134
133
  end
135
134
  member do
136
- put :complete
135
+ put :complete
137
136
  end
138
137
  end
139
138
 
140
139
  resources :users, :id => /\d+/, :except => [:index, :destroy] do
141
140
  member do
142
- get :avatar
143
- get :password
144
- put :upload_avatar
145
- put :change_password
141
+ get :avatar
142
+ get :password
143
+ put :upload_avatar
144
+ put :change_password
146
145
  post :redraw
147
146
  end
148
-
149
147
  collection do
150
- match :auto_complete
151
- end
152
- collection do
153
- get :opportunities_overview
148
+ post :auto_complete
149
+ get :opportunities_overview
154
150
  end
155
151
  end
156
152
 
@@ -168,7 +164,7 @@ Rails.application.routes.draw do
168
164
  end
169
165
  end
170
166
 
171
- resources :field_groups, :except => :index do
167
+ resources :field_groups, :except => [:index, :show] do
172
168
  collection do
173
169
  post :sort
174
170
  end
@@ -187,7 +183,7 @@ Rails.application.routes.draw do
187
183
  end
188
184
  end
189
185
 
190
- resources :tags do
186
+ resources :tags, :except => [:show] do
191
187
  member do
192
188
  get :confirm
193
189
  end
@@ -196,9 +192,8 @@ Rails.application.routes.draw do
196
192
  resources :fields, :as => :custom_fields
197
193
  resources :fields, :as => :core_fields
198
194
 
199
- resources :settings
200
- resources :plugins
195
+ resources :settings, :only => :index
196
+ resources :plugins, :only => :index
201
197
  end
202
198
 
203
- get '/:controller/tagged/:id' => '#tagged'
204
199
  end
@@ -63,12 +63,11 @@
63
63
 
64
64
 
65
65
  # Settings for outgoing email (SMTP)
66
- # - Default configuration is for GMail
67
66
  #------------------------------------------------------------------------------
68
67
  :smtp:
69
- :address : "smtp.gmail.com"
70
- :enable_starttls_auto : true
71
- :port : 587
68
+ :address : "" # e.g. smtp.gmail.com
69
+ :enable_starttls_auto : true # true/false
70
+ :port : "" # e.g. 587
72
71
  :authentication : :plain
73
72
  :user_name : ""
74
73
  :password : ""
@@ -5,7 +5,7 @@
5
5
  #------------------------------------------------------------------------------
6
6
  if defined?(RSpec)
7
7
  require 'rspec/core/rake_task'
8
-
8
+
9
9
  namespace :spec do
10
10
  desc "Preparing test env"
11
11
  task :prepare do
@@ -21,8 +21,4 @@ if defined?(RSpec)
21
21
  Rake::Task["spec"].prerequisites.clear
22
22
  Rake::Task["spec"].prerequisites.push("spec:prepare")
23
23
 
24
- desc 'Run the acceptance specs in ./acceptance'
25
- RSpec::Core::RakeTask.new(:acceptance => 'spec:prepare') do |t|
26
- t.pattern = 'acceptance/**/*_spec.rb'
27
- end
28
24
  end
data/lib/fat_free_crm.rb CHANGED
@@ -9,12 +9,22 @@ module FatFreeCRM
9
9
  # Return either Application or Engine,
10
10
  # depending on how Fat Free CRM has been loaded
11
11
  def application
12
- defined?(FatFreeCRM::Engine) ? Engine : Application
12
+ engine? ? Engine : Application
13
13
  end
14
14
 
15
15
  def root
16
16
  application.root
17
17
  end
18
+
19
+ # Are we running as an engine?
20
+ def engine?
21
+ defined?(FatFreeCRM::Engine).present?
22
+ end
23
+
24
+ def application?
25
+ !engine?
26
+ end
27
+
18
28
  end
19
29
  end
20
30
 
@@ -76,7 +76,7 @@ module FatFreeCRM
76
76
  end
77
77
 
78
78
  def method_missing(method_id, *args, &block)
79
- if method_id.to_s =~ /^cf_/
79
+ if method_id.to_s =~ /\Acf_/
80
80
  # Refresh columns and try again.
81
81
  self.class.reset_column_information
82
82
  # If new record, create new object from class, else reload class
@@ -86,7 +86,7 @@ module ActionView
86
86
  href
87
87
  else
88
88
  # don't include trailing punctuation character as part of the URL
89
- while href.sub!(/[^\w\/-]$/, '')
89
+ while href.sub!(/[^\w\/-]\z/, '')
90
90
  punctuation.push $&
91
91
  if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
92
92
  href << punctuation.pop
@@ -127,4 +127,3 @@ module ActionView
127
127
  end
128
128
  end
129
129
  end
130
-
@@ -0,0 +1,59 @@
1
+ # Copyright (c) 2008-2014 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
+ #------------------------------------------------------------------------------
6
+
7
+ require 'securerandom'
8
+
9
+ module FatFreeCRM
10
+
11
+ class SecretTokenGenerator
12
+
13
+ class << self
14
+
15
+ #
16
+ # If there is no secret token defined, we generate one and save it as a setting
17
+ # If a token has been already been saved, we tell Rails to use it and move on.
18
+ def setup!
19
+ if token.blank?
20
+ Rails.logger.info("No secret key defined yet... generating and saving to Setting.secret_token")
21
+ generate_and_persist_token!
22
+ end
23
+ FatFreeCRM::Application.config.secret_token = token
24
+ raise(FAIL_MESSAGE) if FatFreeCRM::Application.config.secret_token.blank?# and !Rails.env.test?
25
+ end
26
+
27
+ private
28
+
29
+ FAIL_MESSAGE = ::I18n.t('secret_token_generator.fail_message', default: "There was a problem generating the secret token. Please see lib/fat_free_crm/secret_token_generator.rb")
30
+
31
+ #
32
+ # Read the current token from settings
33
+ def token
34
+ Setting.secret_token
35
+ end
36
+
37
+ #
38
+ # Create a new secret token and save it as a setting.
39
+ def generate_and_persist_token!
40
+ quietly do
41
+ Setting.secret_token = SecureRandom.hex(64)
42
+ end
43
+ end
44
+
45
+ #
46
+ # Yields to a block that executes with the logging turned off
47
+ # This stops the secret token from being appended to the log
48
+ def quietly(&block)
49
+ temp_logger = ActiveRecord::Base.logger
50
+ ActiveRecord::Base.logger = nil
51
+ yield
52
+ ActiveRecord::Base.logger = temp_logger
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -7,7 +7,7 @@ module FatFreeCRM
7
7
  module VERSION #:nodoc:
8
8
  MAJOR = 0
9
9
  MINOR = 13
10
- TINY = 0
10
+ TINY = 1
11
11
  PRE = nil
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
@@ -54,10 +54,8 @@ describe Admin::UsersController do
54
54
  #----------------------------------------------------------------------------
55
55
  describe "GET new" do
56
56
  it "assigns a new user as @user and renders [new] template" do
57
- @user = User.new
58
-
59
57
  xhr :get, :new
60
- assigns[:user].attributes.should == @user.attributes
58
+ expect(assigns[:user]).to be_new_record
61
59
  response.should render_template("admin/users/new")
62
60
  end
63
61
  end
@@ -76,13 +76,6 @@ describe HomeController do
76
76
  assigns[:my_accounts].should == [account_1, account_4, account_3, account_2]
77
77
  end
78
78
 
79
- it "should assign @hello and call hook" do
80
- require_user
81
- controller.should_receive(:hook).at_least(:once)
82
-
83
- get :index
84
- assigns[:hello].should == "Hello world"
85
- end
86
79
  end
87
80
 
88
81
  # GET /home/options AJAX
@@ -3,14 +3,32 @@
3
3
  # Fat Free CRM is freely distributable under the terms of MIT license.
4
4
  # See MIT-LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
5
  #------------------------------------------------------------------------------
6
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
6
+ require 'spec_helper'
7
7
 
8
8
  describe PasswordsController do
9
9
 
10
- #Delete this example and add some real ones
11
- it "should use PasswordsController" do
12
- controller.should be_an_instance_of(PasswordsController)
10
+ let(:user) { FactoryGirl.build(:user) }
11
+
12
+ describe "update" do
13
+
14
+ before(:each) do
15
+ User.stub(:find_using_perishable_token).and_return(user)
16
+ end
17
+
18
+ it "should accept non-blank passwords" do
19
+ password = "password"
20
+ user.should_receive(:update_attributes).and_return(true)
21
+ put :update, id: 1, user: { password: password, password_confirmation: password }
22
+ response.should redirect_to( profile_url )
23
+ end
24
+
25
+ it "should not accept blank passwords" do
26
+ password = " "
27
+ user.should_not_receive(:update_attributes)
28
+ put :update, id: 1, user: { password: password, password_confirmation: password }
29
+ response.should render_template('edit')
30
+ end
31
+
13
32
  end
14
33
 
15
34
  end
16
-
@@ -3,7 +3,7 @@
3
3
  # Fat Free CRM is freely distributable under the terms of MIT license.
4
4
  # See MIT-LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
5
  #------------------------------------------------------------------------------
6
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
6
+ require 'spec_helper'
7
7
 
8
8
  describe UsersController do
9
9
 
@@ -15,11 +15,9 @@ describe UsersController do
15
15
  require_user
16
16
  end
17
17
 
18
- it "should expose the requested user as @user and render [show] template" do
19
- @user = FactoryGirl.create(:user)
20
-
21
- get :show, :id => @user.id
22
- assigns[:user].should == @user
18
+ it "should render [show] template" do
19
+ get :show, :id => current_user.id
20
+ assigns[:user].should == current_user
23
21
  response.should render_template("users/show")
24
22
  end
25
23
 
@@ -29,16 +27,30 @@ describe UsersController do
29
27
  response.should render_template("users/show")
30
28
  end
31
29
 
30
+ it "should show user if admin user" do
31
+ @user = create(:user)
32
+ require_user(admin: true)
33
+ get :show, id: @user.id
34
+ assigns[:user].should == @user
35
+ response.should render_template("users/show")
36
+ end
37
+
38
+ it "should not show user if not admin user" do
39
+ @user = create(:user)
40
+ get :show, id: @user.id
41
+ response.should redirect_to(root_url)
42
+ end
43
+
32
44
  describe "with mime type of JSON" do
33
45
  before(:each) do
34
46
  request.env["HTTP_ACCEPT"] = "application/json"
35
47
  end
36
48
 
37
49
  it "should render the requested user as JSON" do
38
- User.should_receive(:find).and_return(user = double("User"))
39
- user.should_receive(:to_json).and_return("generated JSON")
50
+ User.should_receive(:find).and_return(current_user)
51
+ current_user.should_receive(:to_json).and_return("generated JSON")
40
52
 
41
- get :show, :id => 42
53
+ get :show, :id => current_user.id
42
54
  response.body.should == "generated JSON"
43
55
  end
44
56
 
@@ -56,10 +68,10 @@ describe UsersController do
56
68
  end
57
69
 
58
70
  it "should render the requested user as XML" do
59
- User.should_receive(:find).and_return(user = double("User"))
60
- user.should_receive(:to_xml).and_return("generated XML")
71
+ User.should_receive(:find).and_return(current_user)
72
+ current_user.should_receive(:to_xml).and_return("generated XML")
61
73
 
62
- get :show, :id => 42
74
+ get :show, :id => current_user.id
63
75
  response.body.should == "generated XML"
64
76
  end
65
77
 
@@ -79,7 +91,7 @@ describe UsersController do
79
91
 
80
92
  describe "if user is allowed to sign up" do
81
93
  it "should expose a new user as @user and render [new] template" do
82
- @controller.should_receive(:can_signup?).and_return(true)
94
+ User.should_receive(:can_signup?).and_return(true)
83
95
  @user = FactoryGirl.build(:user)
84
96
  User.stub(:new).and_return(@user)
85
97
 
@@ -91,7 +103,7 @@ describe UsersController do
91
103
 
92
104
  describe "if user is not allowed to sign up" do
93
105
  it "should redirect to login_path" do
94
- @controller.should_receive(:can_signup?).and_return(false)
106
+ User.should_receive(:can_signup?).and_return(false)
95
107
 
96
108
  get :new
97
109
  response.should redirect_to(login_path)
@@ -102,14 +114,27 @@ describe UsersController do
102
114
  # GET /users/1/edit AJAX
103
115
  #----------------------------------------------------------------------------
104
116
  describe "responding to GET edit" do
105
- before(:each) do
117
+
118
+ it "should expose current user as @user and render [edit] template" do
106
119
  require_user
107
120
  @user = current_user
121
+ xhr :get, :edit, :id => @user.id
122
+ assigns[:user].should == current_user
123
+ response.should render_template("users/edit")
108
124
  end
109
125
 
110
- it "should expose current user as @user and render [edit] template" do
126
+ it "should not allow current user to edit another user" do
127
+ @user = create(:user)
128
+ require_user
111
129
  xhr :get, :edit, :id => @user.id
112
- assigns[:user].should == current_user
130
+ expect(response.body).to eql("window.location.reload();")
131
+ end
132
+
133
+ it "should allow admin to edit another user" do
134
+ require_user(admin: true)
135
+ @user = create(:user)
136
+ xhr :get, :edit, :id => @user.id
137
+ assigns[:user].should == @user
113
138
  response.should render_template("users/edit")
114
139
  end
115
140
 
@@ -130,6 +155,7 @@ describe UsersController do
130
155
  end
131
156
 
132
157
  it "exposes a newly created user as @user and redirect to profile page" do
158
+ require_user(admin: true)
133
159
  post :create, :user => { :username => @username, :email => @email, :password => @password, :password_confirmation => @password }
134
160
  assigns[:user].should == @user
135
161
  flash[:notice].should =~ /welcome/
@@ -148,6 +174,7 @@ describe UsersController do
148
174
 
149
175
  describe "with invalid params" do
150
176
  it "assigns a newly created but unsaved user as @user and renders [new] template" do
177
+ require_user(admin: true)
151
178
  @user = FactoryGirl.build(:user, :username => "", :email => "")
152
179
  User.stub(:new).and_return(@user)
153
180
 
@@ -292,6 +319,7 @@ describe UsersController do
292
319
  describe "responding to PUT change_password" do
293
320
  before(:each) do
294
321
  require_user
322
+ User.stub(:find).and_return(current_user)
295
323
  @current_user_session.stub(:unauthorized_record=).and_return(current_user)
296
324
  @current_user_session.stub(:save).and_return(current_user)
297
325
  @user = current_user