fat_free_crm 0.13.0 → 0.13.1

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 (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