caboose-cms 0.8.67 → 0.8.68

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 650fd50d2cc40e1d916e15ed23930f3cff2427d6
4
- data.tar.gz: 0cb4538479b27adf6d72fd3dcf640afdac72d071
3
+ metadata.gz: f3be7648fb20dea0f63181aa3fc29816743639b3
4
+ data.tar.gz: 378b44904c3a735619e44c5a150ed12ff50e4c4b
5
5
  SHA512:
6
- metadata.gz: 5f745259efc0b4cfd3e37cce5ccfcf73903497a0f5c2c0f8ddc1798072425f41f34bd71684f94d7e2d32c2473d06e4f3e2324a9b03b19a5507f578788db9c91b
7
- data.tar.gz: f0c6a9d6ef387930ea19b0dc393de4da1246fc386ca666a2d9d204d52dea90ffa1309b85c0cf11f39a6fabdf2edfc736bbcef9c919352a5cc847bf59a6679245
6
+ metadata.gz: f7e3584b65a103265aeeee1d52353053dd3d5277d552b3bc9e16a63be3e5ec03c4be2338c6d2db8787a71d246b8c8f9555784b4cb1e8390ec522518dd02b6933
7
+ data.tar.gz: 03a0db1c20df423d62d674fd7c3d16f49ecff43d14b55f9267850be35c2dd91ee3f067ff1447eef5f5c99616b7438b13c7dabb3627ed264ab4d1e35ba2bf51af
@@ -296,9 +296,12 @@ InvoiceController.prototype = {
296
296
  requires_shipping ? that.noneditable_shipping_address() : "This invoice doesn't require shipping."
297
297
  ));
298
298
  }
