Compare commits
55
Commits
0.9.3
...
0.9-stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a84920ca70 | ||
|
|
21d2de48b7 | ||
|
|
a19a37b600 | ||
|
|
29e7b8d9ea | ||
|
|
f3b9c0027f | ||
|
|
a146c2d03f | ||
|
|
a62ff0841f | ||
|
|
d7ec02691f | ||
|
|
e7790bb6b5 | ||
|
|
34f73b005b | ||
|
|
ba42e1e2ff | ||
|
|
14074da8b1 | ||
|
|
44851d079f | ||
|
|
e6d053c3fd | ||
|
|
f17924c60d | ||
|
|
90e23e4d5d | ||
|
|
88a2792778 | ||
|
|
4c881d54a7 | ||
|
|
a6d45cc68f | ||
|
|
f58f7e0e41 | ||
|
|
473366f887 | ||
|
|
f6d2a4c29f | ||
|
|
b26d0fe041 | ||
|
|
98f3e98d82 | ||
|
|
7b27280c9b | ||
|
|
d287436627 | ||
|
|
666d3d6472 | ||
|
|
36063f16ee | ||
|
|
4a295e723e | ||
|
|
6e67d76194 | ||
|
|
eb55efd604 | ||
|
|
390eb7849c | ||
|
|
1588f3f6dc | ||
|
|
5ef8e8d45f | ||
|
|
cd15eb77d9 | ||
|
|
3b699806d9 | ||
|
|
d2367ccf53 | ||
|
|
9c00b8aa21 | ||
|
|
bbb00b0bc4 | ||
|
|
feac751318 | ||
|
|
eb4a7f9f2e | ||
|
|
7ce9ba9e28 | ||
|
|
53880a4e08 | ||
|
|
f92aa00705 | ||
|
|
b240da3833 | ||
|
|
da8624f7c7 | ||
|
|
46be83cd5e | ||
|
|
667f7927a7 | ||
|
|
3e6f42e46d | ||
|
|
30c45a6187 | ||
|
|
32288ed5d7 | ||
|
|
beb89eb8bb | ||
|
|
62d8016c4f | ||
|
|
5a7a3b2392 | ||
|
|
a2ad66a5c0 |
@@ -25,8 +25,7 @@ class AccountController < ApplicationController
|
|||||||
# Login request and validation
|
# Login request and validation
|
||||||
def login
|
def login
|
||||||
if request.get?
|
if request.get?
|
||||||
# Logout user
|
logout_user
|
||||||
self.logged_user = nil
|
|
||||||
else
|
else
|
||||||
# Authenticate user
|
# Authenticate user
|
||||||
if Setting.openid? && using_open_id?
|
if Setting.openid? && using_open_id?
|
||||||
@@ -39,9 +38,7 @@ class AccountController < ApplicationController
|
|||||||
|
|
||||||
# Log out current user and redirect to welcome page
|
# Log out current user and redirect to welcome page
|
||||||
def logout
|
def logout
|
||||||
cookies.delete :autologin
|
logout_user
|
||||||
Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged?
|
|
||||||
self.logged_user = nil
|
|
||||||
redirect_to home_url
|
redirect_to home_url
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -134,7 +131,15 @@ class AccountController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def logout_user
|
||||||
|
if User.current.logged?
|
||||||
|
cookies.delete :autologin
|
||||||
|
Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin'])
|
||||||
|
self.logged_user = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def password_authentication
|
def password_authentication
|
||||||
user = User.try_to_login(params[:username], params[:password])
|
user = User.try_to_login(params[:username], params[:password])
|
||||||
|
|
||||||
|
|||||||
@@ -107,8 +107,9 @@ class ApplicationController < ActionController::Base
|
|||||||
lang = find_language(User.current.language)
|
lang = find_language(User.current.language)
|
||||||
end
|
end
|
||||||
if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
|
if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
|
||||||
accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
|
accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first
|
||||||
if !accept_lang.blank?
|
if !accept_lang.blank?
|
||||||
|
accept_lang = accept_lang.downcase
|
||||||
lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
|
lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -76,12 +76,12 @@ class EnumerationsController < ApplicationController
|
|||||||
@enumeration.destroy
|
@enumeration.destroy
|
||||||
redirect_to :action => 'index'
|
redirect_to :action => 'index'
|
||||||
elsif params[:reassign_to_id]
|
elsif params[:reassign_to_id]
|
||||||
if reassign_to = Enumeration.find_by_type_and_id(@enumeration.type, params[:reassign_to_id])
|
if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id])
|
||||||
@enumeration.destroy(reassign_to)
|
@enumeration.destroy(reassign_to)
|
||||||
redirect_to :action => 'index'
|
redirect_to :action => 'index'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@enumerations = Enumeration.find(:all, :conditions => ['type = (?)', @enumeration.type]) - [@enumeration]
|
@enumerations = @enumeration.class.find(:all) - [@enumeration]
|
||||||
#rescue
|
#rescue
|
||||||
# flash[:error] = 'Unable to delete enumeration'
|
# flash[:error] = 'Unable to delete enumeration'
|
||||||
# redirect_to :action => 'index'
|
# redirect_to :action => 'index'
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class IssuesController < ApplicationController
|
|||||||
if request.get? || request.xhr?
|
if request.get? || request.xhr?
|
||||||
@issue.start_date ||= Date.today
|
@issue.start_date ||= Date.today
|
||||||
else
|
else
|
||||||
requested_status = IssueStatus.find_by_id(params[:issue][:status_id])
|
requested_status = IssueStatus.find_by_id(params[:issue][:status_id]) if params[:issue]
|
||||||
# Check that the user is allowed to apply the requested status
|
# Check that the user is allowed to apply the requested status
|
||||||
@issue.status = (@allowed_statuses.include? requested_status) ? requested_status : default_status
|
@issue.status = (@allowed_statuses.include? requested_status) ? requested_status : default_status
|
||||||
call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
|
call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
|
||||||
@@ -223,10 +223,13 @@ class IssuesController < ApplicationController
|
|||||||
user = @issue.author
|
user = @issue.author
|
||||||
text = @issue.description
|
text = @issue.description
|
||||||
end
|
end
|
||||||
content = "#{ll(Setting.default_language, :text_user_wrote, user)}\\n> "
|
# Replaces pre blocks with [...]
|
||||||
content << text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub('"', '\"').gsub(/(\r?\n|\r\n?)/, "\\n> ") + "\\n\\n"
|
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
|
||||||
|
content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> "
|
||||||
|
content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
|
||||||
|
|
||||||
render(:update) { |page|
|
render(:update) { |page|
|
||||||
page.<< "$('notes').value = \"#{content}\";"
|
page.<< "$('notes').value = \"#{escape_javascript content}\";"
|
||||||
page.show 'update'
|
page.show 'update'
|
||||||
page << "Form.Element.focus('notes');"
|
page << "Form.Element.focus('notes');"
|
||||||
page << "Element.scrollTo('update');"
|
page << "Element.scrollTo('update');"
|
||||||
@@ -280,14 +283,7 @@ class IssuesController < ApplicationController
|
|||||||
|
|
||||||
def move
|
def move
|
||||||
@copy = params[:copy_options] && params[:copy_options][:copy]
|
@copy = params[:copy_options] && params[:copy_options][:copy]
|
||||||
@allowed_projects = []
|
@allowed_projects = Issue.allowed_target_projects_on_move
|
||||||
# find projects to which the user is allowed to move the issue
|
|
||||||
if User.current.admin?
|
|
||||||
# admin is allowed to move issues to any active (visible) project
|
|
||||||
@allowed_projects = Project.find(:all, :conditions => Project.visible_by(User.current))
|
|
||||||
else
|
|
||||||
User.current.memberships.each {|m| @allowed_projects << m.project if m.roles.detect {|r| r.allowed_to?(:move_issues)}}
|
|
||||||
end
|
|
||||||
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
|
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
|
||||||
@target_project ||= @project
|
@target_project ||= @project
|
||||||
@trackers = @target_project.trackers
|
@trackers = @target_project.trackers
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class MembersController < ApplicationController
|
|||||||
format.js {
|
format.js {
|
||||||
render(:update) {|page|
|
render(:update) {|page|
|
||||||
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
|
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
|
||||||
|
page << 'hideOnLoad()'
|
||||||
members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
|
members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,6 +52,7 @@ class MembersController < ApplicationController
|
|||||||
format.js {
|
format.js {
|
||||||
render(:update) {|page|
|
render(:update) {|page|
|
||||||
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
|
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
|
||||||
|
page << 'hideOnLoad()'
|
||||||
page.visual_effect(:highlight, "member-#{@member.id}")
|
page.visual_effect(:highlight, "member-#{@member.id}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +66,11 @@ class MembersController < ApplicationController
|
|||||||
end
|
end
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
|
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
|
||||||
format.js { render(:update) {|page| page.replace_html "tab-content-members", :partial => 'projects/settings/members'} }
|
format.js { render(:update) {|page|
|
||||||
|
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
|
||||||
|
page << 'hideOnLoad()'
|
||||||
|
}
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class ProjectsController < ApplicationController
|
|||||||
before_filter :authorize, :except => [ :index, :list, :add, :copy, :archive, :unarchive, :destroy, :activity ]
|
before_filter :authorize, :except => [ :index, :list, :add, :copy, :archive, :unarchive, :destroy, :activity ]
|
||||||
before_filter :authorize_global, :only => :add
|
before_filter :authorize_global, :only => :add
|
||||||
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
|
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
|
||||||
accept_key_auth :activity
|
accept_key_auth :activity, :index
|
||||||
|
|
||||||
after_filter :only => [:add, :edit, :archive, :unarchive, :destroy] do |controller|
|
after_filter :only => [:add, :edit, :archive, :unarchive, :destroy] do |controller|
|
||||||
if controller.request.post?
|
if controller.request.post?
|
||||||
@@ -102,18 +102,20 @@ class ProjectsController < ApplicationController
|
|||||||
redirect_to :controller => 'admin', :action => 'projects'
|
redirect_to :controller => 'admin', :action => 'projects'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@project = Project.new(params[:project])
|
Mailer.with_deliveries(params[:notifications] == '1') do
|
||||||
@project.enabled_module_names = params[:enabled_modules]
|
@project = Project.new(params[:project])
|
||||||
if validate_parent_id && @project.copy(@source_project, :only => params[:only])
|
@project.enabled_module_names = params[:enabled_modules]
|
||||||
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
if validate_parent_id && @project.copy(@source_project, :only => params[:only])
|
||||||
flash[:notice] = l(:notice_successful_create)
|
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||||
redirect_to :controller => 'admin', :action => 'projects'
|
flash[:notice] = l(:notice_successful_create)
|
||||||
elsif !@project.new_record?
|
redirect_to :controller => 'admin', :action => 'projects'
|
||||||
# Project was created
|
elsif !@project.new_record?
|
||||||
# But some objects were not copied due to validation failures
|
# Project was created
|
||||||
# (eg. issues from disabled trackers)
|
# But some objects were not copied due to validation failures
|
||||||
# TODO: inform about that
|
# (eg. issues from disabled trackers)
|
||||||
redirect_to :controller => 'admin', :action => 'projects'
|
# TODO: inform about that
|
||||||
|
redirect_to :controller => 'admin', :action => 'projects'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ private
|
|||||||
|
|
||||||
def find_optional_project
|
def find_optional_project
|
||||||
@project = Project.find(params[:project_id]) if params[:project_id]
|
@project = Project.find(params[:project_id]) if params[:project_id]
|
||||||
User.current.allowed_to?(:save_queries, @project, :global => true)
|
render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class ReportsController < ApplicationController
|
|||||||
render :template => "reports/issue_report_details"
|
render :template => "reports/issue_report_details"
|
||||||
when "subproject"
|
when "subproject"
|
||||||
@field = "project_id"
|
@field = "project_id"
|
||||||
@rows = @project.descendants.active
|
@rows = @project.descendants.visible
|
||||||
@data = issues_by_subproject
|
@data = issues_by_subproject
|
||||||
@report_title = l(:field_subproject)
|
@report_title = l(:field_subproject)
|
||||||
render :template => "reports/issue_report_details"
|
render :template => "reports/issue_report_details"
|
||||||
@@ -72,7 +72,7 @@ class ReportsController < ApplicationController
|
|||||||
@categories = @project.issue_categories
|
@categories = @project.issue_categories
|
||||||
@assignees = @project.members.collect { |m| m.user }.sort
|
@assignees = @project.members.collect { |m| m.user }.sort
|
||||||
@authors = @project.members.collect { |m| m.user }.sort
|
@authors = @project.members.collect { |m| m.user }.sort
|
||||||
@subprojects = @project.descendants.active
|
@subprojects = @project.descendants.visible
|
||||||
issues_by_tracker
|
issues_by_tracker
|
||||||
issues_by_version
|
issues_by_version
|
||||||
issues_by_priority
|
issues_by_priority
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ class VersionsController < ApplicationController
|
|||||||
helper :projects
|
helper :projects
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
@issues = @version.fixed_issues.visible.find(:all,
|
||||||
|
:include => [:status, :tracker, :priority],
|
||||||
|
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@@ -46,11 +49,13 @@ class VersionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@version.destroy
|
if @version.fixed_issues.empty?
|
||||||
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
|
@version.destroy
|
||||||
rescue
|
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
|
||||||
flash[:error] = l(:notice_unable_delete_version)
|
else
|
||||||
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
|
flash[:error] = l(:notice_unable_delete_version)
|
||||||
|
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def status_by
|
def status_by
|
||||||
|
|||||||
@@ -52,17 +52,19 @@ module RepositoriesHelper
|
|||||||
else
|
else
|
||||||
change
|
change
|
||||||
end
|
end
|
||||||
end.compact
|
end.compact
|
||||||
|
|
||||||
tree = { }
|
tree = { }
|
||||||
changes.each do |change|
|
changes.each do |change|
|
||||||
p = tree
|
p = tree
|
||||||
dirs = change.path.to_s.split('/').select {|d| !d.blank?}
|
dirs = change.path.to_s.split('/').select {|d| !d.blank?}
|
||||||
|
path = ''
|
||||||
dirs.each do |dir|
|
dirs.each do |dir|
|
||||||
|
path += '/' + dir
|
||||||
p[:s] ||= {}
|
p[:s] ||= {}
|
||||||
p = p[:s]
|
p = p[:s]
|
||||||
p[dir] ||= {}
|
p[path] ||= {}
|
||||||
p = p[dir]
|
p = p[path]
|
||||||
end
|
end
|
||||||
p[:c] = change
|
p[:c] = change
|
||||||
end
|
end
|
||||||
@@ -76,21 +78,26 @@ module RepositoriesHelper
|
|||||||
output = ''
|
output = ''
|
||||||
output << '<ul>'
|
output << '<ul>'
|
||||||
tree.keys.sort.each do |file|
|
tree.keys.sort.each do |file|
|
||||||
s = !tree[file][:s].nil?
|
|
||||||
c = tree[file][:c]
|
|
||||||
|
|
||||||
style = 'change'
|
style = 'change'
|
||||||
style << ' folder' if s
|
text = File.basename(h(file))
|
||||||
style << " change-#{c.action}" if c
|
if s = tree[file][:s]
|
||||||
|
style << ' folder'
|
||||||
text = h(file)
|
path_param = to_path_param(@repository.relative_path(file))
|
||||||
unless c.nil?
|
text = link_to(text, :controller => 'repositories',
|
||||||
|
:action => 'show',
|
||||||
|
:id => @project,
|
||||||
|
:path => path_param,
|
||||||
|
:rev => @changeset.revision)
|
||||||
|
output << "<li class='#{style}'>#{text}</li>"
|
||||||
|
output << render_changes_tree(s)
|
||||||
|
elsif c = tree[file][:c]
|
||||||
|
style << " change-#{c.action}"
|
||||||
path_param = to_path_param(@repository.relative_path(c.path))
|
path_param = to_path_param(@repository.relative_path(c.path))
|
||||||
text = link_to(text, :controller => 'repositories',
|
text = link_to(text, :controller => 'repositories',
|
||||||
:action => 'entry',
|
:action => 'entry',
|
||||||
:id => @project,
|
:id => @project,
|
||||||
:path => path_param,
|
:path => path_param,
|
||||||
:rev => @changeset.revision) unless s || c.action == 'D'
|
:rev => @changeset.revision) unless c.action == 'D'
|
||||||
text << " - #{c.revision}" unless c.revision.blank?
|
text << " - #{c.revision}" unless c.revision.blank?
|
||||||
text << ' (' + link_to('diff', :controller => 'repositories',
|
text << ' (' + link_to('diff', :controller => 'repositories',
|
||||||
:action => 'diff',
|
:action => 'diff',
|
||||||
@@ -98,9 +105,8 @@ module RepositoriesHelper
|
|||||||
:path => path_param,
|
:path => path_param,
|
||||||
:rev => @changeset.revision) + ') ' if c.action == 'M'
|
:rev => @changeset.revision) + ') ' if c.action == 'M'
|
||||||
text << ' ' + content_tag('span', c.from_path, :class => 'copied-from') unless c.from_path.blank?
|
text << ' ' + content_tag('span', c.from_path, :class => 'copied-from') unless c.from_path.blank?
|
||||||
|
output << "<li class='#{style}'>#{text}</li>"
|
||||||
end
|
end
|
||||||
output << "<li class='#{style}'>#{text}</li>"
|
|
||||||
output << render_changes_tree(tree[file][:s]) if s
|
|
||||||
end
|
end
|
||||||
output << '</ul>'
|
output << '</ul>'
|
||||||
output
|
output
|
||||||
|
|||||||
@@ -182,6 +182,11 @@ class Changeset < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
# removes invalid UTF8 sequences
|
# removes invalid UTF8 sequences
|
||||||
Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
|
begin
|
||||||
|
Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
|
||||||
|
rescue Iconv::InvalidEncoding
|
||||||
|
# "UTF-8//IGNORE" is not supported on some OS
|
||||||
|
str
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+21
-5
@@ -80,7 +80,7 @@ class Issue < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def copy_from(arg)
|
def copy_from(arg)
|
||||||
issue = arg.is_a?(Issue) ? arg : Issue.find(arg)
|
issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg)
|
||||||
self.attributes = issue.attributes.dup.except("id", "created_on", "updated_on")
|
self.attributes = issue.attributes.dup.except("id", "created_on", "updated_on")
|
||||||
self.custom_values = issue.custom_values.collect {|v| v.clone}
|
self.custom_values = issue.custom_values.collect {|v| v.clone}
|
||||||
self.status = issue.status
|
self.status = issue.status
|
||||||
@@ -92,7 +92,7 @@ class Issue < ActiveRecord::Base
|
|||||||
def move_to(new_project, new_tracker = nil, options = {})
|
def move_to(new_project, new_tracker = nil, options = {})
|
||||||
options ||= {}
|
options ||= {}
|
||||||
issue = options[:copy] ? self.clone : self
|
issue = options[:copy] ? self.clone : self
|
||||||
transaction do
|
ret = Issue.transaction do
|
||||||
if new_project && issue.project_id != new_project.id
|
if new_project && issue.project_id != new_project.id
|
||||||
# delete issue relations
|
# delete issue relations
|
||||||
unless Setting.cross_project_issue_relations?
|
unless Setting.cross_project_issue_relations?
|
||||||
@@ -129,12 +129,12 @@ class Issue < ActiveRecord::Base
|
|||||||
# Manually update project_id on related time entries
|
# Manually update project_id on related time entries
|
||||||
TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
|
TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
|
||||||
end
|
end
|
||||||
|
true
|
||||||
else
|
else
|
||||||
Issue.connection.rollback_db_transaction
|
raise ActiveRecord::Rollback
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return issue
|
ret ? issue : false
|
||||||
end
|
end
|
||||||
|
|
||||||
def priority_id=(pid)
|
def priority_id=(pid)
|
||||||
@@ -389,6 +389,22 @@ class Issue < ActiveRecord::Base
|
|||||||
Issue.update_versions(["#{Version.table_name}.project_id IN (?) OR #{Issue.table_name}.project_id IN (?)", moved_project_ids, moved_project_ids])
|
Issue.update_versions(["#{Version.table_name}.project_id IN (?) OR #{Issue.table_name}.project_id IN (?)", moved_project_ids, moved_project_ids])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns an array of projects that current user can move issues to
|
||||||
|
def self.allowed_target_projects_on_move
|
||||||
|
projects = []
|
||||||
|
if User.current.admin?
|
||||||
|
# admin is allowed to move issues to any active (visible) project
|
||||||
|
projects = Project.visible.all
|
||||||
|
elsif User.current.logged?
|
||||||
|
if Role.non_member.allowed_to?(:move_issues)
|
||||||
|
projects = Project.visible.all
|
||||||
|
else
|
||||||
|
User.current.memberships.each {|m| projects << m.project if m.roles.detect {|r| r.allowed_to?(:move_issues)}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
projects
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Update issues so their versions are not pointing to a
|
# Update issues so their versions are not pointing to a
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class MailHandler < ActionMailer::Base
|
|||||||
logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]" if logger && logger.info
|
logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]" if logger && logger.info
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@user = User.find_by_mail(sender_email)
|
@user = User.find_by_mail(sender_email) if sender_email.present?
|
||||||
if @user && !@user.active?
|
if @user && !@user.active?
|
||||||
logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]" if logger && logger.info
|
logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]" if logger && logger.info
|
||||||
return false
|
return false
|
||||||
|
|||||||
+11
-2
@@ -114,11 +114,11 @@ class Mailer < ActionMailer::Base
|
|||||||
when 'Project'
|
when 'Project'
|
||||||
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container)
|
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container)
|
||||||
added_to = "#{l(:label_project)}: #{container}"
|
added_to = "#{l(:label_project)}: #{container}"
|
||||||
recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
|
recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
|
||||||
when 'Version'
|
when 'Version'
|
||||||
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
|
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
|
||||||
added_to = "#{l(:label_version)}: #{container.name}"
|
added_to = "#{l(:label_version)}: #{container.name}"
|
||||||
recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
|
recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
|
||||||
when 'Document'
|
when 'Document'
|
||||||
added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
|
added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
|
||||||
added_to = "#{l(:label_document)}: #{container.title}"
|
added_to = "#{l(:label_document)}: #{container.title}"
|
||||||
@@ -310,6 +310,15 @@ class Mailer < ActionMailer::Base
|
|||||||
deliver_reminder(assignee, issues, days) unless assignee.nil?
|
deliver_reminder(assignee, issues, days) unless assignee.nil?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Activates/desactivates email deliveries during +block+
|
||||||
|
def self.with_deliveries(enabled = true, &block)
|
||||||
|
was_enabled = ActionMailer::Base.perform_deliveries
|
||||||
|
ActionMailer::Base.perform_deliveries = !!enabled
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
ActionMailer::Base.perform_deliveries = was_enabled
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def initialize_defaults(method_name)
|
def initialize_defaults(method_name)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
class Principal < ActiveRecord::Base
|
class Principal < ActiveRecord::Base
|
||||||
set_table_name 'users'
|
set_table_name "#{table_name_prefix}users#{table_name_suffix}"
|
||||||
|
|
||||||
has_many :members, :foreign_key => 'user_id', :dependent => :destroy
|
has_many :members, :foreign_key => 'user_id', :dependent => :destroy
|
||||||
has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name"
|
has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# redMine - project management software
|
# Redmine - project management software
|
||||||
# Copyright (C) 2006 Jean-Philippe Lang
|
# Copyright (C) 2006-2010 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
|
||||||
@@ -16,10 +16,9 @@
|
|||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
class Version < ActiveRecord::Base
|
class Version < ActiveRecord::Base
|
||||||
before_destroy :check_integrity
|
|
||||||
after_update :update_issues_from_sharing_change
|
after_update :update_issues_from_sharing_change
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id'
|
has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
|
||||||
acts_as_customizable
|
acts_as_customizable
|
||||||
acts_as_attachable :view_permission => :view_files,
|
acts_as_attachable :view_permission => :view_files,
|
||||||
:delete_permission => :manage_files
|
:delete_permission => :manage_files
|
||||||
@@ -155,10 +154,7 @@ class Version < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def check_integrity
|
|
||||||
raise "Can't delete version" if self.fixed_issues.find(:first)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Update the issue's fixed versions. Used if a version's sharing changes.
|
# Update the issue's fixed versions. Used if a version's sharing changes.
|
||||||
def update_issues_from_sharing_change
|
def update_issues_from_sharing_change
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<%= call_hook :view_account_login_top %>
|
||||||
<div id="login-form">
|
<div id="login-form">
|
||||||
<% form_tag({:action=> "login"}) do %>
|
<% form_tag({:action=> "login"}) do %>
|
||||||
<%= back_url_hidden_field_tag %>
|
<%= back_url_hidden_field_tag %>
|
||||||
@@ -38,3 +39,4 @@
|
|||||||
<%= javascript_tag "Form.Element.focus('username');" %>
|
<%= javascript_tag "Form.Element.focus('username');" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
<%= call_hook :view_account_login_bottom %>
|
||||||
|
|||||||
@@ -26,3 +26,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% html_title @document.title -%>
|
<% html_title @document.title -%>
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= stylesheet_link_tag 'scm' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<% remote_form_for(:group, @group, :url => {:controller => 'groups', :action => 'add_users', :id => @group}, :method => :post) do |f| %>
|
<% remote_form_for(:group, @group, :url => {:controller => 'groups', :action => 'add_users', :id => @group}, :method => :post) do |f| %>
|
||||||
<fieldset><legend><%=l(:label_user_new)%></legend>
|
<fieldset><legend><%=l(:label_user_new)%></legend>
|
||||||
|
|
||||||
<p><%= text_field_tag 'user_search', nil, :size => "40" %></p>
|
<p><%= text_field_tag 'user_search', nil %></p>
|
||||||
<%= observe_field(:user_search,
|
<%= observe_field(:user_search,
|
||||||
:frequency => 0.5,
|
:frequency => 0.5,
|
||||||
:update => :users,
|
:update => :users,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>">
|
<tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>">
|
||||||
<td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
|
<td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
|
||||||
<td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
|
<td class="id"><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
|
||||||
<% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %>
|
<% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %>
|
||||||
</tr>
|
</tr>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
|
|
||||||
<% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
|
<% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
|
||||||
<%= hidden_field_tag('project_id', @project.to_param) if @project %>
|
<%= hidden_field_tag('project_id', @project.to_param) if @project %>
|
||||||
<div id="query_form_content">
|
<div id="query_form_content" class="hide-when-print">
|
||||||
<fieldset id="filters" class="collapsible">
|
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
|
||||||
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
|
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
|
||||||
<div>
|
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
|
||||||
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<p class="buttons">
|
<p class="buttons hide-when-print">
|
||||||
|
|
||||||
<%= link_to_remote l(:button_apply),
|
<%= link_to_remote l(:button_apply),
|
||||||
{ :url => { :set_filter => 1 },
|
{ :url => { :set_filter => 1 },
|
||||||
|
|||||||
@@ -40,9 +40,11 @@
|
|||||||
|
|
||||||
<h1><%= page_header_title %></h1>
|
<h1><%= page_header_title %></h1>
|
||||||
|
|
||||||
|
<% if display_main_menu?(@project) %>
|
||||||
<div id="main-menu">
|
<div id="main-menu">
|
||||||
<%= render_main_menu(@project) %>
|
<%= render_main_menu(@project) %>
|
||||||
</div>
|
</div>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= tag('div', {:id => 'main', :class => (has_content?(:sidebar) ? '' : 'nosidebar')}, true) %>
|
<%= tag('div', {:id => 'main', :class => (has_content?(:sidebar) ? '' : 'nosidebar')}, true) %>
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
|
|
||||||
<% if Setting.rest_api_enabled? %>
|
<% if Setting.rest_api_enabled? %>
|
||||||
<h4><%= l(:label_api_access_key) %></h4>
|
<h4><%= l(:label_api_access_key) %></h4>
|
||||||
<p>
|
<div>
|
||||||
<%= link_to_function(l(:button_show), "$('api-access-key').toggle();")%>
|
<%= link_to_function(l(:button_show), "$('api-access-key').toggle();")%>
|
||||||
<pre id='api-access-key' class='autoscroll'><%= @user.api_key %></pre>
|
<pre id='api-access-key' class='autoscroll'><%= @user.api_key %></pre>
|
||||||
</p>
|
</div>
|
||||||
<%= javascript_tag("$('api-access-key').hide();") %>
|
<%= javascript_tag("$('api-access-key').hide();") %>
|
||||||
<p>
|
<p>
|
||||||
<% if @user.api_token %>
|
<% if @user.api_token %>
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
<label class="block"><%= check_box_tag 'only[]', 'boards', true %> <%= l(:label_board_plural) %> (<%= @source_project.boards.count %>)</label>
|
<label class="block"><%= check_box_tag 'only[]', 'boards', true %> <%= l(:label_board_plural) %> (<%= @source_project.boards.count %>)</label>
|
||||||
<label class="block"><%= check_box_tag 'only[]', 'wiki', true %> <%= l(:label_wiki_page_plural) %> (<%= @source_project.wiki.nil? ? 0 : @source_project.wiki.pages.count %>)</label>
|
<label class="block"><%= check_box_tag 'only[]', 'wiki', true %> <%= l(:label_wiki_page_plural) %> (<%= @source_project.wiki.nil? ? 0 : @source_project.wiki.pages.count %>)</label>
|
||||||
<%= hidden_field_tag 'only[]', '' %>
|
<%= hidden_field_tag 'only[]', '' %>
|
||||||
|
<br />
|
||||||
|
<label class="block"><%= check_box_tag 'notifications', 1, params[:notifications] %> <%= l(:label_project_copy_notifications) %></label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<%= submit_tag l(:button_copy) %>
|
<%= submit_tag l(:button_copy) %>
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= auto_discovery_link_tag(:atom, {:action => 'index', :format => 'atom', :key => User.current.rss_key}) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
<%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'add'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %>
|
<%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'add'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %>
|
||||||
<%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %>
|
<%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
<% remote_form_for(:member, @member, :url => {:controller => 'members', :action => 'new', :id => @project}, :method => :post) do |f| %>
|
<% remote_form_for(:member, @member, :url => {:controller => 'members', :action => 'new', :id => @project}, :method => :post) do |f| %>
|
||||||
<fieldset><legend><%=l(:label_member_new)%></legend>
|
<fieldset><legend><%=l(:label_member_new)%></legend>
|
||||||
|
|
||||||
<p><%= text_field_tag 'principal_search', nil, :size => "40" %></p>
|
<p><%= text_field_tag 'principal_search', nil %></p>
|
||||||
<%= observe_field(:principal_search,
|
<%= observe_field(:principal_search,
|
||||||
:frequency => 0.5,
|
:frequency => 0.5,
|
||||||
:update => :principals,
|
:update => :principals,
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
<h2><%=l(:label_overview)%></h2>
|
<h2><%=l(:label_overview)%></h2>
|
||||||
|
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
<%= textilizable @project.description %>
|
<div class="wiki">
|
||||||
|
<%= textilizable @project.description %>
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<% unless @project.homepage.blank? %><li><%=l(:field_homepage)%>: <%= auto_link(h(@project.homepage)) %></li><% end %>
|
<% unless @project.homepage.blank? %><li><%=l(:field_homepage)%>: <%= auto_link(h(@project.homepage)) %></li><% end %>
|
||||||
<% if @subprojects.any? %>
|
<% if @subprojects.any? %>
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ dirs.each do |dir|
|
|||||||
/ <%= link_to h(filename), :action => 'changes', :id => @project, :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %>
|
/ <%= link_to h(filename), :action => 'changes', :id => @project, :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= "@ #{revision}" if revision %>
|
<%= "@ #{h revision}" if revision %>
|
||||||
|
|
||||||
<% html_title(with_leading_slash(path)) -%>
|
<% html_title(with_leading_slash(path)) -%>
|
||||||
|
|||||||
@@ -32,13 +32,10 @@
|
|||||||
<%= render :partial => 'versions/overview', :locals => {:version => @version} %>
|
<%= render :partial => 'versions/overview', :locals => {:version => @version} %>
|
||||||
<%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %>
|
<%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %>
|
||||||
|
|
||||||
<% issues = @version.fixed_issues.find(:all,
|
<% if @issues.present? %>
|
||||||
:include => [:status, :tracker, :priority],
|
|
||||||
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") %>
|
|
||||||
<% if issues.size > 0 %>
|
|
||||||
<fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend>
|
<fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend>
|
||||||
<ul>
|
<ul>
|
||||||
<% issues.each do |issue| -%>
|
<% @issues.each do |issue| -%>
|
||||||
<li><%= link_to_issue(issue) %></li>
|
<li><%= link_to_issue(issue) %></li>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1,29 +1 @@
|
|||||||
# Settings specified here will take precedence over those in config/environment.rb
|
instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb'))
|
||||||
|
|
||||||
# The test environment is used exclusively to run your application's
|
|
||||||
# test suite. You never need to work with it otherwise. Remember that
|
|
||||||
# your test database is "scratch space" for the test suite and is wiped
|
|
||||||
# and recreated between test runs. Don't rely on the data there!
|
|
||||||
config.cache_classes = true
|
|
||||||
|
|
||||||
# Log error messages when you accidentally call methods on nil.
|
|
||||||
config.whiny_nils = true
|
|
||||||
|
|
||||||
# Show full error reports and disable caching
|
|
||||||
config.action_controller.consider_all_requests_local = true
|
|
||||||
config.action_controller.perform_caching = false
|
|
||||||
|
|
||||||
config.action_mailer.perform_deliveries = true
|
|
||||||
config.action_mailer.delivery_method = :test
|
|
||||||
|
|
||||||
config.action_controller.session = {
|
|
||||||
:session_key => "_test_session",
|
|
||||||
:secret => "some secret phrase for the tests."
|
|
||||||
}
|
|
||||||
|
|
||||||
# Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
|
|
||||||
config.action_controller.allow_forgery_protection = false
|
|
||||||
|
|
||||||
config.gem "thoughtbot-shoulda", :lib => "shoulda", :source => "http://gems.github.com"
|
|
||||||
config.gem "nofxx-object_daddy", :lib => "object_daddy", :source => "http://gems.github.com"
|
|
||||||
config.gem "mocha"
|
|
||||||
|
|||||||
@@ -1,29 +1 @@
|
|||||||
# Settings specified here will take precedence over those in config/environment.rb
|
instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb'))
|
||||||
|
|
||||||
# The test environment is used exclusively to run your application's
|
|
||||||
# test suite. You never need to work with it otherwise. Remember that
|
|
||||||
# your test database is "scratch space" for the test suite and is wiped
|
|
||||||
# and recreated between test runs. Don't rely on the data there!
|
|
||||||
config.cache_classes = true
|
|
||||||
|
|
||||||
# Log error messages when you accidentally call methods on nil.
|
|
||||||
config.whiny_nils = true
|
|
||||||
|
|
||||||
# Show full error reports and disable caching
|
|
||||||
config.action_controller.consider_all_requests_local = true
|
|
||||||
config.action_controller.perform_caching = false
|
|
||||||
|
|
||||||
config.action_mailer.perform_deliveries = true
|
|
||||||
config.action_mailer.delivery_method = :test
|
|
||||||
|
|
||||||
config.action_controller.session = {
|
|
||||||
:session_key => "_test_session",
|
|
||||||
:secret => "some secret phrase for the tests."
|
|
||||||
}
|
|
||||||
|
|
||||||
# Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
|
|
||||||
config.action_controller.allow_forgery_protection = false
|
|
||||||
|
|
||||||
config.gem "thoughtbot-shoulda", :lib => "shoulda", :source => "http://gems.github.com"
|
|
||||||
config.gem "nofxx-object_daddy", :lib => "object_daddy", :source => "http://gems.github.com"
|
|
||||||
config.gem "mocha"
|
|
||||||
|
|||||||
@@ -881,4 +881,4 @@ bg:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -905,3 +905,4 @@ bs:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -884,3 +884,4 @@ ca:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -887,3 +887,4 @@ cs:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -907,3 +907,4 @@ da:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -907,3 +907,4 @@ de:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -887,3 +887,4 @@ el:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -748,6 +748,7 @@ en:
|
|||||||
label_api_access_key: API access key
|
label_api_access_key: API access key
|
||||||
label_missing_api_access_key: Missing an API access key
|
label_missing_api_access_key: Missing an API access key
|
||||||
label_api_access_key_created_on: "API access key created {{value}} ago"
|
label_api_access_key_created_on: "API access key created {{value}} ago"
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|
||||||
button_login: Login
|
button_login: Login
|
||||||
button_submit: Submit
|
button_submit: Submit
|
||||||
|
|||||||
@@ -931,3 +931,4 @@ es:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -917,3 +917,4 @@ fi:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -764,6 +764,7 @@ fr:
|
|||||||
label_missing_feeds_access_key: Clé d'accès RSS manquante
|
label_missing_feeds_access_key: Clé d'accès RSS manquante
|
||||||
label_close_versions: Fermer les versions terminées
|
label_close_versions: Fermer les versions terminées
|
||||||
label_revision_id: Revision {{value}}
|
label_revision_id: Revision {{value}}
|
||||||
|
label_project_copy_notifications: Envoyer les notifications durant la copie du projet
|
||||||
|
|
||||||
button_login: Connexion
|
button_login: Connexion
|
||||||
button_submit: Soumettre
|
button_submit: Soumettre
|
||||||
@@ -811,10 +812,10 @@ fr:
|
|||||||
|
|
||||||
status_active: actif
|
status_active: actif
|
||||||
status_registered: enregistré
|
status_registered: enregistré
|
||||||
status_locked: vérouillé
|
status_locked: verrouillé
|
||||||
|
|
||||||
version_status_open: ouvert
|
version_status_open: ouvert
|
||||||
version_status_locked: vérouillé
|
version_status_locked: verrouillé
|
||||||
version_status_closed: fermé
|
version_status_closed: fermé
|
||||||
|
|
||||||
text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
|
text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
|
||||||
|
|||||||
@@ -907,3 +907,4 @@ gl:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -891,3 +891,4 @@ he:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -894,3 +894,4 @@ hr:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -912,3 +912,4 @@
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -899,3 +899,4 @@ id:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -894,4 +894,4 @@ it:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -916,3 +916,4 @@ ja:
|
|||||||
enumeration_activities: 作業分類 (時間トラッキング)
|
enumeration_activities: 作業分類 (時間トラッキング)
|
||||||
enumeration_system_activity: システム作業分類
|
enumeration_system_activity: システム作業分類
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -947,3 +947,4 @@ ko:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -955,3 +955,4 @@ lt:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -869,3 +869,4 @@ nl:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -882,3 +882,4 @@
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -912,3 +912,4 @@ pl:
|
|||||||
permission_export_wiki_pages: Eksport stron wiki
|
permission_export_wiki_pages: Eksport stron wiki
|
||||||
permission_manage_project_activities: Zarządzanie aktywnościami projektu
|
permission_manage_project_activities: Zarządzanie aktywnościami projektu
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -915,3 +915,4 @@ pt-BR:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -899,3 +899,4 @@ pt:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -884,3 +884,4 @@ ro:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -995,3 +995,4 @@ ru:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -886,3 +886,4 @@ sk:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -883,3 +883,4 @@ sl:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -902,3 +902,4 @@
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -936,3 +936,4 @@ sv:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -884,3 +884,4 @@ th:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -914,3 +914,4 @@ tr:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -883,3 +883,4 @@ uk:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -946,3 +946,4 @@ vi:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -978,3 +978,4 @@
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -909,4 +909,4 @@ zh:
|
|||||||
permission_export_wiki_pages: Export wiki pages
|
permission_export_wiki_pages: Export wiki pages
|
||||||
setting_cache_formatted_text: Cache formatted text
|
setting_cache_formatted_text: Cache formatted text
|
||||||
permission_manage_project_activities: Manage project activities
|
permission_manage_project_activities: Manage project activities
|
||||||
|
label_project_copy_notifications: Send email notifications during the project copy
|
||||||
|
|||||||
@@ -4,6 +4,62 @@ Redmine - project management software
|
|||||||
Copyright (C) 2006-2010 Jean-Philippe Lang
|
Copyright (C) 2006-2010 Jean-Philippe Lang
|
||||||
http://www.redmine.org/
|
http://www.redmine.org/
|
||||||
|
|
||||||
|
== v1.0.0
|
||||||
|
|
||||||
|
Adds context menu to the roadmap issue lists
|
||||||
|
|
||||||
|
== 2010-07-07 v0.9.6
|
||||||
|
|
||||||
|
Fixed: Redmine.pm access by unauthorized users
|
||||||
|
|
||||||
|
== 2010-06-24 v0.9.5
|
||||||
|
|
||||||
|
Linkify folder names on revision view
|
||||||
|
"fiters" and "options" should be hidden in print view via css
|
||||||
|
Fixed: NoMethodError when no issue params are submitted
|
||||||
|
Fixed: projects.atom with required authentication
|
||||||
|
Fixed: External links not correctly displayed in Wiki TOC
|
||||||
|
Fixed: Member role forms in project settings are not hidden after member added
|
||||||
|
Fixed: pre can't be inside p
|
||||||
|
Fixed: session cookie path does not respect RAILS_RELATIVE_URL_ROOT
|
||||||
|
Fixed: mail handler fails when the from address is empty
|
||||||
|
|
||||||
|
|
||||||
|
== 2010-05-01 v0.9.4
|
||||||
|
|
||||||
|
Filters collapsed by default on issues index page for a saved query
|
||||||
|
Fixed: When categories list is too big the popup menu doesn't adjust (ex. in the issue list)
|
||||||
|
Fixed: remove "main-menu" div when the menu is empty
|
||||||
|
Fixed: Code syntax highlighting not working in Document page
|
||||||
|
Fixed: Git blame/annotate fails on moved files
|
||||||
|
Fixed: Failing test in test_show_atom
|
||||||
|
Fixed: Migrate from trac - not displayed Wikis
|
||||||
|
Fixed: Email notifications on file upload sent to empty recipient list
|
||||||
|
Fixed: Migrating from trac is not possible, fails to allocate memory
|
||||||
|
Fixed: Lost password no longer flashes a confirmation message
|
||||||
|
Fixed: Crash while deleting in-use enumeration
|
||||||
|
Fixed: Hard coded English string at the selection of issue watchers
|
||||||
|
Fixed: Bazaar v2.1.0 changed behaviour
|
||||||
|
Fixed: Roadmap display can raise an exception if no trackers are selected
|
||||||
|
Fixed: Gravatar breaks layout of "logged in" page
|
||||||
|
Fixed: Reposman.rb on Windows
|
||||||
|
Fixed: Possible error 500 while moving an issue to another project with SQLite
|
||||||
|
Fixed: backslashes in issue description/note should be escaped when quoted
|
||||||
|
Fixed: Long text in <pre> disrupts Associated revisions
|
||||||
|
Fixed: Links to missing wiki pages not red on project overview page
|
||||||
|
Fixed: Cannot delete a project with subprojects that shares versions
|
||||||
|
Fixed: Update of Subversion changesets broken under Solaris
|
||||||
|
Fixed: "Move issues" permission not working for Non member
|
||||||
|
Fixed: Sidebar overlap on Users tab of Group editor
|
||||||
|
Fixed: Error on db:migrate with table prefix set (hardcoded name in principal.rb)
|
||||||
|
Fixed: Report shows sub-projects for non-members
|
||||||
|
Fixed: 500 internal error when browsing any Redmine page in epiphany
|
||||||
|
Fixed: Watchers selection lost when issue creation fails
|
||||||
|
Fixed: When copying projects, redmine should not generate an email to people who created issues
|
||||||
|
Fixed: Issue "#" table cells should have a class attribute to enable fine-grained CSS theme
|
||||||
|
Fixed: Plugin generators should display help if no parameter is given
|
||||||
|
|
||||||
|
|
||||||
== 2010-02-28 v0.9.3
|
== 2010-02-28 v0.9.3
|
||||||
|
|
||||||
Adds filter for system shared versions on the cross project issue list
|
Adds filter for system shared versions on the cross project issue list
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ Optional:
|
|||||||
4. Generate a session store secret
|
4. Generate a session store secret
|
||||||
Redmine stores session data in cookies by default, which requires
|
Redmine stores session data in cookies by default, which requires
|
||||||
a secret to be generated. Run:
|
a secret to be generated. Run:
|
||||||
rake config/initializers/session_store.rb
|
rake generate_session_store
|
||||||
|
|
||||||
5. Create the database structure. Under the application main directory:
|
5. Create the database structure. Under the application main directory:
|
||||||
rake db:migrate RAILS_ENV="production"
|
rake db:migrate RAILS_ENV="production"
|
||||||
|
|||||||
+2
-2
@@ -12,12 +12,12 @@ http://www.redmine.org/
|
|||||||
2. Copy your database settings (RAILS_ROOT/config/database.yml)
|
2. Copy your database settings (RAILS_ROOT/config/database.yml)
|
||||||
and SMTP settings (RAILS_ROOT/config/email.yml)
|
and SMTP settings (RAILS_ROOT/config/email.yml)
|
||||||
into the new config directory
|
into the new config directory
|
||||||
DO NOT REPLACE ANY OTHERS FILES.
|
DO NOT REPLACE OR EDIT ANY OTHER FILES.
|
||||||
|
|
||||||
3. Generate a session store secret
|
3. Generate a session store secret
|
||||||
Redmine stores session data in cookies by default, which requires
|
Redmine stores session data in cookies by default, which requires
|
||||||
a secret to be generated. Run:
|
a secret to be generated. Run:
|
||||||
rake config/initializers/session_store.rb
|
rake generate_session_store
|
||||||
|
|
||||||
4. Migrate your database (please make a backup before doing this):
|
4. Migrate your database (please make a backup before doing this):
|
||||||
rake db:migrate RAILS_ENV="production"
|
rake db:migrate RAILS_ENV="production"
|
||||||
|
|||||||
+32
-1
@@ -227,9 +227,38 @@ sub authen_handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check if authentication is forced
|
||||||
|
sub is_authentication_forced {
|
||||||
|
my $r = shift;
|
||||||
|
|
||||||
|
my $dbh = connect_database($r);
|
||||||
|
my $sth = $dbh->prepare(
|
||||||
|
"SELECT value FROM settings where settings.name = 'login_required';"
|
||||||
|
);
|
||||||
|
|
||||||
|
$sth->execute();
|
||||||
|
my $ret = 0;
|
||||||
|
if (my @row = $sth->fetchrow_array) {
|
||||||
|
if ($row[0] eq "1" || $row[0] eq "t") {
|
||||||
|
$ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sth->finish();
|
||||||
|
undef $sth;
|
||||||
|
|
||||||
|
$dbh->disconnect();
|
||||||
|
undef $dbh;
|
||||||
|
|
||||||
|
$ret;
|
||||||
|
}
|
||||||
|
|
||||||
sub is_public_project {
|
sub is_public_project {
|
||||||
my $project_id = shift;
|
my $project_id = shift;
|
||||||
my $r = shift;
|
my $r = shift;
|
||||||
|
|
||||||
|
if (is_authentication_forced($r)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
my $dbh = connect_database($r);
|
my $dbh = connect_database($r);
|
||||||
my $sth = $dbh->prepare(
|
my $sth = $dbh->prepare(
|
||||||
@@ -309,7 +338,9 @@ sub is_member {
|
|||||||
bindpw => $rowldap[4] ? $rowldap[4] : "",
|
bindpw => $rowldap[4] ? $rowldap[4] : "",
|
||||||
filter => "(".$rowldap[6]."=%s)"
|
filter => "(".$rowldap[6]."=%s)"
|
||||||
);
|
);
|
||||||
$ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass));
|
my $method = $r->method;
|
||||||
|
$ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass) && ((defined $read_only_methods{$method} && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/));
|
||||||
|
|
||||||
}
|
}
|
||||||
$sthldap->finish();
|
$sthldap->finish();
|
||||||
undef $sthldap;
|
undef $sthldap;
|
||||||
|
|||||||
@@ -221,10 +221,14 @@ def other_read_right?(file)
|
|||||||
end
|
end
|
||||||
|
|
||||||
def owner_name(file)
|
def owner_name(file)
|
||||||
RUBY_PLATFORM =~ /mswin/ ?
|
mswin? ?
|
||||||
$svn_owner :
|
$svn_owner :
|
||||||
Etc.getpwuid( File.stat(file).uid ).name
|
Etc.getpwuid( File.stat(file).uid ).name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mswin?
|
||||||
|
(RUBY_PLATFORM =~ /(:?mswin|mingw)/) || (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i)
|
||||||
|
end
|
||||||
|
|
||||||
projects.each do |project|
|
projects.each do |project|
|
||||||
log("treating project #{project.name}", :level => 1)
|
log("treating project #{project.name}", :level => 1)
|
||||||
@@ -303,4 +307,4 @@ projects.each do |project|
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -6,6 +6,7 @@ class RedminePluginControllerGenerator < ControllerGenerator
|
|||||||
|
|
||||||
def initialize(runtime_args, runtime_options = {})
|
def initialize(runtime_args, runtime_options = {})
|
||||||
runtime_args = runtime_args.dup
|
runtime_args = runtime_args.dup
|
||||||
|
usage if runtime_args.empty?
|
||||||
@plugin_name = "redmine_" + runtime_args.shift.underscore
|
@plugin_name = "redmine_" + runtime_args.shift.underscore
|
||||||
@plugin_pretty_name = plugin_name.titleize
|
@plugin_pretty_name = plugin_name.titleize
|
||||||
@plugin_path = "vendor/plugins/#{plugin_name}"
|
@plugin_path = "vendor/plugins/#{plugin_name}"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class RedminePluginModelGenerator < ModelGenerator
|
|||||||
|
|
||||||
def initialize(runtime_args, runtime_options = {})
|
def initialize(runtime_args, runtime_options = {})
|
||||||
runtime_args = runtime_args.dup
|
runtime_args = runtime_args.dup
|
||||||
|
usage if runtime_args.empty?
|
||||||
@plugin_name = "redmine_" + runtime_args.shift.underscore
|
@plugin_name = "redmine_" + runtime_args.shift.underscore
|
||||||
@plugin_pretty_name = plugin_name.titleize
|
@plugin_pretty_name = plugin_name.titleize
|
||||||
@plugin_path = "vendor/plugins/#{plugin_name}"
|
@plugin_path = "vendor/plugins/#{plugin_name}"
|
||||||
|
|||||||
+1
-1
@@ -818,7 +818,7 @@ class RedCloth3 < String
|
|||||||
post = ")"+post # add closing parenth to post
|
post = ")"+post # add closing parenth to post
|
||||||
end
|
end
|
||||||
atts = pba( atts )
|
atts = pba( atts )
|
||||||
atts = " href=\"#{ url }#{ slash }\"#{ atts }"
|
atts = " href=\"#{ htmlesc url }#{ slash }\"#{ atts }"
|
||||||
atts << " title=\"#{ htmlesc title }\"" if title
|
atts << " title=\"#{ htmlesc title }\"" if title
|
||||||
atts = shelve( atts ) if atts
|
atts = shelve( atts ) if atts
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,11 @@ module Redmine
|
|||||||
render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
|
render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def display_main_menu?(project)
|
||||||
|
menu_name = project && !project.new_record? ? :project_menu : :application_menu
|
||||||
|
Redmine::MenuManager.items(menu_name).size > 1 # 1 element is the root
|
||||||
|
end
|
||||||
|
|
||||||
def render_menu(menu, project=nil)
|
def render_menu(menu, project=nil)
|
||||||
links = []
|
links = []
|
||||||
menu_items_for(menu, project) do |node|
|
menu_items_for(menu, project) do |node|
|
||||||
|
|||||||
@@ -56,14 +56,14 @@ module Redmine
|
|||||||
shellout(cmd) do |io|
|
shellout(cmd) do |io|
|
||||||
prefix = "#{url}/#{path}".gsub('\\', '/')
|
prefix = "#{url}/#{path}".gsub('\\', '/')
|
||||||
logger.debug "PREFIX: #{prefix}"
|
logger.debug "PREFIX: #{prefix}"
|
||||||
re = %r{^V\s+#{Regexp.escape(prefix)}(\/?)([^\/]+)(\/?)\s+(\S+)$}
|
re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)$}
|
||||||
io.each_line do |line|
|
io.each_line do |line|
|
||||||
next unless line =~ re
|
next unless line =~ re
|
||||||
entries << Entry.new({:name => $2.strip,
|
entries << Entry.new({:name => $3.strip,
|
||||||
:path => ((path.empty? ? "" : "#{path}/") + $2.strip),
|
:path => ((path.empty? ? "" : "#{path}/") + $3.strip),
|
||||||
:kind => ($3.blank? ? 'file' : 'dir'),
|
:kind => ($4.blank? ? 'file' : 'dir'),
|
||||||
:size => nil,
|
:size => nil,
|
||||||
:lastrev => Revision.new(:revision => $4.strip)
|
:lastrev => Revision.new(:revision => $5.strip)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -227,16 +227,26 @@ module Redmine
|
|||||||
|
|
||||||
def annotate(path, identifier=nil)
|
def annotate(path, identifier=nil)
|
||||||
identifier = 'HEAD' if identifier.blank?
|
identifier = 'HEAD' if identifier.blank?
|
||||||
cmd = "#{GIT_BIN} --git-dir #{target('')} blame -l #{shell_quote identifier} -- #{shell_quote path}"
|
cmd = "#{GIT_BIN} --git-dir #{target('')} blame -p #{shell_quote identifier} -- #{shell_quote path}"
|
||||||
blame = Annotate.new
|
blame = Annotate.new
|
||||||
content = nil
|
content = nil
|
||||||
shellout(cmd) { |io| io.binmode; content = io.read }
|
shellout(cmd) { |io| io.binmode; content = io.read }
|
||||||
return nil if $? && $?.exitstatus != 0
|
return nil if $? && $?.exitstatus != 0
|
||||||
# git annotates binary files
|
# git annotates binary files
|
||||||
return nil if content.is_binary_data?
|
return nil if content.is_binary_data?
|
||||||
|
identifier = ''
|
||||||
|
# git shows commit author on the first occurrence only
|
||||||
|
authors_by_commit = {}
|
||||||
content.split("\n").each do |line|
|
content.split("\n").each do |line|
|
||||||
next unless line =~ /([0-9a-f]{39,40})\s\((\w*)[^\)]*\)(.*)/
|
if line =~ /^([0-9a-f]{39,40})\s.*/
|
||||||
blame.add_line($3.rstrip, Revision.new(:identifier => $1, :author => $2.strip))
|
identifier = $1
|
||||||
|
elsif line =~ /^author (.+)/
|
||||||
|
authors_by_commit[identifier] = $1.strip
|
||||||
|
elsif line =~ /^\t(.*)/
|
||||||
|
blame.add_line($1, Revision.new(:identifier => identifier, :author => authors_by_commit[identifier]))
|
||||||
|
identifier = ''
|
||||||
|
author = ''
|
||||||
|
end
|
||||||
end
|
end
|
||||||
blame
|
blame
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module Redmine
|
|||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 0
|
MAJOR = 0
|
||||||
MINOR = 9
|
MINOR = 9
|
||||||
TINY = 3
|
TINY = 6
|
||||||
|
|
||||||
# Branch values:
|
# Branch values:
|
||||||
# * official release: nil
|
# * official release: nil
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ module Redmine
|
|||||||
module WikiFormatting
|
module WikiFormatting
|
||||||
module Textile
|
module Textile
|
||||||
class Formatter < RedCloth3
|
class Formatter < RedCloth3
|
||||||
|
include ActionView::Helpers::TagHelper
|
||||||
|
|
||||||
# auto_link rule after textile rules so that it doesn't break !image_url! tags
|
# auto_link rule after textile rules so that it doesn't break !image_url! tags
|
||||||
RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros]
|
RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros]
|
||||||
@@ -66,6 +67,11 @@ module Redmine
|
|||||||
def textile_p_withtoc(tag, atts, cite, content)
|
def textile_p_withtoc(tag, atts, cite, content)
|
||||||
# removes wiki links from the item
|
# removes wiki links from the item
|
||||||
toc_item = content.gsub(/(\[\[([^\]\|]*)(\|([^\]]*))?\]\])/) { $4 || $2 }
|
toc_item = content.gsub(/(\[\[([^\]\|]*)(\|([^\]]*))?\]\])/) { $4 || $2 }
|
||||||
|
# sanitizes titles from links
|
||||||
|
# see redcloth3.rb, same as "#{pre}#{text}#{post}"
|
||||||
|
toc_item.gsub!(LINK_RE) { [$2, $4, $9].join }
|
||||||
|
# sanitizes image links from titles
|
||||||
|
toc_item.gsub!(IMAGE_RE) { [$5].join }
|
||||||
# removes styles
|
# removes styles
|
||||||
# eg. %{color:red}Triggers% => Triggers
|
# eg. %{color:red}Triggers% => Triggers
|
||||||
toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
|
toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
|
||||||
@@ -162,7 +168,8 @@ module Redmine
|
|||||||
url=url[0..-2] # discard closing parenth from url
|
url=url[0..-2] # discard closing parenth from url
|
||||||
post = ")"+post # add closing parenth to post
|
post = ")"+post # add closing parenth to post
|
||||||
end
|
end
|
||||||
%(#{leading}<a class="external" href="#{proto=="www."?"http://www.":proto}#{url}">#{proto + url}</a>#{post})
|
tag = content_tag('a', proto + url, :href => "#{proto=="www."?"http://www.":proto}#{url}", :class => 'external')
|
||||||
|
%(#{leading}#{tag}#{post})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -174,7 +181,7 @@ module Redmine
|
|||||||
if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
|
if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
|
||||||
mail
|
mail
|
||||||
else
|
else
|
||||||
%{<a href="mailto:#{mail}" class="email">#{mail}</a>}
|
content_tag('a', mail, :href => "mailto:#{mail}", :class => "email")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ file 'config/initializers/session_store.rb' do
|
|||||||
# you'll be exposed to dictionary attacks.
|
# you'll be exposed to dictionary attacks.
|
||||||
ActionController::Base.session = {
|
ActionController::Base.session = {
|
||||||
:session_key => '_redmine_session',
|
:session_key => '_redmine_session',
|
||||||
|
#
|
||||||
|
# Uncomment and edit the :session_path below if are hosting your Redmine
|
||||||
|
# at a suburi and don't want the top level path to access the cookies
|
||||||
|
#
|
||||||
|
# See: http://www.redmine.org/issues/3968
|
||||||
|
#
|
||||||
|
# :session_path => '/url_path_to/your/redmine/',
|
||||||
:secret => '#{secret}'
|
:secret => '#{secret}'
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ namespace :redmine do
|
|||||||
# Ticket number re-writing
|
# Ticket number re-writing
|
||||||
text = text.gsub(/#(\d+)/) do |s|
|
text = text.gsub(/#(\d+)/) do |s|
|
||||||
if $1.length < 10
|
if $1.length < 10
|
||||||
TICKET_MAP[$1.to_i] ||= $1
|
# TICKET_MAP[$1.to_i] ||= $1
|
||||||
"\##{TICKET_MAP[$1.to_i] || $1}"
|
"\##{TICKET_MAP[$1.to_i] || $1}"
|
||||||
else
|
else
|
||||||
s
|
s
|
||||||
@@ -682,6 +682,7 @@ namespace :redmine do
|
|||||||
project.trackers << TRACKER_BUG unless project.trackers.include?(TRACKER_BUG)
|
project.trackers << TRACKER_BUG unless project.trackers.include?(TRACKER_BUG)
|
||||||
project.trackers << TRACKER_FEATURE unless project.trackers.include?(TRACKER_FEATURE)
|
project.trackers << TRACKER_FEATURE unless project.trackers.include?(TRACKER_FEATURE)
|
||||||
@target_project = project.new_record? ? nil : project
|
@target_project = project.new_record? ? nil : project
|
||||||
|
@target_project.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.connection_params
|
def self.connection_params
|
||||||
|
|||||||
@@ -207,3 +207,12 @@ Ajax.Responders.register({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function hideOnLoad() {
|
||||||
|
$$('.hol').each(function(el) {
|
||||||
|
el.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Event.observe(window, 'load', hideOnLoad);
|
||||||
|
|
||||||
|
|||||||
@@ -399,6 +399,8 @@ div#tab-content-members fieldset div, div#tab-content-users fieldset div { max-h
|
|||||||
|
|
||||||
table.members td.group { padding-left: 20px; background: url(../images/group.png) no-repeat 0% 50%; }
|
table.members td.group { padding-left: 20px; background: url(../images/group.png) no-repeat 0% 50%; }
|
||||||
|
|
||||||
|
input#principal_search, input#user_search {width:100%}
|
||||||
|
|
||||||
* html div#tab-content-members fieldset div { height: 450px; }
|
* html div#tab-content-members fieldset div { height: 450px; }
|
||||||
|
|
||||||
/***** Flash & error messages ****/
|
/***** Flash & error messages ****/
|
||||||
@@ -640,7 +642,7 @@ div.wiki pre {
|
|||||||
padding: 2px;
|
padding: 2px;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
border: 1px solid #dadada;
|
border: 1px solid #dadada;
|
||||||
width:95%;
|
width:auto;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,14 +817,14 @@ div.issue table img.gravatar {
|
|||||||
|
|
||||||
h2 img.gravatar {
|
h2 img.gravatar {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
margin: -2px 4px 0 0;
|
margin: -2px 4px -4px 0;
|
||||||
float: left;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 img.gravatar {
|
h4 img.gravatar {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
margin: -6px 4px 0 0;
|
margin: -6px 0 -4px 0;
|
||||||
float: left;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.username img.gravatar {
|
td.username img.gravatar {
|
||||||
@@ -850,4 +852,5 @@ h2 img { vertical-align:middle; }
|
|||||||
#main { background: #fff; }
|
#main { background: #fff; }
|
||||||
#content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;}
|
#content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;}
|
||||||
#wiki_add_attachment { display:none; }
|
#wiki_add_attachment { display:none; }
|
||||||
|
.hide-when-print { display: none; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
padding:1px;
|
padding:1px;
|
||||||
z-index:39;
|
z-index:39;
|
||||||
}
|
}
|
||||||
#context-menu li.folder ul { position:absolute; left:168px; /* IE6 */ top:-2px; }
|
#context-menu li.folder ul { position:absolute; left:168px; /* IE6 */ top:-2px; max-height:300px; overflow:hidden; overflow-y: auto; }
|
||||||
#context-menu li.folder>ul { left:148px; }
|
#context-menu li.folder>ul { left:148px; }
|
||||||
|
|
||||||
#context-menu.reverse-y li.folder>ul { top:auto; bottom:0; }
|
#context-menu.reverse-y li.folder>ul { top:auto; bottom:0; }
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Return-Path: <john.doe@somenet.foo>
|
||||||
|
Received: from osiris ([127.0.0.1])
|
||||||
|
by OSIRIS
|
||||||
|
with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
|
||||||
|
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
|
||||||
|
To: <redmine@somenet.foo>
|
||||||
|
Subject: Ticket by unknown user
|
||||||
|
Date: Sun, 22 Jun 2008 12:28:07 +0200
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain;
|
||||||
|
format=flowed;
|
||||||
|
charset="iso-8859-1";
|
||||||
|
reply-type=original
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
This is a ticket submitted by an unknown user.
|
||||||
|
|
||||||
@@ -436,7 +436,7 @@ class IssuesControllerTest < ActionController::TestCase
|
|||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'changes.rxml'
|
assert_template 'changes.rxml'
|
||||||
# Inline image
|
# Inline image
|
||||||
assert @response.body.include?("<img src=\"http://test.host/attachments/download/10\" alt=\"\" />"), "Body did not match. Body: #{@response.body}"
|
assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_new_routing
|
def test_new_routing
|
||||||
@@ -649,6 +649,12 @@ class IssuesControllerTest < ActionController::TestCase
|
|||||||
:value => 'Value for field 2'}
|
:value => 'Value for field 2'}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "POST new with no issue params" do
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
post :new, :project_id => 1
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
def test_copy_routing
|
def test_copy_routing
|
||||||
assert_routing(
|
assert_routing(
|
||||||
{:method => :get, :path => '/projects/world_domination/issues/567/copy'},
|
{:method => :get, :path => '/projects/world_domination/issues/567/copy'},
|
||||||
|
|||||||
@@ -15,6 +15,21 @@ class GitAdapterTest < ActiveSupport::TestCase
|
|||||||
def test_getting_all_revisions
|
def test_getting_all_revisions
|
||||||
assert_equal 12, @adapter.revisions('',nil,nil,:all => true).length
|
assert_equal 12, @adapter.revisions('',nil,nil,:all => true).length
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_annotate
|
||||||
|
annotate = @adapter.annotate('sources/watchers_controller.rb')
|
||||||
|
assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
|
||||||
|
assert_equal 41, annotate.lines.size
|
||||||
|
assert_equal "# This program is free software; you can redistribute it and/or", annotate.lines[4].strip
|
||||||
|
assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", annotate.revisions[4].identifier
|
||||||
|
assert_equal "jsmith", annotate.revisions[4].author
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_annotate_moved_file
|
||||||
|
annotate = @adapter.annotate('renamed_test.txt')
|
||||||
|
assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
|
||||||
|
assert_equal 2, annotate.lines.size
|
||||||
|
end
|
||||||
else
|
else
|
||||||
puts "Git test repository NOT FOUND. Skipping unit tests !!!"
|
puts "Git test repository NOT FOUND. Skipping unit tests !!!"
|
||||||
def test_fake; assert true end
|
def test_fake; assert true end
|
||||||
|
|||||||
@@ -59,12 +59,14 @@ class ApplicationHelperTest < HelperTestCase
|
|||||||
'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
|
'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
|
||||||
# two exclamation marks
|
# two exclamation marks
|
||||||
'http://example.net/path!602815048C7B5C20!302.html' => '<a class="external" href="http://example.net/path!602815048C7B5C20!302.html">http://example.net/path!602815048C7B5C20!302.html</a>',
|
'http://example.net/path!602815048C7B5C20!302.html' => '<a class="external" href="http://example.net/path!602815048C7B5C20!302.html">http://example.net/path!602815048C7B5C20!302.html</a>',
|
||||||
|
# escaping
|
||||||
|
'http://foo"bar' => '<a class="external" href="http://foo"bar">http://foo"bar</a>',
|
||||||
}
|
}
|
||||||
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
|
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_auto_mailto
|
def test_auto_mailto
|
||||||
assert_equal '<p><a href="mailto:test@foo.bar" class="email">test@foo.bar</a></p>',
|
assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>',
|
||||||
textilizable('test@foo.bar')
|
textilizable('test@foo.bar')
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -129,6 +131,8 @@ RAW
|
|||||||
"\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
|
"\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
|
||||||
# two exclamation marks
|
# two exclamation marks
|
||||||
'"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
|
'"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
|
||||||
|
# escaping
|
||||||
|
'"test":http://foo"bar' => '<a href="http://foo"bar" class="external">test</a>',
|
||||||
}
|
}
|
||||||
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
|
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
|
||||||
end
|
end
|
||||||
@@ -360,6 +364,10 @@ h2. Subtitle with %{color:red}red text%
|
|||||||
|
|
||||||
h1. Another title
|
h1. Another title
|
||||||
|
|
||||||
|
h2. An "Internet link":http://www.redmine.org/ inside subtitle
|
||||||
|
|
||||||
|
h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
|
||||||
|
|
||||||
RAW
|
RAW
|
||||||
|
|
||||||
expected = '<ul class="toc">' +
|
expected = '<ul class="toc">' +
|
||||||
@@ -368,8 +376,10 @@ RAW
|
|||||||
'<li class="heading2"><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
|
'<li class="heading2"><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
|
||||||
'<li class="heading2"><a href="#Subtitle-with-red-text">Subtitle with red text</a></li>' +
|
'<li class="heading2"><a href="#Subtitle-with-red-text">Subtitle with red text</a></li>' +
|
||||||
'<li class="heading1"><a href="#Another-title">Another title</a></li>' +
|
'<li class="heading1"><a href="#Another-title">Another title</a></li>' +
|
||||||
|
'<li class="heading2"><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
|
||||||
|
'<li class="heading2"><a href="#Project-Name">Project Name</a></li>' +
|
||||||
'</ul>'
|
'</ul>'
|
||||||
|
|
||||||
assert textilizable(raw).gsub("\n", "").include?(expected)
|
assert textilizable(raw).gsub("\n", "").include?(expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -386,6 +386,16 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
assert_equal 7, issue.fixed_version_id
|
assert_equal 7, issue.fixed_version_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_move_to_another_project_with_disabled_tracker
|
||||||
|
issue = Issue.find(1)
|
||||||
|
target = Project.find(2)
|
||||||
|
target.tracker_ids = [3]
|
||||||
|
target.save
|
||||||
|
assert_equal false, issue.move_to(target)
|
||||||
|
issue.reload
|
||||||
|
assert_equal 1, issue.project_id
|
||||||
|
end
|
||||||
|
|
||||||
def test_copy_to_the_same_project
|
def test_copy_to_the_same_project
|
||||||
issue = Issue.find(1)
|
issue = Issue.find(1)
|
||||||
copy = nil
|
copy = nil
|
||||||
@@ -589,4 +599,20 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context ".allowed_target_projects_on_move" do
|
||||||
|
should "return all active projects for admin users" do
|
||||||
|
User.current = User.find(1)
|
||||||
|
assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
|
||||||
|
end
|
||||||
|
|
||||||
|
should "return allowed projects for non admin users" do
|
||||||
|
User.current = User.find(2)
|
||||||
|
Role.non_member.remove_permission! :move_issues
|
||||||
|
assert_equal 3, Issue.allowed_target_projects_on_move.size
|
||||||
|
|
||||||
|
Role.non_member.add_permission! :move_issues
|
||||||
|
assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -166,6 +166,15 @@ class MailHandlerTest < ActiveSupport::TestCase
|
|||||||
assert issue.author.anonymous?
|
assert issue.author.anonymous?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_add_issue_by_anonymous_user_with_no_from_address
|
||||||
|
Role.anonymous.add_permission!(:add_issues)
|
||||||
|
assert_no_difference 'User.count' do
|
||||||
|
issue = submit_email('ticket_by_empty_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept')
|
||||||
|
assert issue.is_a?(Issue)
|
||||||
|
assert issue.author.anonymous?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_add_issue_by_anonymous_user_on_private_project
|
def test_add_issue_by_anonymous_user_on_private_project
|
||||||
Role.anonymous.add_permission!(:add_issues)
|
Role.anonymous.add_permission!(:add_issues)
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ class MailerTest < ActiveSupport::TestCase
|
|||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
include ActionController::Assertions::SelectorAssertions
|
include ActionController::Assertions::SelectorAssertions
|
||||||
fixtures :projects, :enabled_modules, :issues, :users, :members, :member_roles, :roles, :documents, :attachments, :news, :tokens, :journals, :journal_details, :changesets, :trackers, :issue_statuses, :enumerations, :messages, :boards, :repositories
|
fixtures :projects, :enabled_modules, :issues, :users, :members, :member_roles, :roles, :documents, :attachments, :news, :tokens, :journals, :journal_details, :changesets, :trackers, :issue_statuses, :enumerations, :messages, :boards, :repositories
|
||||||
|
|
||||||
|
def setup
|
||||||
|
ActionMailer::Base.deliveries.clear
|
||||||
|
Setting.host_name = 'mydomain.foo'
|
||||||
|
Setting.protocol = 'http'
|
||||||
|
end
|
||||||
|
|
||||||
def test_generated_links_in_emails
|
def test_generated_links_in_emails
|
||||||
ActionMailer::Base.deliveries.clear
|
ActionMailer::Base.deliveries.clear
|
||||||
@@ -231,6 +237,20 @@ class MailerTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_version_file_added
|
||||||
|
attachements = [ Attachment.find_by_container_type('Version') ]
|
||||||
|
assert Mailer.deliver_attachments_added(attachements)
|
||||||
|
assert_not_nil last_email.bcc
|
||||||
|
assert last_email.bcc.any?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_project_file_added
|
||||||
|
attachements = [ Attachment.find_by_container_type('Project') ]
|
||||||
|
assert Mailer.deliver_attachments_added(attachements)
|
||||||
|
assert_not_nil last_email.bcc
|
||||||
|
assert last_email.bcc.any?
|
||||||
|
end
|
||||||
|
|
||||||
def test_news_added
|
def test_news_added
|
||||||
news = News.find(:first)
|
news = News.find(:first)
|
||||||
valid_languages.each do |lang|
|
valid_languages.each do |lang|
|
||||||
@@ -282,6 +302,14 @@ class MailerTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_test
|
||||||
|
user = User.find(1)
|
||||||
|
valid_languages.each do |lang|
|
||||||
|
user.update_attribute :language, lang.to_s
|
||||||
|
assert Mailer.deliver_test(user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_reminders
|
def test_reminders
|
||||||
ActionMailer::Base.deliveries.clear
|
ActionMailer::Base.deliveries.clear
|
||||||
Mailer.reminders(:days => 42)
|
Mailer.reminders(:days => 42)
|
||||||
@@ -310,4 +338,13 @@ class MailerTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
assert_equal :it, current_language
|
assert_equal :it, current_language
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_with_deliveries_off
|
||||||
|
Mailer.with_deliveries false do
|
||||||
|
Mailer.deliver_test(User.find(1))
|
||||||
|
end
|
||||||
|
assert ActionMailer::Base.deliveries.empty?
|
||||||
|
# should restore perform_deliveries
|
||||||
|
assert ActionMailer::Base.perform_deliveries
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ class WatcherTest < ActiveSupport::TestCase
|
|||||||
assert Issue.watched_by(@user).include?(@issue)
|
assert Issue.watched_by(@user).include?(@issue)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_watcher_user_ids
|
||||||
|
issue = Issue.new
|
||||||
|
issue.watcher_user_ids = ['1', '3']
|
||||||
|
assert issue.watched_by?(User.find(1))
|
||||||
|
end
|
||||||
|
|
||||||
def test_recipients
|
def test_recipients
|
||||||
@issue.watchers.delete_all
|
@issue.watchers.delete_all
|
||||||
@issue.reload
|
@issue.reload
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ module Redmine
|
|||||||
watching ? add_watcher(user) : remove_watcher(user)
|
watching ? add_watcher(user) : remove_watcher(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if object is watched by user
|
# Returns true if object is watched by +user+
|
||||||
def watched_by?(user)
|
def watched_by?(user)
|
||||||
!!(user && self.watchers.detect {|w| w.user_id == user.id })
|
!!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of watchers' email addresses
|
# Returns an array of watchers' email addresses
|
||||||
|
|||||||
Reference in New Issue
Block a user