Class: UserQuery

Inherits:
Query show all
Defined in:
app/models/user_query.rb

Overview

Redmine - project management software Copyright © 2006- Jean-Philippe Lang

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software

Constant Summary

Constants inherited from Query

Query::VISIBILITY_PRIVATE, Query::VISIBILITY_PUBLIC, Query::VISIBILITY_ROLES

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Query

add_available_column, #add_available_filter, #add_filter, #add_filter_error, #add_filters, #add_short_filter, #all_projects, #all_projects_values, #as_params, #assigned_to_values, #author_values, #available_block_columns, #available_display_types, #available_filters, #available_filters_as_json, #available_inline_columns, #available_totalable_columns, #block_columns, build_from_params, #build_from_params, #column_names=, #columns, #css_classes, default, #default_display_type, #default_totalable_names, #delete_available_filter, #display_type, #display_type=, #fixed_version_values, #group_by_column, #group_by_sort_order, #group_by_statement, #groupable_columns, #grouped?, #has_column?, #has_custom_field_column?, #has_default_columns?, #has_filter?, #inline_columns, #is_global?, #is_private?, #is_public?, #issue_custom_fields, #issue_statuses_values, #label_for, #operator_for, operators_labels, #principals, #project_custom_fields, #project_statement, #project_statuses_values, #project_values, #queried_table_name, #result_count_by_group, #sort_clause, #sort_criteria, #sort_criteria=, #sort_criteria_key, #sort_criteria_order, #sortable_columns, #statement, #subproject_values, #time_entry_custom_fields, #total_by_group_for, #total_for, #totalable_columns, #totalable_names, #totalable_names=, #totals, #totals_by_group, #trackers, #type_for, #users, #validate_query_filters, #value_for, #values_for, #watcher_values

Methods included from Redmine::SubclassFactory

included

Methods inherited from ApplicationRecord

human_attribute_name

Constructor Details

#initialize(attributes = nil, *args) ⇒ UserQuery

Returns a new instance of UserQuery.



46
47
48
49
# File 'app/models/user_query.rb', line 46

def initialize(attributes=nil, *args)
  super(attributes)
  self.filters ||= { 'status' => {operator: "=", values: [User::STATUS_ACTIVE]} }
end

Class Method Details

.visible(*args) ⇒ Object



37
38
39
40
41
42
43
44
# File 'app/models/user_query.rb', line 37

def self.visible(*args)
  user = args.shift || User.current
  if user.admin?
    where('1=1')
  else
    where('1=0')
  end
end

Instance Method Details

#auth_sources_valuesObject



85
86
87
# File 'app/models/user_query.rb', line 85

def auth_sources_values
  AuthSource.order(name: :asc).pluck(:name, :id)
end

#available_columnsObject



97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/models/user_query.rb', line 97

def available_columns
  return @available_columns if @available_columns

  @available_columns = self.class.available_columns.dup
  if Setting.twofa?
    @available_columns << QueryColumn.new(:twofa_scheme, sortable: "#{User.table_name}.twofa_scheme")
  end
  @available_columns += user_custom_fields.visible.
                          map {|cf| QueryCustomFieldColumn.new(cf)}

  @available_columns
end

#base_scopeObject



123
124
125
# File 'app/models/user_query.rb', line 123

def base_scope
  User.logged.where(statement).includes(:email_address)
end

#default_columns_namesObject



115
116
117
# File 'app/models/user_query.rb', line 115

def default_columns_names
  @default_columns_names ||= [:login, :firstname, :lastname, :mail, :admin, :created_on, :last_login_on]
end

#default_sort_criteriaObject



119
120
121
# File 'app/models/user_query.rb', line 119

def default_sort_criteria
  [['login', 'asc']]
end

#editable_by?(user) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
# File 'app/models/user_query.rb', line 81

def editable_by?(user)
  user&.admin?
end

#initialize_available_filtersObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/models/user_query.rb', line 51

def initialize_available_filters
  add_available_filter "status",
    type: :list_optional, values: ->{ user_statuses_values }
  add_available_filter "auth_source_id",
    type: :list_optional, values: ->{ auth_sources_values }
  add_available_filter "is_member_of_group",
    type: :list_optional,
    values: ->{ Group.givable.visible.pluck(:name, :id).map {|name, id| [name, id.to_s]} }
  if Setting.twofa?
    add_available_filter "twofa_scheme",
      type: :list_optional,
      values: ->{ Redmine::Twofa.available_schemes.map {|s| [I18n.t("twofa__#{s}__name"), s] } }
  end
  add_available_filter "name", type: :text, label: :field_name_or_email_or_login
  add_available_filter "login", type: :string
  add_available_filter "firstname", type: :string
  add_available_filter "lastname", type: :string
  add_available_filter "mail", type: :string
  add_available_filter "created_on", type: :date_past
  add_available_filter "last_login_on", type: :date_past
  add_available_filter "admin",
    type: :list,
    values: [[l(:general_text_yes), '1'], [l(:general_text_no), '0']]
  add_custom_fields_filters(user_custom_fields)
