echo "hey, it works" > /dev/null

just enough to be dangerous

New Habari release adds access control


A couple of days ago we released a new version of Habari. I think this release is particularly exciting, not just because of the more than 1000 improvements and bug fixes, but because of the main feature new included; Access Control Lists (ACL).

The ACL system gives plugin developers an extensible foundation for controlling who has access to things in a Habari installation, based on group membership. Here "access" means control over read, write, edit, and delete privileges, and "things" means, well anything you can think of, but it could be posts, or admin pages, or tags, or users, or content types, anything.

A default installation has three groups; admin, authenticated, and anonymous. The user that's created when you install Habari is put into the admin group, and has superuser privileges; they can do anything. If new users are created, they get put in the authenticated group. Anyone accessing Habari without signing in is in the anonymous group. Of course, new groups can also be created. There are a bunch of pre-defined access tokens that can be assigned to groups. Here's a few of them, as shown on a group page.

permissions-eg.png

On top of the default tokens, plugins can add their own. For example, the simple private posts plugin that's now bundled with Habari creates a 'private' token, which can be used to restrict access to posts to people in groups with that token.

ACL::create_token('private','Permissions on posts marked as "private"');

With this code, there's an extra permission that can be assigned to groups.

private-permission.png

The plugin also adds a checkbox to the publish page to mark a post private. Incredibly simple.

Without the ACL, the registration plugin just wouldn't have been possible. Users can now sign up to a Habari blog and be put in a group, with associated permissions. What group? Again, anything you can think of. Maybe they could rate posts, or mod comments, or write posts.

With the ACL, and Habari's support for content types, the possibilities are limited only by imagination. An author group with write but not publish permissions and an editor group with publish permissions and you've got a simple workflow. A wikipage content type and an editor group that can create and edit them, along with the registration plugin, and you've got a simple wiki. Hopefully you get the idea.

Owen has written a good overview of how Habari's ACL system works internally, if you want to get into the nitty gritty.

Calling testers for Habari 0.6


Habari trunk has been merged to the 0.x makaanga, our release branch. That means a 0.6 release is just around the corner, and testers are welcome1.

You can get the source via subversion from http://svn.habariproject.org/habari/makaanga/0.x (which I recommend, because you can just svn up to get the latest fixes) or there's a zip file.

  1. Note that there have already been some changes made in trunk that will be merged to the makaanga before release

Registration plugin for Habari


If you want to use Habari as a platform rather than just a blog, as I talked about in my previous post, it's likely you'll come across the situation where you want people to be able to register with your site. To allow this, I've written a simple registration plugin. Activate the plugin and put $theme->registration('group_name') in your template, and you'll get a form for new users to sign up, and they'll be placed in whatever group you specify, in less than 90 lines of code.

As usual, the plugin, which I've creatively named Register Plugin, is in the -extras repository, but I thought I'd talk about what it involves.

First up, when the plugin is activated, we create a UUID, a random string, that we'll use as a secret key. We store this as a site option, and we'll use it a bit later for hashing group names.

