Skip to content

Instantly share code, notes, and snippets.

@clyfe
Created February 3, 2012 13:06
Show Gist options
  • Save clyfe/1730091 to your computer and use it in GitHub Desktop.
Save clyfe/1730091 to your computer and use it in GitHub Desktop.
Short slides for a short talk at wurbe
#===================================================================
0. ACL - lists, individuals
- query DB conforming to ACL
@posts = Post.where( rules as per ACL ) # +joins
- authorize individuals already in memory
@post = Post.find(params[:id])
authorize! :read, @post
Rails usual
@posts = scope_acl.find(params[:id])
#===================================================================
1. Hardcoded
User has_many :posts
def index
@posts = current_user.posts
def show
@post = current_user.posts.find(params[:id])
#===================================================================
2. +Permissions, hardcoded (Squeel)
User
has_many :posts # owner
has_many :permissions # given by others
has_many :shared_posts, through: :permissions
def index
@posts = Post.
joins(:permissions.outer). # Squeel symbol extensions
where(
{user_id: current_user.id} | # Squeel hash extensions
{permissions: {user_id: current_user.id}}
)
def show
@post = Post.
joins(:permissions.outer).
where(
{user_id: current_user.id} |
{permissions: {user_id: current_user.id}}
).
find(params[:id])
#===================================================================
2.1 Refactor it
Post
scope :readable_by, lambda{|user|
joins(:permissions.outer).
where(
{user_id: user.id} |
{permissions: {user_id: user.id}}
)
}
def index
@posts = Post.readable_by(current_user)
def show
@post = Post.readable_by(current_user).find(params[:id])
#===================================================================
3. +Tree taxonomy (WP Categories, DMS Folders/Libraries)
# stuff gets ugly, fast
Category
has_ancestry # belongs_to :parent, nested set etc
User
has_many :categories # owner
has_many :shared_categories, through: :permissions # given by others
has_many :shared_descendant_categories, :somehow # just got ugly
has_many :posts, through: :categories
has_many :shared_posts, through: :shared_categories
has_many :shared_descendant_posts, :somehow # just got ugly
#===================================================================
4. Problems?
- Rules scattered in models
- Authorizing an already loaded instance
- writable_by, deleteable_by ... messy ....
Post
def readable_by?(user)
user.id == user_id ||
user.permissions.map(&:post_id).includes?(id) ||
# this is not DRY (see 2.1) !!!
Post.readable_by(current_user).where(:id => @post.id)
# fires sql :(
#===================================================================
5. CanCan
Ability(user)
can :read, Post, user_id: user.id
can :read, Post, permissions: {user_id: user.id}
def index
@posts = Post.accessible_by(current_ability)
def show
@post = Post.find(params[:id])
authorize! :read, @post
#===================================================================
6. CanCan + Squeel (MetaWhere) https://gist.github.com/1523940
Ability
# outer joins
can :read, Post, :permissions.outer => {user_id: user.id}
# operators other than equality
can :read, Post, category_id: user.shared_categories.map(:&id)
for category in user.shared_categories
can :read, Post, category: {:ancestry.matches => "#{category.child_ancestry}%"}
end
def index
@posts = Post.accessible_by(current_ability)
def show
@post = Post.find(params[:id])
authorize! :read, @post
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment