Friday, June 20, 2014

How Backbone plays nicely with Rails 4 (by skipping the authenticity token and by formatting params properly)

Alright, the blog post title is a little misleading because Backbone doesn't really do either of what I mentioned. Backbone does NOT skip the authenticity token nor does it format params properly for Rails. But it's what I google'd when me and my co-worker were looking for the answers. So I titled it this way to help some peeps.

Alright, so again, credit does not go fully to me on this - my co-worker and I had to figure this out.

How does Backbone 'Skip the authenticity token'

Alright, so I was just starting to learn backbone with a very simple setup: Rails Server with a Backbone app. I was following the tutorial on backbonetutorials.com. So I got to the part where the code calls a 'save' on the model:

user.save(userDetails)

and it all worked - much to my surprise. I thought for sure there was an issue in that there's no way Backbone knew about Rails' authenticity_token. Sure enough, when I went to the Rails log, there was no authenticity token being passed in the params (as there is when you submit a rails built form). Furthermore, looking at the request in Chrome's network tab - nope, no authenticity token in the request parameters.

Yet - somehow, the request was succeeding? Did Rails somehow know this is a Backbone request and ignore the authenticity token?

Turns out - this has nothing to do with Backbone - and everything to do with jquery-rails (the version of JQuery that ships as a gem as part of Rails standard releases these days).

So upon further inspection of the request in Chrome's network tab - indeed there was no authenticity token in the request parameters - BUT there was a X-CSRF-Token in the request headers!!!

Ahhhh - so Rails must check both places (request params AND/OR request headers) for a authenticity token.

The question is - who is appending this token to the request headers?

Turns out, it's JQuery-Rails. JQuery-Rails appends this header to all AJAX requests where the CSRF meta tags are present.

https://groups.google.com/forum/#!topic/rubyonrails-core/eyTb_WZXLcs

Very cool stuff. So Backbone doesn't skip the authenticity token - it just makes an AJAX request, which JQuery-Rails is smart enough to append a authenticity token to the header of that AJAX request.

How does Backbone format its params properly

As long as I've been using Rails, I've always understood the POST CREATE request to accept its parameters in a specific way. If you had a user that had a name and age, you would need to pass the parameters like this:

{ user : {name : "Casey", age : 31 } }

In other words, you would need to nest the values within a object that's named after the resource. However, looking at Backbone, backbone has its parameters like this:

{ name : "Casey", age : 31 }

Notice that it's not nested inside "user". What's really weird, is if I look at the Rails log for the request of a Backbone.model.save, here's what comes in as the parameters:

{ name : "Casey", age : 31, user : { name : "Casey", age : 31 } }

It turns out that Rails (in its infinite magic) uses a module called ParamsWrapper that I can only theorize analyzes what comes in, and if it's only one-level deep, massages the params so that there is an extra param that's formatted properly for Rails (two-levels deep). This way, you have access to the params the way you passed them in:

params[:name]
params[:age]

and you have access to them the way Rails needs it:

params[:user][:name]
params[:user][:age]

Pretty crazy stuff.

Hope this helps some peeps.

Wednesday, April 9, 2014

Ruby on Rails, Rest in Place with Authorization taken into Account

Hey all,

Just a quick one. Just started using Rest in Place in my Rails applications. If you don't know what it is - it seems to be the most popular In-place editing gem (according to Ruby Toolbox).

Anyway, the one thing that kind of got annoying, is that my view templates were getting pretty ugly with a lot of IF statements because I didn't want in-place editing to be active for people who weren't allowed to edit. I realize that Rest in Place still goes through the controller, so any authorization code you have on the controller side prevents true editing - but still, I wanted to prevent the UI in-place editing for people who weren't authorized to do so either.

So I created a simple helper to remedy this.

You can check out the Gist here.

Friday, March 7, 2014

After Effects Editing Mask Path (moving individual points)

