[refs #54] Add CanCan rules for issues and comments. Fix serial_id routes and some actions

This commit is contained in:
konstantin.grabar 2011-12-21 18:48:16 +04:00
parent 375c98366f
commit 3ab55d34b8
9 changed files with 86 additions and 30 deletions

View File

@ -77,7 +77,6 @@ GEM
factory_girl_rails (1.4.0) factory_girl_rails (1.4.0)
factory_girl (~> 2.3.0) factory_girl (~> 2.3.0)
railties (>= 3.0.0) railties (>= 3.0.0)
friendly_id (4.0.0.beta8)
grit (2.4.1) grit (2.4.1)
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (~> 1.15) mime-types (~> 1.15)
@ -220,7 +219,6 @@ DEPENDENCIES
delayed_job delayed_job
devise (~> 1.5.2) devise (~> 1.5.2)
factory_girl_rails (~> 1.4.0) factory_girl_rails (~> 1.4.0)
friendly_id (~> 4.0.0.beta14)
grack! grack!
grit grit
haml-rails (~> 0.3.4) haml-rails (~> 0.3.4)

View File

@ -1,6 +1,11 @@
class CommentsController < ApplicationController class CommentsController < ApplicationController
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :set_commentable, :only => [:index, :edit, :create] before_filter :set_commentable, :only => [:index, :edit, :create]
before_filter :find_project, :only => [:index]
before_filter :find_comment, :only => [:show, :edit, :update, :destroy]
authorize_resource :only => [:show, :edit, :update, :destroy]
authorize_resource :project, :only => [:index]
def index def index
@comments = @commentable.comments @comments = @commentable.comments
@ -19,13 +24,11 @@ class CommentsController < ApplicationController
end end
def edit def edit
@comment = Comment.find(params[:id])
@issue = @commentable @issue = @commentable
@project = @issue.project @project = @issue.project
end end
def update def update
@comment = Comment.find(params[:id])
if @comment.update_attributes(params[:comment]) if @comment.update_attributes(params[:comment])
flash[:notice] = I18n.t("flash.comment.saved") flash[:notice] = I18n.t("flash.comment.saved")
redirect_to :back redirect_to :back
@ -36,7 +39,6 @@ class CommentsController < ApplicationController
end end
def destroy def destroy
@comment = Comment.find(params[:id])
@comment.destroy @comment.destroy
flash[:notice] = t("flash.comment.destroyed") flash[:notice] = t("flash.comment.destroyed")
@ -46,15 +48,24 @@ class CommentsController < ApplicationController
private private
def find_commentable def find_commentable
params.each do |name, value| #params.each do |name, value|
if name =~ /(.+)_id$/ # if name =~ /(.+)_id$/
return $1.classify.constantize.find(value) # return $1.classify.constantize.find(value)
end # end
end #end
nil #nil
return Issue.find(params[:issue_id])
end end
def set_commentable def set_commentable
@commentable = find_commentable @commentable = find_commentable
end end
def find_comment
@comment = Comment.find(params[:id])
end
def find_project
@project = @comment.commentable.project
end
end end

View File

@ -1,13 +1,15 @@
class IssuesController < ApplicationController class IssuesController < ApplicationController
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :find_project before_filter :find_project, :except => [:destroy]
before_filter :find_issue, :only => [:edit, :update, :destroy] before_filter :find_issue_by_serial_id, :only => [:show, :edit]
load_and_authorize_resource load_and_authorize_resource :except => [:show, :edit, :index]
authorize_resource :only => [:show, :edit]
#authorize_resource :through => :project, :only => [:index], :shallow => true
authorize_resource :project, :only => [:index]
autocomplete :user, :uname autocomplete :user, :uname
def show def show
@issue = @project.issues.where(:serial_id => params[:serial_id])[0]
end end
def index def index
@ -30,13 +32,18 @@ class IssuesController < ApplicationController
end end
end end
def edit
@user_id = @issue.user_id
@user_uname = @issue.user.uname
end
def update def update
@user_id = params[:user_id] @user_id = params[:user_id]
@user_uname = params[:user_uname] @user_uname = params[:user_uname]
if @issue.update_attributes( params[:issue].merge({:user_id => @user_id}) ) if @issue.update_attributes( params[:issue].merge({:user_id => @user_id}) )
flash[:notice] = I18n.t("flash.issue.saved") flash[:notice] = I18n.t("flash.issue.saved")
redirect_to @issue redirect_to show_issue_path(@project, @issue.serial_id)
else else
flash[:error] = I18n.t("flash.issue.saved_error") flash[:error] = I18n.t("flash.issue.saved_error")
render :action => :new render :action => :new
@ -56,7 +63,7 @@ class IssuesController < ApplicationController
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
end end
def find_issue def find_issue_by_serial_id
@issue = Issue.find(params[:id]) @issue = @project.issues.where(:serial_id => params[:serial_id])[0]
end end
end end

View File

@ -3,7 +3,7 @@ class Ability
def initialize(user) def initialize(user)
user ||= User.new # guest user (not logged in) user ||= User.new # guest user (not logged in)
if user.admin? if user.admin?
can :manage, :all can :manage, :all
else else
@ -73,7 +73,7 @@ class Ability
can [:read, :update], Group, groups_in_relations_with(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id) do |group| can [:read, :update], Group, groups_in_relations_with(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id) do |group|
group.objects.exists?(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id) group.objects.exists?(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id)
end end
can :manage, Platform, :owner_type => 'User', :owner_id => user.id can :manage, Platform, :owner_type => 'User', :owner_id => user.id
can :manage, Platform, platforms_in_relations_with(:role => 'admin', :object_type => 'User', :object_id => user.id) do |platform| can :manage, Platform, platforms_in_relations_with(:role => 'admin', :object_type => 'User', :object_id => user.id) do |platform|
platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id) platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
@ -95,10 +95,39 @@ class Ability
can [:new, :create], Repository do |repository| can [:new, :create], Repository do |repository|
repository.platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id) repository.platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
end end
can [:show, :index], Issue do |issue|
issue.status == 'open'
end
#can [:show, :index], Issue, with_project_id_in_relations_with(:object_type => 'User', :object_id => user.id) do |issue|
can [:show, :index], Issue do |issue|
issue.project.relations.exists?(:object_type => 'User', :object_id => user.id)
end
can [:create, :new], Issue do |issue|
issue.project.relations.exists?(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id)
end
can [:edit, :update], Issue do |issue|
issue.user_id == user.id || (user.id == issue.project.owner_id && issue.project.owner_type == 'User') ||
issue.project.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
end
can [:create, :new], Comment do |comment|
comment.commentable.project.relations.exists?(:object_type => 'User', :object_id => user.id)
end
can [:edit, :update], Comment do |comment|
comment.user_id == user.id || (user.id == comment.commentable.project.owner_id && comment.commentable.project.owner_type == 'User') ||
comment.commentable.project.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
end
#
cannot [:index, :edit, :update, :create, :new, :show], Issue do |issue|
!issue.project.has_issues
end
cannot [:edit, :update, :create, :new, :destroy], Comment do |comment|
!comment.commentable.project.has_issues
end
#can :read, Repository #can :read, Repository
# TODO: Add personal repos rules # TODO: Add personal repos rules
# Same rights for groups: # Same rights for groups:
can [:read, :create], PrivateUser, :platform => {:owner_type => 'Group', :owner_id => user.group_ids} can [:read, :create], PrivateUser, :platform => {:owner_type => 'Group', :owner_id => user.group_ids}
can :publish, BuildList do |build_list| can :publish, BuildList do |build_list|
@ -121,7 +150,7 @@ class Ability
can [:read, :update, :process_build, :build], Project, projects_in_relations_with(:role => ['writer', 'admin'], :object_type => 'Group', :object_id => user.group_ids) do |project| can [:read, :update, :process_build, :build], Project, projects_in_relations_with(:role => ['writer', 'admin'], :object_type => 'Group', :object_id => user.group_ids) do |project|
project.relations.exists?(:role => ['writer', 'admin'], :object_type => 'Group', :object_id => user.group_ids) project.relations.exists?(:role => ['writer', 'admin'], :object_type => 'Group', :object_id => user.group_ids)
end end
can :manage, Platform, :owner_type => 'Group', :owner_id => user.group_ids can :manage, Platform, :owner_type => 'Group', :owner_id => user.group_ids
#can :read, Platform, :groups => {:id => user.group_ids} #can :read, Platform, :groups => {:id => user.group_ids}
can :read, Platform, platforms_in_relations_with(:role => 'reader', :object_type => 'Group', :object_id => user.group_ids) do |platform| can :read, Platform, platforms_in_relations_with(:role => 'reader', :object_type => 'Group', :object_id => user.group_ids) do |platform|
@ -140,11 +169,12 @@ class Ability
cannot :create, [Platform, User] cannot :create, [Platform, User]
end end
end end
# Shared cannot rights for all users (guests, registered, admin) # Shared cannot rights for all users (guests, registered, admin)
cannot :destroy, Platform, :platform_type => 'personal' cannot :destroy, Platform, :platform_type => 'personal'
cannot :destroy, Repository, :platform => {:platform_type => 'personal'} cannot :destroy, Repository, :platform => {:platform_type => 'personal'}
cannot :fork, Project, :owner_id => user.id, :owner_type => user.class.to_s cannot :fork, Project, :owner_id => user.id, :owner_type => user.class.to_s
cannot :destroy, Issue
end end
# Sub query for platforms, projects relations # Sub query for platforms, projects relations
@ -161,6 +191,16 @@ class Ability
end end
end end
def with_project_id_in_relations_with(opts = {})
query = "issues.project_id IN (SELECT target_id FROM relations WHERE relations.target_type = 'issues'"
opts.each do |key, value|
query = query + " AND relations.#{ key } #{ value.class == Array ? 'IN (?)' : '= ?' } "
end
query = query + ")"
return opts.values.unshift query
end
## Sub query for project relations ## Sub query for project relations
#def projects_in_relations_with(opts={}) #def projects_in_relations_with(opts={})
# ["projects.id IN (SELECT target_id FROM relations WHERE relations.object_id #{ opts[:object_id].class == Array ? 'IN (?)' : '= ?' } AND relations.object_type = '#{ opts[:object_type] }' AND relations.target_type = 'Platform') AND relations.role", opts[:object_id]] # ["projects.id IN (SELECT target_id FROM relations WHERE relations.object_id #{ opts[:object_id].class == Array ? 'IN (?)' : '= ?' } AND relations.object_type = '#{ opts[:object_type] }' AND relations.target_type = 'Platform') AND relations.role", opts[:object_id]]

View File

@ -1,5 +1,5 @@
class Issue < ActiveRecord::Base class Issue < ActiveRecord::Base
STATUSES = ['open', 'close'] STATUSES = ['open', 'closed']
belongs_to :project belongs_to :project
belongs_to :user belongs_to :user

View File

@ -3,10 +3,9 @@
%ul.wat-cf %ul.wat-cf
%li.first= link_to t("layout.issues.list"), project_issues_path(@project) %li.first= link_to t("layout.issues.list"), project_issues_path(@project)
%li= link_to t("layout.issues.new"), new_project_issue_path(@project) %li= link_to t("layout.issues.new"), new_project_issue_path(@project)
%li.active= link_to t("layout.issues.edit"), edit_project_issue_path(@project)
.content .content
%h2.title %h2.title
= t("layout.issues.edit_header") = t("layout.issues.edit_header")
.inner .inner
= form_for @issue, :url => project_issue_path(@issue), :html => { :class => :form } do |f| = form_for @issue, :url => project_issue_path(@project, @issue), :html => { :class => :form } do |f|
= render :partial => "form", :locals => {:f => f} = render :partial => "form", :locals => {:f => f}

View File

@ -2,7 +2,7 @@
.secondary-navigation .secondary-navigation
%ul.wat-cf %ul.wat-cf
%li.first.active= link_to t("layout.issues.list"), project_issues_path(@project) %li.first.active= link_to t("layout.issues.list"), project_issues_path(@project)
%li= link_to t("layout.issues.new"), new_project_issue_path(@project) if can? :create, Issue %li= link_to t("layout.issues.new"), new_project_issue_path(@project) if can? :new, Issue.new(:project_id => @project.id)
.content .content
%h2.title %h2.title
= t("layout.issues.list_header") = t("layout.issues.list_header")

