fat_free_crm 0.12.1 → 0.12.2

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.

checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZWNmOGI2ODA3NzM3ZWY1ZDZlZjE5ZDE5YjhmNTU2YmQ3MmQzZDljZQ==
4
+ ODc2YTUzOGEyMTQyYjM2YjU5NjBhZWIxZjdlYzM3YmU0ZDA2MmRiOA==
5
5
  data.tar.gz: !binary |-
6
- ODQyMGQ0NDFlNDBkMTU2OWVmYzY1ODMzMmJkYTY3ZjVjOTY0MTQxNQ==
6
+ Y2Q5ZGRmY2YxZTYzNzBkYjJhMmJkODliODYxZDQwOTZkYWI1ZmYzOA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NmFhNTU0YmVkZTBhNjkwZWQ3ZTYxODAyOGVkOGQ3Zjc3MzdmNmVkMDRlNGYx
10
- MjljM2UxZDk4ZjY4MWMwNzBjZDk1YWMyODVmYjk2OGE1ODA3NDgwMDA2ZTcy
11
- ODEyNTI5MGZjZDY5YjZmNDZlNzY4MmM0YmFhNDRkMjAyMGM2OTE=
9
+ Zjc1M2JhOGYyNWJhODdlNDVkM2Y1YmU4Yjg2MzlmZmNhNTY4MzUzN2I1NmNk
10
+ NDBiNTcyZjNlY2Y3NTBlODM1OThhMTYyZmNkZjIyYTA4ZmIwYzI4OTFiNmYx
11
+ NjIwODkzYjQ1ZGQwNDFlMDFlZmJkMDg0Zjk0MTJhNzY3ZjY0NzI=
12
12
  data.tar.gz: !binary |-
13
- ZDllMDRjYmIyZjI5YTJhNWE3MmY0ZmRmNzA0N2FiYTY0M2ZiMmRhNjg1ODE4
14
- YmM4ODQyY2VjMjAyMGE1YzkxYWVkYzVmZjJkMjU5YjVjNjUzZDQ0MDc4OWEx
15
- M2ZlMjMzMTJkNmEzODQ0ZjA4ZjA4NmI1Y2U3MTJhNWE4ODAwNjg=
13
+ ZTk3Zjc2MmFmZjU3OGQzNWM1ZTUxOWIyNWRjN2I0Y2ZlZTM5ODA4YWZiZGQ1
14
+ YjEwMzBmYzQ2MWExYTBjMWY2OTEzZTVmYjIwZDQ0MDMwZTkwYjcxMTk3NzJl
15
+ MjQ0NWUxYmZhZDQ4ZTEwNzU4ZWM0OTYzOWZmMDMyMzRlMTdjNzc=
@@ -145,7 +145,7 @@ private
145
145
 
146
146
  #----------------------------------------------------------------------------
147
147
  def can_signup?
148
- [ :allowed, :needs_approval ].include? Setting.user_signup
148
+ User.can_signup?
149
149
  end
150
150
 
151
151
  #----------------------------------------------------------------------------
@@ -199,10 +199,10 @@ private
199
199
  flash[:warning] = t(:msg_asset_not_available, asset)
200
200
 
201
201
  respond_to do |format|
202
- format.html { redirect_to :action => :index }
202
+ format.html { redirect_to(redirection_url) }
203
203
  format.js { render(:update) { |page| page.reload } }
204
- format.json { render :text => flash[:warning], :status => :not_found }
205
- format.xml { render :text => flash[:warning], :status => :not_found }
204
+ format.json { render :text => flash[:warning], :status => :not_found }
205
+ format.xml { render :xml => [flash[:warning]], :status => :not_found }
206
206
  end
207
207
  end
208
208
 
@@ -213,32 +213,32 @@ private
213
213
 
214
214
  url = send("#{related.pluralize}_path")
215
215
  respond_to do |format|
