Here's a link to a just released short (15 minutes) disturbing documentary about the Islamisation of The Netherlands and Europe.

http://video.google.com/videoplay?docid=3369102968312745410

The video quotes parts of the Quran to backup it's claim that Islam is based on intolerance, bigotry and hate as justification for murdering anyone who doesn't play along. So, for comparison and to try to balance things out, I'll throw in a dash a quotes here from another "holy" book that millions of non-muslims use as their own moral compass.

Six days may work be done; but in the seventh is the sabbath of rest, holy to the LORD: whosoever doeth any work in the sabbath day, he shall surely be put to death. Exodus 31:15

If a man also lie with mankind, as he lieth with a woman, both of them have committed an abomination: they shall surely be put to death; their blood shall be upon them. Leviticus 20:13

And he that blasphemeth the name of the LORD, he shall surely be put to death, and all the congregation shall certainly stone him: as well the stranger, as he that is born in the land, when he blasphemeth the name of the Lord, shall be put to death. Leviticus 24:16

And ye shall chase your enemies, and they shall fall before you by the sword. Leviticus 26:7

And while the children of Israel were in the wilderness, they found a man that gathered sticks upon the sabbath day. And they that found him gathering sticks brought him unto Moses and Aaron, and unto all the congregation. And they put him in ward, because it was not declared what should be done to him. And the LORD said unto Moses, The man shall be surely put to death: all the congregation shall stone him with stones without the camp. And all the congregation brought him without the camp, and stoned him with stones, and he died; as the LORD commanded Moses. Numbers 15:32-36

Thou shalt surely smite the inhabitants of that city with the edge of the sword, destroying it utterly, and all that is therein, and the cattle thereof, with the edge of the sword. Deuteronomy 13:15

That whosoever would not seek the LORD God of Israel should be put to death, whether small or great, whether man or woman. 2 Chronicals 15:13

And a whole lot more where that came from...

Comments: 0 [add comment]
It would seem as if the idle time sitting in airports and on planes has a positive influence on PZ's creative juice glands...
Newton killed hope. Once, I might have thought that I could survive falling if I watched my diet and were as light as a feather, but no — Newton's cold equations dictate that no matter what I weigh, I'd fall just as fast, so in despair I have let myself go.... The force of gravity is described as g•M1•M2 / d2, and those little letters don't stand for God, motherhood, marriage (heterosexual), and devotion. There is no room in Newtonism for the reassuring idea that my airplane is being cradled in the loving, supportive hands of an intelligent anti-gravity agent.
A little humor and levity is much appreciated when it's so easy to get pissed off at the crackpots endlessly trying to redefine Science so that it includes their untestable, evidence-free, intellectually dishonest mumbo-jumbo that goes by the name Creationism, errr, no... Intelligent Design... errr... no,... what are the Liars for Jesus calling it this week? Oh, yes... "Academic Freedom."

Sigh... and here's some more fun on that topic. Expelled? No... I think flunked is more like it.

Comments: 0 [add comment]

GateKeeper 0.2 is now available. This version traverses eagerly loaded associations and checks read permissions on each loaded object for the current user. Rdocs and install instructions available at gatekeeper.rubyforge.org.

GateKeeper is a Ruby on Rails plugin providing robust Model level permissions management, allowing you to declare access permissions for instances of ActiveRecord classes with natural language commands. For instance

  • crudable_by_admin
  • creatable_by_my_author
  • updatable_by_friends_of_my_owner :unless => :is_imaginary?
  • updatable_by_monkey_of_my_uncle :if => :has_common_ancestor?
  • readable_by_employee_of_the_month
  • and a whole lot more.
Comments: 0 [add comment]

Well, it was a little more work than I'd originally anticipated, but 5Valleys is now both my personal OpenID server and a consumer for visitors wishing to use OpenID to identify themselves when posting comments. I used the ruby-openid gem, but otherwise wrote all my own code, trying to stay as RESTful as possible (OpenID itself isn't particularly friendly to REST practices), and getting a thorough understanding of the internals before my presentation at next week's Missoula Web Discussion Group meeting. If you have an OpenID, go ahead and post a comment to try it out. Hint: if you have accounts at any of these sites, then you've got an OpenID you can (hopefully) use here, or anyplace else that proudly accepts them.

Comments: 0 [add comment]

Anyone subscribed to an RSS feed for this blog should update their feed URLs. The old ones should still be working for now, but it won't be long until I remove support for them and only support the new ones. So, consider yourselves warned.

I'm due to give a presentation on OpenID at the upcoming Missoula Web Discussion Group meeting and figured before I do a presentation on it, maybe I should actually implement it somewhere first. I've been meaning to implement OpenID on the blog for a while and figured that volunteering to do the presentation would light the proverbial fire under my you-know-what.

However, even longer than I've been wanting to implement OpenID on the blog, I've been meaning to convert it all over to a RESTful routing architecture. So, I sat down this morning with the intent to do that first, then work on the OpenID stuff. There was one unexpected hurdle though.

