Category Archives: code

Rails Authorization Plugin

The Rails authorization plugin is a really nice way of providing role management and restrict access to specific features. It also works nicely with the RESTful authentication plugin which manages user login and authentication.

However, there is a serious lack of documentation of how to use this plugin – the README.txt inside the plugin and the source code is the best I have found. I also learnt some from the slides for the Railsconf 2006 on “Metaprogramming Writertopia”. This blog entry is collecting what I have learnt and also freely copies some text from the different sources.

Assuming you have installed the authorization plugin, you need to extend your models with the plugin. In particular the User model and the model(s) that you would like to use multiple user roles for.


class User < ActiveRecord::Base
# Authorization plugin
acts_as_authorized_user
...
end


class Account < ActiveRecord::Base
# Authorization plugin
acts_as_authorizable
...
end

The acts_as_authorized_user part of the plugin creates the following methods for the User model:

  • has_role? role_name [, authorizable_obj]: finds out if a user has a certain role (for a certain object)
  • has_role role_name [, authorizable_obj]: creates the role if non-existant, and assigns the role to the user (for a certain object)
  • has_no_role role_name [, authorizable_obj]: remove role from user (for a certain object), and the role if not in use any longer

As some background information, the plugin creates 2 tables – one for the roles (name, authorizable_type, authorizable_id, timestamps), and one that maps roles to users roles_users (user_id, role_id, timestamps). The authorizable_type and authorizable_id map the role to the authorizable_obj.

The acts_as_authorizable part of the plugin creates the following methods for the Account model:

  • accepts_role? role_name, user: finds out if the user has the role on the model
  • accepts_role role_name, user: sets the user to have the role on the model
  • accepts_no_role role_name, user: removes the user from having the role on the model

In the code, you can now use the following methods to create roles for users and accounts. Assuming we have a user ‘u’ and an account ‘a’, we can do one of the following to create the role ‘admin’:

  • u.has_role ‘admin’, a
  • a.accepts_role ‘admin’, u
  • u.is_admin_for a
  • u.is_admin (gives user the role ‘admin’, not tied to a class or object)

To check on roles, you can use the following:

  • u.has_role ‘admin’, a: return true/false if the user has the role ‘admin’ on the account
  • u.is_admin? a: return true/false if the user has the role ‘admin’ on the account
  • u.is_admin_of? a: return true/false if the user has the role ‘admin’ on the account
  • u.has_role ‘admin’: return true/false if the user has the role ‘admin’ on anything
  • u.is_admin?: return true/false if the user has the role ‘admin’ on anything
  • u.is_admin_of_what Account: returns array of objects for which this user is a ‘admin’ (only ‘Account’ type)
  • u.is_admin_of_what: returns array of objects for which this user is a ‘admin’ (any type)
  • a.accepts_role? ‘admin’, u: return true/false if the account has the user with the role ‘admin’
  • a.has_admin(s)?: return true/false if the account has users with the role ‘admin’
  • a.has_admin(s): returns array of users which have role ‘admin’ on the account

There are more dynamically generated methods and they are created through the method_missing hook. There is a whole domain-specific language behind this creation of methods. Just about everything that sounds like proper English will work.

An interesting twist is that roles can also be set on model classes: u.has_role 'admin', Account. So, roles can be set on one of the following three scopes:

  • entire application (no class or object specified)
  • model class
  • an instance of a model (i.e., a model object)

In your controller, you can now use two methods to check authorization at the class, instance, or instance method level: permit and permit?. permit and permit? take an authorization expression and a hash of options that typically includes any objects that need to be queried:


def index
if current_user.permit? 'site_admin'
# show all accounts
@account = Account.find(:all)
else
@account = current_user.is_admin_for_what(Account)
end
end


class AccountController public_page
...
def secret_info
permit "site_admin" do
render :text => "The Answer = 42"
end
end
end

The difference between permit and permit? is redirection.

permit is a declarative statement and redirects by default. It can also be used as a class or an instance method, gating the access to an entire controller in a before_filter fashion. permit? is only an instance method, that can be used within expressions. It does not redirect by default. You will find more information on the boolean expression of the permit or permit? methods here.

Google summer of code

If you’re a student and keen to get more open media technology to the Web, apply for a Google summer of code project with Xiph. There are also a few Annodex-style projects in the mix, which bring annotations and metadata to Ogg.

Your interest could be with javascript, ruby, php, XML, or C no matter – you will find a project at Xiph to suit your favorite programming language.

Of the list of proposed projects, my personal favorite is OggPusher – a browser plugin for transcoding video to Theora. Imagine an online service for transcoding video to Ogg Theora without having to worry about having all the libraries installed.

You also have the chance to propose your own project to the Xiph/Annodex guys – you just need to find somebody who is willing to mentor you, so hop on irc channel #xiph at freenode.net and start discussing.

Incidentally, Google is providing a financial reward for successful conclusion of a project – but don’t let that be your only motivation. If you’re not in it with your passion, don’t do a GSoC project. This is about interacting with an open source community whose goals you can identify with. Become involved!

Metavidwiki gone public

