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.
- checksums.yaml +4 -4
- data/Capfile +1 -4
- data/Gemfile.lock +0 -1
- data/README.md +1 -0
- data/app/assets/javascripts/lists.js.coffee +1 -2
- data/app/controllers/application_controller.rb +27 -25
- data/app/controllers/emails_controller.rb +1 -30
- data/app/controllers/entities/contacts_controller.rb +1 -1
- data/app/controllers/entities/opportunities_controller.rb +1 -1
- data/app/controllers/entities_controller.rb +0 -1
- data/app/controllers/home_controller.rb +0 -4
- data/app/controllers/passwords_controller.rb +3 -3
- data/app/controllers/tasks_controller.rb +17 -10
- data/app/controllers/users_controller.rb +23 -46
- data/app/helpers/application_helper.rb +0 -3
- data/app/helpers/campaigns_helper.rb +0 -1
- data/app/helpers/leads_helper.rb +0 -11
- data/app/helpers/opportunities_helper.rb +0 -1
- data/app/helpers/tags_helper.rb +0 -8
- data/app/helpers/versions_helper.rb +1 -1
- data/app/models/entities/account_contact.rb +1 -1
- data/app/models/entities/campaign.rb +3 -3
- data/app/models/entities/contact.rb +3 -3
- data/app/models/entities/lead.rb +5 -5
- data/app/models/entities/opportunity.rb +1 -3
- data/app/models/fields/field_group.rb +1 -0
- data/app/models/list.rb +2 -1
- data/app/models/polymorphic/avatar.rb +1 -1
- data/app/models/polymorphic/task.rb +7 -4
- data/app/models/setting.rb +0 -3
- data/app/models/users/ability.rb +13 -2
- data/app/models/users/user.rb +4 -1
- data/app/views/home/index.html.haml +0 -4
- data/app/views/layouts/application.html.haml +7 -5
- data/app/views/leads/_contact.html.haml +0 -3
- data/app/views/lists/_personal_sidebar.html.haml +2 -2
- data/app/views/lists/_sidebar.html.haml +2 -2
- data/config/application.rb +2 -2
- data/config/environments/development.rb +2 -0
- data/config/environments/production.rb +2 -3
- data/config/initializers/secret_token.rb +25 -1
- data/config/locales/en-US_fat_free_crm.yml +1 -1
- data/config/routes.rb +27 -32
- data/config/settings.default.yml +3 -4
- data/lib/development_tasks/rspec.rake +1 -5
- data/lib/fat_free_crm.rb +11 -1
- data/lib/fat_free_crm/fields.rb +1 -1
- data/lib/fat_free_crm/gem_ext/rails/text_helper.rb +1 -2
- data/lib/fat_free_crm/secret_token_generator.rb +59 -0
- data/lib/fat_free_crm/version.rb +1 -1
- data/spec/controllers/admin/users_controller_spec.rb +1 -3
- data/spec/controllers/home_controller_spec.rb +0 -7
- data/spec/controllers/passwords_controller_spec.rb +23 -5
- data/spec/controllers/users_controller_spec.rb +45 -17
- data/spec/lib/secret_token_generator_spec.rb +55 -0
- data/spec/models/users/abilities/user_ability_spec.rb +58 -0
- data/spec/routing/emails_routing_spec.rb +13 -14
- data/spec/spec_helper.rb +2 -1
- metadata +5 -2
@@ -302,7 +302,6 @@ module ApplicationHelper
|
|
302
302
|
args = { :class => 'gravatar', :size => :large }.merge(args)
|
303
303
|
|
304
304
|
if model.respond_to?(:avatar) and model.avatar.present?
|
305
|
-
Avatar
|
306
305
|
image_tag(model.avatar.image.url(args[:size]), args)
|
307
306
|
else
|
308
307
|
args = Avatar.size_from_style!(args) # convert size format :large => '75x75'
|
@@ -400,7 +399,6 @@ module ApplicationHelper
|
|
400
399
|
check_box_tag("#{name}[]", value, checked, :id => value, :onclick => onclick)
|
401
400
|
end
|
402
401
|
|
403
|
-
|
404
402
|
# Create a column in the 'asset_attributes' table.
|
405
403
|
#----------------------------------------------------------------------------
|
406
404
|
def col(title, value, last = false, email = false)
|
@@ -493,5 +491,4 @@ module ApplicationHelper
|
|
493
491
|
end
|
494
492
|
end
|
495
493
|
|
496
|
-
|
497
494
|
end
|
data/app/helpers/leads_helper.rb
CHANGED
@@ -53,16 +53,6 @@ module LeadsHelper
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
# Returns default permissions intro for leads.
|
57
|
-
#----------------------------------------------------------------------------
|
58
|
-
def get_lead_default_permissions_intro(access)
|
59
|
-
case access
|
60
|
-
when "Private" then t(:lead_permissions_intro_private, t(:opportunity_small))
|
61
|
-
when "Public" then t(:lead_permissions_intro_public, t(:opportunity_small))
|
62
|
-
when "Shared" then t(:lead_permissions_intro_shared, t(:opportunity_small))
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
56
|
# Do not offer :converted status choice if we are creating a new lead or
|
67
57
|
# editing existing lead that hasn't been converted before.
|
68
58
|
#----------------------------------------------------------------------------
|
@@ -93,4 +83,3 @@ module LeadsHelper
|
|
93
83
|
summary.join(', ')
|
94
84
|
end
|
95
85
|
end
|
96
|
-
|
data/app/helpers/tags_helper.rb
CHANGED
@@ -28,12 +28,4 @@ module TagsHelper
|
|
28
28
|
end.html_safe
|
29
29
|
end
|
30
30
|
|
31
|
-
# Generate tag links for the asset landing page (shown on a sidebar).
|
32
|
-
#----------------------------------------------------------------------------
|
33
|
-
def tags_for_show(model)
|
34
|
-
model.tag_list.inject([]) do |arr, tag|
|
35
|
-
arr << link_to(tag, url_for(:action => "tagged", :id => tag), :title => tag)
|
36
|
-
end.join(" ").html_safe
|
37
|
-
end
|
38
|
-
|
39
31
|
end
|
@@ -8,7 +8,7 @@ module VersionsHelper
|
|
8
8
|
# Parse the changes for each version
|
9
9
|
#----------------------------------------------------------------------------
|
10
10
|
def parse_version(attr_name, change)
|
11
|
-
if attr_name =~
|
11
|
+
if attr_name =~ /\Acf_/ and (field = CustomField.where(:name => attr_name).first).present?
|
12
12
|
label = field.label
|
13
13
|
first = field.render(change.first)
|
14
14
|
second = field.render(change.second)
|
@@ -21,7 +21,7 @@ class AccountContact < ActiveRecord::Base
|
|
21
21
|
|
22
22
|
has_paper_trail :meta => { :related => :contact }, :ignore => [ :id, :created_at, :updated_at, :contact_id ]
|
23
23
|
|
24
|
-
|
24
|
+
validates_presence_of :account_id, :contact_id
|
25
25
|
|
26
26
|
ActiveSupport.run_load_hooks(:fat_free_crm_account_contact, self)
|
27
27
|
end
|
@@ -32,7 +32,7 @@
|
|
32
32
|
class Campaign < ActiveRecord::Base
|
33
33
|
belongs_to :user
|
34
34
|
belongs_to :assignee, :class_name => "User", :foreign_key => :assigned_to
|
35
|
-
has_many :tasks, :as => :asset, :dependent => :destroy
|
35
|
+
has_many :tasks, :as => :asset, :dependent => :destroy
|
36
36
|
has_many :leads, :dependent => :destroy, :order => "id DESC"
|
37
37
|
has_many :opportunities, :dependent => :destroy, :order => "id DESC"
|
38
38
|
has_many :emails, :as => :mediator
|
@@ -42,8 +42,8 @@ class Campaign < ActiveRecord::Base
|
|
42
42
|
scope :state, ->(filters) {
|
43
43
|
where('status IN (?)' + (filters.delete('other') ? ' OR status IS NULL' : ''), filters)
|
44
44
|
}
|
45
|
-
scope :created_by, ->(user) { where(
|
46
|
-
scope :assigned_to, ->(user) { where(
|
45
|
+
scope :created_by, ->(user) { where( user_id: user.id ) }
|
46
|
+
scope :assigned_to, ->(user) { where( assigned_to: user.id ) }
|
47
47
|
|
48
48
|
scope :text_search, ->(query) { search('name_cont' => query).result }
|
49
49
|
|
@@ -45,7 +45,7 @@ class Contact < ActiveRecord::Base
|
|
45
45
|
has_one :account, :through => :account_contact
|
46
46
|
has_many :contact_opportunities, :dependent => :destroy
|
47
47
|
has_many :opportunities, :through => :contact_opportunities, :uniq => true, :order => "opportunities.id DESC"
|
48
|
-
has_many :tasks, :as => :asset, :dependent => :destroy
|
48
|
+
has_many :tasks, :as => :asset, :dependent => :destroy
|
49
49
|
has_one :business_address, :dependent => :destroy, :as => :addressable, :class_name => "Address", :conditions => "address_type = 'Business'"
|
50
50
|
has_many :addresses, :dependent => :destroy, :as => :addressable, :class_name => "Address" # advanced search uses this
|
51
51
|
has_many :emails, :as => :mediator
|
@@ -59,8 +59,8 @@ class Contact < ActiveRecord::Base
|
|
59
59
|
|
60
60
|
accepts_nested_attributes_for :business_address, :allow_destroy => true, :reject_if => proc {|attributes| Address.reject_address(attributes)}
|
61
61
|
|
62
|
-
scope :created_by, ->(user) { where(
|
63
|
-
scope :assigned_to, ->(user) { where(
|
62
|
+
scope :created_by, ->(user) { where( user_id: user.id ) }
|
63
|
+
scope :assigned_to, ->(user) { where( assigned_to: user.id ) }
|
64
64
|
|
65
65
|
scope :text_search, ->(query) {
|
66
66
|
t = Contact.arel_table
|
data/app/models/entities/lead.rb
CHANGED
@@ -41,7 +41,7 @@ class Lead < ActiveRecord::Base
|
|
41
41
|
belongs_to :campaign
|
42
42
|
belongs_to :assignee, :class_name => "User", :foreign_key => :assigned_to
|
43
43
|
has_one :contact, :dependent => :nullify # On destroy keep the contact, but nullify its lead_id
|
44
|
-
has_many :tasks, :as => :asset, :dependent => :destroy
|
44
|
+
has_many :tasks, :as => :asset, :dependent => :destroy
|
45
45
|
has_one :business_address, :dependent => :destroy, :as => :addressable, :class_name => "Address", :conditions => "address_type='Business'"
|
46
46
|
has_many :addresses, :dependent => :destroy, :as => :addressable, :class_name => "Address" # advanced search uses this
|
47
47
|
has_many :emails, :as => :mediator
|
@@ -53,10 +53,10 @@ class Lead < ActiveRecord::Base
|
|
53
53
|
scope :state, ->(filters) {
|
54
54
|
where([ 'status IN (?)' + (filters.delete('other') ? ' OR status IS NULL' : ''), filters ])
|
55
55
|
}
|
56
|
-
scope :converted,
|
57
|
-
scope :for_campaign, ->(id)
|
58
|
-
scope :created_by,
|
59
|
-
scope :assigned_to,
|
56
|
+
scope :converted, -> { where( status: 'converted' ) }
|
57
|
+
scope :for_campaign, ->(id) { where( campaign_id: id ) }
|
58
|
+
scope :created_by, ->(user) { where( user_id: user.id ) }
|
59
|
+
scope :assigned_to, ->(user) { where( assigned_to: user.id ) }
|
60
60
|
|
61
61
|
scope :text_search, ->(query) { search('first_name_or_last_name_or_company_or_email_cont' => query).result }
|
62
62
|
|
@@ -51,9 +51,7 @@ class Opportunity < ActiveRecord::Base
|
|
51
51
|
|
52
52
|
# Search by name OR id
|
53
53
|
scope :text_search, ->(query) {
|
54
|
-
|
55
|
-
if query =~ /^\d+$/
|
56
|
-
query = query.gsub(/[^\w\s\-\.'\p{L}]/u, '').strip
|
54
|
+
if query =~ /\A\d+\z/
|
57
55
|
where('upper(name) LIKE upper(:name) OR opportunities.id = :id', :name => "%#{query}%", :id => query)
|
58
56
|
else
|
59
57
|
search('name_cont' => query).result
|
data/app/models/list.rb
CHANGED
@@ -9,7 +9,8 @@ class List < ActiveRecord::Base
|
|
9
9
|
|
10
10
|
# Parses the controller from the url
|
11
11
|
def controller
|
12
|
-
(url || "").sub(
|
12
|
+
(url || "").sub(/\A\//,'').split(/\/|\?/).first
|
13
13
|
end
|
14
|
+
|
14
15
|
ActiveSupport.run_load_hooks(:fat_free_crm_list, self)
|
15
16
|
end
|
@@ -45,7 +45,7 @@ class Avatar < ActiveRecord::Base
|
|
45
45
|
if options[:width] && options[:height]
|
46
46
|
options[:size] = [:width, :height].map{|d| options[d]}.join("x")
|
47
47
|
elsif Avatar::STYLES.keys.include?(options[:size])
|
48
|
-
options[:size] = Avatar::STYLES[options[:size]].sub(
|
48
|
+
options[:size] = Avatar::STYLES[options[:size]].sub(/\#\z/,'')
|
49
49
|
end
|
50
50
|
options
|
51
51
|
end
|
@@ -27,6 +27,7 @@
|
|
27
27
|
|
28
28
|
class Task < ActiveRecord::Base
|
29
29
|
attr_accessor :calendar
|
30
|
+
ALLOWED_VIEWS = %w(pending assigned completed)
|
30
31
|
|
31
32
|
belongs_to :user
|
32
33
|
belongs_to :assignee, :class_name => "User", :foreign_key => :assigned_to
|
@@ -46,8 +47,8 @@ class Task < ActiveRecord::Base
|
|
46
47
|
limit(options[:limit]) # nil selects all records
|
47
48
|
}
|
48
49
|
|
49
|
-
scope :created_by, ->(user) { where(:
|
50
|
-
scope :assigned_to, ->(user) { where(:
|
50
|
+
scope :created_by, ->(user) { where( user_id: user.id ) }
|
51
|
+
scope :assigned_to, ->(user) { where( assigned_to: user.id ) }
|
51
52
|
|
52
53
|
# Tasks assigned by the user to others. That's what we see on Tasks/Assigned.
|
53
54
|
scope :assigned_by, ->(user) {
|
@@ -62,8 +63,8 @@ class Task < ActiveRecord::Base
|
|
62
63
|
where('user_id = ? OR assigned_to = ?', user.id, user.id)
|
63
64
|
}
|
64
65
|
|
66
|
+
# Show opportunities which either belong to the user and are unassigned, or are assigned to the user
|
65
67
|
scope :visible_on_dashboard, ->(user) {
|
66
|
-
# Show opportunities which either belong to the user and are unassigned, or are assigned to the user
|
67
68
|
where('(user_id = :user_id AND assigned_to IS NULL) OR assigned_to = :user_id', :user_id => user.id).where('completed_at IS NULL')
|
68
69
|
}
|
69
70
|
|
@@ -171,6 +172,7 @@ class Task < ActiveRecord::Base
|
|
171
172
|
# Returns list of tasks grouping them by due date as required by tasks/index.
|
172
173
|
#----------------------------------------------------------------------------
|
173
174
|
def self.find_all_grouped(user, view)
|
175
|
+
return {} unless ALLOWED_VIEWS.include?(view)
|
174
176
|
settings = (view == "completed" ? Setting.task_completed : Setting.task_bucket)
|
175
177
|
Hash[
|
176
178
|
settings.map do |key, value|
|
@@ -182,7 +184,7 @@ class Task < ActiveRecord::Base
|
|
182
184
|
# Returns bucket if it's empty (i.e. we have to hide it), nil otherwise.
|
183
185
|
#----------------------------------------------------------------------------
|
184
186
|
def self.bucket_empty?(bucket, user, view = "pending")
|
185
|
-
return false if bucket.blank?
|
187
|
+
return false if bucket.blank? or !ALLOWED_VIEWS.include?(view)
|
186
188
|
if view == "assigned"
|
187
189
|
assigned_by(user).send(bucket).pending.count
|
188
190
|
else
|
@@ -193,6 +195,7 @@ class Task < ActiveRecord::Base
|
|
193
195
|
# Returns task totals for each of the views as needed by tasks sidebar.
|
194
196
|
#----------------------------------------------------------------------------
|
195
197
|
def self.totals(user, view = "pending")
|
198
|
+
return {} unless ALLOWED_VIEWS.include?(view)
|
196
199
|
settings = (view == "completed" ? Setting.task_completed : Setting.task_bucket)
|
197
200
|
settings.inject({ :all => 0 }) do |hash, key|
|
198
201
|
hash[key] = (view == "assigned" ? assigned_by(user).send(key).pending.count : my(user).send(key).send(view).count)
|
data/app/models/setting.rb
CHANGED
@@ -71,7 +71,6 @@ class Setting < ActiveRecord::Base
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
|
75
74
|
# Set setting value
|
76
75
|
#-------------------------------------------------------------------
|
77
76
|
def []=(name, value)
|
@@ -82,7 +81,6 @@ class Setting < ActiveRecord::Base
|
|
82
81
|
cache[name] = value
|
83
82
|
end
|
84
83
|
|
85
|
-
|
86
84
|
# Unrolls [ :one, :two ] settings array into [[ "One", :one ], [ "Two", :two ]]
|
87
85
|
# picking symbol translations from locale. If setting is not a symbol but
|
88
86
|
# string it gets copied without translation.
|
@@ -98,7 +96,6 @@ class Setting < ActiveRecord::Base
|
|
98
96
|
table_exists? rescue false
|
99
97
|
end
|
100
98
|
|
101
|
-
|
102
99
|
# Loads settings from YAML files
|
103
100
|
def load_settings_from_yaml(file)
|
104
101
|
settings = YAML.load_file(file)
|
data/app/models/users/ability.rb
CHANGED
@@ -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
|
-
|
16
|
-
can :
|
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
|
data/app/models/users/user.rb
CHANGED
@@ -61,7 +61,6 @@ class User < ActiveRecord::Base
|
|
61
61
|
|
62
62
|
has_paper_trail :ignore => [:last_request_at, :perishable_token]
|
63
63
|
|
64
|
-
# For some reason this does not play nice with has_paper_trail when set as default scope
|
65
64
|
scope :by_id, -> { order('id DESC') }
|
66
65
|
scope :except, ->(user) { where('id != ?', user.id).by_name }
|
67
66
|
scope :by_name, -> { order('first_name, last_name, email') }
|
@@ -188,6 +187,10 @@ class User < ActiveRecord::Base
|
|
188
187
|
Ability.new(User.current_user)
|
189
188
|
end
|
190
189
|
|
190
|
+
def can_signup?
|
191
|
+
[ :allowed, :needs_approval ].include? Setting.user_signup
|
192
|
+
end
|
193
|
+
|
191
194
|
end
|
192
195
|
|
193
196
|
ActiveSupport.run_load_hooks(:fat_free_crm_user, self)
|
@@ -44,7 +44,3 @@
|
|
44
44
|
|
45
45
|
|
46
46
|
#export= render "shared/export"
|
47
|
-
/
|
48
|
-
Check out HTML source to view the output of the hook if you have sample plugin installed
|
49
|
-
http://github.com/michaeldv/crm_sample_plugin/tree/master
|
50
|
-
= hook(:home_view, self, :hello => "world!", :welcome => "home")
|
@@ -21,13 +21,15 @@
|
|
21
21
|
|
22
22
|
:javascript
|
23
23
|
crm.language = "#{I18n.locale}"
|
24
|
-
#{yield :javascript}
|
25
|
-
var _ffcrm_users = [
|
26
|
-
#{User.all.map{|u| "\"#{u.full_name} (@#{u.username})\"" }.join(",\n")}
|
27
|
-
];
|
28
|
-
|
29
24
|
window.controller = "#{controller.controller_name}"
|
30
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
|
+
|
31
33
|
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
|
32
34
|
<link rel="icon" href="/favicon.ico" type="image/x-icon">
|
33
35
|
|
@@ -8,8 +8,8 @@
|
|
8
8
|
- else
|
9
9
|
- @personal_lists.sort.each_with_index do |list, i|
|
10
10
|
%li[list]{ :class => i < @personal_lists.size - 1 ? "" : "last" }
|
11
|
-
%dt= link_to(truncate(list.name, :length => 25), list.url, :title => list.name)
|
12
|
-
%tt
|
11
|
+
%dt= link_to(truncate(list.name, :length => 25), h(list.url), :title => list.name)
|
12
|
+
%tt
|
13
13
|
= link_to(url_for(list), :method => :delete, :confirm => 'Are you sure?', :remote => true, :class => "list_icon delete_on_hover") do
|
14
14
|
%i.fa{:"data-controller" => list.controller, class: get_icon(list.controller)}
|
15
15
|
|
@@ -8,8 +8,8 @@
|
|
8
8
|
- else
|
9
9
|
- @global_lists.sort.each_with_index do |list, i|
|
10
10
|
%li[list]{ :class => i < @global_lists.size - 1 ? "" : "last" }
|
11
|
-
%dt= link_to(truncate(list.name, :length => 25), list.url, :title => list.name)
|
12
|
-
%tt
|
11
|
+
%dt= link_to(truncate(list.name, :length => 25), h(list.url), :title => list.name)
|
12
|
+
%tt
|
13
13
|
= link_to(url_for(list), :method => :delete, :confirm => 'Are you sure?', :remote => true, :class => "list_icon delete_on_hover") do
|
14
14
|
%i.fa{:"data-controller" => list.controller, class: get_icon(list.controller)}
|
15
15
|
|
data/config/application.rb
CHANGED
@@ -28,7 +28,7 @@ module FatFreeCRM
|
|
28
28
|
config.autoload_paths += Dir[Rails.root.join("app/models/**")] +
|
29
29
|
Dir[Rails.root.join("app/controllers/entities")]
|
30
30
|
|
31
|
-
# Prevent Field class from being
|
31
|
+
# Prevent Field class from being reloaded more than once as this clears registered customfields
|
32
32
|
config.autoload_once_paths += [File.expand_path("../app/models/fields/field.rb", __FILE__)]
|
33
33
|
|
34
34
|
# Activate observers that should always be running.
|
@@ -62,7 +62,7 @@ module FatFreeCRM
|
|
62
62
|
config.encoding = "utf-8"
|
63
63
|
|
64
64
|
# Configure sensitive parameters which will be filtered from the log file.
|
65
|
-
config.filter_parameters += [:password]
|
65
|
+
config.filter_parameters += [:password, :password_hash, :password_salt, :password_confirmation]
|
66
66
|
|
67
67
|
# Use SQL instead of Active Record's schema dumper when creating the database.
|
68
68
|
# This is necessary if your schema can't be completely dumped by the schema dumper,
|
@@ -19,6 +19,8 @@ if defined?(FatFreeCRM::Application)
|
|
19
19
|
config.consider_all_requests_local = true
|
20
20
|
config.action_controller.perform_caching = false
|
21
21
|
|
22
|
+
config.action_mailer.delivery_method = :file
|
23
|
+
|
22
24
|
# Don't care if the mailer can't send
|
23
25
|
config.action_mailer.raise_delivery_errors = true
|
24
26
|
|
@@ -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
|
14
|
-
config.consider_all_requests_local =
|
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
|
-
|
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
|