Writing the blog software myself was, in part, a practice Rails project that I started a long time ago, and I haven't really done much to update or improve the code since the original writing. It seems my coding practices have improved considerably since then. As soon as I opened up the first model I knew I had more to do. It was f'ugly, to put it nicely, and I wasn't about to start trying to build new functionality on top of that garbage. So, some major refactoring took place this morning before I could even start on the RESTful refactoring.

So, now it's late afternoon, I haven't refactored as much as I'd like but it's much better and the routes are now RESTful. However, I haven't even started on the OpenID stuff yet. Ugh.

But anyway, the RESTful upgrade meant that the RSS URLs needed change too. I managed to keep the old feed URLs working, but I'm not going to leave that in long. So, update your RSS client with the new addresses if you want to keep getting updates.

Comments: 0 [add comment]
Announcing GateKeeper

I'm pleased to announce the official release of my latest Rails plugin "GateKeeper". GateKeeper started life as a library in one of my big personal Rails projects where I've been experimenting with multiple methods of setting, managing and enforcing access and security permissions for specific models. This project has lots of users with different security access levels to other user's data based on their roles and relationships to each other. I think this latest experiment was a huge success, so I immediately decided to give it away to you ('cause you're all that and more).

Why GateKeeper?

In most simple and straight forward Rails projects, scoping your finds through has_many associations is probably sufficient for ensuring that users can't get at data they aren't supposed to. For example, a show action might call @current_user.notes.find(params[:id]) to ensure that the current user owns the note with the passed id, or it won't even find it.

However, things quickly get more difficult when users need limited access to other user's objects based on different roles (such as Admin, Moderator, Premium Subscriber, Employee of the Month, etc), or based on their relationship with the object's owner (such as Supervisor, Teacher, Parent, etc). You might want to allow variety of people to read certain objects based on a variety of different roles and relationships, and only allow a subset of those people to update or destroy the same objects. Trying to manage all of this can be daunting, and before long your code starts to look like a mess and it becomes easier and easier to accidentally leave a hole open that allows the wrong people to see or even modify data they're not supposed to. Adding new features that will require a new layer of permissions has now become the thing nightmares are made of and you start to wonder when in the hell Rails stopped being fun.

GateKeeper to the rescue!
  • GateKeeper allows fine grained control of CRUD permissions on individual instances of any ActiveRecord Model.
  • GateKeeper lets you define these permissions in plain English in one central location right in each model.
  • GateKeeper lets you give permissions based on the current users roles (RBAC), and/or based on the current user's relationship with the model instance in question via ActiveRecord associations.
  • GateKeeper allows permissions based on associations to be easily inherited from other classes through multiple chained associations.
  • GateKeeper strictly enforces every CRUD action that occurs on every instance of every ActiveRecord model, making sure no users ever do anything that permission hasn't been explicitly granted for.
  • GateKeeper can optionally scope all finds to only return records that the current user has 'read' permission for.
That's a lot of reading! How about some samples instead?

Sure, how about this?

class User < ActiveRecord::Base
  has_many :articles
  has_and_belongs_to_many :roles
  
  ## GateKeeper Permissions ##
  # Grouped together for easy reference later
  crudable_by_admin
  creatable_by_guest :unless => lambda {|new_user| new_user.username == 'guest'}
  updatable_by_self
  ############################
  
  #etc...
end

class Article < ActiveRecord::Base
  belongs_to :author, :class_name => 'User'
  
  ## GateKeeper Permissions ##
  crudable_by_admin
  creatable_by_my_author
  readable_by_my_author
  updatable_by_my_author :unless => :published?
  readable_by_premium_member :if => :published?
  ############################
end
Ok, I'm sold! What do I need to do to get started.

Well, first, install the plugin. script/plugin install svn://rubyforge.org/var/svn/gatekeeper/trunk

Next, by default GateKeeper assumes that you have a class named 'User' that represents individual users on your site. If not, you'll need to add the following line to your environment.rb to tell GateKeeper the name of the class you use for users. GateKeeper.user_class_name = 'Person' Through the rest of this post, mentally replace any mention of "User" or "User class" with whatever class name you set this to.

Lastly, GateKeeper requires that your User class provide a 'current' class method (eg. User.current)that returns an instance of User representing the user currently logged into the site. How you implement this is based entirely on your method of keeping track of who is logged into your site. (If you ask nice enough, I can probably be talked into doing a future post to outline how I do it.)

How can I do Role Based Access Control (RBAC) with GateKeeper?

By default GateKeeper makes a bunch of assumptions about your User class. If any of this won't work for your application, you can easily override it (details at the end of the section).

If you declare a permission such as updatable_by_admin, then whenever a user tries to update an instance of the class, GateKeeper performs a couple of checks.

