Role based custom queries (#1019).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@11994 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
@@ -45,7 +45,7 @@ class QueriesController < ApplicationController
|
||||
@query = IssueQuery.new
|
||||
@query.user = User.current
|
||||
@query.project = @project
|
||||
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
|
||||
@query.visibility = IssueQuery::VISIBILITY_PRIVATE unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
|
||||
@query.build_from_params(params)
|
||||
end
|
||||
|
||||
@@ -53,7 +53,7 @@ class QueriesController < ApplicationController
|
||||
@query = IssueQuery.new(params[:query])
|
||||
@query.user = User.current
|
||||
@query.project = params[:query_is_for_all] ? nil : @project
|
||||
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
|
||||
@query.visibility = IssueQuery::VISIBILITY_PRIVATE unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
|
||||
@query.build_from_params(params)
|
||||
@query.column_names = nil if params[:default_columns]
|
||||
|
||||
@@ -71,7 +71,7 @@ class QueriesController < ApplicationController
|
||||
def update
|
||||
@query.attributes = params[:query]
|
||||
@query.project = nil if params[:query_is_for_all]
|
||||
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
|
||||
@query.visibility = IssueQuery::VISIBILITY_PRIVATE unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
|
||||
@query.build_from_params(params)
|
||||
@query.column_names = nil if params[:default_columns]
|
||||
|
||||
|
||||
@@ -225,8 +225,8 @@ module IssuesHelper
|
||||
|
||||
def render_sidebar_queries
|
||||
out = ''.html_safe
|
||||
out << query_links(l(:label_my_queries), sidebar_queries.reject(&:is_public?))
|
||||
out << query_links(l(:label_query_plural), sidebar_queries.select(&:is_public?))
|
||||
out << query_links(l(:label_my_queries), sidebar_queries.select(&:is_private?))
|
||||
out << query_links(l(:label_query_plural), sidebar_queries.reject(&:is_private?))
|
||||
out
|
||||
end
|
||||
|
||||
|
||||
@@ -45,9 +45,25 @@ class IssueQuery < Query
|
||||
scope :visible, lambda {|*args|
|
||||
user = args.shift || User.current
|
||||
base = Project.allowed_to_condition(user, :view_issues, *args)
|
||||
user_id = user.logged? ? user.id : 0
|
||||
scope = includes(:project).where("#{table_name}.project_id IS NULL OR (#{base})")
|
||||
|
||||
includes(:project).where("(#{table_name}.project_id IS NULL OR (#{base})) AND (#{table_name}.is_public = ? OR #{table_name}.user_id = ?)", true, user_id)
|
||||
if user.admin?
|
||||
scope.where("#{table_name}.visibility <> ? OR #{table_name}.user_id = ?", VISIBILITY_PRIVATE, user.id)
|
||||
elsif user.memberships.any?
|
||||
scope.where("#{table_name}.visibility = ?" +
|
||||
" OR (#{table_name}.visibility = ? AND #{table_name}.id IN (" +
|
||||
"SELECT DISTINCT q.id FROM #{table_name} q" +
|
||||
" INNER JOIN #{table_name_prefix}queries_roles#{table_name_suffix} qr on qr.query_id = q.id" +
|
||||
" INNER JOIN #{MemberRole.table_name} mr ON mr.role_id = qr.role_id" +
|
||||
" INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = ?" +
|
||||
" WHERE q.project_id IS NULL OR q.project_id = m.project_id))" +
|
||||
" OR #{table_name}.user_id = ?",
|
||||
VISIBILITY_PUBLIC, VISIBILITY_ROLES, user.id, user.id)
|
||||
elsif user.logged?
|
||||
scope.where("#{table_name}.visibility = ? OR #{table_name}.user_id = ?", VISIBILITY_PUBLIC, user.id)
|
||||
else
|
||||
scope.where("#{table_name}.visibility = ?", VISIBILITY_PUBLIC)
|
||||
end
|
||||
}
|
||||
|
||||
def initialize(attributes=nil, *args)
|
||||
@@ -57,7 +73,28 @@ class IssueQuery < Query
|
||||
|
||||
# Returns true if the query is visible to +user+ or the current user.
|
||||
def visible?(user=User.current)
|
||||
(project.nil? || user.allowed_to?(:view_issues, project)) && (self.is_public? || self.user_id == user.id)
|
||||
return true if user.admin?
|
||||
return false unless project.nil? || user.allowed_to?(:view_issues, project)
|
||||
case visibility
|
||||
when VISIBILITY_PUBLIC
|
||||
true
|
||||
when VISIBILITY_ROLES
|
||||
if project
|
||||
(user.roles_for_project(project) & roles).any?
|
||||
else
|
||||
Member.where(:user_id => user.id).joins(:roles).where(:member_roles => {:role_id => roles.map(&:id)}).any?
|
||||
end
|
||||
else
|
||||
user == self.user
|
||||
end
|
||||
end
|
||||
|
||||
def is_private?
|
||||
visibility == VISIBILITY_PRIVATE
|
||||
end
|
||||
|
||||
def is_public?
|
||||
!is_private?
|
||||
end
|
||||
|
||||
def initialize_available_filters
|
||||
|
||||
+17
-2
@@ -116,8 +116,13 @@ class Query < ActiveRecord::Base
|
||||
class StatementInvalid < ::ActiveRecord::StatementInvalid
|
||||
end
|
||||
|
||||
VISIBILITY_PRIVATE = 0
|
||||
VISIBILITY_ROLES = 1
|
||||
VISIBILITY_PUBLIC = 2
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}queries_roles#{table_name_suffix}", :foreign_key => "query_id"
|
||||
serialize :filters
|
||||
serialize :column_names
|
||||
serialize :sort_criteria, Array
|
||||
@@ -126,7 +131,17 @@ class Query < ActiveRecord::Base
|
||||
|
||||
validates_presence_of :name
|
||||
validates_length_of :name, :maximum => 255
|
||||
validates :visibility, :inclusion => { :in => [VISIBILITY_PUBLIC, VISIBILITY_ROLES, VISIBILITY_PRIVATE] }
|
||||
validate :validate_query_filters
|
||||
validate do |query|
|
||||
errors.add(:base, l(:label_role_plural) + ' ' + l('activerecord.errors.messages.blank')) if query.visibility == VISIBILITY_ROLES && roles.blank?
|
||||
end
|
||||
|
||||
after_save do |query|
|
||||
if query.visibility_changed? && query.visibility != VISIBILITY_ROLES
|
||||
query.roles.clear
|
||||
end
|
||||
end
|
||||
|
||||
class_attribute :operators
|
||||
self.operators = {
|
||||
@@ -245,9 +260,9 @@ class Query < ActiveRecord::Base
|
||||
def editable_by?(user)
|
||||
return false unless user
|
||||
# Admin can edit them all and regular users can edit their private queries
|
||||
return true if user.admin? || (!is_public && self.user_id == user.id)
|
||||
return true if user.admin? || (is_private? && self.user_id == user.id)
|
||||
# Members can not edit public queries that are for all project (only admin is allowed to)
|
||||
is_public && !@is_for_all && user.allowed_to?(:manage_public_queries, project)
|
||||
is_public? && !@is_for_all && user.allowed_to?(:manage_public_queries, project)
|
||||
end
|
||||
|
||||
def trackers
|
||||
|
||||
+1
-1
@@ -669,7 +669,7 @@ class User < Principal
|
||||
Message.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
|
||||
News.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
|
||||
# Remove private queries and keep public ones
|
||||
::Query.delete_all ['user_id = ? AND is_public = ?', id, false]
|
||||
::Query.delete_all ['user_id = ? AND visibility = ?', id, ::Query::VISIBILITY_PRIVATE]
|
||||
::Query.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
|
||||
TimeEntry.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
|
||||
Token.delete_all ['user_id = ?', id]
|
||||
|
||||
@@ -6,15 +6,22 @@
|
||||
<%= text_field 'query', 'name', :size => 80 %></p>
|
||||
|
||||
<% if User.current.admin? || User.current.allowed_to?(:manage_public_queries, @project) %>
|
||||
<p><label for="query_is_public"><%=l(:field_is_public)%></label>
|
||||
<%= check_box 'query', 'is_public',
|
||||
:onchange => (User.current.admin? ? nil : 'if (this.checked) {$("#query_is_for_all").removeAttr("checked"); $("#query_is_for_all").attr("disabled", true);} else {$("#query_is_for_all").removeAttr("disabled");}') %></p>
|
||||
<p><label><%=l(:field_visible)%></label>
|
||||
<label class="block"><%= radio_button 'query', 'visibility', Query::VISIBILITY_PRIVATE %> <%= l(:label_visibility_private) %></label>
|
||||
<label class="block"><%= radio_button 'query', 'visibility', Query::VISIBILITY_ROLES %> <%= l(:label_visibility_roles) %>:</label>
|
||||
<% Role.givable.sorted.each do |role| %>
|
||||
<label class="block role-visibility"><%= check_box_tag 'query[role_ids][]', role.id, @query.roles.include?(role), :id => nil %> <%= role.name %></label>
|
||||
<% end %>
|
||||
<label class="block"><%= radio_button 'query', 'visibility', Query::VISIBILITY_PUBLIC %> <%= l(:label_visibility_public) %></label>
|
||||
<%= hidden_field_tag 'query[role_ids][]', '' %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p><label for="query_is_for_all"><%=l(:field_is_for_all)%></label>
|
||||
<%= check_box_tag 'query_is_for_all', 1, @query.project.nil?,
|
||||
:disabled => (!@query.new_record? && (@query.project.nil? || (@query.is_public? && !User.current.admin?))) %></p>
|
||||
|
||||
<fieldset><legend><%= l(:label_options) %></legend>
|
||||
<p><label for="query_default_columns"><%=l(:label_default_columns)%></label>
|
||||
<%= check_box_tag 'default_columns', 1, @query.has_default_columns?, :id => 'query_default_columns',
|
||||
:onclick => 'if (this.checked) {$("#columns").hide();} else {$("#columns").show();}' %></p>
|
||||
@@ -24,6 +31,7 @@
|
||||
|
||||
<p><label><%= l(:button_show) %></label>
|
||||
<%= available_block_columns_tags(@query) %></p>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<fieldset id="filters"><legend><%= l(:label_filter_plural) %></legend>
|
||||
@@ -53,3 +61,12 @@
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
<%= javascript_tag do %>
|
||||
$(document).ready(function(){
|
||||
$("input[name='query[visibility]']").change(function(){
|
||||
var checked = $('#query_visibility_1').is(':checked');
|
||||
$("input[name='query[role_ids][]'][type=checkbox]").attr('disabled', !checked);
|
||||
}).trigger('change');
|
||||
});
|
||||
<% end %>
|
||||
|
||||
@@ -3,7 +3,7 @@ api.array :queries, api_meta(:total_count => @query_count, :offset => @offset, :
|
||||
api.query do
|
||||
api.id query.id
|
||||
api.name query.name
|
||||
api.is_public query.is_public
|
||||
api.is_public query.is_public?
|
||||
api.project_id query.project_id
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user