<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://felixhanley.info/</id>
  <title>Felix Hanley's articles et al</title>
  <updated>2012-04-03T14:00:00Z</updated>
  <link rel="alternate" href="http://felixhanley.info/"/>
  <link rel="self" href="http://felixhanley.info/atom.xml"/>
  <author>
    <name>Felix Hanley</name>
    <uri>http://felixhanley.info</uri>
  </author>
  <entry>
    <id>tag:felixhanley.info,2012-04-04:/projects/timetrackr/</id>
    <title type="html">timetrackr - simple time tracking</title>
    <published>2012-04-03T14:00:00Z</published>
    <updated>2011-04-03T14:00:00Z</updated>
    <link rel="alternate" href="http://felixhanley.info/projects/timetrackr/"/>
    <content type="html">&lt;p&gt;A simple CLI time tracking utility.&lt;/p&gt;

&lt;h2 id="install"&gt;Install&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;$ gem install timetrackr
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="example"&gt;Example&lt;/h2&gt;

&lt;p&gt;(with a Bash alias of ‘tt’)&lt;/p&gt;

&lt;p&gt;start a task:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt start something
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…view durations:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt
something *     0h  0m  4s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…have two running tasks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt start another-thing
$ tt log
2011-05-18   something *     22:11            0h  0m 30s
             another-thing * 22:11            0h  0m 15s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…start with a note:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt start one-more with a note
$ tt log
2011-05-18   something *     22:11            0h  0m 45s
             another-thing * 22:11            0h  0m 30s
             one-more *      22:13            0h  0m 15s  with a note
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…restrict some:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt log something
2011-05-18   something *     22:11            0h  1m 00s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…exclude some:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt log something -n another-thing
2011-05-18   something *     22:11            0h  1m 15s
             one-more *      22:13            0h  0m 45s  with a note
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…stop one (or more):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt stop something
$ tt
something       0h  1m 20s
another-thing * 0h  1m 30s
one-more *      0h  1m 15s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…and delete one:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ tt clear something
another-thing * 0h  1m 45s
one-more *      0h  1m 30s
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="source"&gt;Source&lt;/h2&gt;

&lt;p&gt;From &lt;a href="http://git.seconddrawer.com.au/timetrackr"&gt;my Git repository&lt;/a&gt; or on
&lt;a href="https://github.com/felix/timetrackr"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:felixhanley.info,2011-03-11:/articles/rails-role-based-access-with-cancan/</id>
    <title type="html">Role based access (RBAC) for Rails</title>
    <published>2011-03-10T13:00:00Z</published>
    <updated>2011-03-10T13:00:00Z</updated>
    <link rel="alternate" href="http://felixhanley.info/articles/rails-role-based-access-with-cancan/"/>
    <content type="html">&lt;p&gt;The basics of a role based access control system using Ruby on Rails,
&lt;a href="https://github.com/ryanb/cancan/"&gt;CanCan&lt;/a&gt; and
&lt;a href="https://github.com/plataformatec/devise"&gt;Devise&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;

&lt;p&gt;This are often the requirements/desires I have with an
authentication/authorisation system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;customisable&lt;/li&gt;
  &lt;li&gt;a variety of storage choices (DB, YAML etc.)&lt;/li&gt;
  &lt;li&gt;the ability to change access from within the application (think nice
permission assignments&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;RBAC authorisation is reasonably common in larger projects and is well described
in the &lt;a href="http://en.wikipedia.org/wiki/Role-based_access_control"&gt;Wikipedia
article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We would like &lt;em&gt;users&lt;/em&gt; to be assigned &lt;em&gt;roles&lt;/em&gt; and roles enabling a number of
&lt;em&gt;permissions&lt;/em&gt;. A user may have a number of different roles meaning the
permissions available for each of their roles is combined.&lt;/p&gt;

&lt;p&gt;So we will be able to access a user’s permissions (using DataMapper) like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-ruby"&gt;u = &lt;span class="constant"&gt;User&lt;/span&gt;.get(&lt;span class="integer"&gt;1&lt;/span&gt;)
u.roles.permissions.each {|perm|
  &lt;span class="comment"&gt;#...&lt;/span&gt;
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="models"&gt;Models&lt;/h2&gt;

&lt;p&gt;First of all, get devise and cancan installed and basically configured within
your application. I won’t cover this here.&lt;/p&gt;

&lt;p&gt;These are the models that we will eventually have and their corresponding
relationships. These examples use DataMapper.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;User&lt;/span&gt;
  include &lt;span class="constant"&gt;DataMapper&lt;/span&gt;::&lt;span class="constant"&gt;Resource&lt;/span&gt;

  &lt;span class="comment"&gt;# devise setup&lt;/span&gt;
  devise &lt;span class="symbol"&gt;:database_authenticatable&lt;/span&gt;, &lt;span class="symbol"&gt;:registerable&lt;/span&gt;,
    &lt;span class="symbol"&gt;:recoverable&lt;/span&gt;, &lt;span class="symbol"&gt;:rememberable&lt;/span&gt;, &lt;span class="symbol"&gt;:trackable&lt;/span&gt;, &lt;span class="symbol"&gt;:validatable&lt;/span&gt;


  property &lt;span class="symbol"&gt;:id&lt;/span&gt;, &lt;span class="constant"&gt;Serial&lt;/span&gt;
  property &lt;span class="symbol"&gt;:email&lt;/span&gt;, &lt;span class="constant"&gt;String&lt;/span&gt;, &lt;span class="symbol"&gt;:required&lt;/span&gt; =&amp;gt; &lt;span class="predefined-constant"&gt;true&lt;/span&gt;, &lt;span class="symbol"&gt;:unique&lt;/span&gt; =&amp;gt; &lt;span class="predefined-constant"&gt;true&lt;/span&gt;, &lt;span class="symbol"&gt;:format&lt;/span&gt; =&amp;gt; &lt;span class="symbol"&gt;:email_address&lt;/span&gt;
  property &lt;span class="symbol"&gt;:active&lt;/span&gt;, &lt;span class="constant"&gt;Boolean&lt;/span&gt;
  &lt;span class="comment"&gt;# ...&lt;/span&gt;

  has n, &lt;span class="symbol"&gt;:roles&lt;/span&gt;, &lt;span class="symbol"&gt;:through&lt;/span&gt; =&amp;gt; &lt;span class="constant"&gt;Resource&lt;/span&gt;
  &lt;span class="comment"&gt;# ...&lt;/span&gt;

  &lt;span class="comment"&gt;# for assignment of roles&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;role_ids=&lt;/span&gt;(ids)
    &lt;span class="predefined-constant"&gt;self&lt;/span&gt;.roles.clear
    ids.delete_if{|i| i.empty?}.each &lt;span class="keyword"&gt;do&lt;/span&gt; |id|
      &lt;span class="predefined-constant"&gt;self&lt;/span&gt;.roles &amp;lt;&amp;lt; &lt;span class="constant"&gt;Role&lt;/span&gt;.get(id)
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;has_role?&lt;/span&gt;(role_sym)
    roles.any? { |r| r.name.underscore.to_sym == role_sym }
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;role?&lt;/span&gt;(role)
    &lt;span class="keyword"&gt;return&lt;/span&gt; !!&lt;span class="predefined-constant"&gt;self&lt;/span&gt;.roles.first(&lt;span class="symbol"&gt;:name&lt;/span&gt; =&amp;gt; role.to_s.camelize)
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Role&lt;/span&gt;
  include &lt;span class="constant"&gt;DataMapper&lt;/span&gt;::&lt;span class="constant"&gt;Resource&lt;/span&gt;

  property &lt;span class="symbol"&gt;:id&lt;/span&gt;, &lt;span class="constant"&gt;Serial&lt;/span&gt;
  property &lt;span class="symbol"&gt;:name&lt;/span&gt;, &lt;span class="constant"&gt;String&lt;/span&gt;
  property &lt;span class="symbol"&gt;:description&lt;/span&gt;, &lt;span class="constant"&gt;Text&lt;/span&gt;
  &lt;span class="comment"&gt;# ...&lt;/span&gt;

  has n, &lt;span class="symbol"&gt;:users&lt;/span&gt;, &lt;span class="symbol"&gt;:through&lt;/span&gt; =&amp;gt; &lt;span class="constant"&gt;Resource&lt;/span&gt;
  has n, &lt;span class="symbol"&gt;:permissions&lt;/span&gt;, &lt;span class="symbol"&gt;:through&lt;/span&gt; =&amp;gt; &lt;span class="constant"&gt;Resource&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We are using the anonymous join model &lt;em&gt;Resource&lt;/em&gt; to link users and roles. We
could quite easily make an actual model to hold extra information (for a
history, perhaps).&lt;/p&gt;

&lt;p&gt;There are a few extra methods in the User model to help with the assignment of
roles. This is DataMapper’s way of overriding accessors and enables specific
implementations.&lt;/p&gt;

&lt;h2 id="cancan-setup"&gt;CanCan setup&lt;/h2&gt;

&lt;p&gt;The permissions for many applications are closely tied to the application’s
code. The checks are hard coded into the application. If this is the case there
is no need to have the permissions taken from the database. The roles, yes, but
the defining permissions will only ever change with the application code.&lt;/p&gt;

&lt;p&gt;We can then put the permissions in a static file (YAML) in this case and have it
read by the app when needed. CanCan’s ‘ability’ model is a good place to do
this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Ability&lt;/span&gt;
  include &lt;span class="constant"&gt;CanCan&lt;/span&gt;::&lt;span class="constant"&gt;Ability&lt;/span&gt;

  &lt;span class="class-variable"&gt;@@permissions&lt;/span&gt; = &lt;span class="predefined-constant"&gt;nil&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;initialize&lt;/span&gt;(user)
    &lt;span class="predefined-constant"&gt;self&lt;/span&gt;.clear_aliased_actions

    alias_action &lt;span class="symbol"&gt;:index&lt;/span&gt;, &lt;span class="symbol"&gt;:show&lt;/span&gt;, &lt;span class="symbol"&gt;:to&lt;/span&gt; =&amp;gt; &lt;span class="symbol"&gt;:read&lt;/span&gt;
    alias_action &lt;span class="symbol"&gt;:new&lt;/span&gt;,          &lt;span class="symbol"&gt;:to&lt;/span&gt; =&amp;gt; &lt;span class="symbol"&gt;:create&lt;/span&gt;
    alias_action &lt;span class="symbol"&gt;:edit&lt;/span&gt;,         &lt;span class="symbol"&gt;:to&lt;/span&gt; =&amp;gt; &lt;span class="symbol"&gt;:update&lt;/span&gt;
    alias_action &lt;span class="symbol"&gt;:destroy&lt;/span&gt;,      &lt;span class="symbol"&gt;:to&lt;/span&gt; =&amp;gt; &lt;span class="symbol"&gt;:delete&lt;/span&gt;

    user ||= &lt;span class="constant"&gt;User&lt;/span&gt;.new

    &lt;span class="comment"&gt;# super user can do everything&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; user.role? &lt;span class="symbol"&gt;:super&lt;/span&gt;
      can &lt;span class="symbol"&gt;:manage&lt;/span&gt;, &lt;span class="symbol"&gt;:all&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="comment"&gt;# edit update self&lt;/span&gt;
      can &lt;span class="symbol"&gt;:read&lt;/span&gt;, &lt;span class="constant"&gt;User&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |resource|
        resource == user
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      can &lt;span class="symbol"&gt;:update&lt;/span&gt;, &lt;span class="constant"&gt;User&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |resource|
        resource == user
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="comment"&gt;# enables signup&lt;/span&gt;
      can &lt;span class="symbol"&gt;:create&lt;/span&gt;, &lt;span class="constant"&gt;User&lt;/span&gt;

      user.roles.each &lt;span class="keyword"&gt;do&lt;/span&gt; |role|
        &lt;span class="keyword"&gt;if&lt;/span&gt; role.permissions
          role.permissions.each &lt;span class="keyword"&gt;do&lt;/span&gt; |perm_name|
            &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="constant"&gt;Ability&lt;/span&gt;.permissions[perm_name].nil?
              can(&lt;span class="constant"&gt;Ability&lt;/span&gt;.permissions[perm_name][&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;action&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;].to_sym, &lt;span class="constant"&gt;Ability&lt;/span&gt;.permissions[perm_name][&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;subject_class&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;].constantize) &lt;span class="keyword"&gt;do&lt;/span&gt; |subject|
                &lt;span class="constant"&gt;Ability&lt;/span&gt;.permissions[perm_name][&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;subject_id&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;].nil? ||
                  &lt;span class="constant"&gt;Ability&lt;/span&gt;.permissions[perm_name][&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;subject_id&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;] == subject.id
              &lt;span class="keyword"&gt;end&lt;/span&gt;
            &lt;span class="keyword"&gt;end&lt;/span&gt;
          &lt;span class="keyword"&gt;end&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="predefined-constant"&gt;self&lt;/span&gt;.&lt;span class="function"&gt;permissions&lt;/span&gt;
    &lt;span class="class-variable"&gt;@@permissions&lt;/span&gt; ||= &lt;span class="constant"&gt;Ability&lt;/span&gt;.load_permissions
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="predefined-constant"&gt;self&lt;/span&gt;.&lt;span class="function"&gt;load_permissions&lt;/span&gt;(file=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;permissions.yml&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
    &lt;span class="constant"&gt;YAML&lt;/span&gt;.load_file(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;::&lt;span class="constant"&gt;Rails&lt;/span&gt;.root.to_s&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;/config/&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;file&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This logic is up to you and your project but the above basic implementation does
the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;adds another action alias, &lt;em&gt;modify&lt;/em&gt;
&lt;/li&gt;
  &lt;li&gt;enables the super user to do everything&lt;/li&gt;
  &lt;li&gt;enables the authenticated user to modify (edit, destroy) themselves&lt;/li&gt;
  &lt;li&gt;creates a bunch of abilites taken from the YAML permissions file&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;You can then start using the &lt;em&gt;action&lt;/em&gt;, &lt;em&gt;subject&lt;/em&gt; and optional &lt;em&gt;object&lt;/em&gt;
paramaters with CanCan to check for permissions for which the CanCan
documentation has many examples.&lt;/p&gt;

&lt;h2 id="initial-setup"&gt;Initial Setup&lt;/h2&gt;

&lt;p&gt;We can then define a few roles to seed the database with for use later. Put
this in db/seed.rb:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-ruby"&gt;super_user = &lt;span class="constant"&gt;User&lt;/span&gt;.create(&lt;span class="symbol"&gt;:email&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;super@example.com&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:firstname&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Super&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:surname&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;User&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:password&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;password&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:password_confirmation&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;password&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:active&lt;/span&gt; =&amp;gt; &lt;span class="predefined-constant"&gt;true&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:created_at&lt;/span&gt; =&amp;gt; &lt;span class="constant"&gt;Time&lt;/span&gt;.now)
admin_user = &lt;span class="constant"&gt;User&lt;/span&gt;.create(&lt;span class="symbol"&gt;:email&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;admin@example.com&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:firstname&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Admin&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:surname&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;User&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:password&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;password&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:password_confirmation&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;password&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:active&lt;/span&gt; =&amp;gt; &lt;span class="predefined-constant"&gt;true&lt;/span&gt;,
                         &lt;span class="symbol"&gt;:created_at&lt;/span&gt; =&amp;gt; &lt;span class="constant"&gt;Time&lt;/span&gt;.now)
user = &lt;span class="constant"&gt;User&lt;/span&gt;.create(&lt;span class="symbol"&gt;:email&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;user@example.com&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                   &lt;span class="symbol"&gt;:firstname&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;User&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                   &lt;span class="symbol"&gt;:surname&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;User&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                   &lt;span class="symbol"&gt;:password&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;password&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                   &lt;span class="symbol"&gt;:password_confirmation&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;password&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
                   &lt;span class="symbol"&gt;:active&lt;/span&gt; =&amp;gt; &lt;span class="predefined-constant"&gt;true&lt;/span&gt;,
                   &lt;span class="symbol"&gt;:created_at&lt;/span&gt; =&amp;gt; &lt;span class="constant"&gt;Time&lt;/span&gt;.now)

&lt;span class="comment"&gt;# create roles&lt;/span&gt;
super_role = &lt;span class="constant"&gt;Role&lt;/span&gt;.create(&lt;span class="symbol"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;super&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="symbol"&gt;:description&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Super user&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
admin_role = &lt;span class="constant"&gt;Role&lt;/span&gt;.create(&lt;span class="symbol"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;admin&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="symbol"&gt;:description&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Admin user&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
user_role  = &lt;span class="constant"&gt;Role&lt;/span&gt;.create(&lt;span class="symbol"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;user&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="symbol"&gt;:description&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Normal user&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)

&lt;span class="comment"&gt;# get our permissions&lt;/span&gt;
permissions = &lt;span class="constant"&gt;YAML&lt;/span&gt;.load_file(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;::&lt;span class="constant"&gt;Rails&lt;/span&gt;.root.to_s&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;/config/permissions.yml&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)

&lt;span class="comment"&gt;# assign permissions&lt;/span&gt;
admin_role.permissions = permissions.collect{|n,p| n}
admin_role.save

&lt;span class="comment"&gt;# assign roles&lt;/span&gt;
super_user.roles &amp;lt;&amp;lt; super_role
super_user.save
admin_user.roles &amp;lt;&amp;lt; admin_role
admin_user.save
user.roles &amp;lt;&amp;lt; user_role
user.save&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The actual permissions seeded will be entirely up to you and your application
but this sets up a few basics for one model.&lt;/p&gt;

&lt;h2 id="further"&gt;Further&lt;/h2&gt;

&lt;p&gt;This also enables you to have a nice report of the roles and their permissions
much like the following:
&lt;img src="/images/articles/rbac-report.png" alt="RBAC report screenshot"&gt;&lt;/p&gt;

&lt;p&gt;This can be created in the view something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-ruby"&gt;= form_tag({&lt;span class="symbol"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;roles&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="symbol"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;report&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;}, &lt;span class="symbol"&gt;:method&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;post&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;span class="keyword"&gt;do&lt;/span&gt;
  %table
    %tr
      %th= &lt;span class="constant"&gt;Role&lt;/span&gt;.human_attribute_name(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;permissions&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
      - &lt;span class="instance-variable"&gt;@roles&lt;/span&gt;.sort.each &lt;span class="keyword"&gt;do&lt;/span&gt; |role|
        %th
          = role.name
          = hidden_field_tag &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;permissions[&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;role.name&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;][]&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
    - &lt;span class="constant"&gt;Ability&lt;/span&gt;.permissions.each &lt;span class="keyword"&gt;do&lt;/span&gt; |pname, pdetails|
      %tr
        %td= pdetails[&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;description&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;]
        - &lt;span class="instance-variable"&gt;@roles&lt;/span&gt;.sort.each &lt;span class="keyword"&gt;do&lt;/span&gt; |role|
          %td
            = check_box_tag &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;permissions[&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;role.name&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;][]&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, pname, role.permissions.include?(pname)
  %fieldset.actions
    = submit_tag &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Save&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="dynamic-permissions"&gt;Dynamic Permissions&lt;/h2&gt;

&lt;p&gt;It is quite possible that you may want to have dynamic permissions. For example,
to assign permissions to specific object instances or perhaps in an application
that accesses another service which changes.&lt;/p&gt;

&lt;p&gt;If this is the case, you will need to have the permissions based in a dynamic
datastore, most likely the same database. You would need to define a new model
to store them and update the associations and CanCan logic to do authorisation
checks.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:felixhanley.info,2011-01-01:/projects/tinydnsdyn/</id>
    <title type="html">tinydnsdyn - Dynamic DNS</title>
    <published>2010-12-31T13:00:00Z</published>
    <updated>2011-03-06T13:00:00Z</updated>
    <link rel="alternate" href="http://felixhanley.info/projects/tinydnsdyn/"/>
    <content type="html">&lt;p&gt;This is a basic dynamic client and server for the djbdns DNS 
server ‘tinydns’ by Dan Bernstein.&lt;/p&gt;

&lt;h2 id="requirements"&gt;Requirements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Administrative access to a server running tinydns and hence
daemontools or similar&lt;/li&gt;
  &lt;li&gt;Administrative access to a *nix box on you local network&lt;/li&gt;
  &lt;li&gt;Python (version 2!) installed on both client and server&lt;/li&gt;
  &lt;li&gt;An open port on the server’s firewall&lt;/li&gt;
&lt;/ul&gt;&lt;h2 id="installation"&gt;Installation&lt;/h2&gt;

&lt;p&gt;To install the server code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
    &lt;p&gt;Copy script and all files onto your server (i.e. /etc/tinydnsdyn/)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The supplied ‘run’ script is tailored for debian/ubuntu and may need to be
changed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can added dynamic DNS entries to your main data file or alternatively use
a seperate file for dynamic entries. An existing entry in the tinydns data
file should already exist. This script will NOT add one. Only those hosts
listed (with prefixes ‘+’ and ‘=’) are able to update their entries.&lt;/p&gt;

    &lt;p&gt;For example:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;+groucho.example.com:192.168.0.2:3360
+groucho.example.com:192.168.0.2
=groucho.example.com:192.168.0.2:60
+*.groucho.example.com:192.168.0.2:60
+*.groucho.example.com:192.168.0.2
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;will all get updated if the host groucho.example.com does a request.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create a password file. This is of the format created by Apache’s htpasswd
and consists of one user per line in the following format:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;username:crypted hash:optional,list,of,domains
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The script will run ‘make’ in the data directory. This enables you to
concatenate your data files and whatever else before they are compiled. For
instance, you may need to combine all your primary and seconary zones and
then add the dynamic hosts before compiling.&lt;/p&gt;

    &lt;p&gt;An example Makefile is included with some ideas.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Start the service by symlinking this directory into your svscan directory
(i.e. “ln $(pwd) /etc/service/” ).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The service operates over HTTP and should be reasonably close to the service
operated by DynDns.com having the following request format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://username:password@yourdnsserver.com/?hostname=yourhostname&amp;amp;myip=optionaladdress
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The only required parameter is the hostname you wish to change. This can be a
comma separated list of hostnames to update. The IP address will be determined
automatically if the ‘myip’ parameter is missing.&lt;/p&gt;

&lt;p&gt;The response codes are taken from here (not all of them):&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.dyndns.com/developers/specs/return.html"&gt;http://www.dyndns.com/developers/specs/return.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Python code is basic and inefficient but it should work. I take no
responsibility for anything that may happen to any of your machines.
That said, please let me know if there are any issues.&lt;/p&gt;

&lt;h2 id="source"&gt;Source&lt;/h2&gt;

&lt;p&gt;It can be downloaded from &lt;a href="http://git.seconddrawer.com.au/tinydnsdyn/"&gt;my Git
repository&lt;/a&gt; or from
&lt;a href="https://github.com/felix/tinydnsdyn"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:felixhanley.info,2010-08-22:/articles/webfonts-with-nginx/</id>
    <title type="html">Webfonts with Nginx</title>
    <published>2010-08-21T14:00:00Z</published>
    <updated>2010-08-21T14:00:00Z</updated>
    <link rel="alternate" href="http://felixhanley.info/articles/webfonts-with-nginx/"/>
    <content type="html">&lt;p&gt;I just made some changes on my site to use webfonts for the main menu and any
Lahu language sections of the site. I have chosen to serve the font files
directly from my server as most of the other webfont servers don’t provide a
good Unicode 5 version of any font required for Lahu display.&lt;/p&gt;

&lt;p&gt;This does mean that I needed to update my Nginx mime types to serve the font
files with the correct mime type. I added the following to my mime.types file in
the Nginx config directory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;application/x-font-ttf                ttf;
font/opentype                         otf;
application/vnd.ms-fontobject         eot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and reloaded Nginx. Now they are served correctly instead of
‘application/octet-stream’.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:felixhanley.info,2010-08-21:/articles/logwatch-with-runit/</id>
    <title type="html">Logwatch, socklog and svlogd</title>
    <published>2010-08-20T14:00:00Z</published>
    <updated>2010-08-20T14:00:00Z</updated>
    <link rel="alternate" href="http://felixhanley.info/articles/logwatch-with-runit/"/>
    <content type="html">&lt;p&gt;&lt;a href="http://smarden.org/runit/"&gt;Runit&lt;/a&gt; is a great package that provides process
supervision and can be used as a replacement for ‘sysvinit’. The author of the
package has also made a syslogd replacement called
&lt;a href="http://smarden.org/socklog/"&gt;socklog&lt;/a&gt; which works well with runit.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://logwatch.org/"&gt;Logwatch&lt;/a&gt; is a collection of scripts that can be used to
notify you of changes to your logs. Out of the box on a Debian machine, though,
logwatch will not be able to read all the logs spat out by socklog. The default
setup produces logs that have the log facility and level appended to the log
entry and the hostname removed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;authpriv.info: Aug 21 20:45:44 sshd: pam_unix(sshd...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I recently had to modify Logwatch for some other reasons and thought I would
post my existing scripts here for others to see also. These should be placed in
the /etc/logwatch directory so they are not overwritten on package upgrades.&lt;/p&gt;

&lt;p&gt;conf/logfiles/messages.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile = 
Archive = 
LogFile = socklog/*/current
Archive = socklog/*/@*

*RemoveFacility
*ExpandRepeats
*RemoveService = talkd,telnetd,inetd,nfsd,/sbin/mingetty
*ApplyStdDate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/syslog.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Logfile = 
Archive = 
LogFile = socklog/*/current
Archive = socklog/*/@*

*RemoveFacility
*ExpandRepeats
*RemoveService = talkd,telnetd,inetd,nfsd,/sbin/mingetty
*ApplyStdDate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/secure.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile = 
Archive = 
LogFile = socklog/auth/current
Archive = socklog/auth/@*

*RemoveFacility
*ExpandRepeats
*ApplyStdDate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/maillog.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile =
LogFile = socklog/mail/current
Archive =
Archive = socklog/mail/@*

*RemoveFacility
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/kernel.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile = socklog/kern/current
Archive = socklog/kern/@*
*RemoveFacility
*ExpandRepeats
*ApplyStdDate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There may be others needed for your own system. All these configurations
reference the script &lt;em&gt;RemoveFacility&lt;/em&gt; does the bit of removing the facility and
level from each log entry.&lt;/p&gt;

&lt;p&gt;scripts/shared/removefacility&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# removes the facility and level from logfiles generated by socklog
if ( $ENV{'LOGWATCH_DEBUG'} &amp;gt; 4 ) {
   print STDERR "DEBUG: Inside RemoveFacility\n";
}

while (defined($ThisLine = &amp;lt;STDIN&amp;gt;)) {
   $ThisLine =~ s/^[a-z]+.[a-z]+: //i;
   print $ThisLine;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and also the onlyhost script which is used to restrict entries by host but since
the hostname is not even there we just return them all:&lt;/p&gt;

&lt;p&gt;scripts/shared/onlyhost&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use strict;

my $line;
while (defined($line = &amp;lt;STDIN&amp;gt;)) {
    print $line;
}
&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
</feed>