The revolution is here and now! If you thought you’ve seen it all with video web technology, think again.

Michael Dale and Aphid (Abram Stern) have published a plugin for Mediawiki called Metavidwiki which is simply breathtaking.

It provides all of the following features:

  • wiki-style timed annotations including links to other resources
  • a cool navigation interface for video to annotated clips
  • plain text search for keywords in the annotations
  • search result display of video segments related to the keywords with inline video playback
  • semantic search using speaker and other structured information
  • embedding of full video or select clips out of videos into e.g. blogs
  • web authoring of mashups of select clips from diverse videos
  • embedding of these mashups (represented as xspf playlists)
  • works with Miro through providing media RSS feeds

Try it out and be amazed! It should work in any browser – provide feedback to Michael if you discover any issues.

All of Metavidwiki is built using open standards, open APIs, and open source software. This give us a taste of how far we can take open media technology and how much of a difference it will make to Web Video in comparison to today’s mostly proprietary and non-interoperable Web video applications.

The open source software that Metavidwiki uses is very diverse. It builds on Wikipedia’s Mediawiki, the Xiph Ogg Theora and Vorbis codecs, a standard LAMP stack and AJAX, the Annodex apache server extension mod_annodex, and is capable of providing the annotations as CMML, ROE, or RSS. Client-side it uses the capabilities of your specific Web browser: should you run the latest Firefox with Ogg Theora/Vorbis support compiled in, it will make use of this special capability. Should you have a vlc browser plugin installed, it will make use of that to decode Ogg Theora/Vorbis. The fallback is the java cortado player for Ogg Theora/Vorbis.

Now just imagine for a minute the type of applications that we will be able to build with open video APIs and interchangable video annotation formats, as well as direct addressing of temporal and spatial fragments of media across sites. Finally, video and audio will be able to become a key part in the picture of a semantic Web that Tim Berners-Lee is painting – a picture of open and machine-readable information about any and all information on the Web. We certainly live in exciting times!!!

Editing the Skeleton and CMML standards

In the last few weeks, I’ve created an Internet-Draft (I-D – a draft specification of an IETF RFC) for the Ogg Skeleton meta track, and updated the CMML I-D to include a new element called “caption” (CMML DTD). All of this is work that should have been done a long time ago, but I only got the motivation for it through the WHATWG work on HTML5 which will take Ogg Theora and Ogg Vorbis as baseline codecs. Since liboggplay is the key open source library that implements this baseline codec support, and liboggplay supports Annodex, it seems plausible that Annodex (which adds essentially Skeleton + CMML) will be available in Web browsers of the future. So, now is the time to fix up the few open issues that remain and cast the specifications into readable I-Ds.

If you haven’t seen the great functionality that will be available with liboggplay, you should check out the liboggplay javascript API. I’ve seen Shane make a demo web page through which you can toy with the javascript API, but haven’t got the link available right now.

A long story of logins

The new vquence website, that lets you create vquences yourself, has been out for more than a week now. But we were unhappy to talk about it because the login code was screwed up. It all happened in the last minute: a crash between the beauty of design and the reality of Web browsers. Who won? Well …

Between Julian and I, we had decided to do a cool sliding effect for user login and signup (try it out on the site – it’s hard to explain in words). Very Web 2.0 – very shiny. It all worked well and we quite happily ran the code for a long time.

Then came the time that we wanted to give outside users access and that our more security-conscious people suggested to exchange user passwords over https rather than in plaintext. Fair enough – no worries – quick fix to change the protocol, right? Bah – all wrong – because now you have http and https elements on the same Web page needing to talk to each other. Big sandboxing issue in Firefox – and worse in IE.

Anyway – I leave the details of this problem – and the ultimate solution for it – to somebody better suited to explaining it. I will only say that it has cost us days of pain and suffering and bug #93 will forever be remembered.

But – we fixed it – and now you can happily create video playlists on www.vquence.com and share/socialise them. I have one on my facebook page. 🙂

Xiph file extensions and MIME types

Today we nailed down a policy for Xiph on what file extensions and mime types we recommend using for Xiph technology.

Basically, we have introduced some new file extensions to allow applications to more easily identify whether they are dealing with audio (.oga) or video (.ogv) files, or some random multiplexed codecs inside Ogg (.ogx).

We recognized the fact that existing Ogg Vorbis hardware players will need to continue to work with whatever scheme we come up and therefore decided to dedicate the extension .ogg to Ogg Vorbis I files – and deprecate all other use of it. That includes the deprecation of the use of Ogg Theora and Ogg Flac with this extension. In future, Ogg Theora files should have a .ogv extension and Ogg Flac a .oga extension. (For further details, check out the wiki page.)

MIME types will be changed accordingly and the RFCs required to register them will start to be authored now.

None of this has been written in stone yet though and there is still time to change this policy if it doesn’t make sense. So if you have any strong objections, speak up now!

Rails and plugins

I’ve come to really love working with Ruby on Rails – it forces a structured approach of Web development upon you which helps enough to get you organised, but doesn’t get in the way of being productive.

I’ve also learnt to search for plugins or gems whenever I need a specific functionality because more often than not somebody has already solved the problem that I am trying to address.