216
- format.html { redirect_to url }
217
- format.js { render(:update) { |page| page.redirect_to url } }
218
- format.json { render :text => flash[:warning], :status => :not_found }
219
- format.xml { render :text => flash[:warning], :status => :not_found }
216
+ format.html { redirect_to(url) }
217
+ format.js { render(:update) { |page| page.redirect_to(url) } }
218
+ format.json { render :text => flash[:warning], :status => :not_found }
219
+ format.xml { render :xml => [flash[:warning]], :status => :not_found }
220
220
  end
221
221
  end
222
222
 
223
223
  #----------------------------------------------------------------------------
224
224
  def respond_to_access_denied
225
- if self.action_name == "show"
226
- flash[:warning] = t(:msg_asset_not_authorized, asset)
227
-
228
- else
229
- flick = case self.action_name
230
- when "destroy" then "delete"
231
- when "promote" then "convert"
232
- else self.action_name
233
- end
234
- flash[:warning] = t(:msg_cant_do, :action => flick, :asset => asset)
235
- end
236
-
225
+ flash[:warning] = t(:msg_not_authorized, default: 'You are not authorized to take this action.')
237
226
  respond_to do |format|
238
- format.html { redirect_to :action => :index }
227
+ format.html { redirect_to(redirection_url) }
239
228
  format.js { render(:update) { |page| page.reload } }
240
- format.json { render :text => flash[:warning], :status => :unauthorized }
241
- format.xml { render :text => flash[:warning], :status => :unauthorized }
229
+ format.json { render :text => flash[:warning], :status => :unauthorized }
230
+ format.xml { render :xml => [flash[:warning]], :status => :unauthorized }
242
231
  end
243
232
  end
233
+
234
+ #----------------------------------------------------------------------------
235
+ def redirection_url
236
+ # Try to redirect somewhere sensible. Note: not all controllers have an index action
237
+ url = if current_user.present?
238
+ (respond_to?(:index) and self.action_name != 'index') ? { action: 'index' } : root_url
239
+ else
240
+ login_url
241
+ end
242
+ end
243
+
244
244
  end
@@ -6,7 +6,6 @@
6
6
  class HomeController < ApplicationController
7
7
  before_filter :require_user, :except => [ :toggle, :timezone ]
8
8
  before_filter :set_current_tab, :only => :index
9
- before_filter "hook(:home_before_filter, self, :amazing => true)"
10
9
 
11
10
  #----------------------------------------------------------------------------
12
11
  def index
@@ -5,44 +5,30 @@
5
5
  #------------------------------------------------------------------------------
6
6
  class UsersController < ApplicationController
7
7
 
8
- before_filter :require_no_user, :only => [ :new, :create ]
9
- before_filter :require_user, :only => [ :show, :redraw ]
10
8
  before_filter :set_current_tab, :only => [ :show, :opportunities_overview ] # Don't hightlight any tabs.
11
- before_filter :require_and_assign_user, :except => [ :new, :create, :show, :avatar, :upload_avatar ]
12
- before_filter :assign_given_or_current_user, :only => [ :show, :avatar, :upload_avatar, :edit, :update ]
13
9
 
14
- load_resource
10
+ check_authorization
11
+ load_and_authorize_resource # handles all security
15
12
 
16
13
  respond_to :html, :only => [ :show, :new ]
17
14
 
18
15
  # GET /users/1
19
- # GET /users/1.json
20
- # GET /users/1.xml HTML
16
+ # GET /users/1.js
21
17
  #----------------------------------------------------------------------------
22
18
  def show
19
+ @user = current_user if params[:id].nil?
23
20
  respond_with(@user)
24
21
  end
25
22
 
26
23
  # GET /users/new
27
- # GET /users/new.json
28
- # GET /users/new.xml HTML
24
+ # GET /users/new.js
29
25
  #----------------------------------------------------------------------------
30
26
  def new
31
- if can_signup?
32
- respond_with(@user)
33
- else
34
- redirect_to login_path
35
- end
36
- end
37
-
38
- # GET /users/1/edit AJAX
39
- #----------------------------------------------------------------------------
40
- def edit
41
27
  respond_with(@user)