end

#joins_for_order_statement(order_options) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
# File 'app/models/user_query.rb', line 174

def joins_for_order_statement(order_options)
  joins = [super]

  if order_options
    if order_options.include?('auth_source')
      joins << "LEFT OUTER JOIN #{AuthSource.table_name} auth_sources ON auth_sources.id = #{queried_table_name}.auth_source_id"
    end
  end

  joins.any? ? joins.join(' ') : nil
end

#results_scope(options = {}) ⇒ Object



127
128
129
130
131
132
133
# File 'app/models/user_query.rb', line 127

def results_scope(options={})
  order_option = [group_by_sort_order, (options[:order] || sort_clause)].flatten.reject(&:blank?)

  base_scope.
    order(order_option).
    joins(joins_for_order_statement(order_option.join(',')))
end

#sql_for_admin_field(field, operator, value) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
# File 'app/models/user_query.rb', line 135

def sql_for_admin_field(field, operator, value)
  return unless value = value.first

  true_value = operator == '=' ? '1' : '0'
  val =
    if value.to_s == true_value
      self.class.connection.quoted_true
    else
      self.class.connection.quoted_false
    end
  "(#{User.table_name}.admin = #{val})"
end

#sql_for_is_member_of_group_field(field, operator, value) ⇒ Object



148
149
150
151
152
153
154
155
156
# File 'app/models/user_query.rb', line 148

def sql_for_is_member_of_group_field(field, operator, value)
  if ["*", "!*"].include? operator
    value = Group.givable.ids
  end

  e = operator.start_with?("!") ? "NOT EXISTS" : "EXISTS"

  "(#{e} (SELECT 1 FROM groups_users WHERE #{User.table_name}.id = groups_users.user_id AND #{sql_for_field(field, '=', value, 'groups_users', 'group_id')}))"
end

#sql_for_mail_field(field, operator, value) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'app/models/user_query.rb', line 158

def sql_for_mail_field(field, operator, value)
  if operator == '!*'
    match = false
    operator = '*'
  else
    match = true
  end
  emails = EmailAddress.table_name
  <<-SQL
    #{match ? 'EXISTS' : 'NOT EXISTS'}
    (SELECT 1 FROM #{emails} WHERE
      #{emails}.user_id = #{User.table_name}.id AND
      #{sql_for_field(:mail, operator, value, emails, 'address')})
  SQL
end

#sql_for_name_field(field, operator, value) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'app/models/user_query.rb', line 186

def sql_for_name_field(field, operator, value)
  case operator
  when '*'
    '1=1'
  when '!*'
    '1=0'
  else
    # match = (operator == '~')
    match = !operator.start_with?('!')
    matching_operator = operator.sub /^!/, ''
    name_sql = %w(login firstname lastname).map{|field| sql_for_field(:name, operator, value, User.table_name, field)}

    emails = EmailAddress.table_name
    email_sql = <<-SQL
      #{match ? "EXISTS" : "NOT EXISTS"}
      (SELECT 1 FROM #{emails} WHERE
        #{emails}.user_id = #{User.table_name}.id AND
        #{sql_for_field(:name, matching_operator, value, emails, 'address')})
    SQL

    conditions = name_sql + [email_sql]
    op = match ? " OR " : " AND "
    "(#{conditions.map{|s| "(#{s})"}.join(op)})"
  end
end

#user_custom_fieldsObject

Returns a scope of user custom fields that are available as columns or filters



111
112
113
# File 'app/models/user_query.rb', line 111

def user_custom_fields
  UserCustomField.sorted
end

#user_statuses_valuesObject



89
90
91
92
93
94
95
# File 'app/models/user_query.rb', line 89

def user_statuses_values
  [
    [l(:status_active), User::STATUS_ACTIVE.to_s],
    [l(:status_registered), User::STATUS_REGISTERED.to_s],
    [l(:status_locked), User::STATUS_LOCKED.to_s]
  ]
end

#visible?(user = User.current) ⇒ Boolean

Returns:

  • (Boolean)


77
78
79
# File 'app/models/user_query.rb', line 77

def visible?(user=User.current)
  user&.admin?
end