Skip to content

Instantly share code, notes, and snippets.

@paul
Created December 1, 2008 23:56
Show Gist options
  • Save paul/30912 to your computer and use it in GitHub Desktop.
Save paul/30912 to your computer and use it in GitHub Desktop.
Privilege # ensure that Privilege class is loaded
# This module provides access control behavior to ActiveRecord models.
# The class into which it is included must provide a '#client' method
# the result of which will be used as the context for authorization
# checks.
module AccessControl
# Indicates if +an_account+ is allowed to know of the existence of this
# object.
def visible_to?(an_account)
raise NotImplementedError
end
# Indicates if +an_account+ should allowed to create this object.
# This should be called before calling +#save+ on a new model object
# and the save should be performed only if true is returned.
def creatable_by?(an_account)
raise NotImplementedError
end
# Indicates if +an_account+ should be allowed to modify this object.
# This should before performing any actions which result in the
# database being updated. Such action should only be performed if
# true is returned.
def modifiable_by?(an_account)
raise NotImplementedError
end
def self.included(a_class)
a_class.extend(ActiveRecordClassMethods)
a_class.send(:visibility_privilege, "view_#{a_class.name.underscore}")
a_class.send(:creation_privilege, "create_#{a_class.name.underscore}")
a_class.send(:modification_privilege, "modify_#{a_class.name.underscore}")
end
module ActiveRecordClassMethods
protected
# Declares that object of the class on which this is called are
# visible to users that have the specified privilege.
def visibility_privilege(privilege_name)
define_method(:visible_to?) do |an_account|
an_account.has_privilege_at?(privilege_name, client)
end
end
# Declares that objects of this class are creatable by accounts who
# hold the +privilege+ at the client which owns this resource.
def creation_privilege(privilege_name)
define_method(:creatable_by?) do |an_account|
an_account.has_privilege_at?(privilege_name, client)
end
(class << self; self; end).instance_eval do
define_method(:creatable_by?) do |an_account|
!an_account.clients_at_which_account_has(Privilege(privilege_name)).empty?
end
end
end
# Declares that objects of this class are modifiable by accounts
# who hold the +privilege+ at the client which owns this resource.
def modification_privilege(privilege_name)
define_method(:modifiable_by?) do |an_account|
an_account.has_privilege_at?(privilege_name, client)
end
end
# Adds optional +:visible_to => an_account+ option to +#find(:all,
# options)+. This option will exclude any objects which are not
# visible to the specified account from the returned collection.
def find_every_with_visible_to_handling(options)
if account = options[:visible_to]
find_every_without_visible_to_handling(options).select {|rec| rec.visible_to?(account)}
else
find_every_without_visible_to_handling(options)
end
end
# Validates that the options passed to +#find()+ are all valid
# options
def validate_find_options(options)
options.assert_valid_keys((class << ::ActiveRecord::Base; self; end)::VALID_FIND_OPTIONS + [:visible_to])
end
def self.extended(ar_class)
(class << ar_class; self; end).alias_method_chain :find_every, :visible_to_handling
end
end
end
def index
@clients = Client.find(:all, :visible_to => requester)
respond_to :last_modified_at => @clients.maximum(:updated_at) do |format|
format.html { }
format.any(:sskj1, :ssj) { }
end
end
def show
@client = Client.find(params[:id], :visible_to => requester)
respond_to :last_modified_at => @client.updated_at do |format|
format.html { }
format.any(:sskj1, :ssj) { }
end
end
def new
@client = Client.new
raise NotPermittedError unless requester.may_create? Client
respond_to :html
end
def create
munge_json_params!
@client = Client.new(params[:client])
raise NotPermittedError unless requester.may_create? @client
respond_to do |wants|
if @client.save
wants.html { redirect_to client_url(@client) }
wants.any(:ssj, :sskj1) { head(:created, :location => client_url(@client)) }
else
wants.html { render :action => 'new' }
wants.any(:ssj, :sskj1) { raise ActiveRecord::RecordInvalid, @client }
end
end
end
def edit
@client = client
raise NotPermittedError unless requester.may_modify? @client
respond_to :html, :last_modified_at => @client.updated_at
end
def update
@client = client
raise NotPermittedError unless requester.may_modify? @client
munge_json_params!
@client.update_attributes!(params[:client])
respond_to do |wants|
wants.html { redirect_to client_url(@client) }
wants.any(:sskj1, :ssj) { head(:ok) }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment