Wednesday, March 3, 2010

Drop-Dead Simple Authentication for Microapps

For Inspectinator (a sinatra microapp), I needed a database-less authentication solution that was as lightweight as possible, but with a reasonable amount of security and maintainability. I came up with something that suits this purpose well, and I'm sharing it in case anyone is looking for something similar. I call it EasyAuth.

To use EasyAuth to authenticate your sinatra app, you first need to generate hashed passwords for each user you want to allow into your system. You can do this easily in IRB:
$ irb -r lib/easy_auth/easy_auth.rb
irb(main):001:0> EasyAuth.hash_password("foobar")
=> "8843d7f92416211de9ebb963ff4ce28125932878"
This should be stored in your easy_auth.rb, in the AUTHORIZED_USERS hash.

Next, you mix-in EasyAuth, and in your password-protected route you do something like:
include EasyAuth

get '/admin' do
  if_auth do
    erb :'admin/index'
  end
end

post '/admin' do
  if_auth(params[:login], params[:password]) do
    redirect '/admin'
  end
end


EasyAuth yields to the block if authentication is successful (either based on the passed-in credentials, or cookies). It defaults to rendering /admin/login if not already authenticated, so throw a username/password form on that page and you should be good to go.

Sunday, February 14, 2010

Drop-Dead Simple Token Generation -- Fixnum#to_s

For Inspectinator, I needed a lightweight token generator to allow people to share their results. I found a great solution, and learned a cool ruby trick, too.

The trick is in Fixnum (and Bignum), #to_s takes an optional argument: a number in (2..36). That number is the base it will print the number in (default is 10).

So, for instance (from the ruby docs), to convert a number to binary:
12345654321.to_s(2)      #=> "1011011111110110111011110000110001"

For my token, I went with an 8-character, base 36 number, which gives me almost 3 trillion possible values (should be plenty). To get the 8 characters, I use rand(36**8). I don't do any checking on the length, so 8 is actually the max length (and 1 is the min). In practice, though, the vast majority of tokens will be the target length. On my system, I generated 10,000,000 tokens, and 9,722,373 were 8 characters. I chose to accept that as "close enough" because 1) it doesn't really matter to me if tokens are shorter, and 2) I think the simplicity and elegance of this solution is worth a little uncertainty.

Then, (since I'm using active record), it's just a matter of adding a before_create to set it up:
def set_token
  t = nil
  begin
    t = rand(36**8).to_s(36)
  end while InspectString.find_by_token(t)

  self.token = t
end

Announcing Inspectinator

I've been wanting to experiment with sinatra for a while, so I popped something off my things-to-do-someday list and put together Inspectinator.  It's aim is pretty straight-forward: parse standard ruby #inspect strings into a more palatable form.  It parses a string into a system of nested objects, and displays it as a tree.  Some simple jQuery let's you drill down to the level of detail you want.  You can also link to your results (like pastie for inspects).

Obviously #inspect output can be overridden to anything, but as long as it's along the lines of standard ruby or rails forms, it should be parseable.  If you find something that won't parse (or parses wrong), hit the link at the top ("Parse Error?") and I'll have a look.

It's still in development, and I'm definitely open to thoughts/suggestions about improvements.

Sunday, August 30, 2009

Ruby Hoedown '09

This weekend I was in Nashville, TN for Ruby Hoedown 2009.  There were some great talks -- my favorites were Ben Mabey's Cucumber talk, Luigi Montanez's talk on using public data APIs for civic coding, and Jim Weirich's excellent (and impromtu) talk on Git's internals.

After my recent difficulties with getting Rhodes working for mobile development, I was really excited about Leon Gersing's talk about Appcelerator Titanium, but I missed all but the last five minutes of it because the schedule was changed for some reason (I was skipping what I *thought* was something else). =/  Hopefully he'll post some slides.

The resort where the event was held was horrid, but the conference was a lot of fun.  Hope they continue this next year.

Monday, August 24, 2009

Erlang & Ruby -- Ring Network

As part of my Erlang self-education, I'm doing a selection of sample problems (from the "Programming Erlang" book) in both Erlang and my language of choice: Ruby. The idea is to explore the differences between these very different languages.

Today's problem is to write a ring network benchmark. Given a network of N nodes, where each node is pointing to the next in line (or back to the first), each node should forward a received message along, until it has gone around the ring M times (so that a total of N * M messages are sent).

To start with, I came up with an Erlang module to spawn a set of processes, and pass along a message record. It was pretty ugly at first, but with a little refactoring it turned out alright:
-module(ring_network).
-export([start_ring/1, start_message/3]).

-record(message,
  {loops_remaining=300,
    times_sent = 0,
    runtime, wall_clock, owner, note}).

start_ring(N) ->
  spawn(fun() -> 
        FirstPid = start_ring(N-1, self()),
        io:format("Starting node ~p (~p) pointing to ~p~n",
          [N, self(), FirstPid]),
        loop(N, FirstPid) end).

start_ring(N, Next) ->
  Pid = start_node(N, Next),
  if
    N > 1 -> start_ring(N-1, Pid);
    true  -> Pid
  end.

start_node(Id, Next) ->
  spawn(fun() -> 
        io:format("Starting node ~p (~p) pointing to ~p~n",
          [Id, self(), Next]),
        loop(Id, Next)
    end).

start_message(Pid, Msg, N) ->
  {Runtime, _} = statistics(runtime),
  {WallClock, _} = statistics(wall_clock),
  Pid ! #message{
    loops_remaining = N,
    runtime         = Runtime,
    wall_clock      = WallClock,
    owner           = Pid,
    note            = Msg}.