Today I played with Andy Singleton’s GUID plugin (global unique identifier) and found a bug. I haven’t found a way to publish the solution through the rails wiki (I’m really new to the community), so I’m posting it here. I’ve also sent Andy an email, so hopefully the issue will get addressed.

Here is what happend.

I got the plugin working on my development computer and wanted to test it on another machine. However, the plugin gave me the following error message:

#{RAILS_ROOT}/vendor/plugins/guid/lib/uuidtools.rb:235:in `timestamp_create'
#{RAILS_ROOT}/vendor/plugins/guid/lib/uuidtools.rb:225:in `timestamp_create'
#{RAILS_ROOT}/vendor/plugins/guid/lib/usesguid.rb:25:in `after_initialize'

After some digging I found that it uses the MAC address of the computer for seeding the GUID. To query the MAC address, it calls ifconfig (or ipconfig on a Windows machine) – which is fair enough. It has several cases that it goes through. However, the case of my machine was missing and the code did not address a nil return from the get_mac_address function.

My case was simple to solve: my MAC address comes in upper case characters, while the code only tested for lower-case characters. So, I added another parsing condition for my case:

if mac_addresses.size == 0
ifconfig_output = `/sbin/ifconfig | grep HWaddr | cut -c39-`
mac_addresses = ifconfig_output.scan(
Regexp.new("(#{(["[0-9A-F]{2}"] * 6).join(":")})"))
end

The generic problem is harder to solve – and maybe it should not be solved, but fail on the programmer, since he/she is trying to roll out GUID calculation on a machine where the program is unable to calculate a MAC address…..

Hmmm….

FOMS – the birth of a new open media forum

The first FOMS (Foundations of Open Media Software) workshop is over and it was an overwhelming success – more than ever expected! And wow – we have videos of it, too – thanks to Ralph Giles and Thomas Vander Stichele.

The goal of FOMS was to bring a diverse group of people from all around the planet who are all working on open media software together for the first time so they could get to know each other, exchange ideas, and generally address the things that annoy us all with open media technologies.

Strategically placing FOMS in the week before LCA was a great idea: not only would some of the developers attend LCA anyway and thus would not need to use up extra travel time, but also would LCA provide opportunities for the newly forged relationships to flourish and create code.

A new forum for discussion was created and since the community has committed to achieving a set of community goals, we expect it will have some basic effect on the usability of open media software over time.

And yes … all participants are up for a repetition of FOMS – possibly as a precursor to other FLOSS conferences overseas, but at a minimum again at next year’s LCA in Melbourne. Let’s rock it!

Editing video for LCA

I’ve just finished writing a small script that will help us edit and transcode video recorded at LCA 2007. Since we will record directly to DVD, we will need a simple laptop with a DVD drive and the installed software gmplayer and ffmpeg2theora to do the editing and transcoding, before uploading to a Web server. Which means that just about all LCA participants are potential helpers for making sure the video material gets published on the same day.

If you happen to be a LCA participant and want to help ascertain video publishing happens, please walk up to the video guys and offer your editing & transcoding help.

Ah yes, and here is the script – in case anyone is interested:


#!/bin/sh

# usage function
function func_usage () {
echo "Usage: VOB2Theora.sh "
echo " starttime/endtime given as HH:MM:SS"
echo " filename input file for conversion"
}

# convert from SMPTE to seconds
function func_convert2sec () {
tspec=$1;
tlen=${#tspec} #strlen

# parse seconds out of string
tsecstart=$[ ${tlen} - 2 ]
tsec=${tspec:$tsecstart:2} #substr

# parse minutes
tminstart=$[ ${tlen} - 5 ]
if test $tminstart -ge 0; then
tmin=${tspec:$tminstart:2} #substr
else
tmin=0
fi

# parse hours
thrsstart=$[ ${tlen} - 8 ]
if test $thrsstart -ge 0; then
thrs=${tspec:$thrsstart:2} #substr
else
thrs=0
fi

# calculate number of seconds from hrs, min, sec
tseconds=$[ $tsec + (($tmin + ($thrs * 60)) * 60) ]
}

# test number of parameters of script
if test $# -lt 3; then
func_usage
exit 0
fi

# convert start time
func_convert2sec $1
tstart=$tseconds

# convert end time
func_convert2sec $2
tstop=$tseconds

# input file
inputfile=$3
if test -e $inputfile; then
echo "Converting $3 from $tstart sec to $tstop sec ..."
echo ""
else
echo "File $inputfile does not exist"
exit 1;
fi

# convert using ffmpeg2theora
strdate=`date`;
strorga="LCA";
strcopy="LCA 2007";
strlicense="Creative Commons BY SA 2.5";
strcommand="ffmpeg2theora -s $tstart -e $tstop --date '$strdate' --organization '$strorga' --copyright '$strcopy' --license '$strlicense' --sync $inputfile"

echo $strcommand;

sh -c "$strcommand";

Ralph Giles made an improved version of the VOB2Theora script. It can be found at http://mirror.linux.org.au/linux.conf.au/2007/video/VOB2Theora_v2.sh.