Sunday, April 3, 2011

Ruby on Rails time zone

The following are all the timezones in Ruby on Rails 3  (as of Rails 3.0.5)

We can set it in config/application.rb, as

config.time_zone = 'Pacific Time (US & Canada)'

Note that it needs to be the exact string -- if we use:

config.time_zone = 'Pacific Time'      # NOT GOOD

it will stop the server from starting up.

The line Time.zone = 'Pacific Time (US & Canada)'   can change the time zone in view, but in the controller, the time zone will still be UTC.

The way to get all Time Zones in Rails is:


$ rake time:zones:all

* UTC -11:00 *
International Date Line West
Midway Island
Samoa

* UTC -10:00 *
Hawaii

* UTC -09:00 *
Alaska

* UTC -08:00 *
Pacific Time (US & Canada)
Tijuana

* UTC -07:00 *
Arizona
Chihuahua
Mazatlan
Mountain Time (US & Canada)

[...]


* UTC +00:00 *
Casablanca
Dublin
Edinburgh
Lisbon
London
Monrovia
UTC

[...]


* UTC +08:00 *
Beijing
Chongqing
Hong Kong
Irkutsk
Kuala Lumpur
Perth
Singapore
Taipei
Ulaan Bataar
Urumqi

[...]


Wednesday, March 9, 2011

Ruby on Rails RESTful routing

The following is for Rails 2.3.8 using Ruby 1.8.7

It is for Rails scaffold, but it more or less describes how things are done in Rails.

First, there is nothing yet.


For the Create in CRUD:

We need a form to create a record (unless somebody directly use a program to send an HTTP request to our server). The form is generated by:

www.mysite.com/foos/new

the above generates a form in HTML.  It is a   GET /foos/new

nothing special there.

Note that for this form, when a user enters all the details, and click the "Create" button, it POST to /foos/ that is, it POST to www.mysite.com/foos/

the Rails's FoosController#create action will handle it.

the HTTP request is:

POST http://www.mysite.com/foos/ HTTP/1.1

Near the end of this create action, it redirects to http://www.mysite.com/foos/1

This is a GET /foos/1

and it is for the Retrieval in CRUD.

It is handled by FoosController#show action

GET http://www.mysite.com/foos/1 HTTP/1.1

For the Update in CRUD:

To edit something, we need a form, (unless using a program to directly submit the changes)


  http://www.mysite.com/foos/1/edit

it is just a GEThandled by FoosController#edit action

when user clicks Update button, it sends


POST http://www.mysite.com/foos/1 HTTP/1.1

The Rails development log says it is a PUT, but Fiddler on Windows shows that it is a POST

the POST variables are

_method=put&authenticity_token=9dMLgD4E6liD2%2Bo7dOVsBJ7B3Vdy9e2v%2F5bE36YgpYE%3D&foo%5Bs%5D=hi&foo%5Bi%5D=333&foo%5Bf%5D=2.0&foo%5Bnote%5D=wah&commit=Update

it is handled by FoosController#update action.

After the update, it redirects back to

http://www.mysite.com/foos/1

to show you the record again.

Now the Destroy in CRUD:

The Destroy link is in /foos  which shows all the records for foo

Click on Destroy, and it does a   POST http://www.mysite.com/foos/1 HTTP/1.1
with POST variables

_method=delete&authenticity_token=9dMLgD4E6liD2%2Bo7dOVsBJ7B3Vdy9e2v%2F5bE36YgpYE%3D

so it is not a DELETE. It is handled by FoosController#destroy

To summarize:


Which of CRUDto prepare the formcontroller and action to prepare the formwhen the real action of CRUD is happeningcontroller and action
CGET /foos/newFoosController#newPOST /foos/FoosController#create
RGET /foos/1FoosController#show
UGET /foos/editFoosController#editPOST /foos/1     _method=putFoosController#update
DGET /foos/FoosController#indexPOST /foos/1     _method=deleteFoosController#destroy


This is tested again using Ruby 1.9.2 and Rails 3.0.5, and the Update and Delete are done the same way: using a POST, with _method=put or _method=delete.


Saturday, February 26, 2011

How Ruby on Rails Session secret is generated or stored