loop(Id, Next) ->
  receive
    Message ->
      case Message#message.owner == self() of
        false ->
          Next ! Message#message{
            times_sent = Message#message.times_sent+1},
          loop(Id, Next);
        true ->
          case Message#message.loops_remaining == 0 of
            false ->
              Next ! Message#message{
                times_sent = Message#message.times_sent + 1,
                loops_remaining = Message#message.loops_remaining - 1},
              loop(Id, Next);
            true -> 
              print_totals(Message),
              loop(Id, Next)
          end
      end
  end.

print_totals(Message) ->
  {R2, _} = statistics(runtime),
  {W2, _} = statistics(wall_clock),
  U1 = (R2 - Message#message.runtime),
  U2 = (W2 - Message#message.wall_clock),
  io:format("~n"),
  io:format("Sent '~p' ~p times in..~n",
    [Message#message.note, Message#message.times_sent]),
  io:format("  Runtime: ~p milliseconds~n", [U1]),
  io:format("  WallClock: ~p milliseconds~n", [U2]).



Next I applied the same pattern in ruby. I created a Node class, told it where the next node was, and had it forward messages along the proper number of times:
class Node
  attr_accessor :next_node, :number

  def initialize(number, next_node = nil)
    @number = number
    @next_node = next_node
  end

  def self.ring_network(node_count)
    nodes = Array.new(node_count)
    nodes[0] = Node.new(1)
    (1..node_count-1).each do |i|
      nodes[i] = Node.new(i+1, nodes[i-1])
    end
    nodes[0].next_node = nodes[-1]
    nodes[-1]
  end

  def gets_message(msg)
    if msg.owner == self.object_id
      if (msg.passes_remaining-=1) == 0
        msg.print_totals
        return
      end
    end
    msg.owner = self.object_id if msg.owner.nil?

    msg.total_passes += 1
    next_node.gets_message(msg)
  end
end

class Message
  attr_accessor :runtime, :wallclock, :note,
    :passes_remaining, :owner, :start_time, :total_passes

  def initialize(note, passes_remaining = 300)
    @total_passes = 0
    @start_time = Time.now
    @note = note
    @passes_remaining = passes_remaining
  end

  def print_totals
    puts
    puts "Sent #{total_passes} messages in..."
    puts "  WallClock: #{(Time.now - @start_time) * 1000} milliseconds"
  end
end



The first impression is just what you'd expect: Ruby is easier to read, and erlang is *much* faster:
1> Pid = ring_network:start_ring(10).
Starting node 10 (<0.59.0>) pointing to <0.68.0>
Starting node 9 (<0.60.0>) pointing to <0.59.0>
Starting node 8 (<0.61.0>) pointing to <0.60.0>
Starting node 7 (<0.62.0>) pointing to <0.61.0>
Starting node 6 (<0.63.0>) pointing to <0.62.0>
Starting node 5 (<0.64.0>) pointing to <0.63.0>
Starting node 4 (<0.65.0>) pointing to <0.64.0>
Starting node 3 (<0.66.0>) pointing to <0.65.0>
Starting node 2 (<0.67.0>) pointing to <0.66.0>
Starting node 1 (<0.68.0>) pointing to <0.67.0>
<0.59.0>

2> ring_network:start_message(Pid, hello_world, 300).
{message,300,0,270,298496,<0.59.0>,hello_world}
  
Sent 'hello_world' 3000 times in..  
  Runtime: 0 milliseconds
  WallClock: 3 milliseconds


Versus...
irb(main):001:0> node = Node.ring_network(10); msg = Message.new('Hi!', 300); node.gets_message(msg)

Sent 3000 messages in...
  WallClock: 79.336 milliseconds
=> nil


The real difference comes out when you increase the numbers:
(Erlang):
1> Pid = ring_network:start_ring(10000).
<0.33.0>

2> ring_network:start_message(Pid, hello_world, 10000).
{message,10000,0,460,40488,<0.33.0>,hello_world}
  
Sent 'hello_world' 100000000 times in..
  Runtime: 95350 milliseconds
  WallClock: 157455 milliseconds



(Ruby):
irb(main):002:0> node = Node.ring_network(100); msg = Message.new('Hi!', 300); node.gets_message(msg)
SystemStackError: stack level too deep
  from ./ring_network.rb:29:in 'gets_message'
  from ./ring_network.rb:29:in 'gets_message'
  from (irb):2
  from :0



In both cases, we're using recursion to wait for another message after processing one. In Erlang's case, though, it compiles tail recursion as a JUMP statement, which doesn't eat up stack space. Ruby doesn't do this, which is why I get a "stack too deep" when I up the number of loops. To get around this in ruby, I would have to move towards the Erlang module of forking off separate processes (not just separate instances), each listening for some interprocess communication.

Erlang & Ruby

I've been playing around with Erlang lately, and it's been quite a departure from the language I'm most comfortable with (and use everyday): Ruby. As part of my exploration, I'm doing a variety of sample problems (from the "Programming Erlang" book, among other places) in both Ruby and Erlang, and comparing the different implementations I come up with. Erlang and Ruby are meant to solve different types of problems, and the apples-to-oranges nature of the comparison should be kept in mind. The goal is to improve both my Erlang and my Ruby.

I'll be posting on this periodically under the tag erlang_ruby.

Wednesday, August 19, 2009

ActiveRecord Callbacks Trigger on Clean Objects

I came across this issue the other day at work, and I'm not really sure how I feel about it. It doesn't necessarily seem right or wrong, but was definitely unintuitive for me...

Since Rails 2.1, we have had dirty object checking, which prevents ActiveRecord from saving an object if if hasn't changed:
>> person = Person.first
  Person Load (0.9ms)   SELECT * FROM "people" LIMIT 1
=> #<Person id: 1, first_name: "Patrick", last_name: "Schless", nickname: nil, created_at: "2009-08-20 02:21:13", updated_at: "2009-08-20 02:22:32">

>> person.save
=> true

>> person.nickname = "nick"
=> "nick"

>> person.save
  Person Update (20.6ms)   UPDATE "people" SET "updated_at" = '2009-08-20 02:31:17', "nickname" = 'nick' WHERE "id" = 1
=> true


That part is good, but what happens when you have a callback defined?
>> Person.after_save { puts 'After save...' }
=> [#<ActiveSupport::Callbacks::Callback:0xb7147898 @identifier=nil, @method=#<Proc:0xb71479d8@(irb):6>, @kind=:after_save, @options={}>]

>> person.nickname = nil
=> nil

>> person.save
  Person Update (2.4ms)   UPDATE "people" SET "updated_at" = '2009-08-20 02:33:21', "nickname" = NULL WHERE "id" = 1
After save...
=> true

>> person.save
After save...
=> true


As we see there, the callback gets triggered even if the save is short-circuited.

In my trivial example, the behavior isn't terribly important either way. However, if your callback is doing something relatively expensive it may be pointless (and wasteful) to do that on a clean object. There are certainly situations where you would want it to always trigger, so I guess it's just one of those things that a developer ought to keep in the back of his mind when coding.