Mercurial > hg > soundsoftware-site
changeset 929:5f33065ddc4b redmine-1.3
Update to Redmine SVN rev 9414 on 1.3-stable branch
line wrap: on
line diff
--- a/app/controllers/admin_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/admin_controller.rb Wed Jun 27 14:54:18 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)]
--- a/app/controllers/boards_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/boards_controller.rb Wed Jun 27 14:54:18 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
--- a/app/controllers/comments_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/comments_controller.rb Wed Jun 27 14:54:18 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)
--- a/app/controllers/documents_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/documents_controller.rb Wed Jun 27 14:54:18 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
--- a/app/controllers/issue_categories_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/issue_categories_controller.rb Wed Jun 27 14:54:18 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)
--- a/app/controllers/members_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/members_controller.rb Wed Jun 27 14:54:18 2012 +0100 @@ -28,10 +28,10 @@ attrs = params[:member].dup if (user_ids = attrs.delete(:user_ids)) user_ids.each do |user_id| - members << Member.new(attrs.merge(:user_id => user_id)) + members << Member.new(:role_ids => params[:member][:role_ids], :user_id => user_id) end else - members << Member.new(attrs) + members << Member.new(:role_ids => params[:member][:role_ids], :user_id => params[:member][:user_id]) end @project.members << members end @@ -64,7 +64,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 :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project } format.js { @@ -93,7 +96,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) render :layout => false end
--- a/app/controllers/messages_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/messages_controller.rb Wed Jun 27 14:54:18 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)
--- a/app/controllers/news_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/news_controller.rb Wed Jun 27 14:54:18 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
--- a/app/controllers/projects_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/projects_controller.rb Wed Jun 27 14:54:18 2012 +0100 @@ -66,7 +66,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 }
--- a/app/controllers/timelog_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/timelog_controller.rb Wed Jun 27 14:54:18 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
--- a/app/controllers/versions_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/versions_controller.rb Wed Jun 27 14:54:18 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)
--- a/app/controllers/wikis_controller.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/controllers/wikis_controller.rb Wed Jun 27 14:54:18 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
--- a/app/helpers/application_helper.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/helpers/application_helper.rb Wed Jun 27 14:54:18 2012 +0100 @@ -490,12 +490,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) @@ -778,6 +782,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] "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a></h#{level}>" end
--- a/app/models/board.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/board.rb Wed Jun 27 14:54:18 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
--- a/app/models/changeset.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/changeset.rb Wed Jun 27 14:54:18 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?
--- a/app/models/comment.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/comment.rb Wed Jun 27 14:54:18 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
--- a/app/models/document.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/document.rb Wed Jun 27 14:54:18 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
--- a/app/models/issue_category.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/issue_category.rb Wed Jun 27 14:54:18 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]}}
--- a/app/models/mailer.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/mailer.rb Wed Jun 27 14:54:18 2012 +0100 @@ -354,7 +354,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
--- a/app/models/member.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/member.rb Wed Jun 27 14:54:18 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?
--- a/app/models/message.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/message.rb Wed Jun 27 14:54:18 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
--- a/app/models/news.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/news.rb Wed Jun 27 14:54:18 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
--- a/app/models/principal.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/principal.rb Wed Jun 27 14:54:18 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
--- a/app/models/project.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/project.rb Wed Jun 27 14:54:18 2012 +0100 @@ -253,7 +253,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? @@ -390,16 +390,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
--- a/app/models/time_entry.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/time_entry.rb Wed Jun 27 14:54:18 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
--- a/app/models/user.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/user.rb Wed Jun 27 14:54:18 2012 +0100 @@ -343,6 +343,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
--- a/app/models/user_preference.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/user_preference.rb Wed Jun 27 14:54:18 2012 +0100 @@ -19,7 +19,7 @@ belongs_to :user serialize :others - attr_protected :others + attr_protected :others, :user_id def initialize(attributes = nil) super
--- a/app/models/version.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/version.rb Wed Jun 27 14:54:18 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)
--- a/app/models/wiki.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/models/wiki.rb Wed Jun 27 14:54:18 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
--- a/app/views/issues/_relations.html.erb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/views/issues/_relations.html.erb Wed Jun 27 14:54:18 2012 +0100 @@ -20,7 +20,8 @@ <td class="start_date"><%= format_date(relation.other_issue(@issue).start_date) %></td> <td class="due_date"><%= format_date(relation.other_issue(@issue).due_date) %></td> <td class="buttons"><%= 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') %></td> </tr> <% end %>
--- a/app/views/projects/settings/_members.html.erb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/views/projects/settings/_members.html.erb Wed Jun 27 14:54:18 2012 +0100 @@ -50,7 +50,7 @@ <% end %> </div> -<% 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') %> <div class="splitcontentright"> <% if roles.any? && principals.any? %>
--- a/app/views/projects/settings/_repository.html.erb Fri Feb 24 19:09:32 2012 +0000 +++ b/app/views/projects/settings/_repository.html.erb Wed Jun 27 14:54:18 2012 +0100 @@ -10,7 +10,7 @@ <%= label_tag('repository_scm', l(:label_scm)) %><%= scm_select_tag(@repository) %> <% if @repository && ! @repository.class.scm_available %> <br /> - <em><%= content_tag 'span', l(:text_scm_command_not_available), :class => 'error' %></em> + <em class="info error"><%= content_tag 'span', l(:text_scm_command_not_available) %></em> <% end %> </p> <% button_disabled = true %>
--- a/config/locales/it.yml Fri Feb 24 19:09:32 2012 +0000 +++ b/config/locales/it.yml Wed Jun 27 14:54:18 2012 +0100 @@ -979,7 +979,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
--- a/config/locales/nl.yml Fri Feb 24 19:09:32 2012 +0000 +++ b/config/locales/nl.yml Wed Jun 27 14:54:18 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
--- a/config/locales/zh.yml Fri Feb 24 19:09:32 2012 +0000 +++ b/config/locales/zh.yml Wed Jun 27 14:54:18 2012 +0100 @@ -1002,9 +1002,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})
--- a/doc/CHANGELOG Fri Feb 24 19:09:32 2012 +0000 +++ b/doc/CHANGELOG Wed Jun 27 14:54:18 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..
--- a/extra/svn/Redmine.pm Fri Feb 24 19:09:32 2012 +0000 +++ b/extra/svn/Redmine.pm Wed Jun 27 14:54:18 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;
--- a/lib/redmine/unified_diff.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/lib/redmine/unified_diff.rb Wed Jun 27 14:54:18 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, '<span>').insert(offsets.last, '</span>') - else - line_left - end + line_to_html(line_left, offsets) end def html_line_right - if offsets - line_right.dup.insert(offsets.first, '<span>').insert(offsets.last, '</span>') - else - line_right - end + line_to_html(line_right, offsets) end def html_line - if offsets - line.dup.insert(offsets.first, '<span>').insert(offsets.last, '</span>') - 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 << '<span>' + CGI.escapeHTML(line[offsets.first..offsets.last]) + '</span>' + unless offsets.last == -1 + s << CGI.escapeHTML(line[offsets.last+1..-1]) + end + s + else + CGI.escapeHTML(line) + end + end end end
--- a/lib/redmine/version.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/lib/redmine/version.rb Wed Jun 27 14:54:18 2012 +0100 @@ -4,7 +4,7 @@ module VERSION #:nodoc: MAJOR = 1 MINOR = 3 - TINY = 1 + TINY = 3 # Branch values: # * official release: nil
--- a/public/stylesheets/application.css Fri Feb 24 19:09:32 2012 +0000 +++ b/public/stylesheets/application.css Wed Jun 27 14:54:18 2012 +0100 @@ -481,6 +481,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% } @@ -534,8 +537,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; }
--- a/test/functional/boards_controller_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/functional/boards_controller_test.rb Wed Jun 27 14:54:18 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
--- a/test/functional/issues_controller_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/functional/issues_controller_test.rb Wed Jun 27 14:54:18 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'] }, - '<t+2' => { :op => '=', :values => ['<t+2'] }, - '>t+2' => { :op => '=', :values => ['>t+2'] }, - 't+2' => { :op => 't', :values => ['+2'] }}, + '<t-2' => { :op => '<t-', :values => ['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
--- a/test/functional/messages_controller_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/functional/messages_controller_test.rb Wed Jun 27 14:54:18 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' }
--- a/test/functional/project_enumerations_controller_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/functional/project_enumerations_controller_test.rb Wed Jun 27 14:54:18 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'
--- a/test/functional/trackers_controller_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/functional/trackers_controller_test.rb Wed Jun 27 14:54:18 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
--- a/test/unit/changeset_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/changeset_test.rb Wed Jun 27 14:54:18 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
--- a/test/unit/helpers/application_helper_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/helpers/application_helper_test.rb Wed Jun 27 14:54:18 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 @@ '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' + '<ul>' + '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' + + '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' + '</ul>' + '</li>' + '</ul>' + @@ -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 = '<ul class="toc">' + + '<li><a href="#Title">Title</a>' + + '<ul>' + + '<li><a href="#Subtitle">Subtitle</a></li>' + + '<li><a href="#Subtitle-2">Subtitle</a></li>' + '</ul>' + '</li>' + + '</ul>' + + @project = Project.find(1) + result = textilizable(raw).gsub("\n", "") + assert_include expected, result + assert_include '<a name="Subtitle">', result + assert_include '<a name="Subtitle-2">', 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@ + +<pre> +some code + +h2. heading inside pre + +<h2>html heading inside pre</h2> +</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('<div class="contextual" title="Edit this section">' + + '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' + + '<a name="Subtitle-with-inline-code"></a>' + + '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">¶</a></h2>'), + result + + # last heading + assert_match Regexp.new('<div class="contextual" title="Edit this section">' + + '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' + + '<a name="Subtitle-after-pre-tag"></a>' + + '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">¶</a></h2>'), + 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 '<a href="/projects/1">eCookbook</a>', + link_to_project(Project.find(1)) + end + def test_principals_options_for_select_with_users users = [User.find(2), User.find(4)] assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
--- a/test/unit/lib/redmine/unified_diff_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/lib/redmine/unified_diff_test.rb Wed Jun 27 14:54:18 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<MyClass> myObj) ++void DoSomething(const MyClass& myObj) + +DIFF + + diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs') + assert_equal 1, diff.size + assert_equal 'void DoSomething(<span>std::auto_ptr<MyClass></span> myObj)', diff.first[2].html_line_left + assert_equal 'void DoSomething(<span>const MyClass&</span> myObj)', diff.first[2].html_line_right + + diff = Redmine::UnifiedDiff.new(raw, :type => 'inline') + assert_equal 1, diff.size + assert_equal 'void DoSomething(<span>std::auto_ptr<MyClass></span> myObj)', diff.first[2].html_line + assert_equal 'void DoSomething(<span>const MyClass&</span> 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
--- a/test/unit/mailer_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/mailer_test.rb Wed Jun 27 14:54:18 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
--- a/test/unit/member_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/member_test.rb Wed Jun 27 14:54:18 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")
--- a/test/unit/news_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/news_test.rb Wed Jun 27 14:54:18 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
--- a/test/unit/principal_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/principal_test.rb Wed Jun 27 14:54:18 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
--- a/test/unit/project_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/project_test.rb Wed Jun 27 14:54:18 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')
--- a/test/unit/user_test.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/test/unit/user_test.rb Wed Jun 27 14:54:18 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))
--- a/vendor/gems/rubytree-0.5.2/.specification Fri Feb 24 19:09:32 2012 +0000 +++ b/vendor/gems/rubytree-0.5.2/.specification Wed Jun 27 14:54:18 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: []
--- a/vendor/plugins/rfpdf/lib/tcpdf.rb Fri Feb 24 19:09:32 2012 +0000 +++ b/vendor/plugins/rfpdf/lib/tcpdf.rb Wed Jun 27 14:54:18 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]*)=["\']?([^"\']*)["\']?/)