299
- //.append($('<td/>').attr('valign', 'top').attr('id', 'billing_address' ).append(that.noneditable_billing_address()))
299
+ //.append($('<td/>').attr('valign', 'top').attr('id', 'billing_address' ).append(that.noneditable_billing_address()))
300
+
301
+ var c = that.invoice.customer;
300
302
  tr.append($('<td/>').attr('valign', 'top').append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_status')))
301
303
  .append($('<td/>').attr('valign', 'top')
304
+ .append($('<div/>').append(c && c.card_last4 ? "Card on file: " + c.card_brand + " ending in " + c.card_last4 : "No card on file."))
302
305
  .append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_payment_terms'))
303
306
  .append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_payment_terms'))
304
307
  .append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_financial_status'))
@@ -764,7 +767,12 @@ InvoiceController.prototype = {
764
767
  var p = $('<p/>');
765
768
  p.append($('<input/>').attr('type', 'button').val('< Back').click(function() { window.location = '/admin/invoices'; })).append(' ');
766
769
  if (that.invoice.total > 0 && that.invoice.financial_status == 'pending')
767
- p.append($('<input/>').attr('type', 'button').val('Send for Payment').click(function() { that.send_for_authorization(); })).append(' ');
770
+ {
771
+ if (that.invoice.customer.card_last4)
772
+ p.append($('<input/>').attr('type', 'button').val('Charge Card on File').click(function() { that.authorize_and_capture(); })).append(' ');
773
+ else
774
+ p.append($('<input/>').attr('type', 'button').val('Send for Payment').click(function() { that.send_for_authorization(); })).append(' ');
775
+ }
768
776
  if (that.invoice.total > 0 && (that.invoice.financial_status == 'captured' || that.invoice.financial_status == 'paid by check' || that.invoice.financial_status == 'paid by other means'))
769
777
  p.append($('<input/>').attr('type', 'button').val('Send Receipt to Customer' ).click(function() { that.send_receipt(); })).append(' ');
770
778
  p.append($('<input/>').attr('type', 'button').val('Add Item' ).click(function() { that.add_variant(); })).append(' ');
@@ -1032,6 +1040,30 @@ InvoiceController.prototype = {
1032
1040
  });
1033
1041
  },
1034
1042
 
1043
+ authorize_and_capture: function(confirm)
1044
+ {
1045
+ var that = this;
1046
+ if (!confirm)
1047
+ {
1048
+ var c = that.invoice.customer;
1049
+ var p = $('<p/>').addClass('note confirm')
1050
+ .append("Are you sure you want to authorize and capture $" + curr(that.invoice.total) + " to customer's " + c.card_brand + " ending in " + c.card_last4 + "?<br/><br/>")
1051
+ .append($('<input/>').attr('type','button').val('Yes').click(function() { that.authorize_and_capture(true); }))
1052
+ .append(' ')
1053
+ .append($('<input/>').attr('type','button').val('No').click(function() { $('#message').empty(); }));
1054
+ $('#message').empty().append(p);
1055
+ return;
1056
+ }
1057
+ $('#message').html("<p class='loading'>Charging card on file...</p>");
1058
+ $.ajax({
1059
+ url: '/admin/invoices/' + that.invoice.id + '/authorize-and-capture',
1060
+ success: function(resp) {
1061
+ if (resp.error) { that.flash_error(resp.error); }
1062
+ if (resp.success) { that.refresh(function() { that.flash_success("The customer's card on file has been charged successfuly."); }); }
1063
+ }
1064
+ });
1065
+ },
1066
+
1035
1067
  send_receipt: function(confirm)
1036
1068
  {
1037
1069
  var that = this;
@@ -10,6 +10,8 @@ StripePaymentMethodController.prototype = {
10
10
  card_last4: false,
11
11
  card_name: false,
12
12
  card_zip: false,
13
+ refresh_url: '/checkout/stripe/json',
14
+ after_update_url: '/checkout/stripe-details',
13
15
 
14
16
  init: function(params)
15
17
  {
@@ -22,7 +24,7 @@ StripePaymentMethodController.prototype = {
22
24
  {
23
25
  var that = this;
24
26
  $.ajax({
25
- url: '/checkout/stripe/json',
27
+ url: that.refresh_url,
26
28
  type: 'get',
27
29
  success: function(resp) {
28
30
  that.stripe_key = resp.stripe_key;
@@ -143,7 +145,7 @@ StripePaymentMethodController.prototype = {
143
145
  that.card_brand = resp.card.brand;
144
146
  that.card_last4 = resp.card.last4;
145
147
  $.ajax({
146
- url: '/checkout/stripe-details',
148
+ url: that.after_update_url,
147
149
  type: 'put',
148
150
  data: { token: resp.id, card: resp.card },
149
151
  success: function(resp2) {
@@ -140,18 +140,11 @@ module Caboose
140
140
  end
141
141
 
142
142
  if c.nil?
143
- begin
144
- c = Stripe::Customer.create(
145
- :source => params[:token],
146
- :email => u.email,
147
- :metadata => { :user_id => u.id }
148
- )
149
- rescue Stripe::CardError => e
150
- render :json => {
151
- :error => e.message
152
- }
153
- return
154
- end
143
+ c = Stripe::Customer.create(
144
+ :source => params[:token],
145
+ :email => u.email,
146
+ :metadata => { :user_id => u.id }
147
+ )
155
148
  end
156
149
 
157
150
  u.stripe_customer_id = c.id
@@ -217,7 +210,7 @@ module Caboose
217
210
  :amount => c.amount/100.0,
218
211
  :date_processed => DateTime.now.utc,
219
212
  :success => c.status == 'succeeded'
220
- )
213
+ )
221
214
  end
222
215
 
223
216
  if !ot.success
@@ -113,6 +113,26 @@ module Caboose
113
113
  render :json => resp
114
114
  end
115
115
 
116
+ # @route GET /admin/invoices/:id/authorize-and-capture
117
+ def admin_authorize_and_capture
118
+ return if !user_is_allowed('invoices', 'edit')
119
+
120
+ invoice = Invoice.find(params[:id])
121
+ resp = invoice.authorize_and_capture
122
+
123
+ # Send out emails
124
+ #begin
125
+ # InvoicesMailer.configure_for_site(@site.id).customer_new_invoice(@invoice).deliver
126
+ # InvoicesMailer.configure_for_site(@site.id).fulfillment_new_invoice(@invoice).deliver
127
+ #rescue
128
+ # puts "=================================================================="
129
+ # puts "Error sending out invoice confirmation emails for invoice ID #{@invoice.id}"
130
+ # puts "=================================================================="
131
+ #end
132
+
133
+ render :json => resp
134
+ end
135
+
116
136
  # @route GET /admin/invoices/:id/void
117
137
  def admin_void
118
138
  return if !user_is_allowed('invoices', 'edit')
@@ -54,6 +54,21 @@ module Caboose
54
54
  render :json => u.as_json(:include => :roles)
55
55
  end
56
56
 
57
+ # @route GET /admin/users/:id/stripe/json
58
+ def admin_stripe_json_single
59
+ return if !user_is_allowed('users', 'view')
60
+ sc = @site.store_config
61
+ u = User.find(params[:id])
62
+ render :json => {
63
+ :stripe_key => sc.stripe_publishable_key.strip,
64
+ :customer_id => u.stripe_customer_id,
65
+ :card_last4 => u.card_last4,
66
+ :card_brand => u.card_brand,
67
+ :card_exp_month => u.card_exp_month,
68
+ :card_exp_year => u.card_exp_year
69
+ }
70
+ end
71
+
57
72
  # @route GET /admin/users/new
58
73
  def admin_new
59
74
  return if !user_is_allowed('users', 'add')
@@ -73,7 +88,21 @@ module Caboose
73
88
  @roles = Role.roles_with_user(@edituser.id)
74
89
  end
75
90
 
76
- # @route GET /admin/users/:id/edit-password
91
+ # @route GET /admin/users/:id/roles
92
+ def admin_edit_roles
93
+ return if !user_is_allowed('users', 'edit')
94
+ @edituser = User.find(params[:id])
95
+ @all_roles = Role.tree(@site.id)
96
+ @roles = Role.roles_with_user(@edituser.id)
97
+ end
98
+
99
+ # @route GET /admin/users/:id/payment-method
100
+ def admin_edit_payment_method
101
+ return if !user_is_allowed('users', 'edit')
102
+ @edituser = User.find(params[:id])
103
+ end
104
+
105
+ # @route GET /admin/users/:id/password
77
106
  def admin_edit_password
78
107
  return if !user_is_allowed('users', 'edit')
79
108
  @edituser = User.find(params[:id])
@@ -83,6 +112,12 @@ module Caboose
83
112
  o = [('a'..'z'),('A'..'Z'),('0'..'9')].map { |i| i.to_a }.flatten
84
113
  return (0...length).map { o[rand(o.length)] }.join
85
114
  end
115
+
116
+ # @route GET /admin/users/:id/delete
117
+ def admin_delete_form
118
+ return if !user_is_allowed('users', 'edit')
119
+ @edituser = User.find(params[:id])
120
+ end
86
121
 
87
122
  # @route POST /admin/users/import
88
123
  def admin_import
@@ -212,7 +247,31 @@ module Caboose
212
247
  when "roles"
213
248
  user.roles = [];
214
249
  value.each { |rid| user.roles << Role.find(rid) } unless value.nil?
215
- resp.attribute = { 'text' => user.roles.collect{ |r| r.name }.join(', ') }
250
+ resp.attribute = { 'text' => user.roles.collect{ |r| r.name }.join(', ') }
251
+
252
+ when 'card'
253
+
254
+ sc = @site.store_config
255
+ Stripe.api_key = sc.stripe_secret_key.strip
256
+
257
+ c = nil
258
+ if user.stripe_customer_id
259
+ c = Stripe::Customer.retrieve(user.stripe_customer_id)
260
+ begin
261
+ c.source = params[:token]
262
+ c.save
263
+ rescue
264
+ c = nil
265
+ end
266
+ end
267
+ c = Stripe::Customer.create(:source => params[:token], :email => user.email, :metadata => { :user_id => user.id }) if c.nil?
268
+ user.stripe_customer_id = c.id
269
+ user.card_last4 = params[:card][:last4]
270
+ user.card_brand = params[:card][:brand]
271
+ user.card_exp_month = params[:card][:exp_month]
272
+ user.card_exp_year = params[:card][:exp_year]
273
+ user.save
274
+
216
275
  end
217
276
  end
218
277
 
@@ -71,5 +71,9 @@ class Caboose::CorePlugin < Caboose::CaboosePlugin
71
71
  def self.request_protocol(current_value, request)
72
72
  return current_value
73
73
  end
74
+
75
+ def self.admin_user_tabs(tabs, user, site)
76
+ return tabs
77
+ end
74
78
 
75
79
  end
@@ -289,7 +289,58 @@ module Caboose
289
289
  return true if li.variant.taxable && li.variant.taxable == true
290
290
  end
291
291
  return false
292
- end
292
+ end
293
+
294
+ # Authorize and capture funds
295
+ def authorize_and_capture
296
+
297
+ resp = StdClass.new
298
+ if self.financial_status == Invoice::FINANCIAL_STATUS_CAPTURED
299
+ resp.error = "Funds for this invoice have already been captured."
300
+ else
301
+
302
+ sc = self.site.store_config
303
+ case sc.pp_name
304
+ when StoreConfig::PAYMENT_PROCESSOR_STRIPE
305
+
306
+ Stripe.api_key = sc.stripe_secret_key.strip
307
+ bt = nil
308
+ begin
309
+ c = Stripe::Charge.create(
310
+ :amount => (self.total * 100).to_i,
311
+ :currency => 'usd',
312
+ :customer => self.customer.stripe_customer_id,
313
+ :capture => true,
314
+ :metadata => { :invoice_id => self.id },
315
+ :statement_descriptor => "Invoice ##{self.id}"
316
+ )
317
+ rescue Exception => ex
318
+ resp.error = "Error during capture process\n#{ex.message}"
319
+ end
320
+ if resp.error.nil?
321
+ InvoiceTransaction.create(
322
+ :invoice_id => self.id,
323
+ :transaction_id => c.id,
324
+ :transaction_type => InvoiceTransaction::TYPE_AUTHCAP,
325
+ :payment_processor => sc.pp_name,
326
+ :amount => c.amount / 100.0,
327
+ :captured => true,
328
+ :date_processed => DateTime.now.utc,
329
+ :success => c.status == 'succeeded'
330
+ )
331
+ if c.status == 'succeeded'
332
+ self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
333
+ self.save
334
+ resp.success = true
335
+ else
336
+ resp.error = "Error capturing funds."
337
+ end
338
+ end
339
+
340
+ end
341
+ end
342
+ return resp
343
+ end
293
344
 
294
345
  # Capture funds from a previously authorized transaction
295
346
  def capture_funds
@@ -4,22 +4,23 @@
4
4
  <%= javascript_include_tag "caboose/model/all" %>
5
5
  <% end %>
6
6
 
7
- <h1>Edit Advertiser</h1>
7
+ <h1>Edit User - <%= @edituser.first_name %> <%= @edituser.last_name %></h1>
8
8
  <ul id='tabs'>
9
9
  <%
10
10
  tabs = {
11
- 'General' => "/admin/advertisers/#{@advertiser.id}",
12
- 'Authorize.net Info' => "/admin/advertisers/#{@advertiser.id}/authnet",
13
- 'Users' => "/admin/advertisers/#{@advertiser.id}/users",
14
- 'Campaigns' => "/admin/advertisers/#{@advertiser.id}/campaigns",
15
- 'Invoices' => "/admin/advertisers/#{@advertiser.id}/invoices",
16
- 'Delete' => "/admin/advertisers/#{@advertiser.id}/delete"
11
+ 'General' => "/admin/users/#{@edituser.id}",
12
+ 'Payment Method' => "/admin/users/#{@edituser.id}/payment-method",
13
+ 'Login Logs' => "/admin/login-logs?user_id=#{@edituser.id}",
14
+ 'Password' => "/admin/users/#{@edituser.id}/password",
15
+ 'Roles' => "/admin/users/#{@edituser.id}/roles",
16
+ 'Delete' => "/admin/users/#{@edituser.id}/delete"
17
17
  }
18
+ tabs = Caboose.plugin_hook('admin_user_tabs', tabs, @edituser, @site)
18
19
  %>
19
20
  <% tabs.each do |text, href| %>
20
21
  <% selected = true if request.fullpath == href || (text != 'General' && request.fullpath.starts_with?(href)) %>
21
22
  <li<% if selected %> class='selected'<% end %>><a href='<%= href %>'><%= raw text %></a></li>
22
23
  <% end %>
23
- <li class='back'><input type='button' value='< Back' onclick="window.location='/admin/advertisers';" /></li>
24
+ <li class='back'><input type='button' value='< Back' onclick="window.location='/admin/users';" /></li>
24
25
  </ul>
25
26
  <div id='content2'>
@@ -0,0 +1,59 @@
1
+
2
+ <%= render :partial => 'caboose/users/admin_header' %>
3
+
4
+ <h1>Delete User</h1>
5
+
6
+ <div id='message'>
7
+ <input type='button' value='Delete User' onclick="delete_user(<%= @edituser.id %>);" />
8
+ </div>
9
+
10
+ <%= render :partial => 'caboose/users/admin_footer' %>
11
+
12
+ <% content_for :caboose_css do %>
13
+ <style type='text/css'>
14
+ </style>
15
+ <% end %>
16
+ <% content_for :caboose_js do %>
17
+ <%= javascript_include_tag "caboose/model/all" %>
18
+ <script type="text/javascript">
19
+
20
+ $(document).ready(function() {
21
+ new ModelBinder({
22
+ name: 'User',
23
+ id: <%= @edituser.id %>,
24
+ update_url: '/admin/users/<%= @edituser.id %>',
25
+ authenticity_token: '<%= form_authenticity_token %>',
26
+ attributes: [
27
+ { name: 'first_name' , nice_name: 'First name', type: 'text' , value: <%= raw Caboose.json(@edituser.first_name) %>, width: 280 },
28
+ { name: 'last_name' , nice_name: 'Last name' , type: 'text' , value: <%= raw Caboose.json(@edituser.last_name) %>, width: 280 },
29
+ { name: 'username' , nice_name: 'Username' , type: 'text' , value: <%= raw Caboose.json(@edituser.username) %>, width: 280 },
30
+ { name: 'email' , nice_name: 'Email' , type: 'text' , value: <%= raw Caboose.json(@edituser.email) %>, width: 280 },
31
+ { name: 'locked' , nice_name: 'Locked' , type: 'checkbox' , value: <%= @edituser.locked ? 1 : 0 %>, width: 280 }
32
+ ]
33
+ });
34
+ });
35
+
36
+ function delete_user(user_id, confirm)
37
+ {
38
+ if (!confirm)
39
+ {
40
+ var p = $('<p/>').addClass('note confirm')
41
+ .append('Are you sure you want to delete the user? ')
42
+ .append($('<input/>').attr('type','button').val('Yes').click(function() { delete_user(user_id, true); })).append(' ')
43
+ .append($('<input/>').attr('type','button').val('No').click(function() { $('#message').empty(); }));
44
+ $('#message').empty().append(p);
45
+ return;
46
+ }
47
+ $('#message').html("<p class='loading'>Deleting user...</p>");
48
+ $.ajax({
49
+ url: '/admin/users/' + user_id,
50
+ type: 'delete',
51
+ success: function(resp) {
52
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
53
+ if (resp.redirect) window.location = resp.redirect;
54
+ }
55
+ });
56
+ }
57
+
58
+ </script>
59
+ <% end %>
@@ -2,28 +2,17 @@
2
2
  gravatar_id = Digest::MD5.hexdigest(@edituser.email.downcase)
3
3
  pic = "http://gravatar.com/avatar/#{gravatar_id}.png?s=150" #&d=/assets/caboose/default_user_pic.png"
4
4
  %>
5
- <h1>Edit User</h1>
5
+
6
+ <%= render :partial => 'caboose/users/admin_header' %>
7
+
6
8
  <p id='gravatar'><img src='<%= pic %>' /><a href='http://gravatar.com'>Update on gravatar</a></p>
7
9
  <p><div id='user_<%= @edituser.id %>_first_name' ></div></p>
8
10
  <p><div id='user_<%= @edituser.id %>_last_name' ></div></p>
9
11
  <p><div id='user_<%= @edituser.id %>_username' ></div></p>
10
12
  <p><div id='user_<%= @edituser.id %>_email' ></div></p>
11
13
  <p><div id='user_<%= @edituser.id %>_locked' ></div></p>
12
- <div id='roles'>
13
- <table class='data'>
14
- <% Caboose::Role.flat_tree(@site.id).each do |r| %>
15
- <% is_member = Caboose::RoleMembership.where(:role_id => r.id, :user_id => @edituser.id).exists? %>
16
- <tr><td><input type='checkbox' name='role<%= r.id %>' <%= is_member ? "checked='true'" : '' %> onclick="toggle_role(<%= @edituser.id %>, <%= r.id %>, $(this).prop('checked'));" /></td><td><%= r.name %></td></tr>
17
- <% end %>
18
- </table>
19
- </div>
20
- <div id='message'></div>
21
- <div id='controls'>
22
- <input type='button' value='Back' onclick="window.location='/admin/users';" />
23
- <input type='button' value='Login Logs for this User' onclick="window.location='/admin/login-logs?user_id=<%= @edituser.id %>';" />
24
- <input type='button' value='Reset Password' onclick="window.location='/admin/users/<%= @edituser.id %>/edit-password';" />
25
- <input type='button' value='Delete User' onclick="delete_user(<%= @edituser.id %>);" />
26
- </div>
14
+
15
+ <%= render :partial => 'caboose/users/admin_footer' %>
27
16
 
28
17
  <% content_for :caboose_css do %>
29
18
  <style type='text/css'>
@@ -51,44 +40,12 @@ $(document).ready(function() {
51
40
  });
52
41
  });
53
42
 
54
- function delete_user(user_id, confirm)
55
- {
56
- if (!confirm)
57
- {
58
- var p = $('<p/>').addClass('note confirm')
59
- .append('Are you sure you want to delete the user? ')
60
- .append($('<input/>').attr('type','button').val('Yes').click(function() { delete_user(user_id, true); })).append(' ')
61
- .append($('<input/>').attr('type','button').val('No').click(function() { $('#message').empty(); }));
62
- $('#message').empty().append(p);
63
- return;
64
- }
65
- $('#message').html("<p class='loading'>Deleting user...</p>");
66
- $.ajax({
67
- url: '/admin/users/' + user_id,
68
- type: 'delete',
69
- success: function(resp) {
70
- if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
71
- if (resp.redirect) window.location = resp.redirect;
72
- }
73
- });
74
- }
75
-
76
- function toggle_role(user_id, role_id, checked)
77
- {
78
- $.ajax({
79
- url: '/admin/users/' + user_id +'/roles/' + role_id,
80
- type: checked ? 'post' : 'delete',
81
- succes: function(resp) { }
82
- });
83
- }
84
-
85
43
  </script>
86
44
  <% end %>
87
45
 
88
46
  <% content_for :caboose_css do %>
89
47
  <style type='text/css'>
90
- #gravatar {
91
- float: right;
48
+ #gravatar {
92
49
  width: 150px;
93
50
  text-align: right;
94
51
  margin: 0 4px 0 0;
@@ -1,14 +1,15 @@
1
1
 
2
- <h1>Reset Password for <%= "#{@edituser.first_name} #{@edituser.last_name}" %></h1>
2
+ <%= render :partial => 'caboose/users/admin_header' %>
3
+
4
+ <h2>Reset Password for <%= "#{@edituser.first_name} #{@edituser.last_name}" %></h2>
3
5
  <form action='/admin/users/<%= @edituser.id %>' method='put' id='password_form'>
4
6
  <input type='hidden' name='authenticity_token' value='<%= form_authenticity_token %>' />
5
7
  <p><input type='password' name='password' id='password' value="" placeholder='Password' /></p>
6
8
  <p><input type='password' name='password2' id='password2' value="" placeholder='Confirm password' /></p>
7
9
  <div id='message'></div>
8
- <p>
9
- <input type='button' value='Back' onclick="window.location='/admin/users/<%= @edituser.id %>';" />
10
- <input type='button' value='Update Password' onclick="update_password();" />
11
- </p>
10
+ <p><input type='button' value='Update Password' onclick="update_password();" /></p>
11
+
12
+ <%= render :partial => 'caboose/users/admin_footer' %>
12
13
 
13
14
  <% content_for :caboose_js do %>
14
15
  <script type="text/javascript">
@@ -0,0 +1,52 @@
1
+
2
+ <%= render :partial => 'caboose/users/admin_header' %>
3
+
4
+ <div id='payment_method_container'></div>
5
+
6
+ <%= render :partial => 'caboose/users/admin_footer' %>
7
+
8
+ <% content_for :caboose_css do %>
9
+ <style type='text/css'>
10
+
11
+ .stripe_form { width: 400px; }
12
+ .stripe_form .card_number_container { position: relative; width: 100%; } .stripe_form .card_number_container input { padding-left: 30px; height: 37px; font-size: 15px; width: 100%; border-color: #b9b9b9; border-style: solid; border-width: 1px 1px 0px 1px; }
13
+ .stripe_form .card_exp_container { position: relative; width: 50% !important; float: left; } .stripe_form .card_exp_container input { padding-left: 30px; height: 37px; font-size: 15px; width: 100%; border-color: #b9b9b9; border-style: solid; border-width: 1px 1px 0px 1px; }
14
+ .stripe_form .card_cvc_container { position: relative; width: 50%; float: left; } .stripe_form .card_cvc_container input { padding-left: 30px; height: 37px; font-size: 15px; width: 100%; border-color: #b9b9b9; border-style: solid; border-width: 1px 1px 0px 0px; }
15
+ .stripe_form .card_name_container { position: relative; width: 50%; float: left; } .stripe_form .card_name_container input { padding-left: 10px; height: 37px !important; font-size: 15px; width: 100%; border-color: #b9b9b9; border-style: solid; border-width: 1px 0px 1px 1px; }
16
+ .stripe_form .card_zip_container { position: relative; width: 50%; float: left; margin-bottom: 4px; } .stripe_form .card_zip_container input { padding-left: 10px; height: 37px; font-size: 15px; width: 100%; border-color: #b9b9b9; border-style: solid; border-width: 1px 1px 1px 0px; }
17
+
18
+ .stripe_form .card_number_container .icon { position: absolute; top: 3px; left: 1px; transform-origin: 50% 50% 0; pointer-events: none; }
19
+ .stripe_form .card_exp_container .icon { position: absolute; top: 3px; left: 1px; transform-origin: 50% 50% 0; pointer-events: none; }
20
+ .stripe_form .card_cvc_container .icon { position: absolute; top: 3px; left: 1px; transform-origin: 50% 50% 0; pointer-events: none; }
21
+
22
+ .stripe_form .note { width: 100%; margin-bottom: 10px !important; text-align: center; }
23
+ .stripe_form .payment_controls { clear: left; margin-top: 4px !important; }
24
+
25
+ </style>
26
+ <%= stylesheet_link_tag "caboose/my_account", :media => "all" %>
27
+ <% end %>
28
+
29
+ <% content_for :caboose_js do %>
30
+ <%= javascript_include_tag 'https://js.stripe.com/v2/' %>
31
+ <%= javascript_include_tag 'caboose/checkout/stripe_payment_method_controller' %>
32
+ <%= javascript_include_tag 'caboose/model/all' %>
33
+ <%= javascript_include_tag 'caboose/united_states' %>
34
+ <%= javascript_include_tag 'caboose/jquery.payment' %>
35
+ <%= javascript_include_tag 'caboose/card' %>
36
+ <script type='text/javascript'>
37
+
38
+ var controller = false;
39
+ $(document).ready(function() {
40
+ controller = new StripePaymentMethodController({
41
+ cc: {
42
+ invoice: { total: 1.00 },
43
+ print_ready_message: function() {},
44
+ },
45
+ refresh_url: '/admin/users/<%= @edituser.id %>/stripe/json',
46
+ after_update_url: '/admin/users/<%= @edituser.id %>'
47
+ });
48
+ controller.print();
49
+ });
50
+
51
+ </script>
52
+ <% end %>
@@ -0,0 +1,35 @@
1
+
2
+ <%= render :partial => 'caboose/users/admin_header' %>
3
+
4
+ <div id='roles'>
5
+ <table class='data'>
6
+ <% Caboose::Role.flat_tree(@site.id).each do |r| %>
7
+ <% is_member = Caboose::RoleMembership.where(:role_id => r.id, :user_id => @edituser.id).exists? %>
8
+ <tr><td><input type='checkbox' name='role<%= r.id %>' <%= is_member ? "checked='true'" : '' %> onclick="toggle_role(<%= @edituser.id %>, <%= r.id %>, $(this).prop('checked'));" /></td><td><%= r.name %></td></tr>
9
+ <% end %>
10
+ </table>
11
+ </div>
12
+
13
+ <%= render :partial => 'caboose/users/admin_footer' %>
14
+
15
+ <% content_for :caboose_css do %>
16
+ <style type='text/css'>
17
+ #content input[type=checkbox] { position: relative; }
18
+ #roles {}
19
+ </style>
20
+ <% end %>
21
+ <% content_for :caboose_js do %>
22
+ <%= javascript_include_tag "caboose/model/all" %>
23
+ <script type="text/javascript">
24
+
25
+ function toggle_role(user_id, role_id, checked)
26
+ {
27
+ $.ajax({
28
+ url: '/admin/users/' + user_id +'/roles/' + role_id,
29
+ type: checked ? 'post' : 'delete',
30
+ succes: function(resp) { }
31
+ });
32
+ }
33
+
34
+ </script>
35
+ <% end %>
@@ -1,3 +1,3 @@
1
1
  module Caboose
2
- VERSION = '0.8.67'
2
+ VERSION = '0.8.68'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caboose-cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.67
4
+ version: 0.8.68
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Barry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-16 00:00:00.000000000 Z
11
+ date: 2016-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -745,7 +745,6 @@ files:
745
745
  - app/assets/templates/caboose/product/images.jst.ejs
746
746
  - app/assets/templates/caboose/product/images_old.jst.ejs
747
747
  - app/assets/templates/caboose/product/options.jst.ejs
748
- - app/controllers/caboose/#checkout_controller.rb#
749
748
  - app/controllers/caboose/ab_options_controller.rb
750
749
  - app/controllers/caboose/ab_variants_controller.rb
751
750
  - app/controllers/caboose/admin_controller.rb
@@ -1210,8 +1209,11 @@ files:
1210
1209
  - app/views/caboose/subscriptions/admin_index.html.erb
1211
1210
  - app/views/caboose/users/_admin_footer.html.erb
1212
1211
  - app/views/caboose/users/_admin_header.html.erb
1212
+ - app/views/caboose/users/admin_delete_form.html.erb
1213
1213
  - app/views/caboose/users/admin_edit.html.erb
1214
1214
  - app/views/caboose/users/admin_edit_password.html.erb
1215
+ - app/views/caboose/users/admin_edit_payment_method.html.erb
1216
+ - app/views/caboose/users/admin_edit_roles.html.erb
1215
1217
  - app/views/caboose/users/admin_import_form.html.erb
1216
1218
  - app/views/caboose/users/admin_index.html.erb
1217
1219
  - app/views/caboose/users/admin_new.html.erb
@@ -1,464 +0,0 @@
1
- require 'authorize_net'
2
-
3
- module Caboose
4
- class CheckoutController < Caboose::ApplicationController
5
-
6
- before_filter :ensure_line_items, :only => [:step_one, :step_two]
7
- protect_from_forgery
8
-
9
- def ensure_line_items
10
- redirect_to '/checkout/empty' if @invoice.line_items.empty?
11
- end
12
-
13
- # @route GET /checkout/json
14
- def invoice_json
15
- render :json => @invoice.as_json(
16
- :include => [
17
- :customer,
18
- :shipping_address,
19
- :billing_address,
20
- :invoice_transactions,
21
- {
22
- :line_items => {
23
- :include => {
24
- :variant => {
25
- :include => [
26
- { :product_images => { :methods => :urls }},
27
- { :product => { :include => { :product_images => { :methods => :urls }}}}
28
- ],
29
- :methods => :title
30
- }
31
- }
32
- }
33
- },
34
- { :invoice_packages => { :include => [:shipping_package, :shipping_method] }},
35
- { :discounts => { :include => :gift_card }}
36
- ]
37
- )
38
- end
39
-
40
- # @route GET /checkout/stripe/json
41
- def stripe_json
42
- sc = @site.store_config
43
- u = logged_in_user
44
- render :json => {
45
- :stripe_key => sc.stripe_publishable_key.strip,
46
- :customer_id => u.stripe_customer_id,
47
- :card_last4 => u.card_last4,
48
- :card_brand => u.card_brand,
49
- :card_exp_month => u.card_exp_month,
50
- :card_exp_year => u.card_exp_year
51
- }
52
- end
53
-
54
- #===========================================================================
55
-
56
- # Step 1 - Login or register
57
- # @route GET /checkout
58
- def index
59
- if logged_in?
60
- if @invoice.customer_id.nil?
61
- @invoice.customer_id = logged_in_user.id
62
- @invoice.save
63
- end
64
- #redirect_to '/checkout/addresses'
65
- #return
66
-
67
- @invoice.verify_invoice_packages
68
-
69
- # See if any there are any empty invoice packages
70
- #@invoice.invoice_packages.each do |op|
71
- # count = 0
72
- # @invoice.line_items.each do |li|
73
- # count = count + 1 if li.invoice_package_id == op.id
74
- # end
75
- # op.destroy if count == 0
76
- #end
77
- #
78
- ## See if any line items aren't associated with an invoice package
79
- #line_items_attached = true
80
- #@invoice.line_items.each do |li|
81
- # line_items_attached = false if li.invoice_package_id.nil?
82
- #end
83
- #
84
- #ops = @invoice.invoice_packages
85
- #if ops.count == 0 || !line_items_attached
86
- # @invoice.calculate
87
- # LineItem.where(:invoice_id => @invoice.id).update_all(:invoice_package_id => nil)
88
- # InvoicePackage.where(:invoice_id => @invoice.id).destroy_all
89
- # InvoicePackage.create_for_invoice(@invoice)
90
- #end
91
-
92
- #render :file => "caboose/checkout/checkout_#{@site.store_config.pp_name}"
93
- render :file => "caboose/checkout/checkout"
94
- end
95
- end
96
-
97
- # Step 3 - Shipping method
98
- # @route GET /checkout/shipping/json
99
- def shipping_json
100
- render :json => { :error => 'Not logged in.' } and return if !logged_in?
101
- render :json => { :error => 'No shippable items.' } and return if !@invoice.has_shippable_items?
102
- render :json => { :error => 'Empty shipping address.' } and return if @invoice.shipping_address.nil?
103
-
104
- @invoice.calculate
105
-
106
- #ops = @invoice.invoice_packages
107
- #if params[:recalculate_invoice_packages] || ops.count == 0
108
- # # Remove any invoice packages
109
- # LineItem.where(:invoice_id => @invoice.id).update_all(:invoice_package_id => nil)
110
- # InvoicePackage.where(:invoice_id => @invoice.id).destroy_all
111
- #
112
- # # Calculate what shipping packages we'll need
113
- # InvoicePackage.create_for_invoice(@invoice)
114
- #end
115
-
116
- # Now get the rates for those packages
117
- rates = ShippingCalculator.rates(@invoice)
118
- render :json => rates
119
- end
120
-
121
- # Step 5 - Update Stripe Details
122
- # @route PUT /checkout/stripe-details
123
- def update_stripe_details
124
- render :json => false and return if !logged_in?
125
-
126
- sc = @site.store_config
127
- Stripe.api_key = sc.stripe_secret_key.strip
128
-
129
- u = logged_in_user
130
-
131
- c = nil
132
- if u.stripe_customer_id
133
- c = Stripe::Customer.retrieve(u.stripe_customer_id)
134
- begin
135
- c.source = params[:token]
136
- c.save
137
- rescue
138
- c = nil
139
- end
140
- end
141
-
142
- if c.nil?
143
- c = Stripe::Customer.create(
144
- :source => params[:token],
145
- :email => u.email,
146
- :metadata => { :user_id => u.id }
147
- )
148
- end
149
-
150
- u.stripe_customer_id = c.id
151
- u.card_last4 = params[:card][:last4]
152
- u.card_brand = params[:card][:brand]
153
- u.card_exp_month = params[:card][:exp_month]
154
- u.card_exp_year = params[:card][:exp_year]
155
- u.save
156
-
157
- render :json => {
158
- :success => true,
159
- :customer_id => u.stripe_customer_id
160
- }
161
- end
162
-
163
- # @route POST /checkout/confirm
164
- def confirm
165
- render :json => { :error => 'Not logged in.' } and return if !logged_in?
166
- #render :json => { :error => 'Invalid billing address.' } and return if @invoice.billing_address.nil?
167
- render :json => { :error => 'Invalid shipping address.' } and return if @invoice.has_shippable_items? && @invoice.shipping_address.nil?
168
- render :json => { :error => 'Invalid shipping methods.' } and return if @invoice.has_shippable_items? && @invoice.has_empty_shipping_methods?
169
-
170
- resp = Caboose::StdClass.new
171
- sc = @site.store_config
172
-
173
- # Make sure all the variants still exist
174
- @invoice.line_items.each do |li|
175
- v = Variant.where(:id => li.variant_id).first
176
- if v.nil? || v.status == 'Deleted'
177
- render :json => { :error => 'One or more of the products you are purchasing are no longer available.' }
178
- return
179
- end
180
- end
181
-
182
- error = false
183
- requires_payment = @invoice.line_items.count > 0 && @invoice.total > 0 && @invoice.payment_terms == Invoice::PAYMENT_TERMS_PIA
184
- if requires_payment
185
-
186
- ot = nil
187
- case sc.pp_name
188
- when StoreConfig::PAYMENT_PROCESSOR_AUTHNET
189
-
190
- when StoreConfig::PAYMENT_PROCESSOR_STRIPE
191
- Stripe.api_key = sc.stripe_secret_key.strip
192
- begin
193
- c = Stripe::Charge.create(
194
- :amount => (@invoice.total * 100).to_i,
195
- :currency => 'usd',
196
- :customer => logged_in_user.stripe_customer_id,
197
- :capture => false,
198
- :metadata => { :invoice_id => @invoice.id },
199
- :statement_descriptor => "Invoice ##{@invoice.id}"
200
- )
201
- rescue Exception => ex
202
- render :json => { :error => ex.message }
203
- return
204
- end
205
- ot = Caboose::InvoiceTransaction.create(
206
- :invoice_id => @invoice.id,
207
- :transaction_id => c.id,
208
- :transaction_type => c.captured ? Caboose::InvoiceTransaction::TYPE_AUTHCAP : Caboose::InvoiceTransaction::TYPE_AUTHORIZE,
209
- :payment_processor => sc.pp_name,
210
- :amount => c.amount/100.0,
211
- :date_processed => DateTime.now.utc,
212
- :success => c.status == 'succeeded'
213
- )
214
- end
215
-
216
- if !ot.success
217
- render :json => { :error => error }
218
- return
219
- else
220
- @invoice.financial_status = Invoice::FINANCIAL_STATUS_AUTHORIZED
221
- @invoice.take_gift_card_funds
222
- end
223
- end
224
-
225
- @invoice.status = Invoice::STATUS_PENDING
226
- @invoice.invoice_number = @site.store_config.next_invoice_number
227
-
228
- # Send out emails
229
- begin
230
- InvoicesMailer.configure_for_site(@site.id).customer_new_invoice(@invoice).deliver
231
- InvoicesMailer.configure_for_site(@site.id).fulfillment_new_invoice(@invoice).deliver
232
- rescue
233
- puts "=================================================================="
234
- puts "Error sending out invoice confirmation emails for invoice ID #{@invoice.id}"
235
- puts "=================================================================="
236
- end
237
-
238
- # Emit invoice event
239
- Caboose.plugin_hook('invoice_authorized', @invoice) if @invoice.total > 0
240
-
241
- # Save the invoice
242
- @invoice.save
243
-
244
- # Decrement quantities of variants
245
- @invoice.decrement_quantities
246
-
247
- # Clear the cart and re-initialize
248
- session[:cart_id] = nil
249
- init_cart
250
-
251
- resp.success = true
252
- resp.redirect = '/checkout/thanks'
253
- render :json => resp
254
- end
255
-
256
- # @route GET /checkout/thanks
257
- def thanks
258
- @logged_in_user = logged_in_user
259
-
260
- # Find the last invoice for the user
261
- @last_invoice = Invoice.where(:customer_id => @logged_in_user.id).reorder("id desc").limit(1).first
262
- add_ga_event('Ecommerce', 'Checkout', 'Payment', (@last_invoice.total*100).to_i)
263
- end
264
-
265
- #===========================================================================
266
-
267
- # @route GET /checkout/state-options
268
- def state_options
269
- options = Caboose::States.all.collect { |abbr, state| { 'value' => abbr, 'text' => abbr }}
270
- render :json => options
271
- end
272
-
273
- # @route GET /checkout/total
274
- def verify_total
275
- total = 0.00
276
- if logged_in?
277
- @invoice.calculate
278
- total = @invoice.total
279
- end
280
- render :json => total.to_f
281
- end
282
-
283
- # @route GET /checkout/address
284
- def address
285
- render :json => {
286
- :shipping_address => @invoice.shipping_address,
287
- :billing_address => @invoice.billing_address
288
- }
289
- end
290
-
291
- # @route PUT /checkout/addresses
292
- def update_addresses
293
-
294
- # Grab or create addresses
295
- shipping_address = if @invoice.shipping_address then @invoice.shipping_address else Address.new end
296
- billing_address = if @invoice.billing_address then @invoice.billing_address else Address.new end
297
-
298
- has_shippable_items = @invoice.has_shippable_items?
299
-
300
- # Shipping address
301
- if has_shippable_items
302
- shipping_address.first_name = params[:shipping][:first_name]
303
- shipping_address.last_name = params[:shipping][:last_name]
304
- shipping_address.company = params[:shipping][:company]
305
- shipping_address.address1 = params[:shipping][:address1]
306
- shipping_address.address2 = params[:shipping][:address2]
307
- shipping_address.city = params[:shipping][:city]
308
- shipping_address.state = params[:shipping][:state]
309
- shipping_address.zip = params[:shipping][:zip]
310
- end
311
-
312
- # Billing address
313
- if has_shippable_items && params[:use_as_billing]
314
- billing_address.update_attributes(shipping_address.attributes)
315
- else
316
- billing_address.first_name = params[:billing][:first_name]
317
- billing_address.last_name = params[:billing][:last_name]
318
- billing_address.company = params[:billing][:company]
319
- billing_address.address1 = params[:billing][:address1]
320
- billing_address.address2 = params[:billing][:address2]
321
- billing_address.city = params[:billing][:city]
322
- billing_address.state = params[:billing][:state]
323
- billing_address.zip = params[:billing][:zip]
324
- end
325
-
326
- # Save address info; generate ids
327
- render :json => { :success => false, :errors => shipping_address.errors.full_messages, :address => 'shipping' } and return if has_shippable_items && !shipping_address.save
328
- render :json => { :success => false, :errors => billing_address.errors.full_messages, :address => 'billing' } and return if !billing_address.save
329
-
330
- # Associate address info with invoice
331
- @invoice.shipping_address_id = shipping_address.id
332
- @invoice.billing_address_id = billing_address.id
333
-
334
- #render :json => { :redirect => 'checkout/shipping' }
335
- render :json => { :success => @invoice.save, :errors => @invoice.errors.full_messages }
336
- end
337
-
338
- # @route PUT /checkout/shipping-address
339
- def update_shipping_address
340
- resp = Caboose::StdClass.new
341
-
342
- # Grab or create addresses
343
- sa = @invoice.shipping_address
344
- if sa.nil?
345
- sa = Address.create
346
- @invoice.shipping_address_id = sa.id
347
- @invoice.save
348
- end
349
-
350
- save = true
351
- recalc_shipping = false
352
- params.each do |name, value|
353
- case name
354
- when 'address1' then recalc_shipping = true if sa.address1 != value
355
- when 'address2' then recalc_shipping = true if sa.address2 != value
356
- when 'city' then recalc_shipping = true if sa.city != value
357
- when 'state' then recalc_shipping = true if sa.state != value
358
- when 'zip' then recalc_shipping = true if sa.zip != value
359
- end
360
- case name
361
- when 'name' then sa.name = value
362
- when 'first_name' then sa.first_name = value
363
- when 'last_name' then sa.last_name = value
364
- when 'street' then sa.street = value
365
- when 'address1' then sa.address1 = value
366
- when 'address2' then sa.address2 = value
367
- when 'company' then sa.company = value
368
- when 'city' then sa.city = value
369
- when 'state' then sa.state = value
370
- when 'province' then sa.province = value
371
- when 'province_code' then sa.province_code = value
372
- when 'zip' then sa.zip = value
373
- when 'country' then sa.country = value
374
- when 'country_code' then sa.country_code = value
375
- when 'phone' then sa.phone = value
376
- end
377
- end
378
- if recalc_shipping
379
- @invoice.invoice_packages.each do |op|
380
- op.shipping_method_id = nil
381
- op.total = nil
382
- op.save
383
- end
384
- end
385
-
386
- resp.success = save && sa.save
387
- render :json => resp
388
- end
389
-
390
- # @route PUT /checkout/billing-address
391
- def update_billing_address
392
-
393
- # Grab or create addresses
394
- ba = @invoice.billing_address
395
- if ba.nil?
396
- ba = Address.create
397
- @invoice.billing_address_id = ba.id
398
- @invoice.save
399
- end
400
-
401
- ba.first_name = params[:first_name]
402
- ba.last_name = params[:last_name]
403
- ba.company = params[:company]
404
- ba.address1 = params[:address1]
405
- ba.address2 = params[:address2]
406
- ba.city = params[:city]
407
- ba.state = params[:state]
408
- ba.zip = params[:zip]
409
- ba.save
410
-
411
- render :json => { :success => true }
412
- end
413
-
414
- # @route POST /checkout/attach-user
415
- def attach_user
416
- render :json => { :success => false, :errors => ['User is not logged in'] } and return if !logged_in?
417
- @invoice.customer_id = logged_in_user.id
418
- #Caboose.log("Attaching user to invoice: customer_id = #{@invoice.customer_id}")
419
- render :json => { :success => @invoice.save, :errors => @invoice.errors.full_messages, :logged_in => logged_in? }
420
- end
421
-
422
- # @route POST /checkout/guest
423
- def attach_guest
424
- resp = Caboose::StdClass.new
425
- email = params[:email]
426
-
427
- if email != params[:confirm_email]
428
- resp.error = "Emails do not match."
429
- elsif Caboose::User.where(:email => email, :is_guest => false).exists?
430
- resp.error = "A user with that email address already exists."
431
- else
432
- user = Caboose::User.where(:email => email, :is_guest => true).first
433
- if user.nil?
434
- user = Caboose::User.create(:email => email)
435
- user.is_guest = true
436
- user.save
437
- user = Caboose::User.where(:email => email).first
438
- end
439
- @invoice.customer_id = user.id
440
- login_user(user)
441
-
442
- if !@invoice.valid?
443
- resp.errors = @invoice.errors.full_messages
444
- else
445
- @invoice.save
446
- resp.redirect = '/checkout/addresses'
447
- end
448
- end
449
- render :json => resp
450
- end
451
-
452
- # @route PUT /checkout/shipping
453
- def update_shipping
454
- op = InvoicePackage.find(params[:invoice_package_id])
455
- op.shipping_method_id = params[:shipping_method_id]
456
- op.total = params[:total]
457
- op.save
458
- op.invoice.calculate
459
-
460
- render :json => { :success => true }
461
- end
462
-
463
- end
464
- end