caboose-cms 0.6.16 → 0.6.17

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.
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Nestable
3
+ */
4
+
5
+ .dd { position: relative; display: block; margin: 0; padding: 0; max-width: 600px; list-style: none; font-size: 13px; line-height: 20px; }
6
+
7
+ .dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; }
8
+ .dd-list .dd-list { padding-left: 10px; }
9
+ .dd-collapsed .dd-list { display: none; }
10
+
11
+ .dd-item,
12
+ .dd-empty,
13
+ .dd-placeholder { display: block; position: relative; margin: 0; padding: 0; min-height: 20px; font-size: 13px; line-height: 20px; }
14
+
15
+ .dd-handle { display: block; height: 30px; margin: 2px 0; padding: 5px 10px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc;
16
+ background: #fafafa;
17
+ background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
18
+ background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
19
+ background: linear-gradient(top, #fafafa 0%, #eee 100%);
20
+ -webkit-border-radius: 3px;
21
+ border-radius: 3px;
22
+ box-sizing: border-box; -moz-box-sizing: border-box;
23
+ }
24
+ .dd-handle:hover { color: #2ea8e5; background: #fff; }
25
+
26
+ .dd-item > button { display: block; position: relative; cursor: pointer; float: left; width: 25px; height: 20px; margin: 5px 0; padding: 0; text-indent: 100%; white-space: nowrap; overflow: hidden; border: 0; background: transparent; font-size: 12px; line-height: 1; text-align: center; font-weight: bold; }
27
+ .dd-item > button:before { content: '+'; display: block; position: absolute; width: 100%; text-align: center; text-indent: 0; }
28
+ .dd-item > button[data-action="collapse"]:before { content: '-'; }
29
+
30
+ .dd-placeholder,
31
+ .dd-empty { margin: 5px 0; padding: 0; min-height: 30px; background: #f2fbff; border: 1px dashed #b6bcbf; box-sizing: border-box; -moz-box-sizing: border-box; }
32
+ .dd-empty { border: 1px dashed #bbb; min-height: 100px; background-color: #e5e5e5;
33
+ background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
34
+ background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
35
+ background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
36
+ background-size: 60px 60px;
37
+ background-position: 0 0, 30px 30px;
38
+ }
39
+
40
+ .dd-dragel { position: absolute; pointer-events: none; z-index: 9999; }
41
+ .dd-dragel > .dd-item .dd-handle { margin-top: 0; }
42
+ .dd-dragel .dd-handle {
43
+ -webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);
44
+ box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);
45
+ }
46
+
47
+ /**
48
+ * Nestable Extras
49
+ */
50
+
51
+ .nestable-lists { display: block; clear: both; padding: 30px 0; width: 100%; border: 0; border-top: 2px solid #ddd; border-bottom: 2px solid #ddd; }
52
+
53
+ #categories-menu { padding: 0; margin: 20px 0; }
54
+
55
+ #categories-output,
56
+ #categories2-output { width: 100%; height: 7em; font-size: 0.75em; line-height: 1.333333em; font-family: Consolas, monospace; padding: 5px; box-sizing: border-box; -moz-box-sizing: border-box; }
57
+
58
+ #categories2 .dd-handle {
59
+ color: #fff;
60
+ border: 1px solid #999;
61
+ background: #bbb;
62
+ background: -webkit-linear-gradient(top, #bbb 0%, #999 100%);
63
+ background: -moz-linear-gradient(top, #bbb 0%, #999 100%);
64
+ background: linear-gradient(top, #bbb 0%, #999 100%);
65
+ }
66
+ #categories2 .dd-handle:hover { background: #bbb; }
67
+ #categories2 .dd-item > button:before { color: #fff; }
68
+
69
+ @media only screen and (min-width: 700px) {
70
+
71
+ .dd { float: left; width: 48%; }
72
+ .dd + .dd { margin-left: 2%; }
73
+
74
+ }
75
+
76
+ .dd-hover > .dd-handle { background: #2ea8e5 !important; }
77
+
78
+ /**
79
+ * Nestable Draggable Handles
80
+ */
81
+
82
+ .dd3-content { display: block; height: 30px; margin: 5px 0; padding: 5px 10px 5px 40px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc;
83
+ background: #fafafa;
84
+ background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
85
+ background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
86
+ background: linear-gradient(top, #fafafa 0%, #eee 100%);
87
+ -webkit-border-radius: 3px;
88
+ border-radius: 3px;
89
+ box-sizing: border-box; -moz-box-sizing: border-box;
90
+ }
91
+ .dd3-content:hover { color: #2ea8e5; background: #fff; }
92
+
93
+ .dd-dragel > .dd3-item > .dd3-content { margin: 0; }
94
+
95
+ .dd3-item > button { margin-left: 30px; }
96
+
97
+ .dd3-handle { position: absolute; margin: 0; left: 0; top: 0; cursor: pointer; width: 30px; text-indent: 100%; white-space: nowrap; overflow: hidden;
98
+ border: 1px solid #aaa;
99
+ background: #ddd;
100
+ background: -webkit-linear-gradient(top, #ddd 0%, #bbb 100%);
101
+ background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%);
102
+ background: linear-gradient(top, #ddd 0%, #bbb 100%);
103
+ border-top-right-radius: 0;
104
+ border-bottom-right-radius: 0;
105
+ }
106
+ .dd3-handle:before { content: '≡'; display: block; position: absolute; left: 0; top: 3px; width: 100%; text-align: center; text-indent: 0; color: #fff; font-size: 20px; font-weight: normal; }
107
+ .dd3-handle:hover { background: #ddd; }
@@ -31,7 +31,7 @@ module Caboose
31
31
  else
32
32
  bouncer_class = Caboose::authenticator_class.constantize
33
33
  bouncer = bouncer_class.new
34
- login_resp = bouncer.authenticate(username, password, @site)
34
+ login_resp = bouncer.authenticate(username, password, @site, request)
35
35
 
36
36
  if login_resp.error
37
37
  resp.error = login_resp.error
@@ -0,0 +1,34 @@
1
+
2
+ module Caboose
3
+ class LoginLogsController < ApplicationController
4
+ layout 'caboose/admin'
5
+
6
+ def before_action
7
+ @page = Page.page_with_uri(request.host_with_port, '/admin')
8
+ end
9
+
10
+ # GET /admin/login-logs
11
+ def index
12
+ return if !user_is_allowed('users', 'view')
13
+
14
+ @gen = PageBarGenerator.new(params, {
15
+ 'site_id' => @site.id,
16
+ 'username_like' => '',
17
+ 'user_id' => '',
18
+ 'date_attempted_lte' => '',
19
+ 'date_attempted_gte' => '',
20
+ 'ip_like' => '',
21
+ 'success' => ''
22
+ },{
23
+ 'model' => 'Caboose::LoginLog',
24
+ 'sort' => 'date_attempted',
25
+ 'desc' => false,
26
+ 'base_url' => '/admin/login-logs',
27
+ 'use_url_params' => false
28
+ })
29
+ @logs = @gen.items
30
+ end
31
+
32
+ end
33
+ end
34
+
@@ -16,7 +16,7 @@ module Caboose
16
16
  tree = Caboose::MediaCategory.flat_tree(@site.id, prefix)
17
17
  render :json => tree
18
18
  end
19
-
19
+
20
20
  # GET /admin/media-categories/options
21
21
  def admin_options
22
22
  return unless user_is_allowed('mediacategories', 'view')
@@ -25,6 +25,12 @@ module Caboose
25
25
  options = tree.collect{ |mc| { 'value' => mc[:id], 'text' => mc[:name] }}
26
26
  render :json => options
27
27
  end
28
+
29
+ # GET /admin/media-categories/tree
30
+ def admin_tree
31
+ return unless user_is_allowed('mediacategories', 'view')
32
+ render :json => Caboose::MediaCategory.tree_hash(@site.id)
33
+ end
28
34
 
29
35
  # POST /admin/media-categories
30
36
  def admin_add
@@ -35,6 +35,7 @@ module Caboose
35
35
  when 'google_plus_url' then sc.google_plus_url = value
36
36
  when 'linkedin_url' then sc.linkedin_url = value
37
37
  when 'google_analytics_id' then sc.google_analytics_id = value
38
+ when 'google_analytics_id2' then sc.google_analytics_id2 = value
38
39
  when 'auto_ga_js' then sc.auto_ga_js = value
39
40
  end
40
41
  end
@@ -179,7 +179,8 @@ module Caboose
179
179
  when 'zip' then user.zip = value
180
180
  when 'phone' then user.phone = value
181
181
  when 'fax' then user.fax = value
182
- when 'utc_offset' then user.utc_offset = value.to_f
182
+ when 'utc_offset' then user.utc_offset = value.to_f
183
+ when 'locked' then user.locked = value
183
184
  when "password"
184
185
  confirm = params[:password2]
185
186
  if (value != confirm)
@@ -4,6 +4,11 @@ module Caboose
4
4
  def forgot_password_email(user)
5
5
  @user = user
6
6
  mail(:to => user.email, :subject => "#{Caboose::website_name} Forgot Password")
7
+ end
8
+
9
+ def locked_account(user)
10
+ @user = user
11
+ mail(:to => user.email, :subject => "#{Caboose::website_name} Locked Account")
7
12
  end
8
13
 
9
14
  end
@@ -1,40 +1,62 @@
1
1
 
2
- class Caboose::Authenticator
2
+ module Caboose
3
+ class Authenticator
3
4
 
4
- def authenticate(username, password, site = nil)
5
- resp = Caboose::StdClass.new(
6
- 'error' => nil,
7
- 'user' => nil
8
- )
9
- pass = Digest::SHA1.hexdigest(Caboose::salt + password)
10
-
11
- user = Caboose::User.where(:username => username, :site_id => site.id).first
12
- user = Caboose::User.where(:email => username, :site_id => site.id).first if user.nil?
13
-
14
- valid_credentials = false
15
- if user && user.password == pass
16
- valid_credentials = true
17
- elsif site
18
- mp = Caboose::Setting.where(:site_id => site.id, :name => 'master_password').first
19
- mp = mp ? mp.value : nil
20
- if mp && mp.strip.length > 0 && mp == pass
5
+ def authenticate(username, password, site = nil, request = nil)
6
+ resp = StdClass.new
7
+ pass = Digest::SHA1.hexdigest(Caboose::salt + password)
8
+
9
+ user = User.where(:username => username, :site_id => site.id).first
10
+ user = User.where(:email => username, :site_id => site.id).first if user.nil?
11
+
12
+ ll = LoginLog.new
13
+ ll.username = username
14
+ ll.date_attempted = DateTime.now.utc
15
+ ll.user_id = user.id if user
16
+ ll.site_id = user.site_id if user
17
+ ll.ip = request.remote_ip if request
18
+
19
+ valid_credentials = false
20
+ if user && user.password == pass
21
21
  valid_credentials = true
22
+ resp.user = user
23
+ ll.success = true
24
+
25
+ elsif user && user.password != pass
26
+
27
+ fail_count = Caboose::LoginLog.fail_count(user)
28
+ if (fail_count+1) >= user.site.login_fail_lock_count
29
+ user.locked = true
30
+ user.save
31
+ LoginMailer.locked_account(user).deliver
32
+ resp.error = "Too many failed login attempts. Your account has been locked and the site administrator has been notified."
33
+ ll.success = false
34
+ else
35
+ attempts_left = user.site.login_fail_lock_count - fail_count - 1
36
+ resp.error = "Invalid password. You have #{attempts_left} attempt#{attempts_left == 1 ? '' : 's'} left before your account is locked."
37
+ ll.success = false
38
+ end
39
+
40
+ elsif site
41
+
42
+ mp = Setting.where(:site_id => site.id, :name => 'master_password').first
43
+ mp = mp ? mp.value : nil
44
+ if mp && mp.strip.length > 0 && mp == pass
45
+ resp.user = user
46
+ ll.success = true
47
+ else
48
+ resp.error = "Invalid credentials"
49
+ ll.success = false
50
+ end
51
+
52
+ else
53
+ resp.error = "Invalid credentials"
54
+ ll.success = false
22
55
  end
56
+
57
+ ll.save
58
+ return resp
23
59
  end
24
60
 
25
- if valid_credentials
26
- resp.user = user
27
- else
28
- resp.error = "Invalid credentials"
29
- end
30
-
31
- #resp.user = Caboose::User.where(:username => username, :password => pass).first
32
- #if (resp.user.nil?)
33
- # resp.user = Caboose::User.where(:email => username, :password => pass).first
34
- #end
35
- #resp.error = "Invalid credentials" if resp.user.nil?
36
-
37
- return resp
38
61
  end
39
-
40
62
  end
@@ -0,0 +1,22 @@
1
+
2
+ class Caboose::LoginLog < ActiveRecord::Base
3
+ self.table_name = "login_logs"
4
+
5
+ belongs_to :site, :class_name => 'Caboose::Site'
6
+ belongs_to :user, :class_name => 'Caboose::User'
7
+
8
+ attr_accessible :id,
9
+ :site_id ,
10
+ :username ,
11
+ :user_id ,
12
+ :date_attempted ,
13
+ :ip ,
14
+ :success
15
+
16
+ def self.fail_count(user)
17
+ last_successful_login = Caboose::LoginLog.where(:user_id => user.id, :success => true).reorder("date_attempted desc").first
18
+ id = last_successful_login ? last_successful_login.id : 1
19
+ return Caboose::LoginLog.where("user_id = ? and success = ? and id > ?", user.id, false, id).count
20
+ end
21
+
22
+ end
@@ -50,6 +50,20 @@ class Caboose::MediaCategory < ActiveRecord::Base
50
50
  return arr
51
51
  end
52
52
 
53
+ def self.tree_hash(site_id)
54
+ top_cat = self.where(:parent_id => nil, :site_id => site_id).first
55
+ return self.tree_hash_helper(top_cat)
56
+ end
57
+
58
+ def self.tree_hash_helper(cat)
59
+ return {
60
+ :id => cat.id,
61
+ :name => cat.name,
62
+ :media_count => cat.media.count,
63
+ :children => cat.children.collect{ |kid| self.tree_hash_helper(kid) }
64
+ }
65
+ end
66
+
53
67
  def is_ancestor_of?(cat)
54
68
  if cat.is_a?(Integer) || cat.is_a?(String)
55
69
  cat_id = cat.to_i
@@ -325,6 +325,14 @@ class Caboose::Schema < Caboose::Utilities::Schema
325
325
  [ :modification_value_id , :integer ],
326
326
  [ :input , :string ]
327
327
  ],
328
+ Caboose::LoginLog => [
329
+ [ :site_id , :integer ],
330
+ [ :username , :string ],
331
+ [ :user_id , :integer ],
332
+ [ :date_attempted , :datetime ],
333
+ [ :ip , :string ],
334
+ [ :success , :boolean , { :default => false }]
335
+ ],
328
336
  Caboose::MediaCategory => [
329
337
  [ :parent_id , :integer ],
330
338
  [ :site_id , :integer ],
@@ -620,11 +628,12 @@ class Caboose::Schema < Caboose::Utilities::Schema
620
628
  [ :use_fonts , :boolean , { :default => true }],
621
629
  [ :logo , :attachment ],
622
630
  [ :is_master , :boolean , { :default => false }],
623
- [ :analytics_id , :string ],
631
+ [ :analytics_id , :string ],
624
632
  [ :use_retargeting , :boolean , { :default => false }],
625
633
  [ :date_js_updated , :datetime ],
626
634
  [ :date_css_updated , :datetime ],
627
- [ :default_layout_id , :integer ]
635
+ [ :default_layout_id , :integer ],
636
+ [ :login_fail_lock_count , :integer , { :default => 5 }]
628
637
  ],
629
638
  Caboose::SiteMembership => [
630
639
  [ :site_id , :integer ],
@@ -653,6 +662,7 @@ class Caboose::Schema < Caboose::Utilities::Schema
653
662
  [ :google_plus_url , :string ],
654
663
  [ :linkedin_url , :string ],
655
664
  [ :google_analytics_id , :string ],
665
+ [ :google_analytics_id2 , :string ],
656
666
  [ :auto_ga_js , :boolean , { :default => false }]
657
667
  ],
658
668
  Caboose::StackableGroup => [
@@ -724,16 +734,17 @@ class Caboose::Schema < Caboose::Utilities::Schema
724
734
  [ :zip , :string ],
725
735
  [ :phone , :string ],
726
736
  [ :fax , :string ],
727
- [ :timezone , :string , { :default => 'Central Time (US & Canada)' }],
737
+ [ :timezone , :string , { :default => 'Central Time (US & Canada)' }],
728
738
  [ :password , :string ],
729
739
  [ :password_reset_id , :string ],
730
740
  [ :password_reset_sent , :datetime ],
731
741
  [ :token , :string ],
732
742
  [ :date_created , :datetime ],
733
743
  [ :image , :attachment ],
734
- [ :is_guest , :boolean , { :default => false }],
744
+ [ :is_guest , :boolean , { :default => false }],
735
745
  [ :customer_profile_id , :string ],
736
- [ :payment_profile_id , :string ]
746
+ [ :payment_profile_id , :string ],
747
+ [ :locked , :boolean , { :default => false }]
737
748
  ],
738
749
  Caboose::Variant => [
739
750
  [ :product_id , :integer ],
@@ -745,21 +756,21 @@ class Caboose::Schema < Caboose::Utilities::Schema
745
756
  [ :date_sale_starts , :datetime ],
746
757
  [ :date_sale_ends , :datetime ],
747
758
  [ :date_sale_end , :datetime ],
748
- [ :available , :boolean ],
749
- [ :quantity_in_stock , :integer , :default => 0 ],
750
- [ :ignore_quantity , :boolean ],
751
- [ :allow_backorder , :boolean ],
759
+ [ :available , :boolean , { :default => true }],
760
+ [ :quantity_in_stock , :integer , { :default => 0 }],
761
+ [ :ignore_quantity , :boolean , { :default => false }],
762
+ [ :allow_backorder , :boolean , { :default => false }],
752
763
  [ :weight , :decimal ],
753
764
  [ :length , :decimal ],
754
765
  [ :width , :decimal ],
755
766
  [ :height , :decimal ],
756
767
  [ :volume , :decimal ],
757
- [ :cylinder , :boolean ],
768
+ [ :cylinder , :boolean , { :default => false }],
758
769
  [ :option1 , :string ],
759
770
  [ :option2 , :string ],
760
771
  [ :option3 , :string ],
761
- [ :requires_shipping , :boolean ],
762
- [ :taxable , :boolean ],
772
+ [ :requires_shipping , :boolean , { :default => true }],
773
+ [ :taxable , :boolean , { :default => true }],
763
774
  [ :shipping_unit_value , :numeric ],
764
775
  [ :flat_rate_shipping , :boolean , { :default => false }],
765
776
  [ :flat_rate_shipping_package_id , :integer ],
@@ -796,6 +807,8 @@ class Caboose::Schema < Caboose::Utilities::Schema
796
807
  # end
797
808
  # c.remove_column(:pages, :content)
798
809
  #end
810
+
811
+ #c.change_column :store_variants, :taxable, :boolean
799
812
 
800
813
  admin_user = nil
801
814
  if !Caboose::User.exists?(:username => 'admin')
@@ -23,5 +23,23 @@ if sc.auto_ga_js && sc.google_analytics_id
23
23
  ga('send', 'event'<% arr2.each do |x| %>, <%= raw Caboose.json(x) %><% end %>);
24
24
  <% end %>
25
25
  <% end %>
26
+ <% if sc.google_analytics_id2 && sc.google_analytics_id2.strip.length > 0 %>
27
+ ga('create', '<%= raw sc.google_analytics_id2 %>', 'auto', {'name': 'property2'});
28
+ ga('property2.send', 'pageview');
29
+ <% if ga_events && ga_events.count > 0 %>
30
+ <% ga_events.each do |arr| %>
31
+ <%
32
+ cat = arr[0] ? arr[0] : nil
33
+ action = arr[1] ? arr[1] : nil
34
+ label = arr[2] ? arr[2] : nil
35
+ value = arr[3] ? arr[3] : nil
36
+ arr2 = [cat, action]
37
+ arr2 << (label ? label : '') if label || (label.nil? && value)
38
+ arr2 << value if value
39
+ %>
40
+ ga('property2.send', 'event'<% arr2.each do |x| %>, <%= raw Caboose.json(x) %><% end %>);
41
+ <% end %>
42
+ <% end %>
43
+ <% end %>
26
44
  </script>
27
45
  <% end %>