Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
131b15fc7a | ||
|
|
f6b1583a1a | ||
|
|
5bea900443 | ||
|
|
81baddad00 | ||
|
|
f6b5632fec | ||
|
|
f7ede727fd | ||
|
|
b870417860 | ||
|
|
25a7838e0a | ||
|
|
7c3ddf2bc0 | ||
|
|
0f8df81b87 | ||
|
|
c5121d804d | ||
|
|
8bcbbebf65 | ||
|
|
2d2afab549 | ||
|
|
35f601e769 | ||
|
|
b84cffd62e | ||
|
|
2eba0b66d4 | ||
|
|
eb2d814344 | ||
|
|
d9385ce9a2 | ||
|
|
d3522c10e4 | ||
|
|
b9957264eb | ||
|
|
da641f4122 | ||
|
|
287d86e363 | ||
|
|
faf1f1e812 | ||
|
|
cd64338a7f | ||
|
|
1b8c5d4058 | ||
|
|
5ccbeba5c2 |
@@ -150,6 +150,7 @@ class ApplicationController < ActionController::Base
|
|||||||
def render_feed(items, options={})
|
def render_feed(items, options={})
|
||||||
@items = items || []
|
@items = items || []
|
||||||
@items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
|
@items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
|
||||||
|
@items = @items.slice(0, Setting.feeds_limit.to_i)
|
||||||
@title = options[:title] || Setting.app_title
|
@title = options[:title] || Setting.app_title
|
||||||
render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
|
render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ class IssuesController < ApplicationController
|
|||||||
# Send html if the query is not valid
|
# Send html if the query is not valid
|
||||||
render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
|
render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
|
||||||
end
|
end
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
def changes
|
def changes
|
||||||
@@ -87,6 +89,8 @@ class IssuesController < ApplicationController
|
|||||||
end
|
end
|
||||||
@title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
|
@title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
|
||||||
render :layout => false, :content_type => 'application/atom+xml'
|
render :layout => false, :content_type => 'application/atom+xml'
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@@ -384,7 +388,10 @@ private
|
|||||||
# Retrieve query from session or build a new query
|
# Retrieve query from session or build a new query
|
||||||
def retrieve_query
|
def retrieve_query
|
||||||
if !params[:query_id].blank?
|
if !params[:query_id].blank?
|
||||||
@query = Query.find(params[:query_id], :conditions => {:project_id => (@project ? @project.id : nil)})
|
cond = "project_id IS NULL"
|
||||||
|
cond << " OR project_id = #{@project.id}" if @project
|
||||||
|
@query = Query.find(params[:query_id], :conditions => cond)
|
||||||
|
@query.project = @project
|
||||||
session[:query] = {:id => @query.id, :project_id => @query.project_id}
|
session[:query] = {:id => @query.id, :project_id => @query.project_id}
|
||||||
else
|
else
|
||||||
if params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
|
if params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
|
||||||
|
|||||||
@@ -18,19 +18,14 @@
|
|||||||
class QueriesController < ApplicationController
|
class QueriesController < ApplicationController
|
||||||
layout 'base'
|
layout 'base'
|
||||||
menu_item :issues
|
menu_item :issues
|
||||||
before_filter :find_project, :authorize
|
before_filter :find_query, :except => :new
|
||||||
|
before_filter :find_optional_project, :only => :new
|
||||||
def index
|
|
||||||
@queries = @project.queries.find(:all,
|
|
||||||
:order => "name ASC",
|
|
||||||
:conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
|
|
||||||
end
|
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@query = Query.new(params[:query])
|
@query = Query.new(params[:query])
|
||||||
@query.project = @project
|
@query.project = params[:query_is_for_all] ? nil : @project
|
||||||
@query.user = User.current
|
@query.user = User.current
|
||||||
@query.is_public = false unless current_role.allowed_to?(:manage_public_queries)
|
@query.is_public = false unless (@query.project && current_role.allowed_to?(:manage_public_queries)) || User.current.admin?
|
||||||
@query.column_names = nil if params[:default_columns]
|
@query.column_names = nil if params[:default_columns]
|
||||||
|
|
||||||
params[:fields].each do |field|
|
params[:fields].each do |field|
|
||||||
@@ -52,7 +47,8 @@ class QueriesController < ApplicationController
|
|||||||
@query.add_filter(field, params[:operators][field], params[:values][field])
|
@query.add_filter(field, params[:operators][field], params[:values][field])
|
||||||
end if params[:fields]
|
end if params[:fields]
|
||||||
@query.attributes = params[:query]
|
@query.attributes = params[:query]
|
||||||
@query.is_public = false unless current_role.allowed_to?(:manage_public_queries)
|
@query.project = nil if params[:query_is_for_all]
|
||||||
|
@query.is_public = false unless (@query.project && current_role.allowed_to?(:manage_public_queries)) || User.current.admin?
|
||||||
@query.column_names = nil if params[:default_columns]
|
@query.column_names = nil if params[:default_columns]
|
||||||
|
|
||||||
if @query.save
|
if @query.save
|
||||||
@@ -64,18 +60,21 @@ class QueriesController < ApplicationController
|
|||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@query.destroy if request.post?
|
@query.destroy if request.post?
|
||||||
redirect_to :controller => 'queries', :project_id => @project
|
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def find_project
|
def find_query
|
||||||
if params[:id]
|
@query = Query.find(params[:id])
|
||||||
@query = Query.find(params[:id])
|
@project = @query.project
|
||||||
@project = @query.project
|
render_403 unless @query.editable_by?(User.current)
|
||||||
render_403 unless @query.editable_by?(User.current)
|
rescue ActiveRecord::RecordNotFound
|
||||||
else
|
render_404
|
||||||
@project = Project.find(params[:project_id])
|
end
|
||||||
end
|
|
||||||
|
def find_optional_project
|
||||||
|
@project = Project.find(params[:project_id]) if params[:project_id]
|
||||||
|
User.current.allowed_to?(:save_queries, @project, :global => true)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,6 +33,19 @@ module IssuesHelper
|
|||||||
"<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
|
"<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sidebar_queries
|
||||||
|
unless @sidebar_queries
|
||||||
|
# User can see public queries and his own queries
|
||||||
|
visible = ARCondition.new(["is_public = ? OR user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
|
||||||
|
# Project specific queries and global queries
|
||||||
|
visible << (@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id])
|
||||||
|
@sidebar_queries = Query.find(:all,
|
||||||
|
:order => "name ASC",
|
||||||
|
:conditions => visible.conditions)
|
||||||
|
end
|
||||||
|
@sidebar_queries
|
||||||
|
end
|
||||||
|
|
||||||
def show_detail(detail, no_html=false)
|
def show_detail(detail, no_html=false)
|
||||||
case detail.property
|
case detail.property
|
||||||
when 'attr'
|
when 'attr'
|
||||||
|
|||||||
+10
-3
@@ -116,6 +116,11 @@ class Query < ActiveRecord::Base
|
|||||||
set_language_if_valid(User.current.language)
|
set_language_if_valid(User.current.language)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_initialize
|
||||||
|
# Store the fact that project is nil (used in #editable_by?)
|
||||||
|
@is_for_all = project.nil?
|
||||||
|
end
|
||||||
|
|
||||||
def validate
|
def validate
|
||||||
filters.each_key do |field|
|
filters.each_key do |field|
|
||||||
errors.add label_for(field), :activerecord_error_blank unless
|
errors.add label_for(field), :activerecord_error_blank unless
|
||||||
@@ -128,8 +133,10 @@ class Query < ActiveRecord::Base
|
|||||||
|
|
||||||
def editable_by?(user)
|
def editable_by?(user)
|
||||||
return false unless user
|
return false unless user
|
||||||
return true if !is_public && self.user_id == user.id
|
# Admin can edit them all and regular users can edit their private queries
|
||||||
is_public && user.allowed_to?(:manage_public_queries, project)
|
return true if user.admin? || (!is_public && 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)
|
||||||
end
|
end
|
||||||
|
|
||||||
def available_filters
|
def available_filters
|
||||||
@@ -139,7 +146,7 @@ class Query < ActiveRecord::Base
|
|||||||
|
|
||||||
@available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
|
@available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
|
||||||
"tracker_id" => { :type => :list, :order => 2, :values => trackers.collect{|s| [s.name, s.id.to_s] } },
|
"tracker_id" => { :type => :list, :order => 2, :values => trackers.collect{|s| [s.name, s.id.to_s] } },
|
||||||
"priority_id" => { :type => :list, :order => 3, :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } },
|
"priority_id" => { :type => :list, :order => 3, :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI'], :order => 'position').collect{|s| [s.name, s.id.to_s] } },
|
||||||
"subject" => { :type => :text, :order => 8 },
|
"subject" => { :type => :text, :order => 8 },
|
||||||
"created_on" => { :type => :date_past, :order => 9 },
|
"created_on" => { :type => :date_past, :order => 9 },
|
||||||
"updated_on" => { :type => :date_past, :order => 10 },
|
"updated_on" => { :type => :date_past, :order => 10 },
|
||||||
|
|||||||
+19
-10
@@ -222,17 +222,26 @@ class User < ActiveRecord::Base
|
|||||||
# action can be:
|
# action can be:
|
||||||
# * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
|
# * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
|
||||||
# * a permission Symbol (eg. :edit_project)
|
# * a permission Symbol (eg. :edit_project)
|
||||||
def allowed_to?(action, project)
|
def allowed_to?(action, project, options={})
|
||||||
# No action allowed on archived projects
|
if project
|
||||||
return false unless project.active?
|
# No action allowed on archived projects
|
||||||
# No action allowed on disabled modules
|
return false unless project.active?
|
||||||
return false unless project.allows_to?(action)
|
# No action allowed on disabled modules
|
||||||
# Admin users are authorized for anything else
|
return false unless project.allows_to?(action)
|
||||||
return true if admin?
|
# Admin users are authorized for anything else
|
||||||
|
return true if admin?
|
||||||
|
|
||||||
role = role_for_project(project)
|
role = role_for_project(project)
|
||||||
return false unless role
|
return false unless role
|
||||||
role.allowed_to?(action) && (project.is_public? || role.member?)
|
role.allowed_to?(action) && (project.is_public? || role.member?)
|
||||||
|
|
||||||
|
elsif options[:global]
|
||||||
|
# authorize if user has at least one role that has this permission
|
||||||
|
roles = memberships.collect {|m| m.role}.uniq
|
||||||
|
roles.detect {|r| r.allowed_to?(action)}
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.current=(user)
|
def self.current=(user)
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<h3><%= l(:label_issue_plural) %></h3>
|
<h3><%= l(:label_issue_plural) %></h3>
|
||||||
<%= link_to l(:label_issue_view_all), { :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 } %><br />
|
<%= link_to l(:label_issue_view_all), { :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 } %><br />
|
||||||
|
<% if @project %>
|
||||||
<%= link_to l(:field_summary), :controller => 'reports', :action => 'issue_report', :id => @project %><br />
|
<%= link_to l(:field_summary), :controller => 'reports', :action => 'issue_report', :id => @project %><br />
|
||||||
<%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %>
|
<%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% unless sidebar_queries.empty? -%>
|
||||||
<h3><%= l(:label_query_plural) %></h3>
|
<h3><%= l(:label_query_plural) %></h3>
|
||||||
|
|
||||||
<% queries = @project.queries.find(:all,
|
<% sidebar_queries.each do |query| -%>
|
||||||
:order => "name ASC",
|
|
||||||
:conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
|
|
||||||
queries.each do |query| %>
|
|
||||||
<%= link_to query.name, :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query %><br />
|
<%= link_to query.name, :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query %><br />
|
||||||
<% end %>
|
<% end -%>
|
||||||
|
<% end -%>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
:update => "content",
|
:update => "content",
|
||||||
}, :class => 'icon icon-reload' %>
|
}, :class => 'icon icon-reload' %>
|
||||||
|
|
||||||
<% if current_role && current_role.allowed_to?(:save_queries) %>
|
<% if User.current.allowed_to?(:save_queries, @project, :global => true) %>
|
||||||
<%= link_to l(:button_save), {}, :onclick => "$('query_form').submit(); return false;", :class => 'icon icon-save' %>
|
<%= link_to l(:button_save), {}, :onclick => "$('query_form').submit(); return false;", :class => 'icon icon-save' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
<% content_for :sidebar do %>
|
<% content_for :sidebar do %>
|
||||||
<%= render :partial => 'issues/sidebar' %>
|
<%= render :partial => 'issues/sidebar' %>
|
||||||
<% end if @project%>
|
<% end %>
|
||||||
|
|
||||||
<% content_for :header_tags do %>
|
<% content_for :header_tags do %>
|
||||||
<%= auto_discovery_link_tag(:atom, {:query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_issue_plural)) %>
|
<%= auto_discovery_link_tag(:atom, {:query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_issue_plural)) %>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="message reply">
|
<div class="message reply">
|
||||||
<h4><%=h message.subject %> - <%= authoring message.created_on, message.author %></h4>
|
<h4><%=h message.subject %> - <%= authoring message.created_on, message.author %></h4>
|
||||||
<div class="wiki"><%= textilizable message.content %></div>
|
<div class="wiki"><%= textilizable message, :content, :attachments => message.attachments %></div>
|
||||||
<%= link_to_attachments message.attachments, :no_author => true %>
|
<%= link_to_attachments message.attachments, :no_author => true %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<div id="preview" class="wiki"></div>
|
<div id="preview" class="wiki"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p><em><% unless @news.summary.empty? %><%=h @news.summary %><br /><% end %>
|
<p><em><% unless @news.summary.blank? %><%=h @news.summary %><br /><% end %>
|
||||||
<span class="author"><%= authoring @news.created_on, @news.author %></span></em></p>
|
<span class="author"><%= authoring @news.created_on, @news.author %></span></em></p>
|
||||||
<div class="wiki">
|
<div class="wiki">
|
||||||
<%= textilizable(@news.description) %>
|
<%= textilizable(@news.description) %>
|
||||||
|
|||||||
@@ -6,11 +6,16 @@
|
|||||||
<p><label for="query_name"><%=l(:field_name)%></label>
|
<p><label for="query_name"><%=l(:field_name)%></label>
|
||||||
<%= text_field 'query', 'name', :size => 80 %></p>
|
<%= text_field 'query', 'name', :size => 80 %></p>
|
||||||
|
|
||||||
<% if current_role.allowed_to?(:manage_public_queries) %>
|
<% if User.current.admin? || (@project && current_role.allowed_to?(:manage_public_queries)) %>
|
||||||
<p><label for="query_is_public"><%=l(:field_is_public)%></label>
|
<p><label for="query_is_public"><%=l(:field_is_public)%></label>
|
||||||
<%= check_box 'query', 'is_public' %></p>
|
<%= check_box 'query', 'is_public',
|
||||||
|
:onchange => (User.current.admin? ? nil : 'if (this.checked) {$("query_is_for_all").checked = false; $("query_is_for_all").disabled = true;} else {$("query_is_for_all").disabled = false;}') %></p>
|
||||||
<% end %>
|
<% 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>
|
||||||
|
|
||||||
<p><label for="query_default_columns"><%=l(:label_default_columns)%></label>
|
<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',
|
<%= check_box_tag 'default_columns', 1, @query.has_default_columns?, :id => 'query_default_columns',
|
||||||
:onclick => 'if (this.checked) {Element.hide("columns")} else {Element.show("columns")}' %></p>
|
:onclick => 'if (this.checked) {Element.hide("columns")} else {Element.show("columns")}' %></p>
|
||||||
|
|||||||
+185
-23
@@ -8,8 +8,8 @@ against redmine database
|
|||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
This module allow anonymous users to browse public project and
|
This module allow anonymous users to browse public project and
|
||||||
registred users to browse and commit their project. authentication is
|
registred users to browse and commit their project. Authentication is
|
||||||
done on the redmine database.
|
done against the redmine database or the LDAP configured in redmine.
|
||||||
|
|
||||||
This method is far simpler than the one with pam_* and works with all
|
This method is far simpler than the one with pam_* and works with all
|
||||||
database without an hassle but you need to have apache/mod_perl on the
|
database without an hassle but you need to have apache/mod_perl on the
|
||||||
@@ -29,12 +29,16 @@ On debian/ubuntu you must do :
|
|||||||
|
|
||||||
aptitude install libapache-dbi-perl libapache2-mod-perl2 libdbd-mysql-perl
|
aptitude install libapache-dbi-perl libapache2-mod-perl2 libdbd-mysql-perl
|
||||||
|
|
||||||
|
If your Redmine users use LDAP authentication, you will also need
|
||||||
|
Authen::Simple::LDAP (and IO::Socket::SSL if LDAPS is used):
|
||||||
|
|
||||||
|
aptitude install libauthen-simple-ldap-perl libio-socket-ssl-perl
|
||||||
|
|
||||||
=head1 CONFIGURATION
|
=head1 CONFIGURATION
|
||||||
|
|
||||||
## if the module isn't in your perl path
|
## This module has to be in your perl path
|
||||||
PerlRequire /usr/local/apache/Redmine.pm
|
## eg: /usr/lib/perl5/Apache/Authn/Redmine.pm
|
||||||
## else
|
PerlLoadModule Apache::Authn::Redmine
|
||||||
# PerlModule Apache::Authn::Redmine
|
|
||||||
<Location /svn>
|
<Location /svn>
|
||||||
DAV svn
|
DAV svn
|
||||||
SVNParentPath "/var/svn"
|
SVNParentPath "/var/svn"
|
||||||
@@ -47,12 +51,19 @@ On debian/ubuntu you must do :
|
|||||||
PerlAuthenHandler Apache::Authn::Redmine::authen_handler
|
PerlAuthenHandler Apache::Authn::Redmine::authen_handler
|
||||||
|
|
||||||
## for mysql
|
## for mysql
|
||||||
PerlSetVar dsn DBI:mysql:database=databasename;host=my.db.server
|
RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"
|
||||||
## for postgres
|
## for postgres
|
||||||
# PerlSetVar dsn DBI:Pg:dbname=databasename;host=my.db.server
|
# RedmineDSN "DBI:Pg:dbname=databasename;host=my.db.server"
|
||||||
|
|
||||||
PerlSetVar db_user redmine
|
RedmineDbUser "redmine"
|
||||||
PerlSetVar db_pass password
|
RedmineDbPass "password"
|
||||||
|
## Optional where clause (fulltext search would be slow and
|
||||||
|
## database dependant).
|
||||||
|
# RedmineDbWhereClause "and members.role_id IN (1,2)"
|
||||||
|
## Configuration for memcached
|
||||||
|
# RedmineMemcacheServers "127.0.0.1:112211"
|
||||||
|
# RedmineMemcacheExpirySec "60"
|
||||||
|
# RedmineMemcacheNamespace "RedmineCreds:"
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
To be able to browse repository inside redmine, you must add something
|
To be able to browse repository inside redmine, you must add something
|
||||||
@@ -87,18 +98,119 @@ And you need to upgrade at least reposman.rb (after r860).
|
|||||||
=cut
|
=cut
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
|
use warnings FATAL => 'all', NONFATAL => 'redefine';
|
||||||
|
|
||||||
use DBI;
|
use DBI;
|
||||||
use Digest::SHA1;
|
use Digest::SHA1;
|
||||||
|
# optional module for LDAP authentication
|
||||||
|
my $CanUseLDAPAuth = eval("use Authen::Simple::LDAP; 1");
|
||||||
|
my $CanUseMemcached = eval("use Cache::Memcached; 1");
|
||||||
|
|
||||||
use Apache2::Module;
|
use Apache2::Module;
|
||||||
use Apache2::Access;
|
use Apache2::Access;
|
||||||
use Apache2::ServerRec qw();
|
use Apache2::ServerRec qw();
|
||||||
use Apache2::RequestRec qw();
|
use Apache2::RequestRec qw();
|
||||||
use Apache2::RequestUtil qw();
|
use Apache2::RequestUtil qw();
|
||||||
use Apache2::Const qw(:common);
|
use Apache2::Const qw(:common :override :cmd_how);
|
||||||
|
|
||||||
# use Apache2::Directive qw();
|
# use Apache2::Directive qw();
|
||||||
|
|
||||||
|
my @directives = (
|
||||||
|
{
|
||||||
|
name => 'RedmineDSN',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
errmsg => 'Dsn in format used by Perl DBI. eg: "DBI:Pg:dbname=databasename;host=my.db.server"',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineDbUser',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineDbPass',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineDbWhereClause',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineMemcacheServers',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineMemcacheExpirySec',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineMemcacheNamespace',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
sub RedmineDSN {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
$self->{RedmineDSN} = $arg;
|
||||||
|
my $query = "SELECT
|
||||||
|
hashed_password, auth_source_id
|
||||||
|
FROM members, projects, users
|
||||||
|
WHERE
|
||||||
|
projects.id=members.project_id
|
||||||
|
AND users.id=members.user_id
|
||||||
|
AND users.status=1
|
||||||
|
AND login=?
|
||||||
|
AND identifier=? ";
|
||||||
|
$self->{RedmineQuery} = trim($query);
|
||||||
|
}
|
||||||
|
sub RedmineDbUser { set_val('RedmineDbUser', @_); }
|
||||||
|
sub RedmineDbPass { set_val('RedmineDbPass', @_); }
|
||||||
|
sub RedmineDbWhereClause {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
$self->{RedmineQuery} = trim($self->{RedmineQuery}.($arg ? $arg : "")." ");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub RedmineMemcacheServers {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
if ($arg && $CanUseMemcached) {
|
||||||
|
$self->{RedmineMemcached} = new Cache::Memcached {
|
||||||
|
'servers' => [ $arg, ],
|
||||||
|
'debug' => 0,
|
||||||
|
};
|
||||||
|
$self->{RedmineMemcache} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub RedmineMemcacheExpirySec { set_val('RedmineMemcacheExpirySec', @_); }
|
||||||
|
|
||||||
|
sub RedmineMemcacheNamespace {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
if ($self->{RedmineMemcache}) {
|
||||||
|
# Undocumented feature of Cache::Memcached, please don't kill me
|
||||||
|
$self->{RedmineMemcached}->{namespace} = $arg;
|
||||||
|
$self->{RedmineMemcached}->{namespace_len} = length $self->{RedmineMemcached}->{namespace};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub trim {
|
||||||
|
my $string = shift;
|
||||||
|
$string =~ s/\s{2,}/ /g;
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub set_val {
|
||||||
|
my ($key, $self, $parms, $arg) = @_;
|
||||||
|
$self->{$key} = $arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Apache2::Module::add(__PACKAGE__, \@directives);
|
||||||
|
|
||||||
|
|
||||||
my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
|
my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
|
||||||
|
|
||||||
sub access_handler {
|
sub access_handler {
|
||||||
@@ -110,7 +222,7 @@ sub access_handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $method = $r->method;
|
my $method = $r->method;
|
||||||
return OK unless 1 == $read_only_methods{$method};
|
return OK if defined $read_only_methods{$method};
|
||||||
|
|
||||||
my $project_id = get_project_identifier($r);
|
my $project_id = get_project_identifier($r);
|
||||||
|
|
||||||
@@ -126,7 +238,11 @@ sub authen_handler {
|
|||||||
my ($res, $redmine_pass) = $r->get_basic_auth_pw();
|
my ($res, $redmine_pass) = $r->get_basic_auth_pw();
|
||||||
return $res unless $res == OK;
|
return $res unless $res == OK;
|
||||||
|
|
||||||
if (is_member($r->user, $redmine_pass, $r)) {
|
my $project_id = get_project_identifier($r);
|
||||||
|
if (!$project_id) {
|
||||||
|
return FORBIDDEN;
|
||||||
|
}
|
||||||
|
if (is_member($r->user, $redmine_pass, $r, $project_id)) {
|
||||||
return OK;
|
return OK;
|
||||||
} else {
|
} else {
|
||||||
$r->note_auth_failure();
|
$r->note_auth_failure();
|
||||||
@@ -138,14 +254,27 @@ sub is_public_project {
|
|||||||
my $project_id = shift;
|
my $project_id = shift;
|
||||||
my $r = shift;
|
my $r = shift;
|
||||||
|
|
||||||
|
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
|
||||||
|
if ($cfg->{RedmineMemcache}) {
|
||||||
|
return 1 if ($cfg->{RedmineMemcached}->get($project_id));
|
||||||
|
}
|
||||||
my $dbh = connect_database($r);
|
my $dbh = connect_database($r);
|
||||||
my $sth = $dbh->prepare(
|
my $sth = $dbh->prepare(
|
||||||
"SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
|
"SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
|
||||||
);
|
);
|
||||||
|
|
||||||
$sth->execute($project_id);
|
$sth->execute($project_id);
|
||||||
my $ret = $sth->fetchrow_array ? 1 : 0;
|
my $ret = $sth->fetchrow_array ? 1 : 0;
|
||||||
|
$sth->finish();
|
||||||
$dbh->disconnect();
|
$dbh->disconnect();
|
||||||
|
if ($cfg->{RedmineMemcache}) {
|
||||||
|
if ($cfg->{RedmineMemcacheExpirySec}) {
|
||||||
|
$cfg->{RedmineMemcached}->set($project_id, $ret, $cfg->{RedmineMemcacheExpirySec});
|
||||||
|
} else {
|
||||||
|
$cfg->{RedmineMemcached}->set($project_id, $ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$ret;
|
$ret;
|
||||||
}
|
}
|
||||||
@@ -169,26 +298,59 @@ sub is_member {
|
|||||||
my $redmine_user = shift;
|
my $redmine_user = shift;
|
||||||
my $redmine_pass = shift;
|
my $redmine_pass = shift;
|
||||||
my $r = shift;
|
my $r = shift;
|
||||||
|
my $project_id = shift;
|
||||||
|
|
||||||
my $dbh = connect_database($r);
|
my $dbh = connect_database($r);
|
||||||
my $project_id = get_project_identifier($r);
|
|
||||||
|
|
||||||
my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
|
my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
|
||||||
|
|
||||||
my $sth = $dbh->prepare(
|
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
|
||||||
"SELECT hashed_password FROM members, projects, users WHERE projects.id=members.project_id AND users.id=members.user_id AND users.status=1 AND login=? AND identifier=?;"
|
my $usrprojpass;
|
||||||
);
|
if ($cfg->{RedmineMemcache}) {
|
||||||
|
$usrprojpass = $cfg->{RedmineMemcached}->get($redmine_user.":".$project_id);
|
||||||
|
return 1 if (defined $usrprojpass and ($usrprojpass eq $pass_digest));
|
||||||
|
}
|
||||||
|
my $query = $cfg->{RedmineQuery};
|
||||||
|
my $sth = $dbh->prepare($query);
|
||||||
$sth->execute($redmine_user, $project_id);
|
$sth->execute($redmine_user, $project_id);
|
||||||
|
|
||||||
my $ret;
|
my $ret;
|
||||||
while (my @row = $sth->fetchrow_array) {
|
while (my @row = $sth->fetchrow_array) {
|
||||||
if ($row[0] eq $pass_digest) {
|
unless ($row[1]) {
|
||||||
$ret = 1;
|
if ($row[0] eq $pass_digest) {
|
||||||
last;
|
$ret = 1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
} elsif ($CanUseLDAPAuth) {
|
||||||
|
my $sthldap = $dbh->prepare(
|
||||||
|
"SELECT host,port,tls,account,account_password,base_dn,attr_login from auth_sources WHERE id = ?;"
|
||||||
|
);
|
||||||
|
$sthldap->execute($row[1]);
|
||||||
|
while (my @rowldap = $sthldap->fetchrow_array) {
|
||||||
|
my $ldap = Authen::Simple::LDAP->new(
|
||||||
|
host => ($rowldap[2] == 1 || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0],
|
||||||
|
port => $rowldap[1],
|
||||||
|
basedn => $rowldap[5],
|
||||||
|
binddn => $rowldap[3] ? $rowldap[3] : "",
|
||||||
|
bindpw => $rowldap[4] ? $rowldap[4] : "",
|
||||||
|
filter => "(".$rowldap[6]."=%s)"
|
||||||
|
);
|
||||||
|
$ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass));
|
||||||
|
}
|
||||||
|
$sthldap->finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$sth->finish();
|
||||||
$dbh->disconnect();
|
$dbh->disconnect();
|
||||||
|
|
||||||
|
if ($cfg->{RedmineMemcache} and $ret) {
|
||||||
|
if ($cfg->{RedmineMemcacheExpirySec}) {
|
||||||
|
$cfg->{RedmineMemcached}->set($redmine_user.":".$project_id, $pass_digest, $cfg->{RedmineMemcacheExpirySec});
|
||||||
|
} else {
|
||||||
|
$cfg->{RedmineMemcached}->set($redmine_user.":".$project_id, $pass_digest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$ret;
|
$ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,8 +365,8 @@ sub get_project_identifier {
|
|||||||
sub connect_database {
|
sub connect_database {
|
||||||
my $r = shift;
|
my $r = shift;
|
||||||
|
|
||||||
my ($dsn, $db_user, $db_pass) = map { $r->dir_config($_) } qw/dsn db_user db_pass/;
|
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
|
||||||
return DBI->connect($dsn, $db_user, $db_pass);
|
return DBI->connect($cfg->{RedmineDSN}, $cfg->{RedmineDbUser}, $cfg->{RedmineDbPass});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
Vendored
+50
-3
@@ -1,7 +1,9 @@
|
|||||||
---
|
---
|
||||||
queries_001:
|
queries_001:
|
||||||
name: Multiple custom fields query
|
id: 1
|
||||||
project_id: 1
|
project_id: 1
|
||||||
|
is_public: true
|
||||||
|
name: Multiple custom fields query
|
||||||
filters: |
|
filters: |
|
||||||
---
|
---
|
||||||
cf_1:
|
cf_1:
|
||||||
@@ -17,6 +19,51 @@ queries_001:
|
|||||||
- "125"
|
- "125"
|
||||||
:operator: "="
|
:operator: "="
|
||||||
|
|
||||||
id: 1
|
|
||||||
is_public: true
|
|
||||||
user_id: 1
|
user_id: 1
|
||||||
|
column_names:
|
||||||
|
queries_002:
|
||||||
|
id: 2
|
||||||
|
project_id: 1
|
||||||
|
is_public: false
|
||||||
|
name: Private query for cookbook
|
||||||
|
filters: |
|
||||||
|
---
|
||||||
|
tracker_id:
|
||||||
|
:values:
|
||||||
|
- "3"
|
||||||
|
:operator: "="
|
||||||
|
status_id:
|
||||||
|
:values:
|
||||||
|
- "1"
|
||||||
|
:operator: o
|
||||||
|
|
||||||
|
user_id: 3
|
||||||
|
column_names:
|
||||||
|
queries_003:
|
||||||
|
id: 3
|
||||||
|
project_id:
|
||||||
|
is_public: false
|
||||||
|
name: Private query for all projects
|
||||||
|
filters: |
|
||||||
|
---
|
||||||
|
tracker_id:
|
||||||
|
:values:
|
||||||
|
- "3"
|
||||||
|
:operator: "="
|
||||||
|
|
||||||
|
user_id: 3
|
||||||
|
column_names:
|
||||||
|
queries_004:
|
||||||
|
id: 4
|
||||||
|
project_id:
|
||||||
|
is_public: true
|
||||||
|
name: Public query for all projects
|
||||||
|
filters: |
|
||||||
|
---
|
||||||
|
tracker_id:
|
||||||
|
:values:
|
||||||
|
- "3"
|
||||||
|
:operator: "="
|
||||||
|
|
||||||
|
user_id: 2
|
||||||
|
column_names:
|
||||||
|
|||||||
Vendored
-2
@@ -57,7 +57,6 @@ roles_002:
|
|||||||
- :add_issue_notes
|
- :add_issue_notes
|
||||||
- :move_issues
|
- :move_issues
|
||||||
- :delete_issues
|
- :delete_issues
|
||||||
- :manage_public_queries
|
|
||||||
- :save_queries
|
- :save_queries
|
||||||
- :view_gantt
|
- :view_gantt
|
||||||
- :view_calendar
|
- :view_calendar
|
||||||
@@ -94,7 +93,6 @@ roles_003:
|
|||||||
- :manage_issue_relations
|
- :manage_issue_relations
|
||||||
- :add_issue_notes
|
- :add_issue_notes
|
||||||
- :move_issues
|
- :move_issues
|
||||||
- :manage_public_queries
|
|
||||||
- :save_queries
|
- :save_queries
|
||||||
- :view_gantt
|
- :view_gantt
|
||||||
- :view_calendar
|
- :view_calendar
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
require 'queries_controller'
|
||||||
|
|
||||||
|
# Re-raise errors caught by the controller.
|
||||||
|
class QueriesController; def rescue_action(e) raise e end; end
|
||||||
|
|
||||||
|
class QueriesControllerTest < Test::Unit::TestCase
|
||||||
|
fixtures :projects, :users, :members, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@controller = QueriesController.new
|
||||||
|
@request = ActionController::TestRequest.new
|
||||||
|
@response = ActionController::TestResponse.new
|
||||||
|
User.current = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_get_new_project_query
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
get :new, :project_id => 1
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'new'
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query[is_public]',
|
||||||
|
:checked => nil }
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query_is_for_all',
|
||||||
|
:checked => nil,
|
||||||
|
:disabled => nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_get_new_global_query
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
get :new
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'new'
|
||||||
|
assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query[is_public]' }
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query_is_for_all',
|
||||||
|
:checked => 'checked',
|
||||||
|
:disabled => nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_new_project_public_query
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
post :new,
|
||||||
|
:project_id => 'ecookbook',
|
||||||
|
:confirm => '1',
|
||||||
|
:default_columns => '1',
|
||||||
|
:fields => ["status_id", "assigned_to_id"],
|
||||||
|
:operators => {"assigned_to_id" => "=", "status_id" => "o"},
|
||||||
|
:values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
|
||||||
|
:query => {"name" => "test_new_project_public_query", "is_public" => "1"}
|
||||||
|
|
||||||
|
q = Query.find_by_name('test_new_project_public_query')
|
||||||
|
assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q
|
||||||
|
assert q.is_public?
|
||||||
|
assert q.has_default_columns?
|
||||||
|
assert q.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_new_project_private_query
|
||||||
|
@request.session[:user_id] = 3
|
||||||
|
post :new,
|
||||||
|
:project_id => 'ecookbook',
|
||||||
|
:confirm => '1',
|
||||||
|
:default_columns => '1',
|
||||||
|
:fields => ["status_id", "assigned_to_id"],
|
||||||
|
:operators => {"assigned_to_id" => "=", "status_id" => "o"},
|
||||||
|
:values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
|
||||||
|
:query => {"name" => "test_new_project_private_query", "is_public" => "1"}
|
||||||
|
|
||||||
|
q = Query.find_by_name('test_new_project_private_query')
|
||||||
|
assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q
|
||||||
|
assert !q.is_public?
|
||||||
|
assert q.has_default_columns?
|
||||||
|
assert q.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_new_global_private_query_with_custom_columns
|
||||||
|
@request.session[:user_id] = 3
|
||||||
|
post :new,
|
||||||
|
:confirm => '1',
|
||||||
|
:fields => ["status_id", "assigned_to_id"],
|
||||||
|
:operators => {"assigned_to_id" => "=", "status_id" => "o"},
|
||||||
|
:values => { "assigned_to_id" => ["me"], "status_id" => ["1"]},
|
||||||
|
:query => {"name" => "test_new_global_private_query", "is_public" => "1", "column_names" => ["", "tracker", "subject", "priority", "category"]}
|
||||||
|
|
||||||
|
q = Query.find_by_name('test_new_global_private_query')
|
||||||
|
assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q
|
||||||
|
assert !q.is_public?
|
||||||
|
assert !q.has_default_columns?
|
||||||
|
assert_equal [:tracker, :subject, :priority, :category], q.columns.collect {|c| c.name}
|
||||||
|
assert q.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_get_edit_global_public_query
|
||||||
|
@request.session[:user_id] = 1
|
||||||
|
get :edit, :id => 4
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'edit'
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query[is_public]',
|
||||||
|
:checked => 'checked' }
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query_is_for_all',
|
||||||
|
:checked => 'checked',
|
||||||
|
:disabled => 'disabled' }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_global_public_query
|
||||||
|
@request.session[:user_id] = 1
|
||||||
|
post :edit,
|
||||||
|
:id => 4,
|
||||||
|
:confirm => '1',
|
||||||
|
:default_columns => '1',
|
||||||
|
:fields => ["status_id", "assigned_to_id"],
|
||||||
|
:operators => {"assigned_to_id" => "=", "status_id" => "o"},
|
||||||
|
:values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
|
||||||
|
:query => {"name" => "test_edit_global_public_query", "is_public" => "1"}
|
||||||
|
|
||||||
|
assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 4
|
||||||
|
q = Query.find_by_name('test_edit_global_public_query')
|
||||||
|
assert q.is_public?
|
||||||
|
assert q.has_default_columns?
|
||||||
|
assert q.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_get_edit_global_private_query
|
||||||
|
@request.session[:user_id] = 3
|
||||||
|
get :edit, :id => 3
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'edit'
|
||||||
|
assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query[is_public]' }
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query_is_for_all',
|
||||||
|
:checked => 'checked',
|
||||||
|
:disabled => 'disabled' }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_global_private_query
|
||||||
|
@request.session[:user_id] = 3
|
||||||
|
post :edit,
|
||||||
|
:id => 3,
|
||||||
|
:confirm => '1',
|
||||||
|
:default_columns => '1',
|
||||||
|
:fields => ["status_id", "assigned_to_id"],
|
||||||
|
:operators => {"assigned_to_id" => "=", "status_id" => "o"},
|
||||||
|
:values => { "assigned_to_id" => ["me"], "status_id" => ["1"]},
|
||||||
|
:query => {"name" => "test_edit_global_private_query", "is_public" => "1"}
|
||||||
|
|
||||||
|
assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 3
|
||||||
|
q = Query.find_by_name('test_edit_global_private_query')
|
||||||
|
assert !q.is_public?
|
||||||
|
assert q.has_default_columns?
|
||||||
|
assert q.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_get_edit_project_private_query
|
||||||
|
@request.session[:user_id] = 3
|
||||||
|
get :edit, :id => 2
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'edit'
|
||||||
|
assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query[is_public]' }
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query_is_for_all',
|
||||||
|
:checked => nil,
|
||||||
|
:disabled => nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_get_edit_project_public_query
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
get :edit, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'edit'
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query[is_public]',
|
||||||
|
:checked => 'checked'
|
||||||
|
}
|
||||||
|
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||||
|
:name => 'query_is_for_all',
|
||||||
|
:checked => nil,
|
||||||
|
:disabled => 'disabled' }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_destroy
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
post :destroy, :id => 1
|
||||||
|
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :set_filter => 1, :query_id => nil
|
||||||
|
assert_nil Query.find_by_id(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
+32
-2
@@ -1,5 +1,5 @@
|
|||||||
# redMine - project management software
|
# redMine - project management software
|
||||||
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU General Public License
|
# modify it under the terms of the GNU General Public License
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
|
||||||
class QueryTest < Test::Unit::TestCase
|
class QueryTest < Test::Unit::TestCase
|
||||||
fixtures :projects, :users, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries
|
fixtures :projects, :users, :members, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries
|
||||||
|
|
||||||
def test_query_with_multiple_custom_fields
|
def test_query_with_multiple_custom_fields
|
||||||
query = Query.find(1)
|
query = Query.find(1)
|
||||||
@@ -41,4 +41,34 @@ class QueryTest < Test::Unit::TestCase
|
|||||||
c = q.columns.first
|
c = q.columns.first
|
||||||
assert q.has_column?(c)
|
assert q.has_column?(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_editable_by
|
||||||
|
admin = User.find(1)
|
||||||
|
manager = User.find(2)
|
||||||
|
developer = User.find(3)
|
||||||
|
|
||||||
|
# Public query on project 1
|
||||||
|
q = Query.find(1)
|
||||||
|
assert q.editable_by?(admin)
|
||||||
|
assert q.editable_by?(manager)
|
||||||
|
assert !q.editable_by?(developer)
|
||||||
|
|
||||||
|
# Private query on project 1
|
||||||
|
q = Query.find(2)
|
||||||
|
assert q.editable_by?(admin)
|
||||||
|
assert !q.editable_by?(manager)
|
||||||
|
assert q.editable_by?(developer)
|
||||||
|
|
||||||
|
# Private query for all projects
|
||||||
|
q = Query.find(3)
|
||||||
|
assert q.editable_by?(admin)
|
||||||
|
assert !q.editable_by?(manager)
|
||||||
|
assert q.editable_by?(developer)
|
||||||
|
|
||||||
|
# Public query for all projects
|
||||||
|
q = Query.find(4)
|
||||||
|
assert q.editable_by?(admin)
|
||||||
|
assert !q.editable_by?(manager)
|
||||||
|
assert !q.editable_by?(developer)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user