Alright, this was frustrating the hell out of me - especially considering most posts and forum responses had the right idea but were missing one key element.

The issue is in Adobe After Effects and Masks.

Here's the setup


  • You have some layer (shape, picture, footage, whatever)
  • You add a layer Mask
  • You edit the Mask over time by setting keyframes on the Mask Path property

The issue

  • Anytime you try to move a single point on the Mask Path - the entire mask path moves - regardless of if you have the Pen Tool or Selection Tool selected

So yes - most posts ands forum responses I've seen talk about - "Make sure you have the Pen Tool" selected - so that way you're in path editing mode and then you should be able to move the individual points. I tried ad nausea and I couldn't get this to work.

Solution

  • It all had to do with what was selected in the timeline. I had the Mask selected (that is, the Mask property that shows up when you twirl down the layer itself) - which is wrong. This was the issue.
  • Once I selected the layer itself and NOT the mask, I could then select the Pen Tool and edit the points individually.
Kind of strange - but yeah - select the Layer and not its mask if you want to edit the Mask points individually. And yes - use the Pen Tool.

(note this is in Adobe After Effects CS6 - not sure about other versions).

Hope this helps out some peeps.

Sunday, February 9, 2014

Ruby on Rails, Stripe Checkout Payments, and Internet Explorer 9, IE 9 Not Working

Alright, this was a long battle, but I finally figured out what was happening. I'm not sure why this fails, but at least I know what's causing the error and how to fix it.

Problem


So the setup is the following:

  • Ruby on Rails Application
  • Using Stripe Checkout (JS) for Payments (version 3 I believe)
  • Payments working in almost every browser except for Internet Explorer 9
The way the error manifested itself is that a IE 9 user would try to make a payment - the Stripe form would pop up properly, the user is able to enter their information, and the Green Check even happens and the Stripe form disappears but

  • The following post action of the form doesn't happen
  • And when I checked the Stripe dashboard - it looks like the payment didn't actually go through

So what's the culprit? It has to do with the form_tag and what it interjects into the form. I basically had the following code:


<%= form_tag "/some_action", class: "stripe-form" do %>
  <script
    src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
    data-amount="<%= amount %>"
    data-name="app"
    data-description="<%= description %>"
    data-email="<%= current_user.email %>">
  </script>
<% end %>

So you know how the form_tag helper throws in the authenticity_token for security (if you don't, visit your webpage and look at the HTML source and you'll see that rails injects 2 hidden input fields for security checks). Now what's the issue? IE 9 does not like the DIV tags that surround the authenticity_token inputs fields. That's what causes the issue.


Solution

So how to solve this? Well, I couldn't find an easy way to get rails to do this itself through the form_tag (and I would welcome if anybody knows how to do this using the form_tag), but basically you have to manually reconstruct the HTML that form_tag produces, and just don't include the DIV tags that surround the authenticity_token inputs. I also added some "display:none" styles to make sure formatting look good. So the code looks like this (the important thing is to remember to still include the authenticity_token inputs, just NOT inside DIV tags):









<form accept-charset="UTF-8" action="<%= "/some_action" %>" method="POST" class="stripe-form">
  <input name="utf8" type="hidden" value="✓" style="display:none">
  <input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>" style="display:none">

  <script>
    src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
    data-amount="<%= amount %>"
    data-name="app"
    data-description="<%= description %>"
    data-email="<%= current_user.email %>">
  </script>
</form>

Hope this helps out some peeps.

Monday, December 2, 2013

Resetting PostgreSQL 'postgres' user password in Mac

  1. Edit the pg_hba.conf file
    1. sudo vi /Library/PostgreSQL/9.2/data/pg_hba.conf
    2. Change the "md5" method for all users to "trust" near the bottom of the file
  2. Find the name of the service
    1. ls /Library/LaunchDaemons
    2. Look for postgresql
  3. Stop the postgresql service
    1. sudo launchctl stop com.edb.launchd.postgresql-9.2
  4. Start the postgresql service
    1. sudo launchctl start com.edb.launchd.postgresql-9.2
  5. Start psql session as postgres
    1. psql -U postgres
    2. (shouldn't ask for password because of 'trust' setting)
  6. Reset password in psql session by typing
    1. ALTER USER postgres with password 'secure-new-password';
    2. \q
    3. enter
  7. Edit the pg_hba.conf file
    1. Switch it back to 'md5'
  8. Restart services again

Thursday, July 25, 2013

Listy - Ruby Gem for Rails developers who just want to create lists easily

Hey everyone,

Just a quick one - but I've recently published a Ruby Gem called Listy. It allows you to easily create lists based on ActiveRecord collections. One thing I find most useful about it is creating a tree of ActiveRecord has_many nested collections.

Check it out at https://github.com/caseyli/listy

Enjoy!

Thursday, July 11, 2013

Google Apps 'From' Address Spoofing / 'From' Address Override [Update]

Please be sure to read the important update at the end of this article

Alright, so I was just working on a client's project that has a very typical request that always seems to be an issue when using GMail / Google Apps as an integration piece.

And I stumbled upon a solution that although doesn't solve all cases - I'm sure will help a couple of people out.

So here's the dilemma.

Let's say you have a integration solution that includes an e-mail gateway, in this kind of setup.

(Application A) <----> (SMTP/POP/IMAP Server) <---> (E-mail Gateway) <----> (Application B)

So this situation is that you have an application (Application A) which ultimately wants to get a message to another application (Application B). And a lot of the times, the way they do this is through a E-mail Gateway (in other words an application that is able to receive and send e-mail on behalf of Application B). Further to this, perhaps Application B is really a multitude of destinations differentiated by the "To:" e-mailing address in the original message.

Here's an example

(Application A) - is an e-mail generator.
(SMTP/POP/IMAP Server) -
(E-mail Gateway) - is an application that maps the "To:" e-mailing address to a smartphone app user.id
(Application B) - is a smartphone app, where each user has a user.id

So the series of steps would go this way:

- User of (Application A) generates an e-mail to Johnny@hello.com
- (SMTP/POP/IMAP Server) is setup with a catchall@hello.com and will catch all the e-mails that don't have real addresses like Johnny@hello.com. So the original e-mail ends up in the catchall@hello.com inbox.
- (E-mail Gateway) periodically checks the (SMTP/POP/IMAP Server) for e-mails and finds the e-mail meant for Johnny@hello.com. The (E-mail Gateway) maps the "Johnny" part of Johnny@hello.com to a user.id "Johnny" and send a message to (Application B) running on Johnny's smartphone.
- Johnny on his smartphone replies to the message.
- (E-mail Gateway) gets Johnny's reply, and sends the e-mail using the catchall@hello.com account back to the originator (Application A).

Alright so this seems all good except for one piece. No matter who (Application A) sends the e-mail to, even though it will get to the right smartphone, the replies will always come from catchall@hello.com. Well, I shouldn't say that - if you use a GMail or Google Apps for Business GMail account - the from address will always be from catchall@hello.com.

This is because the e-mail gateway can only hook up to the one account and GMail and Google Apps for business (rightly so) prevents overriding/spoofing of the From address.

Now in some instances, this may be fine - the from address won't matter. But in the particular case that I was dealing with, (Application A) would reject the response if it didn't match the original e-mail. So if (Application A) sent out an e-mail to "Johnny@hello.com", it would only accept responses that came back from "Johnny@hello.com".

And the main issue here is that GMail / Google Apps for Business don't allow you to override the From address. So if your E-mail Gateway tries to set From address - GMail will prevent it.

Solution

Well here's the thing - yes, in most cases, if you adopt this kind of solution, GMail and Google Apps for Business will prevent setting the from address.

But there is a way around it if you

  1. legitimately own the addresses you are sending to (or the domain of those e-mail addresses) and 
  2. are willing to pay for Google Apps (which if it's for a client, hopefully $50/year is not bad)


This situation will actually allow you to use just one e-mail account - but have multiple "From" addresses.

So this situation is:

- (Application A) wants to generate e-mails for Johnny@hello.com, Max@hello.com, Tiffany@hello.com, and Kelly@hello.com.
- And, it will only accept responses from those e-mail addresses.

Here are the 4 key things you need to do:


  1. Use Google Apps for Business (yes, yes, it's always annoying when you come across a post that requires you pay money, but again - this may help out some peeps)
  2. Create a default account
  3. Add nicknames (or aliases)
  4. Setup "Send mail as..." for those aliases


So let's say you own hello.com.

1) Setup Google Apps for Business with this domain and

2) create a default account like receiver@hello.com.

Please refer to the update as step 3 is not really valid if you need more than 30 nicknames.
3) Thirdly, from the Admin of your Google Apps (admin.google.com), where you setup your receiver@hello.com account, add your nicknames to the receiver@hello.com

  • Johnny@hello.com
  • Max@hello.com
  • Tiffany@hello.com
  • Kelly@hello.com