42
28
  end
43
29
 
44
30
  # POST /users
45
- # POST /users.xml HTML
31
+ # POST /users.js
46
32
  #----------------------------------------------------------------------------
47
33
  def create
48
34
  if @user.save
@@ -58,31 +44,29 @@ class UsersController < ApplicationController
58
44
  end
59
45
  end
60
46
 
61
- # PUT /users/1
62
- # PUT /users/1.json
63
- # PUT /users/1.xml AJAX
47
+ # GET /users/1/edit.js
64
48
  #----------------------------------------------------------------------------
65
- def update
66
- @user.update_attributes(params[:user])
49
+ def edit
67
50
  respond_with(@user)
68
51
  end
69
52
 
70
- # DELETE /users/1
71
- # DELETE /users/1.xml HTML and AJAX (not directly exposed yet)
53
+ # PUT /users/1
54
+ # PUT /users/1.js
72
55
  #----------------------------------------------------------------------------
73
- def destroy
74
- # not exposed
56
+ def update
57
+ @user.update_attributes(params[:user])
58
+ respond_with(@user)
75
59
  end
76
60
 
77
61
  # GET /users/1/avatar
78
- # GET /users/1/avatar.xml AJAX
62
+ # GET /users/1/avatar.js
79
63
  #----------------------------------------------------------------------------
80
64
  def avatar
81
65
  respond_with(@user)
82
66
  end
83
67
 
84
68
  # PUT /users/1/upload_avatar
85
- # PUT /users/1/upload_avatar.xml AJAX
69
+ # PUT /users/1/upload_avatar.js
86
70
  #----------------------------------------------------------------------------
87
71
  def upload_avatar
88
72
  if params[:gravatar]
@@ -106,19 +90,21 @@ class UsersController < ApplicationController
106
90
  end
107
91
 
108
92
  # GET /users/1/password
109
- # GET /users/1/password.xml AJAX
93
+ # GET /users/1/password.js
110
94
  #----------------------------------------------------------------------------
111
95
  def password
112
96
  respond_with(@user)
113
97
  end
114
98
 
115
99
  # PUT /users/1/change_password
116
- # PUT /users/1/change_password.xml AJAX
100
+ # PUT /users/1/change_password.js
117
101
  #----------------------------------------------------------------------------
118
102
  def change_password
119
103
  if @user.valid_password?(params[:current_password], true) || @user.password_hash.blank?
120
104
  unless params[:user][:password].blank?
121
- @user.update_attributes(params[:user])
105
+ @user.password = params[:user][:password]
106
+ @user.password_confirmation = params[:user][:password_confirmation]
107
+ @user.save
122
108
  flash[:notice] = t(:msg_password_changed)
123
109
  else
124
110
  flash[:notice] = t(:msg_password_not_changed)
@@ -130,27 +116,18 @@ class UsersController < ApplicationController
130
116
  respond_with(@user)
131
117
  end
132
118
 
133
- # POST /users/1/redraw AJAX
119
+ # POST /users/1/redraw
134
120
  #----------------------------------------------------------------------------
135
121
  def redraw
136
122
  current_user.preference[:locale] = params[:locale]
137
123
  render(:update) { |page| page.redirect_to user_path(current_user) }
138
124
  end
139
125
 
126
+ # GET /users/opportunities_overview
127
+ #----------------------------------------------------------------------------
140
128
  def opportunities_overview
141
129
  @users_with_opportunities = User.have_assigned_opportunities.order(:first_name)
142
130
  @unassigned_opportunities = Opportunity.unassigned.pipeline.order(:stage)
143
131
  end
144
132
 
145
- private
146
-
147
- #----------------------------------------------------------------------------
148
- def require_and_assign_user
149
- require_user
150
- @user = current_user
151
- end
152
-
153
- def assign_given_or_current_user
154
- @user = params[:id] ? User.find(params[:id]) : current_user
155
- end
156
133
  end
@@ -9,11 +9,22 @@ class Ability
9
9
  include CanCan::Ability
10
10
 
11
11
  def initialize(user)
12
+
13
+ # handle signup
14
+ can(:create, User) if User.can_signup?
15
+
12
16
  if user.present?
13
17
  entities = [Account, Campaign, Contact, Lead, Opportunity]
14
18
 
15
- can :create, :all
16
- can :read, [User] # for search autocomplete
19
+ # User
20
+ can :manage, User, id: user.id # can do any action on themselves
21
+
22
+ # Tasks
23
+ can :create, Task
24
+ can :manage, Task, user: user.id
25
+ can :manage, Task, assigned_to: user.id
26
+
27
+ # Entities
17
28
  can :manage, entities, :access => 'Public'
18
29
  can :manage, entities + [Task], :user_id => user.id
19
30
  can :manage, entities + [Task], :assigned_to => user.id
@@ -187,6 +187,10 @@ class User < ActiveRecord::Base
187
187
  Ability.new(User.current_user)
188
188
  end
189
189
 
190
+ def can_signup?
191
+ [ :allowed, :needs_approval ].include? Setting.user_signup
192
+ end
193
+
190
194
  end
191
195
 
192
196
  ActiveSupport.run_load_hooks(:fat_free_crm_user, self)
@@ -20,13 +20,16 @@
20
20
  = hook(:javascript_includes, self)
21
21
 
22
22
  :javascript
23
- #{yield :javascript}
24
- var _ffcrm_users = [
25
- #{User.all.map{|u| "\"#{u.full_name} (@#{u.username})\"" }.join(",\n")}
26
- ];
27
-
23
+ crm.language = "#{I18n.locale}"
28
24
  window.controller = "#{controller.controller_name}"
29
25
 
26
+ - if current_user.present?
27
+ :javascript
28
+ #{yield :javascript}
29
+ var _ffcrm_users = [
30
+ #{User.all.map{|u| "\"#{u.full_name} (@#{u.username})\"" }.join(",\n")}
31
+ ];
32
+
30
33
  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
31
34
  <link rel="icon" href="/favicon.ico" type="image/x-icon">
32
35
 
@@ -65,7 +65,7 @@ module FatFreeCRM
65
65
  config.encoding = "utf-8"
66
66
 
67
67
  # Configure sensitive parameters which will be filtered from the log file.
68
- config.filter_parameters += [:password]
68
+ config.filter_parameters += [:password, :password_hash, :password_salt, :password_confirmation]
69
69
 
70
70
  # Use SQL instead of Active Record's schema dumper when creating the database.
71
71
  # This is necessary if your schema can't be completely dumped by the schema dumper,
@@ -10,9 +10,8 @@ if defined?(FatFreeCRM::Application)
10
10
  # Code is not reloaded between requests
11
11
  config.cache_classes = true
12
12
 
13
- # Full error reports are enabled, since this is an internal application.
14
- config.consider_all_requests_local = true
15
- # Caching is turned on
13
+ # Full error reports are disabled and caching is turned on.
14
+ config.consider_all_requests_local = false
16
15
  config.action_controller.perform_caching = true
17
16
 
18
17
  # Disable Rails's static asset server (Apache or nginx will already do this)
@@ -1 +1,25 @@
1
- FatFreeCRM::Application.config.secret_token = 'bb6810b6691d68fae269cfa4ce1805a5b4b0826e2680988e1102a4b3b80e5753af76d25a90f3ba7bc4c2fa68c4bce3b36df72baa18a0e35a71d3199918766db9'
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
+ #------------------------------------------------------------------------------
6
+
7
+ # Be sure to restart your server when you modify this file.
8
+
9
+ # Your secret key is used for verifying the integrity of signed cookies.
10
+ # If you change this key, all old signed cookies will become invalid!
11
+
12
+ # Make sure the secret is at least 30 characters and all random,
13
+ # no regular words or you'll be exposed to dictionary attacks.
14
+ # You can use `rake secret` to generate a secure secret key.
15
+
16
+ # Make sure your secret_key_base is kept private
17
+ # if you're sharing your code publicly.
18
+
19
+ #
20
+ # We should setup a secret token if FFCRM is running in application mode but NOT in engine mode.
21
+ # This functionality has been extracted to lib so it can be tested.
22
+ if FatFreeCRM.application?
23
+ require 'fat_free_crm/secret_token_generator'
24
+ FatFreeCRM::SecretTokenGenerator.setup!
25
+ end
@@ -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/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
 