View File

@ -2,7 +2,7 @@
.secondary-navigation .secondary-navigation
%ul.wat-cf %ul.wat-cf
%li.first= link_to t("layout.issues.list"), project_issues_path(@project) %li.first= link_to t("layout.issues.list"), project_issues_path(@project)
%li= link_to t("layout.issues.edit"), edit_project_issue_path(@project, @issue) if can? :edit, @issue %li= link_to t("layout.issues.edit"), edit_project_issue_path(@project, @issue.serial_id) if can? :edit, @issue
.content .content
.inner .inner
%p %p

View File

@ -67,7 +67,8 @@ Rosa::Application.routes.draw do
resources :categories, :only => [:index, :show] resources :categories, :only => [:index, :show]
end end
match "projects/:project_id/issues/:serial_id" => 'issues#show', :as => :show_issue, :via => :get match "projects/:project_id/issues/:serial_id" => 'issues#show', :serial_id => /\d+/, :as => :show_issue, :via => :get
match "projects/:project_id/issues/:serial_id/edit" => 'issues#edit', :serial_id => /\d+/, :as => :edit_issue, :via => :get
resources :projects do resources :projects do
resources :issues, :except => [:show] do resources :issues, :except => [:show] do
resources :comments, :only => [:edit, :create, :update, :destroy] resources :comments, :only => [:edit, :create, :update, :destroy]