Alright - so that's the first step. What that step does is allow for incoming mail to all end up in the same box so that your (E-mail Gateway) can poll that single inbox to get all the e-mail.

Alright - so that's not the trick to this solution - because that part usually people have figured out how it works. Do note though - that I'm not really using a receiver@hello.com as a catchall account - catchall accounts usually trap all e-mail that does not have an associated account with it. Rather, I'm using aliases - for an account. This is one of the keys to the success.

4) And here we go - the clincher that makes all this work -

SETUP YOUR "SEND MAIL AS..." e-mail addresses.

So log into the regular Mail with receiver@hello.com and go to your mail account settings (click on the little Gear and go to settings.) Make sure you're in your Mail settings, not your overall google account settings.

Then, hit up the "Accounts" tab and you'll see a section called "Send mail as...". This will be a little bit of a tedious process - but add each of the nicknames to this list:

  • Johnny@hello.com
  • Max@hello.com
  • Tiffany@hello.com
  • Kelly@hello.com


You'll have to verify each one with a code. When you add one of those e-mail addresses, Google will send you an e-mail (which will end up in the receiver@hello.com inbox) with a verification code. Just verify that code and leave the rest of the settings as is.

And that's it.

This is the key - you can "spoof" - not really spoof - "override" the "From" e-mail address from a piece of software with addresses that appear in the "Send mail as..." list.

Usually the issue that programmers run into is no matter what they set the "From" address to, if they use a Google Mail account - it will always be from that account.

This way it opens up a bit to a set number of addresses.

With this setup up, from the single receiver@hello.com account, I can send e-mails (programmatically and from Gmail itself) from

  • Johnny@teldio.com
  • Max@teldio.com
  • Tiffany@hello.com
  • Kelly@hello.com



So again - I know it's not as open as being able to send from absolutely any address - but it does open up the door for a lot of integrations. I myself have dealt with a lot of integrations that are looking for this exact solution.

Hope this helps out some peeps - if it's confusing at all, feel free to leave a comment and I'll get back to you asap.

[Update]

Alright - so there is an important update to this solution. It turns out that Google Apps / GMail actually puts a cap of 30 nicknames / aliases on each account. And our problem is that we had more than that.

So what's the solution - well it's to half do what I explained above and half not.


  1. Setup a single account to be your catch-all account for Incoming E-mail (rather than using nicknames and aliases)
  2. Still setup the "Send mail as..." accounts on that catch-all account.
The key here is that there seems to be no limit on the "Send mail as..." - so you can still send on behalf of all those accounts.

And instead of using nicknames / aliases - just use a catch-all account so that all your e-mails will end up in that account.