public function action_plugin_activation( $plugin_file ) { if ( Plugins::id_from_file(__FILE__) == Plugins::id_from_file($plugin_file) ) { // Store a secret key for hashing group names Options::set('register_secret', UUID::get()); } }

Next we use the FormUI class to create a registration form.

public function get_form( $group ) { // Create the registration form, and add a CSS class $form = new FormUI('registration'); $form->class[] = 'registration';

// Add a field for the email address // The 'null:null' tells FormUI not to store the submitted values $form->append('text', 'email', 'null:null', _t('Email'), 'formcontrol_text'); // Get FormUI to make sure it's a valid address $form->email->add_validator('validate_email'); // Add a field for the username $form->append('text', 'username', 'null:null', _t('Username'), 'formcontrol_text'); // Get FormUI to make sure the username is filled in and available $form->username->add_validator('validate_required'); $form->username->add_validator('validate_username'); // Add a password field, which is required $form->append('text', 'password', 'null:null', _t('Password'), 'formcontrol_text'); $form->password->add_validator('validate_required');

// Store the group to be added, all secreted up $form->append('hidden', 'group_name', 'group_name'); $group_hash = md5($group); $form->group_name->value = $group_hash; $form->append('hidden', 'group_digest', 'group_digest'); $form->group_digest->value = $this->hmac($group_hash); // Create the Register button $form->append('submit', 'register', _t('Register'), 'formcontrol_submit');

// Tell FormUI to process the submitted form // with the register_user function in this class $form->on_success( array( $this, 'register_user' ) ); // Return the form object return $form; }

Most of that is pretty straightforward FormUI stuff, which is documented on the wiki (though I do love how easy validation is). The interesting part is were we secret up the group name, because of course we don't want to have people adding themselves to the admin group. We send a hash of the group name, along with a digest of the hash. We create the digest as follows.

function hmac($data) { return md5(md5($data) . Options::get( 'title' ) . md5(Options::get('register_secret'))); }

We hash the data and secret, with a little salt, for which we've used the blog title. We send the digest and the hashed group name with the form, and test it when we get it back, like this.

public function register_user( $form ) { // Get all the groups $allowed_groups = array(); foreach ( UserGroups::get_all() as $group ) { $allowed_groups[] = $group->name; } // Make them accessible via the hashed group name $allowed_groups = array_combine( array_map('md5', $allowed_groups), $allowed_groups ); // Recreate the digest of the submitted group // If it matches the digest, we're all good $group = ''; if ($this->hmac($form->group_name->value) == $form->group_digest->value) { $group = UserGroup::get($allowed_groups[$form->group_name]); } else { die('You naughty hacker!'); }

// Create a new user, with the submitted data $user = new User( array( 'username' => $form->username, 'email' => $form->email, 'password' => Utils::crypt( $form->password ) ) ); // Add the user to the group if ( $user->insert() ) { $group->add($user); Session::notice( sprintf( _t( "Added user '%s'" ), $form->username ) ); } else { $dberror = DB::get_last_error(); Session::error( $dberror[2], 'adduser' ); } }

And the magic bit that makes it available as a theme function is this.

public function theme_registration( $theme, $group ) { $this->get_form($group)->out(); }

As I said, it's very simple at the moment. The only complexity is in all the hashing, for which I thank Matt Read (aka BigJibby).

Other things that I might add include moderated registrations, email confirmation, optionally disallowing users to be added to groups that have super user access, and a registration content type so that you don't have to edit templates at all. Hopefully I haven't made the simple plugin sound complex.

[Update: As Owen points out in the comments, as we can set options in the FormUI object that are stored locally and not tainted as user input, we can safely store the group name there, rather than passing it to the user encrypted. The registration plugin in the Habari extras repository now does this. Thanks, Owen.]

What would make a WordPress geek go to Habari?


While stalking people recently, I had a little conversation with Jamison Kelly, who asked,

It may be a tall order to convince someone who calls themself a 'WordPress geek' that anything else is going to meet their needs, but I'm assuming a willingness to listen. I mentioned a couple of reasons in reply, but I think the question deserves a reply of more than 140 characters.

I think there are great reasons that a WordPress geek might want to move to Habari, and benefit from doing so. These are a few reasons why I think Habari is a good place to be. In the spirit of full disclosure, I should say that I've done much more development on Habari than WordPress.

Community

The first thing that attracted me to Habari was the community, and I've written before about how much I love it. It might not have the size of the WordPress community, but try mentioning some problem you're having with Habari on Twitter, or identi.ca, or FriendFeed. Or drop in to the #habari IRC channel on Freenode (try the LiveHelp plugin if you're not familiar with IRC). The promptness and friendliness of the support is generally fantastic. And I'm not just talking about some peripheral community that's built up around the software, I'm talking about the core developers as well.

Meritocracy

I think one of the reasons the community is so responsive and helpful is that people are rewarded for their participation. This is the idea of a meritocracy, the organisational model that Habari is based on. The people who show the ability, dedication, and willingness to contribute, get given the power to do so. It doesn't matter if that contribution is writing code, or documenting Habari, or marshalling the community, or anything else that benefits the project. The main concrete way that contributions are recognised is through an invitation to the Habari Project Management Committee, jokingly referred to as the Cabal, the main benefits of which are voting rights on the project and commit access to the code base. As of the time of writing, there are 25 people in the Cabal. For a project that had its first developer release less than two years ago, that's convincing evidence of the openness of the project. How many WordPress committers are there ? And where do they work ?

It's a small pond ...

... for now. Being such a young project, the pool of developers and themers is quite small. As such, writing a couple of killer plugins or some quality themes can get you a lot of recognition. By starting developing for Habari early, you can really make a name for yourself as it grows.

In addition, Owen has also written about why theme and plugin authors should choose Habari on licensing grounds.

All of those reasons are soft and fluffy, but there are good technical reasons to use Habari.

An extensible platform

It's incredibly easy to write themes and plugins for Habari. Andrew Rickmann has written a good side-by-side comparison of theming for WordPress and Habari. There are hooks throughout Habari that allow plugins to act or filter based on events. This is much the same as WordPress, though Habari doesn't require that you register your functions. So my action_admin_footer() is the same as my action_admin_footer().

Themes and plugins both extend the Pluggable class, by way of the Theme and Plugin classes respectively. Want to change the way act_display_home() works ? Just define the function in the Theme class in your theme.php file and Habari will use your code instead of core. In addition, the active theme acts just like a plugin, so you write code to can hook events, just like a plugin can.

And if existing hooks don't let you do what you need, you can override system classes. Want to tweak the way Utils::slugify() works ? No need to tweak the core, just copy system/classes/utils.php to /user/classes and change it to work how you'd like.

The ease with which Habari can be extended, customised, and bent to your own evil ends has led one developer recently to implement an issue tracking system on top of it. In three hours.

Of course, it may be the "WordPress geek" label indicates an emotional position, and not a logical one, in which case I'm really wasting my time. But if you're willing to be swayed, those are some of my - completely subjective - reasons.

Habari users, what are yours ?

Include tweets in your posts with the Twitter silo


On my recent post Stalking Habari comments, I stuffed around with and reordered screenshots of tweets to make a coherent conversation. In the comments, Sean Coates said, "You should be using my Twitter Silo." It's in the Habari extras repository (direct link), so I checked it out.

After activation, you need to configure the silo with your Twitter username and password. On the publish page, the silo has a tab along with your other silos. You can see this in the screenshot below. You'll also see that there are three directories.

Your own tweets.
twitter-silo.png

Your friends' tweets.
twitter-silo-friends.png

Custom tweets, where you simply enter the URL of a particular tweet.
twitter-silo-custom.png

And this is Sean, talking about how beer is a soporific, as inserted by the silo.

So, yes, I should have used the Twitter Silo.

Stalking Habari comments


Like some others, I scan the intarwebs for references to Habari. I recommend that all open source projects do the same, as you can often turn someone who's making a complaint into a supporter by sorting out their issues.

It's also nice when you see people say nice things about the project, like this recent Twitter conversation between @elduderino78 and @dotjay.

twitter_habari.jpg

I put the tweets in order to make it readable.

A Year on Habari


Sometime in September 2007, while searching for resources about WordPress's AtomPub implementation, I stumbled upon a post by Chris J. Davis about Habari's implementation. I'd been blogging using WordPress for a short time, around six months, and was interested in contributing, but I found it hard to get my foot in that door (not that I tried terribly hard). This was the first time I'd heard of Habari, and I decided to check it out, with the hope that I might be able to learn some stuff, and maybe lend a hand.

About 17 seconds after joining the #habari IRC channel on Freenode, Andrew da Silva (aka freakerz) greeted me and engaged me in conversation. It's unusual that newbies are greeted on entering a channel, but it happens often on #habari, and it was definitely a hook that drew me in to the community. Before long, I was installing Habari all over the place, porting the theme I was using (Connections, which I'm still using, and which is publically available), digging in with the AtomPub implementation, and generally enjoying the community. And finally, after working out how to match WordPress permalinks in Habari, I made the jump and moved this blog to Habari, one year ago today.

I've always run Habari from the development trunk, where there are no guarantees of stability and always the risk of data loss, yet I haven't had more than the slightest of hiccoughs. When I went live, Habari was on revision 1224, and the stable version was 0.3, which had just been released. Now it's 2957, and we're working on 0.6, so I've updated over more than 1700 revisions, and some major feature additions. It's true that updating does on occasion break a theme or plugin, but that's usually sorted out pretty quickly with the help of the community on IRC.

The Habari Extras repository didn't even exist. Now it holds 149 plugins and 10 themes, dozens of contributors, and has had almost 1500 commits. It holds most of the plugins you might need, but if there is something you'd like, you can add it to the wishlist. The Extras repository has also taught me more about open source software licensing than I'd ever hoped to know, which is to say the only thing I'm sure of is that licensing is hard, and people are passionate about it. Still, this might be an opportunity for Habari, as the ASL, under which Habari is licensed, provides a more solid foundation for premium theme developers than GPL-licensed software such as the dominant player, WordPress. Theme authors, it's time to get your hands dirty with Habari.

There was some nice recognition for Habari, such as being announced as a finalist of the 2008 SourceForge Community Awards, and a positive write up on ReadWriteWeb. Personally, the undoubted highlight of the year was being invited to join the Habari Project Management Committee (aka the Cabal).

I've only scratched the surface of what I'd like to do with and for Habari. It's been an enormous amount of fun so far, and I've learnt a heap; about open source projects and culture, source code management, coding, and community. Thanks to everyone who's been a part of it.

Tagging a couple of TinyMCE plugins for Habari


I've decided to follow the new versioning scheme being used on the Habari extras repository for all of my plugins and themes (the ones I have to host myself since licensing restrictions mean I can't put them in extras itself). The lack of a proper versioning scheme meant that I'd made changes to the TinyMCE plugin targeted to Habari 0.6-alpha that weren't compatible with 0.5, the current stable release. To rectify the situation, I've released a 0.6 version and a 0.5 version. You can find them on the TinyMCE plugin page. Thanks to Ian Barber for the backwards patch, and Mike Lietz for troubleshooting.

If you have any requests for these plugins, please let me know.

Update your Habaris !


Habari 0.5.1 has been released. This is a security fix and you should update immediately if you're running 0.5. If you're running trunk, you should svn up, making sure you back up your data if you haven't updated for a while, as we recently merged some significant schema changes for the upcoming 0.6 release.

TinyMCE plugin updated


There have been some major changes to Habari since the last update of the TinyMCE plugin, so I've updated. It's still not perfect, but it works with the newest version of Habari. As usual, if there's anyone willing to take over maintenance and development of the plugin, let me know. I'm happy to give advice, but I'm finding it hard to find the time to put into improving it.

These are the changes in version 0.4, which you can download from my TinyMCE plugin page:

  • Updated configuration to work with updated FormUI.
  • Play nicely with Monolith.
  • Reformat code to meet Habari's code standards.