# HG changeset patch
# User Chris Cannam
# Date 1342009813 -3600
# Node ID d36724ef856a3db557e01d5172eddc5861421fc0
# Parent 9ee5fd0b9bd3613986af6cdabf42ac1408cf1f53# Parent ec1c49528f3655d45bb7f58dc8a77c2bc4886a2c
Merge from branch "cannam_integration"
diff -r 9ee5fd0b9bd3 -r d36724ef856a .svn/wc.db
Binary file .svn/wc.db has changed
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/admin_controller.rb
--- a/app/controllers/admin_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/admin_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -73,9 +73,7 @@
def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name
@checklist = [
- [:text_default_administrator_account_changed,
- User.find(:first,
- :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?],
+ [:text_default_administrator_account_changed, User.default_admin_account_changed?],
[:text_file_repository_writable, File.writable?(Attachment.storage_path)],
[:text_plugin_assets_writable, File.writable?(Engines.public_directory)],
[:text_rmagick_available, Object.const_defined?(:Magick)]
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/boards_controller.rb
--- a/app/controllers/boards_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/boards_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -65,7 +65,8 @@
verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index }
def new
- @board = Board.new(params[:board])
+ @board = Board.new
+ @board.safe_attributes = params[:board]
@board.project = @project
if request.post? && @board.save
flash[:notice] = l(:notice_successful_create)
@@ -74,7 +75,8 @@
end
def edit
- if request.post? && @board.update_attributes(params[:board])
+ @board.safe_attributes = params[:board]
+ if request.post? && @board.save
redirect_to_settings_in_projects
end
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/comments_controller.rb
--- a/app/controllers/comments_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/comments_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -7,7 +7,8 @@
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
- @comment = Comment.new(params[:comment])
+ @comment = Comment.new
+ @comment.safe_attributes = params[:comment]
@comment.author = User.current
if @news.comments << @comment
flash[:notice] = l(:label_comment_added)
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/documents_controller.rb
--- a/app/controllers/documents_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/documents_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -47,7 +47,8 @@
end
def new
- @document = @project.documents.build(params[:document])
+ @document = @project.documents.build
+ @document.safe_attributes = params[:document]
if request.post? and @document.save
attachments = Attachment.attach_files(@document, params[:attachments])
render_attachment_warning_if_needed(@document)
@@ -58,7 +59,8 @@
def edit
@categories = DocumentCategory.active #TODO: use it in the views
- if request.post? and @document.update_attributes(params[:document])
+ @document.safe_attributes = params[:document]
+ if request.post? and @document.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @document
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/issue_categories_controller.rb
--- a/app/controllers/issue_categories_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/issue_categories_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -39,12 +39,14 @@
end
def new
- @category = @project.issue_categories.build(params[:issue_category])
+ @category = @project.issue_categories.build
+ @category.safe_attributes = params[:issue_category]
end
verify :method => :post, :only => :create
def create
- @category = @project.issue_categories.build(params[:issue_category])
+ @category = @project.issue_categories.build
+ @category.safe_attributes = params[:issue_category]
if @category.save
respond_to do |format|
format.html do
@@ -75,7 +77,8 @@
verify :method => :put, :only => :update
def update
- if @category.update_attributes(params[:issue_category])
+ @category.safe_attributes = params[:issue_category]
+ if @category.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/members_controller.rb
--- a/app/controllers/members_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/members_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -39,7 +39,7 @@
attrs = params[:member].dup
if (user_ids = attrs.delete(:user_ids))
user_ids.each do |user_id|
- @new_member = Member.new(attrs.merge(:user_id => user_id))
+ @new_member = Member.new(:role_ids => params[:member][:role_ids], :user_id => user_id)
members << @new_member
# send notification to member
@@ -47,7 +47,7 @@
end
else
- @new_member = Member.new(attrs)
+ @new_member = Member.new(:role_ids => params[:member][:role_ids], :user_id => params[:member][:user_id])
members << @new_member
# send notification to member
@@ -87,7 +87,10 @@
end
def edit
- if request.post? and @member.update_attributes(params[:member])
+ if params[:member]
+ @member.role_ids = params[:member][:role_ids]
+ end
+ if request.post? and @member.save
respond_to do |format|
format.html { redirect_to :action => 'index', :project_id => @project }
format.js {
@@ -116,7 +119,7 @@
end
def autocomplete_for_member
- @principals = Principal.active.like(params[:q]).find(:all, :limit => 100) - @project.principals
+ @principals = Principal.active.not_member_of(@project).like(params[:q]).all(:limit => 100)
logger.debug "Query for #{params[:q]} returned #{@principals.size} results"
render :layout => false
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/messages_controller.rb
--- a/app/controllers/messages_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/messages_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -53,13 +53,10 @@
# Create a new topic
def new
- @message = Message.new(params[:message])
+ @message = Message.new
@message.author = User.current
@message.board = @board
- if params[:message] && User.current.allowed_to?(:edit_messages, @project)
- @message.locked = params[:message]['locked']
- @message.sticky = params[:message]['sticky']
- end
+ @message.safe_attributes = params[:message]
if request.post? && @message.save
call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
attachments = Attachment.attach_files(@message, params[:attachments])
@@ -70,9 +67,10 @@
# Reply to a topic
def reply
- @reply = Message.new(params[:reply])
+ @reply = Message.new
@reply.author = User.current
@reply.board = @board
+ @reply.safe_attributes = params[:reply]
@topic.children << @reply
if !@reply.new_record?
call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
@@ -85,11 +83,8 @@
# Edit a message
def edit
(render_403; return false) unless @message.editable_by?(User.current)
- if params[:message]
- @message.locked = params[:message]['locked']
- @message.sticky = params[:message]['sticky']
- end
- if request.post? && @message.update_attributes(params[:message])
+ @message.safe_attributes = params[:message]
+ if request.post? && @message.save
attachments = Attachment.attach_files(@message, params[:attachments])
render_attachment_warning_if_needed(@message)
flash[:notice] = l(:notice_successful_update)
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/news_controller.rb
--- a/app/controllers/news_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/news_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -67,8 +67,8 @@
def create
@news = News.new(:project => @project, :author => User.current)
+ @news.safe_attributes = params[:news]
if request.post?
- @news.attributes = params[:news]
if @news.save
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'news', :action => 'index', :project_id => @project
@@ -82,7 +82,8 @@
end
def update
- if request.put? and @news.update_attributes(params[:news])
+ @news.safe_attributes = params[:news]
+ if request.put? and @news.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @news
else
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/projects_controller.rb
--- a/app/controllers/projects_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/projects_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -79,7 +79,8 @@
def new
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all
- @project = Project.new(params[:project])
+ @project = Project.new
+ @project.safe_attributes = params[:project]
end
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/timelog_controller.rb
--- a/app/controllers/timelog_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/timelog_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -105,7 +105,7 @@
def new
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
- @time_entry.attributes = params[:time_entry]
+ @time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
render :action => 'edit'
@@ -114,7 +114,7 @@
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
- @time_entry.attributes = params[:time_entry]
+ @time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
@@ -135,14 +135,14 @@
end
def edit
- @time_entry.attributes = params[:time_entry]
+ @time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update
- @time_entry.attributes = params[:time_entry]
+ @time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
@@ -173,7 +173,7 @@
unsaved_time_entry_ids = []
@time_entries.each do |time_entry|
time_entry.reload
- time_entry.attributes = attributes
+ time_entry.safe_attributes = attributes
call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
unless time_entry.save
# Keep unsaved time_entry ids to display them in flash error
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/versions_controller.rb
--- a/app/controllers/versions_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/versions_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -23,7 +23,7 @@
before_filter :find_project, :only => [:index, :new, :create, :close_completed]
before_filter :authorize
- accept_api_auth :index, :create, :update, :destroy
+ accept_api_auth :index, :show, :create, :update, :destroy
helper :custom_fields
helper :projects
@@ -75,7 +75,7 @@
if params[:version]
attributes = params[:version].dup
attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
- @version.attributes = attributes
+ @version.safe_attributes = attributes
end
end
@@ -85,7 +85,7 @@
if params[:version]
attributes = params[:version].dup
attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
- @version.attributes = attributes
+ @version.safe_attributes = attributes
end
if request.post?
@@ -124,7 +124,8 @@
if request.put? && params[:version]
attributes = params[:version].dup
attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
- if @version.update_attributes(attributes)
+ @version.safe_attributes = attributes
+ if @version.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/controllers/wikis_controller.rb
--- a/app/controllers/wikis_controller.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/controllers/wikis_controller.rb Wed Jul 11 13:30:13 2012 +0100
@@ -22,7 +22,7 @@
# Create or update a project's wiki
def edit
@wiki = @project.wiki || Wiki.new(:project => @project)
- @wiki.attributes = params[:wiki]
+ @wiki.safe_attributes = params[:wiki]
@wiki.save if request.post?
render(:update) {|page| page.replace_html "tab-content-wiki", :partial => 'projects/settings/wiki'}
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/helpers/application_helper.rb
--- a/app/helpers/application_helper.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/helpers/application_helper.rb Wed Jul 11 13:30:13 2012 +0100
@@ -497,12 +497,16 @@
text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr)
@parsed_headings = []
+ @heading_anchors = {}
@current_section = 0 if options[:edit_section_links]
+
+ parse_sections(text, project, obj, attr, only_path, options)
text = parse_non_pre_blocks(text) do |text|
- [:parse_sections, :parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_macros, :parse_headings].each do |method_name|
+ [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_macros].each do |method_name|
send method_name, text, project, obj, attr, only_path, options
end
end
+ parse_headings(text, project, obj, attr, only_path, options)
if @parsed_headings.any?
replace_toc(text, @parsed_headings)
@@ -785,6 +789,11 @@
anchor = sanitize_anchor_name(item)
# used for single-file wiki export
anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version))
+ @heading_anchors[anchor] ||= 0
+ idx = (@heading_anchors[anchor] += 1)
+ if idx > 1
+ anchor = "#{anchor}-#{idx}"
+ end
@parsed_headings << [level, anchor, item]
"\n#{content}¶"
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/board.rb
--- a/app/models/board.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/board.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Board < ActiveRecord::Base
+ include Redmine::SafeAttributes
belongs_to :project
has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC"
@@ -30,6 +31,8 @@
named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_messages, *args) } }
+ safe_attributes 'name', 'description', 'move_to'
+
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_messages, project)
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/changeset.rb
--- a/app/models/changeset.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/changeset.rb Wed Jul 11 13:30:13 2012 +0100
@@ -151,12 +151,16 @@
@long_comments || split_comments.last
end
- def text_tag
- if scmid?
+ def text_tag(ref_project=nil)
+ tag = if scmid?
"commit:#{scmid}"
else
"r#{revision}"
end
+ if ref_project && project && ref_project != project
+ tag = "#{project.identifier}:#{tag}"
+ end
+ tag
end
# Returns the previous changeset
@@ -213,7 +217,7 @@
# don't change the status is the issue is closed
return if issue.status && issue.status.is_closed?
- journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag))
+ journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag(issue.project)))
issue.status = status
unless Setting.commit_fix_done_ratio.blank?
issue.done_ratio = Setting.commit_fix_done_ratio.to_i
@@ -232,7 +236,7 @@
:hours => hours,
:issue => issue,
:spent_on => commit_date,
- :comments => l(:text_time_logged_by_changeset, :value => text_tag,
+ :comments => l(:text_time_logged_by_changeset, :value => text_tag(issue.project),
:locale => Setting.default_language)
)
time_entry.activity = log_time_activity unless log_time_activity.nil?
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/comment.rb
--- a/app/models/comment.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/comment.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,8 +16,11 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Comment < ActiveRecord::Base
+ include Redmine::SafeAttributes
belongs_to :commented, :polymorphic => true, :counter_cache => true
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :commented, :author, :comments
+
+ safe_attributes 'comments'
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/document.rb
--- a/app/models/document.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/document.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Document < ActiveRecord::Base
+ include Redmine::SafeAttributes
belongs_to :project
belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
acts_as_attachable :delete_permission => :manage_documents
@@ -32,6 +33,8 @@
named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_documents, *args) } }
+ safe_attributes 'category_id', 'title', 'description'
+
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_documents, project)
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/issue_category.rb
--- a/app/models/issue_category.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/issue_category.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategory < ActiveRecord::Base
+ include Redmine::SafeAttributes
belongs_to :project
belongs_to :assigned_to, :class_name => 'Principal', :foreign_key => 'assigned_to_id'
has_many :issues, :foreign_key => 'category_id', :dependent => :nullify
@@ -24,7 +25,7 @@
validates_uniqueness_of :name, :scope => [:project_id]
validates_length_of :name, :maximum => 30
- attr_protected :project_id
+ safe_attributes 'name', 'assigned_to_id'
named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/mailer.rb
--- a/app/models/mailer.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/mailer.rb Wed Jul 11 13:30:13 2012 +0100
@@ -375,7 +375,7 @@
:conditions => s.conditions
).group_by(&:assigned_to)
issues_by_assignee.each do |assignee, issues|
- deliver_reminder(assignee, issues, days) if assignee && assignee.active?
+ deliver_reminder(assignee, issues, days) if assignee.is_a?(User) && assignee.active?
end
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/member.rb
--- a/app/models/member.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/member.rb Wed Jul 11 13:30:13 2012 +0100
@@ -50,7 +50,17 @@
def <=>(member)
a, b = roles.sort.first, member.roles.sort.first
- a == b ? (principal <=> member.principal) : (a <=> b)
+ if a == b
+ if principal
+ principal <=> member.principal
+ else
+ 1
+ end
+ elsif a
+ a <=> b
+ else
+ 1
+ end
end
def deletable?
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/message.rb
--- a/app/models/message.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/message.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Message < ActiveRecord::Base
+ include Redmine::SafeAttributes
belongs_to :board
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
@@ -36,7 +37,6 @@
:author_key => :author_id
acts_as_watchable
- attr_protected :locked, :sticky
validates_presence_of :board, :subject, :content
validates_length_of :subject, :maximum => 255
validate :cannot_reply_to_locked_topic, :on => :create
@@ -48,6 +48,12 @@
named_scope :visible, lambda {|*args| { :include => {:board => :project},
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_messages, *args) } }
+ safe_attributes 'subject', 'content'
+ safe_attributes 'locked', 'sticky', 'board_id',
+ :if => lambda {|message, user|
+ user.allowed_to?(:edit_messages, message.project)
+ }
+
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_messages, project)
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/news.rb
--- a/app/models/news.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/news.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class News < ActiveRecord::Base
+ include Redmine::SafeAttributes
belongs_to :project
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
@@ -37,6 +38,8 @@
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_news, *args)
}}
+ safe_attributes 'title', 'summary', 'description'
+
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_news, project)
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/principal.rb
--- a/app/models/principal.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/principal.rb Wed Jul 11 13:30:13 2012 +0100
@@ -32,6 +32,16 @@
:order => 'type, login, lastname, firstname, mail'
}
}
+ # Principals that are not members of projects
+ named_scope :not_member_of, lambda {|projects|
+ projects = [projects] unless projects.is_a?(Array)
+ if projects.empty?
+ {:conditions => "1=0"}
+ else
+ ids = projects.map(&:id)
+ {:conditions => ["#{Principal.table_name}.id NOT IN (SELECT DISTINCT user_id FROM #{Member.table_name} WHERE project_id IN (?))", ids]}
+ end
+ }
before_create :set_default_empty_values
@@ -40,7 +50,9 @@
end
def <=>(principal)
- if self.class.name == principal.class.name
+ if principal.nil?
+ -1
+ elsif self.class.name == principal.class.name
self.to_s.downcase <=> principal.to_s.downcase
else
# groups after users
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/project.rb
--- a/app/models/project.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/project.rb Wed Jul 11 13:30:13 2012 +0100
@@ -258,7 +258,7 @@
def to_param
# id is used for projects with a numeric identifier (compatibility)
- @to_param ||= (identifier.to_s =~ %r{^\d*$} ? id : identifier)
+ @to_param ||= (identifier.to_s =~ %r{^\d*$} ? id.to_s : identifier)
end
def active?
@@ -395,16 +395,21 @@
# Returns a scope of the Versions used by the project
def shared_versions
- @shared_versions ||= begin
- r = root? ? self : root
+ if new_record?
Version.scoped(:include => :project,
- :conditions => "#{Project.table_name}.id = #{id}" +
- " OR (#{Project.table_name}.status = #{Project::STATUS_ACTIVE} AND (" +
+ :conditions => "#{Project.table_name}.status = #{Project::STATUS_ACTIVE} AND #{Version.table_name}.sharing = 'system'")
+ else
+ @shared_versions ||= begin
+ r = root? ? self : root
+ Version.scoped(:include => :project,
+ :conditions => "#{Project.table_name}.id = #{id}" +
+ " OR (#{Project.table_name}.status = #{Project::STATUS_ACTIVE} AND (" +
" #{Version.table_name}.sharing = 'system'" +
" OR (#{Project.table_name}.lft >= #{r.lft} AND #{Project.table_name}.rgt <= #{r.rgt} AND #{Version.table_name}.sharing = 'tree')" +
" OR (#{Project.table_name}.lft < #{lft} AND #{Project.table_name}.rgt > #{rgt} AND #{Version.table_name}.sharing IN ('hierarchy', 'descendants'))" +
" OR (#{Project.table_name}.lft > #{lft} AND #{Project.table_name}.rgt < #{rgt} AND #{Version.table_name}.sharing = 'hierarchy')" +
"))")
+ end
end
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/time_entry.rb
--- a/app/models/time_entry.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/time_entry.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TimeEntry < ActiveRecord::Base
+ include Redmine::SafeAttributes
# could have used polymorphic association
# project association here allows easy loading of time entries at project level with one database trip
belongs_to :project
@@ -46,6 +47,8 @@
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_time_entries, *args)
}}
+ safe_attributes 'hours', 'comments', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values'
+
def after_initialize
if new_record? && self.activity.nil?
if default_activity = TimeEntryActivity.default
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/user.rb
--- a/app/models/user.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/user.rb Wed Jul 11 13:30:13 2012 +0100
@@ -357,6 +357,11 @@
find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
end
+ # Returns true if the default admin account can no longer be used
+ def self.default_admin_account_changed?
+ !User.active.find_by_login("admin").try(:check_password?, "admin")
+ end
+
def to_s
name
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/user_preference.rb
--- a/app/models/user_preference.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/user_preference.rb Wed Jul 11 13:30:13 2012 +0100
@@ -19,7 +19,7 @@
belongs_to :user
serialize :others
- attr_protected :others
+ attr_protected :others, :user_id
def initialize(attributes = nil)
super
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/version.rb
--- a/app/models/version.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/version.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Version < ActiveRecord::Base
+ include Redmine::SafeAttributes
after_update :update_issues_from_sharing_change
belongs_to :project
has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
@@ -38,6 +39,15 @@
named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } }
+ safe_attributes 'name',
+ 'description',
+ 'effective_date',
+ 'due_date',
+ 'wiki_page_title',
+ 'status',
+ 'sharing',
+ 'custom_field_values'
+
# Returns true if +user+ or current user is allowed to view the version
def visible?(user=User.current)
user.allowed_to?(:view_issues, self.project)
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/models/wiki.rb
--- a/app/models/wiki.rb Fri May 11 16:13:59 2012 +0100
+++ b/app/models/wiki.rb Wed Jul 11 13:30:13 2012 +0100
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Wiki < ActiveRecord::Base
+ include Redmine::SafeAttributes
belongs_to :project
has_many :pages, :class_name => 'WikiPage', :dependent => :destroy, :order => 'title'
has_many :redirects, :class_name => 'WikiRedirect', :dependent => :delete_all
@@ -25,6 +26,8 @@
validates_presence_of :start_page
validates_format_of :start_page, :with => /^[^,\.\/\?\;\|\:]*$/
+ safe_attributes 'start_page'
+
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_wiki_pages, project)
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/views/issues/_relations.html.erb
--- a/app/views/issues/_relations.html.erb Fri May 11 16:13:59 2012 +0100
+++ b/app/views/issues/_relations.html.erb Wed Jul 11 13:30:13 2012 +0100
@@ -20,7 +20,8 @@
<%= format_date(relation.other_issue(@issue).start_date) %> |
<%= format_date(relation.other_issue(@issue).due_date) %> |
<%= link_to_remote(image_tag('link_break.png'), { :url => {:controller => 'issue_relations', :action => 'destroy', :id => relation},
- :method => :delete
+ :method => :delete,
+ :confirm => l(:text_are_you_sure)
}, :title => l(:label_relation_delete)) if authorize_for('issue_relations', 'destroy') %> |
<% end %>
diff -r 9ee5fd0b9bd3 -r d36724ef856a app/views/projects/settings/_members.html.erb
--- a/app/views/projects/settings/_members.html.erb Fri May 11 16:13:59 2012 +0100
+++ b/app/views/projects/settings/_members.html.erb Wed Jul 11 13:30:13 2012 +0100
@@ -50,7 +50,7 @@
<% end %>
-<% principals = Principal.active.find(:all, :limit => 100, :order => 'type, login, lastname ASC') - @project.principals %>
+<% principals = Principal.active.not_member_of(@project).all(:limit => 100, :order => 'type, login, lastname ASC') %>
<% if roles.any? && principals.any? %>
diff -r 9ee5fd0b9bd3 -r d36724ef856a config/locales/it.yml
--- a/config/locales/it.yml Fri May 11 16:13:59 2012 +0100
+++ b/config/locales/it.yml Wed Jul 11 13:30:13 2012 +0100
@@ -980,7 +980,7 @@
label_between: tra
setting_issue_group_assignment: Permetti di assegnare una segnalazione a gruppi
label_diff: diff
- text_git_repository_note: Il repository è bare e locale (e.g. /gitrepo, c:\gitrepo)
+ text_git_repository_note: Il repository è spoglio e locale (e.g. /gitrepo, c:\gitrepo)
description_query_sort_criteria_direction: Ordinamento
description_project_scope: Search scope
description_filter: Filtro
diff -r 9ee5fd0b9bd3 -r d36724ef856a config/locales/nl.yml
--- a/config/locales/nl.yml Fri May 11 16:13:59 2012 +0100
+++ b/config/locales/nl.yml Wed Jul 11 13:30:13 2012 +0100
@@ -399,7 +399,7 @@
label_f_hour_plural: "%{value} uren"
label_feed_plural: Feeds
label_feeds_access_key_created_on: "RSS toegangssleutel %{value} geleden gemaakt."
- label_file_added: Bericht toegevoegd
+ label_file_added: Bestand toegevoegd
label_file_plural: Bestanden
label_filter_add: Voeg filter toe
label_filter_plural: Filters
diff -r 9ee5fd0b9bd3 -r d36724ef856a config/locales/zh.yml
--- a/config/locales/zh.yml Fri May 11 16:13:59 2012 +0100
+++ b/config/locales/zh.yml Wed Jul 11 13:30:13 2012 +0100
@@ -1003,9 +1003,9 @@
label_child_revision: 子修订
error_scm_annotate_big_text_file: 输入文本内容超长,无法输入。
setting_default_issue_start_date_to_creation_date: 使用当前日期作为新问题的开始日期
- button_edit_section: Edit this section
- setting_repositories_encodings: Attachments and repositories encodings
- description_all_columns: All Columns
- button_export: Export
- label_export_options: "%{export_format} export options"
- error_attachment_too_big: This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})
+ button_edit_section: 编辑此区域
+ setting_repositories_encodings: 附件和版本库编码
+ description_all_columns: 所有列
+ button_export: 导出
+ label_export_options: "%{export_format} 导出选项"
+ error_attachment_too_big: 该文件无法上传。超过文件大小限制 (%{max_size})
diff -r 9ee5fd0b9bd3 -r d36724ef856a doc/CHANGELOG
--- a/doc/CHANGELOG Fri May 11 16:13:59 2012 +0100
+++ b/doc/CHANGELOG Wed Jul 11 13:30:13 2012 +0100
@@ -4,6 +4,36 @@
Copyright (C) 2006-2012 Jean-Philippe Lang
http://www.redmine.org/
+== 2012-04-14 v1.3.3
+
+* Defect #10505: Error when exporting to PDF with NoMethodError (undefined method `downcase' for nil:NilClass)
+* Defect #10554: Defect symbols when exporting tasks in pdf
+* Defect #10564: Unable to change locked, sticky flags and board when editing a message
+* Defect #10591: Dutch "label_file_added" translation is wrong
+* Defect #10622: "Default administrator account changed" is always true
+* Patch #10555: rake redmine:send_reminders aborted if issue assigned to group
+* Patch #10611: Simplified Chinese translations for 1.3-stable
+
+== 2012-03-11 v1.3.2
+
+* Defect #8194: {{toc}} uses identical anchors for subsections with the same name
+* Defect #9143: Partial diff comparison should be done on actual code, not on html
+* Defect #9523: {{toc}} does not display headers with @ code markup
+* Defect #9815: Release 1.3.0 does not detect rubytree with rubgems 1.8
+* Defect #10053: undefined method `<=>' for nil:NilClass when accessing the settings of a project
+* Defect #10135: ActionView::TemplateError (can't convert Fixnum into String)
+* Defect #10193: Unappropriate icons in highlighted code block
+* Defect #10199: No wiki section edit when title contains code
+* Defect #10218: Error when creating a project with a version custom field
+* Defect #10241: "get version by ID" fails with "401 not authorized" error when using API access key
+* Defect #10284: Note added by commit from a subproject does not contain project identifier
+* Defect #10374: User list is empty when adding users to project / group if remaining users are added late
+* Defect #10390: Mass assignment security vulnerability
+* Patch #8413: Confirmation message before deleting a relationship
+* Patch #10160: Bulgarian translation (r8777)
+* Patch #10242: Migrate Redmine.pm from Digest::Sha1 to Digest::Sha
+* Patch #10258: Italian translation for 1.3-stable
+
== 2012-02-06 v1.3.1
* Defect #9775: app/views/repository/_revision_graph.html.erb sets window.onload directly..
diff -r 9ee5fd0b9bd3 -r d36724ef856a extra/svn/Redmine.pm
--- a/extra/svn/Redmine.pm Fri May 11 16:13:59 2012 +0100
+++ b/extra/svn/Redmine.pm Wed Jul 11 13:30:13 2012 +0100
@@ -99,7 +99,7 @@
use warnings FATAL => 'all', NONFATAL => 'redefine';
use DBI;
-use Digest::SHA1;
+use Digest::SHA;
# optional module for LDAP authentication
my $CanUseLDAPAuth = eval("use Authen::Simple::LDAP; 1");
@@ -327,7 +327,7 @@
my $dbh = connect_database($r);
my $project_id = get_project_identifier($r);
- my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
+ my $pass_digest = Digest::SHA::sha1_hex($redmine_pass);
my $access_mode = defined $read_only_methods{$r->method} ? "R" : "W";
@@ -346,7 +346,7 @@
unless ($auth_source_id) {
my $method = $r->method;
- my $salted_password = Digest::SHA1::sha1_hex($salt.$pass_digest);
+ my $salted_password = Digest::SHA::sha1_hex($salt.$pass_digest);
if ($hashed_password eq $salted_password && (($access_mode eq "R" && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/) ) {
$ret = 1;
last;
diff -r 9ee5fd0b9bd3 -r d36724ef856a lib/redmine/unified_diff.rb
--- a/lib/redmine/unified_diff.rb Fri May 11 16:13:59 2012 +0100
+++ b/lib/redmine/unified_diff.rb Wed Jul 11 13:30:13 2012 +0100
@@ -112,11 +112,6 @@
private
- # Escape the HTML for the diff
- def escapeHTML(line)
- CGI.escapeHTML(line)
- end
-
def diff_for_added_line
if @type == 'sbs' && @removed > 0 && @added < @removed
self[-(@removed - @added)]
@@ -130,7 +125,7 @@
def parse_line(line, type="inline")
if line[0, 1] == "+"
diff = diff_for_added_line
- diff.line_right = escapeHTML line[1..-1]
+ diff.line_right = line[1..-1]
diff.nb_line_right = @line_num_r
diff.type_diff_right = 'diff_in'
@line_num_r += 1
@@ -138,7 +133,7 @@
true
elsif line[0, 1] == "-"
diff = Diff.new
- diff.line_left = escapeHTML line[1..-1]
+ diff.line_left = line[1..-1]
diff.nb_line_left = @line_num_l
diff.type_diff_left = 'diff_out'
self << diff
@@ -149,9 +144,9 @@
write_offsets
if line[0, 1] =~ /\s/
diff = Diff.new
- diff.line_right = escapeHTML line[1..-1]
+ diff.line_right = line[1..-1]
diff.nb_line_right = @line_num_r
- diff.line_left = escapeHTML line[1..-1]
+ diff.line_left = line[1..-1]
diff.nb_line_left = @line_num_l
self << diff
@line_num_l += 1
@@ -224,27 +219,15 @@
end
def html_line_left
- if offsets
- line_left.dup.insert(offsets.first, '
').insert(offsets.last, '')
- else
- line_left
- end
+ line_to_html(line_left, offsets)
end
def html_line_right
- if offsets
- line_right.dup.insert(offsets.first, '
').insert(offsets.last, '')
- else
- line_right
- end
+ line_to_html(line_right, offsets)
end
def html_line
- if offsets
- line.dup.insert(offsets.first, '
').insert(offsets.last, '')
- else
- line
- end
+ line_to_html(line, offsets)
end
def inspect
@@ -254,5 +237,23 @@
puts self.nb_line_right
puts self.line_right
end
+
+ private
+
+ def line_to_html(line, offsets)
+ if offsets
+ s = ''
+ unless offsets.first == 0
+ s << CGI.escapeHTML(line[0..offsets.first-1])
+ end
+ s << '
' + CGI.escapeHTML(line[offsets.first..offsets.last]) + ''
+ unless offsets.last == -1
+ s << CGI.escapeHTML(line[offsets.last+1..-1])
+ end
+ s
+ else
+ CGI.escapeHTML(line)
+ end
+ end
end
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a lib/redmine/version.rb
--- a/lib/redmine/version.rb Fri May 11 16:13:59 2012 +0100
+++ b/lib/redmine/version.rb Wed Jul 11 13:30:13 2012 +0100
@@ -4,7 +4,7 @@
module VERSION #:nodoc:
MAJOR = 1
MINOR = 3
- TINY = 1
+ TINY = 3
# Branch values:
# * official release: nil
diff -r 9ee5fd0b9bd3 -r d36724ef856a public/stylesheets/application.css
--- a/public/stylesheets/application.css Fri May 11 16:13:59 2012 +0100
+++ b/public/stylesheets/application.css Wed Jul 11 13:30:13 2012 +0100
@@ -513,6 +513,9 @@
a.atom { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; }
+em.info {font-style:normal;font-size:90%;color:#888;display:block;}
+em.info.error {padding-left:20px; background:url(../images/exclamation.png) no-repeat 0 50%;}
+
/* Project members tab */
div#tab-content-members .splitcontentleft, div#tab-content-memberships .splitcontentleft, div#tab-content-users .splitcontentleft { width: 64% }
div#tab-content-members .splitcontentright, div#tab-content-memberships .splitcontentright, div#tab-content-users .splitcontentright { width: 34% }
@@ -566,8 +569,6 @@
color: #A6750C;
}
-span.error {padding-left:20px; background:url(../images/exclamation.png) no-repeat 0 50%;}
-
#errorExplanation ul { font-size: 0.9em;}
#errorExplanation h2, #errorExplanation p { display: none; }
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/functional/boards_controller_test.rb
--- a/test/functional/boards_controller_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/functional/boards_controller_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -88,6 +88,14 @@
assert_equal 'Testing', Board.find(2).name
end
+ def test_update_position
+ @request.session[:user_id] = 2
+ post :edit, :project_id => 1, :id => 2, :board => { :move_to => 'highest'}
+ assert_redirected_to '/projects/ecookbook/settings/boards'
+ board = Board.find(2)
+ assert_equal 1, board.position
+ end
+
def test_post_destroy
@request.session[:user_id] = 2
assert_difference 'Board.count', -1 do
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/functional/issues_controller_test.rb
--- a/test/functional/issues_controller_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/functional/issues_controller_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -147,7 +147,6 @@
end
def test_index_with_short_filters
-
to_test = {
'status_id' => {
'o' => { :op => 'o', :values => [''] },
@@ -181,9 +180,9 @@
't-2' => { :op => 't-', :values => ['2'] }},
'created_on' => {
'>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
- '
{ :op => '=', :values => ['t+2' => { :op => '=', :values => ['>t+2'] },
- 't+2' => { :op => 't', :values => ['+2'] }},
+ ' { :op => ' ['2'] },
+ '>t-2' => { :op => '>t-', :values => ['2'] },
+ 't-2' => { :op => 't-', :values => ['2'] }},
'cf_1' => {
'c' => { :op => '=', :values => ['c'] },
'!c' => { :op => '!', :values => ['c'] },
@@ -215,7 +214,6 @@
assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters)
end
end
-
end
def test_index_with_project_and_empty_filters
@@ -933,7 +931,7 @@
def test_post_new_with_group_assignment
group = Group.find(11)
project = Project.find(1)
- project.members << Member.new(:principal => group, :roles => [Role.first])
+ project.members << Member.new(:principal => group, :roles => [Role.givable.first])
with_settings :issue_group_assignment => '1' do
@request.session[:user_id] = 2
@@ -1803,7 +1801,7 @@
def test_bulk_update_with_group_assignee
group = Group.find(11)
project = Project.find(1)
- project.members << Member.new(:principal => group, :roles => [Role.first])
+ project.members << Member.new(:principal => group, :roles => [Role.givable.first])
@request.session[:user_id] = 2
# update issues assignee
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/functional/messages_controller_test.rb
--- a/test/functional/messages_controller_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/functional/messages_controller_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -131,6 +131,30 @@
assert_equal 'New body', message.content
end
+ def test_post_edit_sticky_and_locked
+ @request.session[:user_id] = 2
+ post :edit, :board_id => 1, :id => 1,
+ :message => { :subject => 'New subject',
+ :content => 'New body',
+ :locked => '1',
+ :sticky => '1'}
+ assert_redirected_to '/boards/1/topics/1'
+ message = Message.find(1)
+ assert_equal true, message.sticky?
+ assert_equal true, message.locked?
+ end
+
+ def test_post_edit_should_allow_to_change_board
+ @request.session[:user_id] = 2
+ post :edit, :board_id => 1, :id => 1,
+ :message => { :subject => 'New subject',
+ :content => 'New body',
+ :board_id => 2}
+ assert_redirected_to '/boards/2/topics/1'
+ message = Message.find(1)
+ assert_equal Board.find(2), message.board
+ end
+
def test_reply
@request.session[:user_id] = 2
post :reply, :board_id => 1, :id => 1, :reply => { :content => 'This is a test reply', :subject => 'Test reply' }
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/functional/project_enumerations_controller_test.rb
--- a/test/functional/project_enumerations_controller_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/functional/project_enumerations_controller_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -13,6 +13,8 @@
:custom_fields_trackers, :custom_values,
:time_entries
+ self.use_transactional_fixtures = false
+
def setup
@request.session[:user_id] = nil
Setting.default_language = 'en'
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/functional/trackers_controller_test.rb
--- a/test/functional/trackers_controller_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/functional/trackers_controller_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -64,7 +64,7 @@
tracker = Tracker.first(:order => 'id DESC')
assert_equal 'New tracker', tracker.name
assert_equal [1], tracker.project_ids.sort
- assert_equal [1, 6], tracker.custom_field_ids
+ assert_equal [1, 6], tracker.custom_field_ids.sort
assert_equal 0, tracker.workflows.count
end
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/changeset_test.rb
--- a/test/unit/changeset_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/changeset_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -178,6 +178,24 @@
assert c.issues.first.project != c.project
end
+ def test_commit_closing_a_subproject_issue
+ with_settings :commit_fix_status_id => 5, :commit_fix_keywords => 'closes' do
+ issue = Issue.find(5)
+ assert !issue.closed?
+ assert_difference 'Journal.count' do
+ c = Changeset.new(:repository => Project.find(1).repository,
+ :committed_on => Time.now,
+ :comments => 'closes #5, a subproject issue',
+ :revision => '12345')
+ assert c.save
+ end
+ assert issue.reload.closed?
+ journal = Journal.first(:order => 'id DESC')
+ assert_equal issue, journal.issue
+ assert_include "Applied in changeset ecookbook:r12345.", journal.notes
+ end
+ end
+
def test_commit_referencing_a_parent_project_issue
# repository of child project
r = Repository::Subversion.create!(
@@ -197,6 +215,16 @@
assert_equal 'r520', c.text_tag
end
+ def test_text_tag_revision_with_same_project
+ c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
+ assert_equal 'r520', c.text_tag(Project.find(1))
+ end
+
+ def test_text_tag_revision_with_different_project
+ c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
+ assert_equal 'ecookbook:r520', c.text_tag(Project.find(2))
+ end
+
def test_text_tag_hash
c = Changeset.new(
:scmid => '7234cb2750b63f47bff735edc50a1c0a433c2518',
@@ -204,6 +232,16 @@
assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag
end
+ def test_text_tag_hash_with_same_project
+ c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
+ assert_equal 'commit:7234cb27', c.text_tag(Project.find(1))
+ end
+
+ def test_text_tag_hash_with_different_project
+ c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
+ assert_equal 'ecookbook:commit:7234cb27', c.text_tag(Project.find(2))
+ end
+
def test_text_tag_hash_all_number
c = Changeset.new(:scmid => '0123456789', :revision => '0123456789')
assert_equal 'commit:0123456789', c.text_tag
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/helpers/application_helper_test.rb
--- a/test/unit/helpers/application_helper_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/helpers/application_helper_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -732,6 +732,8 @@
h3. Subtitle with *some* _modifiers_
+h3. Subtitle with @inline code@
+
h1. Another title
h3. An "Internet link":http://www.redmine.org/ inside subtitle
@@ -748,6 +750,7 @@
'Subtitle with red text' +
'' +
'' +
'' +
@@ -768,6 +771,33 @@
assert textilizable(raw).gsub("\n", "").include?(expected)
end
+ def test_table_of_content_should_generate_unique_anchors
+ raw = <<-RAW
+{{toc}}
+
+h1. Title
+
+h2. Subtitle
+
+h2. Subtitle
+RAW
+
+ expected = '' +
+ '- Title' +
+ ''
+ '
' +
+ '
'
+
+ @project = Project.find(1)
+ result = textilizable(raw).gsub("\n", "")
+ assert_include expected, result
+ assert_include '', result
+ assert_include '', result
+ end
+
def test_table_of_content_should_contain_included_page_headings
raw = <<-RAW
{{toc}}
@@ -786,6 +816,48 @@
assert textilizable(raw).gsub("\n", "").include?(expected)
end
+ def test_section_edit_links
+ raw = <<-RAW
+h1. Title
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
+
+h2. Subtitle with a [[Wiki]] link
+
+h2. Subtitle with *some* _modifiers_
+
+h2. Subtitle with @inline code@
+
+
+some code
+
+h2. heading inside pre
+
+html heading inside pre
+
+
+h2. Subtitle after pre tag
+RAW
+
+ @project = Project.find(1)
+ set_language_if_valid 'en'
+ result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
+
+ # heading that contains inline code
+ assert_match Regexp.new('' +
+ '
?)
' +
+ '' +
+ 'Subtitle with inline code
¶
'),
+ result
+
+ # last heading
+ assert_match Regexp.new('' +
+ '
?)
' +
+ '' +
+ 'Subtitle after pre tag¶
'),
+ result
+ end
+
def test_default_formatter
Setting.text_formatting = 'unknown'
text = 'a *link*: http://www.example.net/'
@@ -853,6 +925,14 @@
link_to_project(project, {:action => 'settings'}, :class => "project")
end
+ def test_link_to_legacy_project_with_numerical_identifier_should_use_id
+ # numeric identifier are no longer allowed
+ Project.update_all "identifier=25", "id=1"
+
+ assert_equal 'eCookbook',
+ link_to_project(Project.find(1))
+ end
+
def test_principals_options_for_select_with_users
users = [User.find(2), User.find(4)]
assert_equal %(),
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/lib/redmine/unified_diff_test.rb
--- a/test/unit/lib/redmine/unified_diff_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/lib/redmine/unified_diff_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -91,6 +91,29 @@
end
+ def test_partials_with_html_entities
+ raw = <<-DIFF
+--- test.orig.txt Wed Feb 15 16:10:39 2012
++++ test.new.txt Wed Feb 15 16:11:25 2012
+@@ -1,5 +1,5 @@
+ Semicolons were mysteriously appearing in code diffs in the repository
+
+-void DoSomething(std::auto_ptr myObj)
++void DoSomething(const MyClass& myObj)
+
+DIFF
+
+ diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
+ assert_equal 1, diff.size
+ assert_equal 'void DoSomething(std::auto_ptr<MyClass> myObj)', diff.first[2].html_line_left
+ assert_equal 'void DoSomething(const MyClass& myObj)', diff.first[2].html_line_right
+
+ diff = Redmine::UnifiedDiff.new(raw, :type => 'inline')
+ assert_equal 1, diff.size
+ assert_equal 'void DoSomething(std::auto_ptr<MyClass> myObj)', diff.first[2].html_line
+ assert_equal 'void DoSomething(const MyClass& myObj)', diff.first[3].html_line
+ end
+
def test_line_starting_with_dashes
diff = Redmine::UnifiedDiff.new(<<-DIFF
--- old.txt Wed Nov 11 14:24:58 2009
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/mailer_test.rb
--- a/test/unit/mailer_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/mailer_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -370,7 +370,7 @@
end
def test_wiki_content_added
- content = WikiContent.find(:first)
+ content = WikiContent.find(1)
valid_languages.each do |lang|
Setting.default_language = lang.to_s
assert_difference 'ActionMailer::Base.deliveries.size' do
@@ -380,7 +380,7 @@
end
def test_wiki_content_updated
- content = WikiContent.find(:first)
+ content = WikiContent.find(1)
valid_languages.each do |lang|
Setting.default_language = lang.to_s
assert_difference 'ActionMailer::Base.deliveries.size' do
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/member_test.rb
--- a/test/unit/member_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/member_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -82,6 +82,23 @@
assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
end
+ def test_sort_without_roles
+ a = Member.new(:roles => [Role.first])
+ b = Member.new
+
+ assert_equal -1, a <=> b
+ assert_equal 1, b <=> a
+ end
+
+ def test_sort_without_principal
+ role = Role.first
+ a = Member.new(:roles => [role], :principal => User.first)
+ b = Member.new(:roles => [role])
+
+ assert_equal -1, a <=> b
+ assert_equal 1, b <=> a
+ end
+
context "removing permissions" do
setup do
Watcher.delete_all("user_id = 9")
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/news_test.rb
--- a/test/unit/news_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/news_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -30,7 +30,7 @@
def test_create_should_send_email_notification
ActionMailer::Base.deliveries.clear
Setting.notified_events << 'news_added'
- news = Project.find(:first).news.new(valid_news)
+ news = Project.find(1).news.new(valid_news)
assert news.save
assert_equal 1, ActionMailer::Base.deliveries.size
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/principal_test.rb
--- a/test/unit/principal_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/principal_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -18,6 +18,13 @@
require File.expand_path('../../test_helper', __FILE__)
class PrincipalTest < ActiveSupport::TestCase
+ fixtures :users, :projects, :members, :member_roles
+
+ def test_not_member_of_scope_should_return_users_that_have_no_memberships
+ projects = Project.find_all_by_id(1, 2)
+ expected = (Principal.all - projects.map(&:memberships).flatten.map(&:principal)).sort
+ assert_equal expected, Principal.not_member_of(projects).sort
+ end
context "#like" do
setup do
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/project_test.rb
--- a/test/unit/project_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/project_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -96,8 +96,8 @@
assert_equal ['issue_tracking', 'repository'], Project.new.enabled_module_names
end
- assert_equal Tracker.all, Project.new.trackers
- assert_equal Tracker.find(1, 3), Project.new(:tracker_ids => [1, 3]).trackers
+ assert_equal Tracker.all.sort, Project.new.trackers.sort
+ assert_equal Tracker.find(1, 3).sort, Project.new(:tracker_ids => [1, 3]).trackers.sort
end
def test_update
@@ -586,6 +586,13 @@
assert !versions.collect(&:id).include?(6)
end
+ def test_shared_versions_for_new_project_should_include_system_shared_versions
+ p = Project.find(5)
+ v = Version.create!(:name => 'system_sharing', :project => p, :sharing => 'system')
+
+ assert_include v, Project.new.shared_versions
+ end
+
def test_next_identifier
ProjectCustomField.delete_all
Project.create!(:name => 'last', :identifier => 'p2008040')
diff -r 9ee5fd0b9bd3 -r d36724ef856a test/unit/user_test.rb
--- a/test/unit/user_test.rb Fri May 11 16:13:59 2012 +0100
+++ b/test/unit/user_test.rb Wed Jul 11 13:30:13 2012 +0100
@@ -574,6 +574,38 @@
end
end
+ def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
+ user = User.find_by_login("admin")
+ user.password = "admin"
+ user.save!
+
+ assert_equal false, User.default_admin_account_changed?
+ end
+
+ def test_default_admin_account_changed_should_return_true_if_password_was_changed
+ user = User.find_by_login("admin")
+ user.password = "newpassword"
+ user.save!
+
+ assert_equal true, User.default_admin_account_changed?
+ end
+
+ def test_default_admin_account_changed_should_return_true_if_account_is_disabled
+ user = User.find_by_login("admin")
+ user.password = "admin"
+ user.status = User::STATUS_LOCKED
+ user.save!
+
+ assert_equal true, User.default_admin_account_changed?
+ end
+
+ def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
+ user = User.find_by_login("admin")
+ user.destroy
+
+ assert_equal true, User.default_admin_account_changed?
+ end
+
def test_roles_for_project
# user with a role
roles = @jsmith.roles_for_project(Project.find(1))
diff -r 9ee5fd0b9bd3 -r d36724ef856a vendor/gems/rubytree-0.5.2/.specification
--- a/vendor/gems/rubytree-0.5.2/.specification Fri May 11 16:13:59 2012 +0100
+++ b/vendor/gems/rubytree-0.5.2/.specification Wed Jul 11 13:30:13 2012 +0100
@@ -11,17 +11,8 @@
date: 2007-12-20 00:00:00 -08:00
default_executable:
-dependencies:
-- !ruby/object:Gem::Dependency
- name: hoe
- type: :runtime
- version_requirement:
- version_requirements: !ruby/object:Gem::Requirement
- requirements:
- - - ">="
- - !ruby/object:Gem::Version
- version: 1.3.0
- version:
+dependencies: []
+
description: "Provides a generic tree data-structure with ability to store keyed node-elements in the tree. The implementation mixes in the Enumerable module. Website: http://rubytree.rubyforge.org/"
email: anupamsg@gmail.com
executables: []
diff -r 9ee5fd0b9bd3 -r d36724ef856a vendor/plugins/redmine_tags/app/views/projects/_tags_form.html.erb
--- a/vendor/plugins/redmine_tags/app/views/projects/_tags_form.html.erb Fri May 11 16:13:59 2012 +0100
+++ b/vendor/plugins/redmine_tags/app/views/projects/_tags_form.html.erb Wed Jul 11 13:30:13 2012 +0100
@@ -1,8 +1,11 @@
<% fields_for :project, project, :builder => TabularFormBuilder do |f| -%>
-
<%= f.text_field :tag_list, :label => :tags, :size => 60, :class => 'hol' %>
+
<%= f.text_field :tag_list, :label => :tags, :size => 60, :class => 'hol' %>
+
+ <%= l(:text_tags_info) %>
+
<%= javascript_include_tag 'tags_input', :plugin => 'redmine_tags' %>
- <%= javascript_tag "observeProjectTagsField('#{url_for(:controller => 'auto_completes', :action => 'project_tags', :project_id => Project.first.id)}', false)" %>
+ <%= javascript_tag "observeProjectTagsField('#{url_for(:controller => 'auto_completes', :action => 'project_tags', :project_id => Project.first.id)}', false)" %>
<% end -%>
\ No newline at end of file
diff -r 9ee5fd0b9bd3 -r d36724ef856a vendor/plugins/redmine_tags/config/locales/en.yml
--- a/vendor/plugins/redmine_tags/config/locales/en.yml Fri May 11 16:13:59 2012 +0100
+++ b/vendor/plugins/redmine_tags/config/locales/en.yml Wed Jul 11 13:30:13 2012 +0100
@@ -39,3 +39,7 @@
project_filtering_q_label: "Search for text:"
project_filter_no_results: "No matching projects found"
button_filter: "Filter"
+
+ text_tags_info: "A tag can be any text you like, but they're most useful if you choose tags that are already being used for the same thing by other projects (where possible).
Some tag examples are: library, plugin, paper, c++, mir, alpha, stable, bsd, android, ...
Tags help others find your work: please don't forget to tag your projects!"
+
+
diff -r 9ee5fd0b9bd3 -r d36724ef856a vendor/plugins/rfpdf/lib/tcpdf.rb
--- a/vendor/plugins/rfpdf/lib/tcpdf.rb Fri May 11 16:13:59 2012 +0100
+++ b/vendor/plugins/rfpdf/lib/tcpdf.rb Wed Jul 11 13:30:13 2012 +0100
@@ -1803,7 +1803,7 @@
w = @w - @r_margin - @x;
end
- wmax = (w - 2 * @c_margin);
+ wmax = (w - 3 * @c_margin);
s = txt.gsub("\r", ''); # remove carriage returns
nb = s.length;
@@ -1862,7 +1862,7 @@
ns += 1;
end
- l = GetStringWidth(s[from_j, to_index - from_j + 1]);
+ l = GetStringWidth(s[from_j, to_index - from_j]);
if (l > wmax)
#Automatic line break
@@ -1945,7 +1945,7 @@
#Output text in flowing mode
w = @w - @r_margin - @x;
- wmax = (w - 2 * @c_margin);
+ wmax = (w - 3 * @c_margin);
s = txt.gsub("\r", '');
nb = s.length;
@@ -1974,7 +1974,7 @@
if (nl == 1)
@x = @l_margin;
w = @w - @r_margin - @x;
- wmax = (w - 2 * @c_margin);
+ wmax = (w - 3 * @c_margin);
end
nl += 1;
next
@@ -1982,7 +1982,7 @@
if (c == " "[0])
sep= i;
end
- l = GetStringWidth(s[j, i - j + 1]);
+ l = GetStringWidth(s[j, i - j]);
if (l > wmax)
#Automatic line break (word wrapping)
if (sep == -1)
@@ -1991,7 +1991,7 @@
@x = @l_margin;
@y += h;
w=@w - @r_margin - @x;
- wmax=(w - 2 * @c_margin);
+ wmax=(w - 3 * @c_margin);
i += 1
nl += 1
next
@@ -2010,7 +2010,7 @@
if (nl==1)
@x = @l_margin;
w = @w - @r_margin - @x;
- wmax = (w - 2 * @c_margin);
+ wmax = (w - 3 * @c_margin);
end
nl += 1;
else
@@ -3474,7 +3474,7 @@
#Extract attributes
# get tag name
tag = element.scan(/([a-zA-Z0-9]*)/).flatten.delete_if {|x| x.length == 0}
- tag = tag[0].downcase;
+ tag = tag[0].to_s.downcase;
# get attributes
attr_array = element.scan(/([^=\s]*)=["\']?([^"\']*)["\']?/)
@@ -3497,7 +3497,7 @@
#Extract attributes
# get tag name
tag = element.scan(/([a-zA-Z0-9]*)/).flatten.delete_if {|x| x.length == 0}
- tag = tag[0].downcase;
+ tag = tag[0].to_s.downcase;
# get attributes
attr_array = element.scan(/([^=\s]*)=["\']?([^"\']*)["\']?/)