First, GateKeeper checks to see if instances of your User class respond to is_admin?, and if so, calls that method on User.current. If that method returns true, the update is allowed to proceed.

If the above method returns false (or isn't defined), then GateKeeper checks to see if instances of your user class respond to roles (provided by an association like has_and_belongs_to_many :roles), and if so calls User.current.roles.find_by_name('admin') to see if your user has a role with the name defined in the permission declaration. If it does, the the update is allowed to proceed.

If both of the above two checks fail, then the update is halted and a permission error is raised.

If for any reason that won't work for you (i.e. you use some other method to check users roles), then you can simply define an instance method named has_gate_keeper_role? that takes one string argument which will be the name of the roles GateKeeper wants to know about, and will return true or false. Precisely what you do inside has_gate_keeper_role? is entirely your business.

How do permissions based on associations work?

When you declare a permission such as updatable_by_my_owner, GateKeeper treats the 'my_' prefix on the role as a flag to indicate it needs to check associations on the object in question (instead of a user's role as described above). Whenever a user tries to update an instance of the class with this permission, GateKeeper expects to find a owner method (presumably provided by an association, but not necessarily) that returns an instance of User. GateKeeper then simply compares the object returned by 'owner' with User.current and if they math, the action is allowed to proceed.

Can a model "inherit" some or all of it's permissions from some other model?

Absolutely, thanks to associations and the '_as_' preposition. Let's say you have an instance of Chair, which belongs_to :table. If you declare updatable_as_my_table in your Chair class, then anyone who has update permission of the specific table that your instance of chair belongs to can also update the chair. You may find that the permission declaration that you use most often is simply crudable_as_my_<association>, which will cause instances of the class to inherit all of their permissions from the associated object.

What if the association isn't a user?

Often times associations refer to some other class with it's own associations, and to get from your current object to an instance of User you need to travel through several associations (eg. @chair.table.room.house.owner ). GateKeeper lets you dictate how to get from the current object to an instance of User in either of two styles.

First, you can simply chain multiple 'crudable_as_*' permissions across multiple associations. In the example above we had an instance of Chair inheriting it's update permissions from the instance of Table it belonged to. If in turn Table declared updatable_as_my_room then Chair and Table would both get their update permissions from Room.

Alternatively, you can declare the entire chain directly in Chair with the '_of_' separator, and you can chain as many of them toegther as you like, so you might do something like updatable_by_owner_of_house_of_room_of_my_table as long as each class has the correct associations setup so that @chair.table.room.house.owner returns an instance of User to compare to User.current.

Additional Conditionals!

In addition to all of the above, permission declarations may also be given an ':if' or ':unless' argument that takes a string, symbol, or proc that will return a boolean, allowing you limitless flexibility in dictating when certain actions are allowed to occur.

What's this "permission scoping" thing you mentioned earlier?

By default, if any of the ActiveRecord finder methods find an object that User.current doesn't have permission to read, GateKeeper will throw a permission error. Even with permission scoping turned on, this is still true any time the finder method is expected to return an exact number of objects (eg find(1,3,5,9)).

However, any ActiveRecord finder methods that typically return arrays of arbitrary length (eg. find(:all)), GateKeeper allows you to tell it to just return those that User.current has permission to read, instead of throwing an error for those they can't. This can be enabled in one of two ways.

First, you can turn permission scoping on globally for your application by setting GateKeeper.permission_scoping_enabled = true in your environment.rb. Or, if you prefer to leave permission scoping off most of the time, you can simply pass a block to GateKeeper.with_permission_scoping and that block will be executed with permission scoping enabled just for it.

Note however, that it is still strongly advisable to limit your find in some way. Since GateKeeper still needs to iterate through each and every item returned by the finder to to check if it's readable, running GateKeeper.with_permission_scoping { Article.find(:all) } is likely going to be a very long running command if you have thousands, or even just a couple hundred, articles in your database. If this happens to you, work on making your block return fewer records in the first place, such as with extra conditions, limits, or paginating.

More information?

More information, including installation instructions, can be found in the online documentation at rubyforge. Enjoy, and please let me know how it goes. You can post questions or comments either here, or on the Ruby on Rails mailing list (be sure to include the word "GateKeeper" in the body to catch my attention.)

Comments: 0 [add comment]

I released CrossSiteSniper version 0.3 today with one small enhancement.

In v0.2, only instance methods directly associated with a column in the database had the ability to get the data without html escaping via the _without_html_escaping call. Now,thanks to the magic of method_missing, that works on all methods. So, imagine you have a method defined in your model that draws from one or more text fields in your table. Usually each of those fields will be escaped by CrossSiteSniper. But now, calling that same method with the '_without_html_escaping' suffix will temporarily turn off html_escaping just long enough to for that method to get all all it's data and return the unescaped result of whatever it does. It's not a feature most people will have a need for, but we did come across a need for it at the day job, so now you can use it too.

Comments: 0 [add comment]