@@ -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?
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 = 12
10
- TINY = 1
10
+ TINY = 2
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
@@ -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 = mock("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 = mock("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,8 +319,9 @@ describe UsersController do
292
319
  describe "responding to PUT change_password" do
293
320
  before(:each) do
294
321
  require_user
295
- @current_user_session.stub!(:unauthorized_record=).and_return(current_user)
296
- @current_user_session.stub!(:save).and_return(current_user)
322
+ User.stub(:find).and_return(current_user)
323
+ @current_user_session.stub(:unauthorized_record=).and_return(current_user)
324
+ @current_user_session.stub(:save).and_return(current_user)
297
325
  @user = current_user
298
326
  @new_password = "secret?!"
299
327
  end
@@ -0,0 +1,55 @@
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 'spec_helper'
8
+ require 'fat_free_crm/secret_token_generator'
9
+
10
+ describe FatFreeCRM::SecretTokenGenerator do
11
+
12
+ let(:token) { 'e5a4b315c062dec4ecb40dabcde84fd6c067cb016a813702d2f4299ad16255c88ed1020bd47fb527e8e5f7052b04be1fbb8e63c043b8fb36f88d3c7d79a68681' }
13
+
14
+ describe "setup!" do
15
+
16
+ it "should not generate a token if one already exists" do
17
+ FatFreeCRM::SecretTokenGenerator.stub(:token).and_return(nil)
18
+ expect(FatFreeCRM::SecretTokenGenerator).to receive(:generate_and_persist_token!)
19
+ FatFreeCRM::Application.config.stub(:secret_token).and_return(token)
20
+ FatFreeCRM::SecretTokenGenerator.setup!
21
+ end
22
+
23
+ it "should generate a token if none exists already" do
24
+ FatFreeCRM::SecretTokenGenerator.stub(:token).and_return(token)
25
+ expect(FatFreeCRM::SecretTokenGenerator).not_to receive(:generate_and_persist_token!)
26
+ FatFreeCRM::SecretTokenGenerator.setup!
27
+ end
28
+
29
+ it "should raise an error if the token is still blank (should never happen)" do
30
+ FatFreeCRM::SecretTokenGenerator.stub(:token).and_return(nil)
31
+ lambda { FatFreeCRM::SecretTokenGenerator.setup! }.should raise_error(RuntimeError)
32
+ end
33
+
34
+ end
35
+
36
+ describe "token" do
37
+
38
+ it "should delegate to Setting" do
39
+ expect(Setting).to receive(:secret_token).and_return(token)
40
+ expect(FatFreeCRM::SecretTokenGenerator.send(:token)).to eql(token)
41
+ end
42
+
43
+ end
44
+
45
+ describe "generate_and_persist_token!" do
46
+
47
+ it "should generate a random token" do
48
+ expect(SecureRandom).to receive(:hex).with(64).and_return(token)
49
+ expect(Setting).to receive(:secret_token=).with(token)
50
+ FatFreeCRM::SecretTokenGenerator.send(:generate_and_persist_token!)
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'cancan/matchers'
3
+
4
+ def all_actions
5
+ [:index, :show, :create, :update, :destroy, :manage]
6
+ end
7
+
8
+ describe "User abilities" do
9
+
10
+ subject(:ability) { Ability.new(user) }
11
+ let(:subject_user) { create :user }
12
+
13
+ context "when site manager, I" do
14
+ let(:user) { create :user, admin: true}
15
+ all_actions.each do |do_action|
16
+ it{ should be_able_to(do_action, subject_user) }
17
+ end
18
+ end
19
+
20
+ context "when myself, I" do
21
+ let(:user) { create :user }
22
+ let(:subject_user) { user }
23
+ all_actions.each do |do_action|
24
+ it{ should be_able_to(do_action, subject_user) }
25
+ end
26
+ end
27
+
28
+ context "when another user, I" do
29
+ let(:user) { create :user }
30
+ let(:can) { [] }
31
+ let(:cannot) { [:show, :create, :update, :index, :destroy, :manage] }
32
+ it{ can.each do |do_action|
33
+ should be_able_to(do_action, subject_user)
34
+ end}
35
+ it{ cannot.each do |do_action|
36
+ should_not be_able_to(do_action, subject_user)
37
+ end}
38
+ end
39
+
40
+ context "when anonymous user, I" do
41
+ let(:user) { nil }
42
+ let(:can) { [] }
43
+ let(:cannot) { [:show, :create, :update, :index, :destroy, :manage] }
44
+ it{ can.each do |do_action|
45
+ should be_able_to(do_action, subject_user)
46
+ end}
47
+ it{ cannot.each do |do_action|
48
+ should_not be_able_to(do_action, subject_user)
49
+ end}
50
+
51
+ it "and signup enabled" do
52
+ User.stub(:can_signup?).and_return(true)
53
+ should be_able_to(:create, User)
54
+ end
55
+
56
+ end
57
+
58
+ end
data/spec/spec_helper.rb CHANGED
@@ -11,7 +11,7 @@ require 'rspec/rails'
11
11
  require 'capybara/rails'
12
12
 
13
13
  require 'acts_as_fu'
14
- require 'factory_girl'
14
+ require 'factory_girl_rails'
15
15
  require 'ffaker'
16
16
 
17
17
  require 'coveralls'
@@ -38,6 +38,7 @@ RSpec.configure do |config|
38
38
 
39
39
  # RSpec configuration options for Fat Free CRM.
40
40
  config.include RSpec::Rails::Matchers
41
+ config.include(FactoryGirl::Syntax::Methods)
41
42
 
42
43
  config.before(:each) do
43
44
  # Overwrite locale settings within "config/settings.yml" if necessary.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fat_free_crm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Dvorkin
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-12-27 00:00:00.000000000 Z
14
+ date: 2014-01-07 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -1052,6 +1052,7 @@ files:
1052
1052
  - lib/fat_free_crm/plugin.rb
1053
1053
  - lib/fat_free_crm/plugin_dependencies.rb
1054
1054
  - lib/fat_free_crm/renderers.rb
1055
+ - lib/fat_free_crm/secret_token_generator.rb
1055
1056
  - lib/fat_free_crm/sortable.rb
1056
1057
  - lib/fat_free_crm/tabs.rb
1057
1058
  - lib/fat_free_crm/version.rb
@@ -1171,6 +1172,7 @@ files:
1171
1172
  - spec/lib/mail_processor/dropbox_spec.rb
1172
1173
  - spec/lib/mail_processor/sample_emails/dropbox.rb
1173
1174
  - spec/lib/permissions_spec.rb
1175
+ - spec/lib/secret_token_generator_spec.rb
1174
1176
  - spec/lib/view_factory_spec.rb
1175
1177
  - spec/mailers/subscription_mailer_spec.rb
1176
1178
  - spec/mailers/user_mailer_spec.rb
@@ -1196,6 +1198,7 @@ files:
1196
1198
  - spec/models/polymorphic/task_spec.rb
1197
1199
  - spec/models/polymorphic/version_spec.rb
1198
1200
  - spec/models/setting_spec.rb
1201
+ - spec/models/users/abilities/user_ability_spec.rb
1199
1202
  - spec/models/users/authentication_spec.rb
1200
1203
  - spec/models/users/group_spec.rb
1201
1204
  - spec/models/users/permission_spec.rb