Ruby on Rails's default session store is cookies, and it has all the info encoded in Base 64. So anybody can look at the info by Base64 decode. Note that often, even the user id of the logged in user is in the cookie, and the authenticated system installed or implemented on Rails will assume that this is the valid user id of the logged in user and fetch all data / settings, allow permission according to this user id. So how can Rails prevent somebody from faking to be another user?

It is by verifying the cookie data by encrypting with a secret key. Then the result is compared to the checksum tagged along in the session cookie. (The session cookie has 2 parts: the data, and the checksum).

When a Rails application is created, the secret key is automatically generated for you. So even if you don't specify a secret key, don't worry, one is already there:

Rails 2.2.2:
in config/environment.rb


# Your secret key for verifying cookie session data integrity.
# If you change this key, all old sessions will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
config.action_controller.session = {
:session_key => '_foobar_session',
:secret => '0d7d7d5ec0680cfd1d716bba057bce35a92a920a4471aa274ef0224ee52ebaa9eae43952418f7954fdef49b63d5b8eacc6efecf4bc2a29c45e8625a07f820e48'
}

Rails 2.3.8
in config/initializers/session_store.rb

# Your secret key for verifying cookie session data integrity.
# If you change this key, all old sessions will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
ActionController::Base.session = {
:key => '_foobar_session',
:secret => '81c3c1e81b899ea2cff8d9321a67df7c88978ad985a4b39118d2061f2f8b946392575cdff2e5e7cd83eb0493ba200eb07c51d11cd191a681dbdb19673f2d0da7'
}

Rails 3.0.4
in config/initializers/secret_token.rb

# Your secret key for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
Foobar::Application.config.secret_token = 'ce90ddf2fb13e290e077fc8a3ac865a52fde53595fe905af032fd07301a1715c2f6efd28c285c3543cbd45b27107fb95ed7d6778c28cc1225c1157e0fa69bf25'



Ruby on Rails Restful Authentication - How it works

This is an overview of how Restful Authentication works. Restful Authentication a Ruby on Rails plugin. You install it, and the code is in

vendor/plugins/restful_authentication

if your directory is restful-authentication (a hyphen instead of an underscore, then you probably want to rename it to using an underscore, because as stated in the GitHub, there is an issue if it is not.

A method of major importance is

current_user

Note that it looks like a variable, but it is actually a method. It returns the current logged in user. Note that it is actually a User object, so you can use the fields in the users table in the database as you wish. So for example, if your Rails application is to add a blog post to the database, and how do you know who the author is of this blog post? It is current_user.id

Another important method is logged_in? It merely returns whether current_user is equal to false or nil. (Technically, it does a !!current_user, which is to booleanize the value to true or false. In Ruby, only a false or nil will become false that way. Any other value will become true). So when you need to understand how the whole system works when it comes to logged_in?, merely think about current_user == false or nil is the comparison it does.

If you ever need to change Restful Authentication in any way, such as adding log in using OpenID, or using OmniAuth, or JanRain (log in using Facebook, Twitter, Gmail, AOL, Yahoo account, etc), or Facebook Connect, then it is important to understand how Restful Authentication works.

The most important element there is to understand that current_user checks against 3 things:

1. The user id stored in the Rails session (cookie or in DB, or in any other mechanism). This is how a page request to the next page request keep remembering who the user is, until the user closes and exit the browser, at which time the session will go away.

2. HTTP Basic Authentication. We can skip this part usually, because it uses a rare authenticated system which you see sometimes a website pops up an application window asking you for username and password, and won't show content if it is not. (it'd probably say 401 - Unauthorized)

3. If the user exits the browser (or turn off the computer and come back an hour later or 2 days later), then if the user actually checked the checkbox "Remember me" when that user logged in previously, then there is a "remember me" cookie. This cookie has a value which can be checked against the remember_me field in the users table. It they match, then the Restful Authentication will also think the user has come back and let current_user return this user. The name of this cookie usually is auth_token.

Also worth noting is that when the current_user needs to be set (if you are modifying Restful Authentication), then use self.current_user = a_user. Look into the code -- a good portion of the code is in your project after you run the Restful Authentication generator (when you or somebody who ran it long time ago):

lib/authenticated_system.rb

If you Google for any more info, note that the module name is AuthenticatedSystem.


Followers