Feature #24013 » issue-24013-r16009-misc.diff
| app/controllers/application_controller.rb | ||
|---|---|---|
| 170 | 170 |
if User.current.logged? |
| 171 | 171 |
cookies.delete(autologin_cookie_name) |
| 172 | 172 |
Token.where(["user_id = ? AND action = ?", User.current.id, 'autologin']).delete_all |
| 173 |
Token.where(["user_id = ? AND action = ? AND value = ?", User.current.id, 'session', session[:tk]]).delete_all
|
|
| 173 |
Token.where(["user_id = ? AND action = ?", User.current.id, 'session']).where(:value => session[:tk]).delete_all
|
|
| 174 | 174 |
self.logged_user = nil |
| 175 | 175 |
end |
| 176 | 176 |
end |
| app/controllers/versions_controller.rb | ||
|---|---|---|
| 50 | 50 |
includes(:project, :tracker). |
| 51 | 51 |
preload(:status, :priority, :fixed_version). |
| 52 | 52 |
where(:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)). |
| 53 |
order("#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
|
|
| 53 |
order("#{Project.table_name}.lft, #{Tracker.table_name}.#{'position'.quote_column_name}, #{Issue.table_name}.id")
|
|
| 54 | 54 |
@issues_by_version = issues.group_by(&:fixed_version) |
| 55 | 55 |
end |
| 56 | 56 |
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
|
| ... | ... | |
| 67 | 67 |
@issues = @version.fixed_issues.visible. |
| 68 | 68 |
includes(:status, :tracker, :priority). |
| 69 | 69 |
preload(:project). |
| 70 |
reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
|
|
| 70 |
reorder("#{Issue.table_name}.id").
|
|
| 71 | 71 |
to_a |
| 72 | 72 |
} |
| 73 | 73 |
format.api |
| app/models/project.rb | ||
|---|---|---|
| 44 | 44 |
has_many :documents, :dependent => :destroy |
| 45 | 45 |
has_many :news, lambda {includes(:author)}, :dependent => :destroy
|
| 46 | 46 |
has_many :issue_categories, lambda {order("#{IssueCategory.table_name}.name")}, :dependent => :delete_all
|
| 47 |
has_many :boards, lambda {order("position ASC")}, :dependent => :destroy
|
|
| 47 |
has_many :boards, lambda { order(:position) }, :dependent => :destroy
|
|
| 48 | 48 |
has_one :repository, lambda {where(["is_default = ?", true])}
|
| 49 | 49 |
has_many :repositories, :dependent => :destroy |
| 50 | 50 |
has_many :changesets, :through => :repository |
| 51 | 51 |
has_one :wiki, :dependent => :destroy |
| 52 | 52 |
# Custom field for the project issues |
| 53 | 53 |
has_and_belongs_to_many :issue_custom_fields, |
| 54 |
lambda {order("#{CustomField.table_name}.position")},
|
|
| 54 |
lambda { order("#{CustomField.table_name}.#{'position'.quote_column_name}") },
|
|
| 55 | 55 |
:class_name => 'IssueCustomField', |
| 56 | 56 |
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
|
| 57 | 57 |
:association_foreign_key => 'custom_field_id' |
| app/models/query.rb | ||
|---|---|---|
| 824 | 824 | |
| 825 | 825 |
def sql_for_custom_field(field, operator, value, custom_field_id) |
| 826 | 826 |
db_table = CustomValue.table_name |
| 827 |
db_field = 'value' |
|
| 827 |
db_field = 'value'.quote_column_name
|
|
| 828 | 828 |
filter = @available_filters[field] |
| 829 | 829 |
return nil unless filter |
| 830 | 830 |
if filter[:field].format.target_class && filter[:field].format.target_class <= User |
| ... | ... | |
| 869 | 869 |
int_values = value.first.to_s.scan(/[+-]?\d+/).map(&:to_i).join(",")
|
| 870 | 870 |
if int_values.present? |
| 871 | 871 |
if is_custom_filter |
| 872 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) IN (#{int_values}))"
|
|
| 872 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) IN (#{int_values}))"
|
|
| 873 | 873 |
else |
| 874 | 874 |
sql = "#{db_table}.#{db_field} IN (#{int_values})"
|
| 875 | 875 |
end |
| ... | ... | |
| 878 | 878 |
end |
| 879 | 879 |
when :float |
| 880 | 880 |
if is_custom_filter |
| 881 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5})"
|
|
| 881 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5})"
|
|
| 882 | 882 |
else |
| 883 | 883 |
sql = "#{db_table}.#{db_field} BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5}"
|
| 884 | 884 |
end |
| ... | ... | |
| 907 | 907 |
sql = date_clause(db_table, db_field, parse_date(value.first), nil, is_custom_filter) |
| 908 | 908 |
else |
| 909 | 909 |
if is_custom_filter |
| 910 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) >= #{value.first.to_f})"
|
|
| 910 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) >= #{value.first.to_f})"
|
|
| 911 | 911 |
else |
| 912 | 912 |
sql = "#{db_table}.#{db_field} >= #{value.first.to_f}"
|
| 913 | 913 |
end |
| ... | ... | |
| 917 | 917 |
sql = date_clause(db_table, db_field, nil, parse_date(value.first), is_custom_filter) |
| 918 | 918 |
else |
| 919 | 919 |
if is_custom_filter |
| 920 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) <= #{value.first.to_f})"
|
|
| 920 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) <= #{value.first.to_f})"
|
|
| 921 | 921 |
else |
| 922 | 922 |
sql = "#{db_table}.#{db_field} <= #{value.first.to_f}"
|
| 923 | 923 |
end |
| ... | ... | |
| 927 | 927 |
sql = date_clause(db_table, db_field, parse_date(value[0]), parse_date(value[1]), is_custom_filter) |
| 928 | 928 |
else |
| 929 | 929 |
if is_custom_filter |
| 930 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) BETWEEN #{value[0].to_f} AND #{value[1].to_f})"
|
|
| 930 |
sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) BETWEEN #{value[0].to_f} AND #{value[1].to_f})"
|
|
| 931 | 931 |
else |
| 932 | 932 |
sql = "#{db_table}.#{db_field} BETWEEN #{value[0].to_f} AND #{value[1].to_f}"
|
| 933 | 933 |
end |
| ... | ... | |
| 1079 | 1079 |
s = [] |
| 1080 | 1080 |
if from |
| 1081 | 1081 |
if from.is_a?(Date) |
| 1082 |
from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day |
|
| 1082 |
if Redmine::Database.firebird? |
|
| 1083 |
from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day.to_date |
|
| 1084 |
else |
|
| 1085 |
from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day |
|
| 1086 |
end |
|
| 1083 | 1087 |
else |
| 1084 | 1088 |
from = from - 1 # second |
| 1085 | 1089 |
end |
| ... | ... | |
| 1090 | 1094 |
end |
| 1091 | 1095 |
if to |
| 1092 | 1096 |
if to.is_a?(Date) |
| 1093 |
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day |
|
| 1097 |
if Redmine::Database.firebird? |
|
| 1098 |
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day.to_date |
|
| 1099 |
else |
|
| 1100 |
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day |
|
| 1101 |
end |
|
| 1094 | 1102 |
end |
| 1095 | 1103 |
if self.class.default_timezone == :utc |
| 1096 | 1104 |
to = to.utc |
| app/models/repository.rb | ||
|---|---|---|
| 422 | 422 |
# Notes: |
| 423 | 423 |
# - this hash honnors the users mapping defined for the repository |
| 424 | 424 |
def stats_by_author |
| 425 |
commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
|
|
| 425 |
commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as commit_count").group("committer, user_id")
|
|
| 426 | 426 | |
| 427 | 427 |
#TODO: restore ordering ; this line probably never worked |
| 428 | 428 |
#commits.to_a.sort! {|x, y| x.last <=> y.last}
|
| 429 | 429 | |
| 430 |
changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
|
|
| 430 |
changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as commit_count").group("committer, user_id")
|
|
| 431 | 431 | |
| 432 | 432 |
user_ids = changesets.map(&:user_id).compact.uniq |
| 433 | 433 |
authors_names = User.where(:id => user_ids).inject({}) do |memo, user|
|
| ... | ... | |
| 442 | 442 |
end |
| 443 | 443 |
hash[mapped_name] ||= { :commits_count => 0, :changes_count => 0 }
|
| 444 | 444 |
if element.is_a?(Changeset) |
| 445 |
hash[mapped_name][:commits_count] += element.count.to_i |
|
| 445 |
hash[mapped_name][:commits_count] += element.commit_count.to_i
|
|
| 446 | 446 |
else |
| 447 |
hash[mapped_name][:changes_count] += element.count.to_i |
|
| 447 |
hash[mapped_name][:changes_count] += element.commit_count.to_i
|
|
| 448 | 448 |
end |
| 449 | 449 |
hash |
| 450 | 450 |
end |
| app/models/user.rb | ||
|---|---|---|
| 684 | 684 |
# Returns true if the user is allowed to delete the user's own account |
| 685 | 685 |
def own_account_deletable? |
| 686 | 686 |
Setting.unsubscribe? && |
| 687 |
(!admin? || User.active.where("admin = ? AND id <> ?", true, id).exists?)
|
|
| 687 |
(!admin? || User.active.where("id <> ?", id).where(:admin => true).exists?)
|
|
| 688 | 688 |
end |
| 689 | 689 | |
| 690 | 690 |
safe_attributes 'firstname', |
| ... | ... | |
| 821 | 821 |
where(["property = 'attr' AND prop_key = 'assigned_to_id' AND old_value = ?", id.to_s]). |
| 822 | 822 |
update_all(['old_value = ?', substitute.id.to_s]) |
| 823 | 823 |
JournalDetail. |
| 824 |
where(["property = 'attr' AND prop_key = 'assigned_to_id' AND value = ?", id.to_s]). |
|
| 825 |
update_all(['value = ?', substitute.id.to_s]) |
|
| 824 |
where(["property = 'attr' AND prop_key = 'assigned_to_id'"]). |
|
| 825 |
where(:value => id.to_s). |
|
| 826 |
update_all(:value => substitute.id.to_s) |
|
| 826 | 827 |
Message.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
| 827 | 828 |
News.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
| 828 | 829 |
# Remove private queries and keep public ones |
| lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb | ||
|---|---|---|
| 27 | 27 |
return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods) |
| 28 | 28 |
cattr_accessor :customizable_options |
| 29 | 29 |
self.customizable_options = options |
| 30 |
has_many :custom_values, lambda {includes(:custom_field).order("#{CustomField.table_name}.position")},
|
|
| 30 |
has_many :custom_values, lambda {joins(:custom_field).merge(CustomField.order(:position))},
|
|
| 31 | 31 |
:as => :customized, |
| 32 | 32 |
:dependent => :delete_all, |
| 33 | 33 |
:validate => false |
| lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb | ||
|---|---|---|
| 1 | 1 |
module OpenIdAuthentication |
| 2 | 2 |
class Association < ActiveRecord::Base |
| 3 |
self.table_name = :open_id_authentication_associations
|
|
| 3 |
self.table_name = :open_id_auth_associations |
|
| 4 | 4 | |
| 5 | 5 |
def from_record |
| 6 | 6 |
OpenID::Association.new(handle, secret, issued, lifetime, assoc_type) |
| lib/redmine/database.rb | ||
|---|---|---|
| 49 | 49 |
(ActiveRecord::Base.connection.adapter_name =~ /mysql/i).present? |
| 50 | 50 |
end |
| 51 | 51 | |
| 52 |
# Returns +true+ if the database is Firebird or RedDatabase |
|
| 53 |
def firebird? |
|
| 54 |
(ActiveRecord::Base.connection.adapter_name =~ /fb/i).present? |
|
| 55 |
end |
|
| 56 | ||
| 52 | 57 |
# Returns a SQL statement for case/accent (if possible) insensitive match |
| 53 | 58 |
def like(left, right, options={})
|
| 54 | 59 |
neg = (options[:match] == false ? 'NOT ' : '') |
| lib/redmine/field_format.rb | ||
|---|---|---|
| 294 | 294 |
# Returns nil if the custom field can not be used for sorting. |
| 295 | 295 |
def order_statement(custom_field) |
| 296 | 296 |
# COALESCE is here to make sure that blank and NULL values are sorted equally |
| 297 |
"COALESCE(#{join_alias custom_field}.value, '')"
|
|
| 297 |
"COALESCE(#{join_alias custom_field}.#{value_column}, '')"
|
|
| 298 | 298 |
end |
| 299 | 299 | |
| 300 | 300 |
# Returns a GROUP BY clause that can used to group by custom value |
| ... | ... | |
| 312 | 312 |
" AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" +
|
| 313 | 313 |
" AND #{alias_name}.custom_field_id = #{custom_field.id}" +
|
| 314 | 314 |
" AND (#{custom_field.visibility_by_project_condition})" +
|
| 315 |
" AND #{alias_name}.value <> ''" +
|
|
| 315 |
" AND #{alias_name}.#{value_column} <> ''" +
|
|
| 316 | 316 |
" AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" +
|
| 317 | 317 |
" WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" +
|
| 318 | 318 |
" AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" +
|
| ... | ... | |
| 322 | 322 |
def join_alias(custom_field) |
| 323 | 323 |
"cf_#{custom_field.id}"
|
| 324 | 324 |
end |
| 325 | ||
| 326 |
def value_column |
|
| 327 |
'value'.quote_column_name |
|
| 328 |
end |
|
| 325 | 329 |
protected :join_alias |
| 326 | 330 |
end |
| 327 | 331 | |
| ... | ... | |
| 431 | 435 |
# Make the database cast values into numeric |
| 432 | 436 |
# Postgresql will raise an error if a value can not be casted! |
| 433 | 437 |
# CustomValue validations should ensure that it doesn't occur |
| 434 |
"CAST(CASE #{join_alias custom_field}.value WHEN '' THEN '0' ELSE #{join_alias custom_field}.value END AS decimal(30,3))"
|
|
| 438 |
"CAST(CASE #{join_alias custom_field}.#{value_column} WHEN '' THEN '0' ELSE #{join_alias custom_field}.#{value_column} END AS decimal(18,3))"
|
|
| 435 | 439 |
end |
| 436 | 440 | |
| 437 | 441 |
# Returns totals for the given scope |
| ... | ... | |
| 439 | 443 |
scope.joins(:custom_values). |
| 440 | 444 |
where(:custom_values => {:custom_field_id => custom_field.id}).
|
| 441 | 445 |
where.not(:custom_values => {:value => ''}).
|
| 442 |
sum("CAST(#{CustomValue.table_name}.value AS decimal(30,3))")
|
|
| 446 |
sum("CAST(#{CustomValue.table_name}.#{value_column} AS decimal(18,3))")
|
|
| 443 | 447 |
end |
| 444 | 448 | |
| 445 | 449 |
def cast_total_value(custom_field, value) |
| ... | ... | |
| 719 | 723 |
end |
| 720 | 724 | |
| 721 | 725 |
def group_statement(custom_field) |
| 722 |
"COALESCE(#{join_alias custom_field}.value, '')"
|
|
| 726 |
"COALESCE(#{join_alias custom_field}.#{value_column}, '')"
|
|
| 723 | 727 |
end |
| 724 | 728 | |
| 725 | 729 |
def join_for_order_statement(custom_field) |
| ... | ... | |
| 730 | 734 |
" AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" +
|
| 731 | 735 |
" AND #{alias_name}.custom_field_id = #{custom_field.id}" +
|
| 732 | 736 |
" AND (#{custom_field.visibility_by_project_condition})" +
|
| 733 |
" AND #{alias_name}.value <> ''" +
|
|
| 737 |
" AND #{alias_name}.#{value_column} <> ''" +
|
|
| 734 | 738 |
" AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" +
|
| 735 | 739 |
" WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" +
|
| 736 | 740 |
" AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" +
|
| 737 | 741 |
" AND #{alias_name}_2.custom_field_id = #{alias_name}.custom_field_id)" +
|
| 738 | 742 |
" LEFT OUTER JOIN #{target_class.table_name} #{value_join_alias custom_field}" +
|
| 739 |
" ON CAST(CASE #{alias_name}.value WHEN '' THEN '0' ELSE #{alias_name}.value END AS decimal(30,0)) = #{value_join_alias custom_field}.id"
|
|
| 743 |
" ON CAST(CASE #{alias_name}.#{value_column} WHEN '' THEN '0' ELSE #{alias_name}.#{value_column} END AS decimal(18,0)) = #{value_join_alias custom_field}.id"
|
|
| 740 | 744 |
end |
| 741 | 745 | |
| 742 | 746 |
def value_join_alias(custom_field) |
| lib/tasks/migrate_from_mantis.rake | ||
|---|---|---|
| 52 | 52 |
TRACKER_BUG = Tracker.find_by_position(1) |
| 53 | 53 |
TRACKER_FEATURE = Tracker.find_by_position(2) |
| 54 | 54 | |
| 55 |
roles = Role.where(:builtin => 0).order('position ASC').all
|
|
| 55 |
roles = Role.where(:builtin => 0).order(:position).all
|
|
| 56 | 56 |
manager_role = roles[0] |
| 57 | 57 |
developer_role = roles[1] |
| 58 | 58 |
DEFAULT_ROLE = roles.last |
| lib/tasks/migrate_from_trac.rake | ||
|---|---|---|
| 60 | 60 |
'patch' =>TRACKER_FEATURE |
| 61 | 61 |
} |
| 62 | 62 | |
| 63 |
roles = Role.where(:builtin => 0).order('position ASC').all
|
|
| 63 |
roles = Role.where(:builtin => 0).order(:position).all
|
|
| 64 | 64 |
manager_role = roles[0] |
| 65 | 65 |
developer_role = roles[1] |
| 66 | 66 |
DEFAULT_ROLE = roles.last |
| test/unit/user_test.rb | ||
|---|---|---|
| 1051 | 1051 |
end |
| 1052 | 1052 | |
| 1053 | 1053 |
def test_own_account_deletable_should_be_false_for_a_single_admin |
| 1054 |
User.where(["admin = ? AND id <> ?", true, 1]).delete_all
|
|
| 1054 |
User.where(["id <> ?", 1]).where(:admin => true).delete_all
|
|
| 1055 | 1055 | |
| 1056 | 1056 |
with_settings :unsubscribe => '1' do |
| 1057 | 1057 |
assert_equal false, User.find(1).own_account_deletable? |