Topic: Token generator

I would like to develop an application where the user can add records to the database without the need of register.
After that he will receive by email an url  to edit or delete that record.

A good example of this approach is doodle.
In doodle we can add an appointment/schedule without register. After that we will receive by email the url where other people can contribute and the url to edit or delete the appointment.
For instance, the url is like that:

http://www.doodle.com/6zd6r3fspv2cpq59 -> For  visualization and participation of other persons
http://www.doodle.com/6zd6r3fspv2cpq597r4fw29n/admin -> The link for the creator of the record. To edit or delete the pool.

My approach is similar. I would like to have a token for edit or delete and a partial (part of) token for visualization. What will be the best approach for this ?

I can generate the token with a random string or a UUID to be the unique id of my table. The problem is with the partial of that token because I can’t guarantee that when I truncate the token I don’t get more than one record. I’m missing something ? What is your advice for this particular case?

You opinion and help is highly appreciated.

Best regards,

Re: Token generator

Funnily enough, I just implemented exactly that. :-)

To the model for which you'd like to use the token as an id, add a string field "token" to the database to store the token, then to the model add:

before_save :create_token
  
def to_param 
  token
end
 
def create_token
  begin
    # self.token =  SecureRandom.urlsafe_base64(len=7)
    # self.token =  SecureRandom.hex.to_i(16).base62_encode[0..9]
    self.token =  SecureRandom.hex(len=7).to_i(16).to_s(36)[0..9].upcase
  end while self.class.exists?(token: token) # ensure uniqueness
end

def to_param lets the token act as the id. In the controller you will need to use: @model = Model.find_by_token(params[:id]) etc.

"end while self.class.exists?" ensures the token is unique, even if you truncate the generated token.

I've included a few options depending on how you want the URL to appear. url_safe_base64 has the most entropy per string of length n, but means that as well as uppercase, lowercase and numeric, it includes - and _.

Base62 is alphanumeric only, but you will need the base62 gem in your gemfile, and "include 'base62'" somewhere (the model if it's the only place you use it).

I opted for base36 - single case alpha-numeric, which I'm truncating to 10 characters, and converting to uppercase (it's lower-case be default which matches your example).

hope that helps!

Last edited by scooter (2012-06-07 17:46:27)

Re: Token generator

Oh, also if you want the token to work off the root URL as in your example, try something along the lines of:

match '/:id' => 'model#show', :constraints => { :id => /[a-z0-9]*/ }, :as => 'show_token'

in your routes.rb.

The ':constraints' and ':as' are optional...

Re: Token generator

Scooter,

Thanks a lot for your contribution. It's exactly what I was looking for.

Best regards,

Venas

Re: Token generator

Thanks a lot for your contribution. It's exactly what I was looking for.