Rob van Dijk's Blog

Using declarative_authorization with subdomains

Posted in rubyonrails by Rob van Dijk on 24/01/2010

The Rails portal I’m working on uses subdomains to distinguish between schools (i.e. schoolname.schoudercom.nl). Access to various parts of the portal is controlled through roles using declarative_authorization. All this using one app and one database. So far so good.

But what if a teacher in school1 is a parent in school2? So, when this user requests a page for school1 (under subdomain “school1″) his role should be “teacher” and when he requests a page for school2 his role should be “parent”.

Sounds simple enough to accomplish,  until you realize that information about the subdomain is not accessible from the User model. And so also not available in method role_symbols that is called by declarative_authorization.

This separation of logic between the layers of the MVC pattern is a basic Rails aspect. Various workarounds can be found on the Internet, some of which involve class or instance variables or usage of Thread.current. For a typical discussion on this subject see this topic, more information about threading can be found in Thread safety for your Rails.

Having read the available information I finally settled on adding an instance variable to the User model and setting this from a before_filter in ApplicationController. Let’s start with the model definitions, showing only the relevant lines:

class User < ActiveRecord::Base
    has_many :user_roles
    has_many :roles, :through => :user_roles, :conditions => 'school_id=#{self.current_subdomain ? self.current_subdomain.id : -1}'
    attr_accessor :current_subdomain
    # method for declarative_authorization
    def role_symbols
        roles.map do |role|
          role.name.underscore.to_sym
        end
    end
end

class School < ActiveRecord::Base
    has_many :user_roles
end

class Role < ActiveRecord::Base
  has_many :user_roles
  has_many :users, :through => :user_roles
end

class UserRole < ActiveRecord::Base
    belongs_to :user
    belongs_to :role
    belongs_to :school
end

The instance variable is current_subdomain. Note that the :condition for the has_many assocation for roles uses single quotes. When declarative_authorization calls role_symbols, which iterates the roles array, the condition is dynamically executed and the roles are filtered based on subdomain. The single quotes will cause the query to be “lazy evaluated” as mentioned e.g. in this blog.
When no subdomain is available (e.g. for the public portal starting with ‘www’) the ‘-1′ ensures that no roles are assigned.

In ApplicationController add a before_filter and two methods that will set the current_subdomain variable for current_user (provided by AuthLogic in my case):

before_filter :set_current_subdomain

def current_subdomain
    return @current_subdomain if defined?(@current_subdomain)
    @current_subdomain = request.subdomains.join(".")
    @current_subdomain = nil unless (@current_subdomain && @current_subdomain.casecmp("www") != 0 )
    if @current_subdomain
        @current_subdomain = School.find_by_subdomain(@current_subdomain)
    end
    @current_subdomain
end

def set_current_subdomain
    ca = current_subdomain
    current_user.current_subdomain = ca unless current_user.nil?
end

This may be trivial for experienced Rails developers, but I decided to blog about it anyway – for people like me who just started working with Rails a couple of months ago it may be useful information.

A Tweet is not a LinkedIn Status Update

Posted in new social media by Rob van Dijk on 19/01/2010


I was recently forced to delete one of my LinkedIn connections. Why?

I like to follow the LinkedIn status updates posted by my connections. They inform me about big projects they work on, about seminars they visit, about job changes and other career-related events. Until recently I was happily following these updates from my iPhone.

That is, until LinkedIn decided to offer a connection between its status update and Twitter. One of the usage scenarios – a Tweet with #in is passed to LinkedIn as status update – makes perfect sense. Once in while you tweet something that is worthwhile knowing for your LinkedIn connections as well: just add #in and you’re done. The second usage scenario however – all Tweets are passed to LinkedIn as status update – turns out to be a pain for those following status updates using the iPhone LinkedIn app. In fact, it just turns into a useless copy of Twitter. You have to wade through 20 Tweets of person X before encountering a single LinkedIn status update of another person, and then another 17 Tweets of the same person X before encountering the next. As people say on Twitter: #fail.

Apart from this practical issue, it usually doesn’t make sense to connect Twitter one-on-one with your LinkedIn status. LinkedIn gives me the career overview of my connections. Careers develop relatively slowly, and so status updates are relatively sparse. That is a completely different model than Twitter, where the update frequency is typically much higher.

So, to be able to see status updates of all my connections on the iPhone LinkedIn app (and not just Tweets from person X) I had to delete the connection. Which makes me very curious: how do you handle this?

Leerkracht gezocht

Posted in new social media, School-ouder communicatie by Rob van Dijk on 14/01/2010

Dit bericht is verplaatst naar blog.schoudercom.nl en is nu te bereiken via http://blog.schoudercom.nl/2010/01/14/leerkracht-gezocht/.

Volg

Ontvang elk nieuw bericht direct in je inbox.