2016-10-19 03:11:36 +00:00
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
2019-07-04 11:16:55 +00:00
require_dependency 'karma/user'
2012-04-16 08:04:49 +00:00
class User < ApplicationModel
2019-01-28 06:04:05 +00:00
include CanBeImported
2017-05-02 15:21:13 +00:00
include HasActivityStreamLog
include ChecksClientNotification
include HasHistory
include HasSearchIndexBackend
2018-02-20 04:29:30 +00:00
include CanCsvImport
2019-02-12 07:38:59 +00:00
include ChecksHtmlSanitized
2017-06-16 20:43:09 +00:00
include HasGroups
include HasRoles
2019-03-13 23:51:22 +00:00
include HasObjectManagerAttributesValidation
2020-02-20 13:34:03 +00:00
include HasTicketCreateScreenImpact
include User :: HasTicketCreateScreenImpact
2013-08-19 06:29:49 +00:00
include User :: Assets
2018-04-26 08:55:53 +00:00
include User :: Search
2016-07-06 06:13:44 +00:00
include User :: SearchIndex
2013-08-19 06:29:49 +00:00
2018-04-12 14:57:37 +00:00
has_and_belongs_to_many :organizations , after_add : :cache_update , after_remove : :cache_update , class_name : 'Organization'
has_many :tokens , after_add : :cache_update , after_remove : :cache_update
has_many :authorizations , after_add : :cache_update , after_remove : :cache_update
2019-07-04 11:16:55 +00:00
belongs_to :organization , inverse_of : :members , optional : true
2018-04-12 14:57:37 +00:00
2018-08-30 08:39:50 +00:00
before_validation :check_name , :check_email , :check_login , :ensure_uniq_email , :ensure_password , :ensure_roles , :ensure_identifier
before_validation :check_mail_delivery_failed , on : :update
2018-11-06 05:42:52 +00:00
before_create :check_preferences_default , :validate_preferences , :validate_ooo , :domain_based_assignment , :set_locale
before_update :check_preferences_default , :validate_preferences , :validate_ooo , :reset_login_failed , :validate_agent_limit_by_attributes , :last_admin_check_by_attribute
2019-02-28 14:21:59 +00:00
after_create :avatar_for_email_check , unless : - > { BulkImportInfo . enabled? }
after_update :avatar_for_email_check , unless : - > { BulkImportInfo . enabled? }
2018-11-06 05:42:52 +00:00
after_commit :update_caller_id
before_destroy :destroy_longer_required_objects
2018-04-12 14:57:37 +00:00
store :preferences
2012-04-14 15:53:00 +00:00
2017-01-31 17:13:45 +00:00
activity_stream_permission 'admin.user'
activity_stream_attributes_ignored :last_login ,
:login_failed ,
:image ,
:image_source ,
:preferences
history_attributes_ignored :password ,
2017-02-03 07:56:40 +00:00
:last_login ,
2017-01-31 17:13:45 +00:00
:image ,
:image_source ,
:preferences
search_index_attributes_ignored :password ,
:image ,
:image_source ,
:source ,
2017-12-14 20:05:59 +00:00
:login_failed
2017-01-31 17:13:45 +00:00
2018-02-20 04:29:30 +00:00
csv_object_ids_ignored 1
csv_attributes_ignored :password ,
:login_failed ,
:source ,
:image_source ,
:image ,
:authorizations ,
:organizations ,
:groups ,
:user_groups
2019-02-12 07:38:59 +00:00
sanitized_html :note
2017-01-31 17:13:45 +00:00
def ignore_search_indexing? ( _action )
# ignore internal user
return true if id == 1
2018-10-09 06:17:41 +00:00
2017-01-31 17:13:45 +00:00
false
end
2013-09-28 00:07:11 +00:00
2013-08-17 22:10:02 +00:00
= begin
fullname of user
user = User . find ( 123 )
2016-02-20 10:12:15 +00:00
result = user . fullname
2013-08-17 22:10:02 +00:00
returns
result = " Bob Smith "
= end
2012-07-10 08:09:58 +00:00
def fullname
2016-02-20 10:12:15 +00:00
name = ''
2017-10-24 20:34:52 +00:00
if firstname . present?
name = firstname
2012-07-10 08:09:58 +00:00
end
2017-10-24 20:34:52 +00:00
if lastname . present?
2016-02-20 10:12:15 +00:00
if name != ''
name += ' '
2012-07-10 08:09:58 +00:00
end
2016-02-20 10:12:15 +00:00
name += lastname
2012-07-10 08:09:58 +00:00
end
2017-10-24 20:34:52 +00:00
if name . blank? && email . present?
2016-02-20 10:12:15 +00:00
name = email
2015-01-07 20:42:12 +00:00
end
2016-02-20 10:12:15 +00:00
name
end
= begin
longname of user
user = User . find ( 123 )
result = user . longname
returns
result = " Bob Smith "
or with org
result = " Bob Smith (Org ABC) "
= end
def longname
name = fullname
if organization_id
organization = Organization . lookup ( id : organization_id )
if organization
name += " ( #{ organization . name } ) "
end
end
name
2012-07-10 08:09:58 +00:00
end
2013-08-17 22:10:02 +00:00
= begin
check if user is in role
user = User . find ( 123 )
2015-05-08 08:15:45 +00:00
result = user . role? ( 'Customer' )
2013-08-17 22:10:02 +00:00
2015-09-11 08:22:15 +00:00
result = user . role? ( [ 'Agent' , 'Admin' ] )
2013-08-17 22:10:02 +00:00
returns
result = true | false
= end
2016-01-15 19:09:16 +00:00
def role? ( role_name )
2016-12-02 11:24:00 +00:00
roles . where ( name : role_name ) . any?
2012-09-04 21:28:49 +00:00
end
2013-08-17 22:10:02 +00:00
= begin
2017-09-05 09:49:32 +00:00
check if user is in role
user = User . find ( 123 )
result = user . out_of_office?
returns
result = true | false
= end
def out_of_office?
return false if out_of_office != true
return false if out_of_office_start_at . blank?
return false if out_of_office_end_at . blank?
2018-10-09 06:17:41 +00:00
2017-09-05 09:49:32 +00:00
Time . zone . today . between? ( out_of_office_start_at , out_of_office_end_at )
end
= begin
check if user is in role
user = User . find ( 123 )
result = user . out_of_office_agent
returns
result = user_model
= end
def out_of_office_agent
return if ! out_of_office?
return if out_of_office_replacement_id . blank?
2018-10-09 06:17:41 +00:00
2017-09-05 09:49:32 +00:00
User . find_by ( id : out_of_office_replacement_id )
end
= begin
2017-09-11 00:50:05 +00:00
gets users where user is replacement
user = User . find ( 123 )
result = user . out_of_office_agent_of
returns
result = [ user_model1 , user_model2 ]
= end
def out_of_office_agent_of
User . where ( active : true , out_of_office : true , out_of_office_replacement_id : id ) . where ( 'out_of_office_start_at <= ? AND out_of_office_end_at >= ?' , Time . zone . today , Time . zone . today )
end
= begin
2013-09-28 00:07:11 +00:00
get users activity stream
user = User . find ( 123 )
2016-01-15 19:09:16 +00:00
result = user . activity_stream ( 20 )
2013-09-28 00:07:11 +00:00
returns
result = [
{
2016-06-08 04:56:05 +00:00
id : 2 ,
o_id : 2 ,
created_by_id : 3 ,
created_at : '2013-09-28 00:57:21' ,
object : " User " ,
type : " created " ,
2013-09-28 00:07:11 +00:00
} ,
{
2016-06-08 04:56:05 +00:00
id : 2 ,
o_id : 2 ,
created_by_id : 3 ,
created_at : '2013-09-28 00:59:21' ,
object : " User " ,
type : " updated " ,
2013-09-28 00:07:11 +00:00
} ,
]
= end
2016-01-15 19:09:16 +00:00
def activity_stream ( limit , fulldata = false )
2018-03-20 12:16:17 +00:00
stream = ActivityStream . list ( self , limit )
return stream if ! fulldata
2013-09-28 00:07:11 +00:00
# get related objects
2018-03-20 12:16:17 +00:00
assets = { }
stream . each do | item |
assets = item . assets ( assets )
end
2014-08-26 07:40:25 +00:00
2015-04-30 17:20:27 +00:00
{
2018-03-20 12:16:17 +00:00
stream : stream ,
2015-04-27 13:42:53 +00:00
assets : assets ,
2013-09-28 00:07:11 +00:00
}
end
= begin
2013-08-17 22:10:02 +00:00
authenticate user
result = User . authenticate ( username , password )
returns
result = user_model # user model if authentication was successfully
= end
2016-01-15 19:09:16 +00:00
def self . authenticate ( username , password )
2012-07-29 15:27:01 +00:00
2012-04-20 12:24:37 +00:00
# do not authenticate with nothing
2016-12-02 11:24:00 +00:00
return if username . blank? || password . blank?
2012-07-29 15:27:01 +00:00
2017-04-19 10:09:54 +00:00
user = User . identify ( username )
return if ! user
2012-07-29 15:27:01 +00:00
2017-04-19 10:09:54 +00:00
return if ! Auth . can_login? ( user )
return user if Auth . valid? ( user , password )
sleep 1
user . login_failed += 1
2017-10-20 11:32:52 +00:00
user . save!
2017-04-19 10:09:54 +00:00
nil
end
= begin
checks if a user has reached the maximum of failed login tries
2012-07-29 15:27:01 +00:00
2017-04-19 10:09:54 +00:00
user = User . find ( 123 )
result = user . max_login_failed?
returns
result = true | false
= end
def max_login_failed?
2015-02-11 23:04:13 +00:00
max_login_failed = Setting . get ( 'password_max_login_failed' ) . to_i || 10
2017-04-19 10:09:54 +00:00
login_failed > max_login_failed
end
2012-07-29 15:27:01 +00:00
2017-04-19 10:09:54 +00:00
= begin
2013-01-23 22:13:02 +00:00
2017-04-19 10:09:54 +00:00
tries to find the matching instance by the given identifier . Currently email and login is supported .
2013-02-07 21:24:03 +00:00
2017-04-19 10:09:54 +00:00
user = User . indentify ( 'User123' )
# or
user = User . indentify ( 'user-123@example.com' )
returns
# User instance
user . login # 'user123'
= end
def self . identify ( identifier )
# try to find user based on login
user = User . find_by ( login : identifier . downcase )
return user if user
# try second lookup with email
User . find_by ( email : identifier . downcase )
2012-04-10 14:06:46 +00:00
end
2013-08-17 22:10:02 +00:00
= begin
create user from from omni auth hash
result = User . create_from_hash! ( hash )
returns
result = user_model # user model if create was successfully
= end
2012-04-10 14:06:46 +00:00
def self . create_from_hash! ( hash )
2015-07-06 18:33:37 +00:00
2012-04-10 14:06:46 +00:00
url = ''
2017-11-23 08:09:44 +00:00
hash [ 'info' ] [ 'urls' ] & . each_value do | local_url |
next if local_url . blank?
2018-10-09 06:17:41 +00:00
2017-11-23 08:09:44 +00:00
url = local_url
2012-04-10 14:06:46 +00:00
end
2018-07-16 15:07:23 +00:00
begin
2018-10-11 12:40:12 +00:00
data = {
2018-12-19 17:31:51 +00:00
login : hash [ 'info' ] [ 'nickname' ] || hash [ 'uid' ] ,
firstname : hash [ 'info' ] [ 'name' ] || hash [ 'info' ] [ 'display_name' ] ,
email : hash [ 'info' ] [ 'email' ] ,
image_source : hash [ 'info' ] [ 'image' ] ,
web : url ,
address : hash [ 'info' ] [ 'location' ] ,
note : hash [ 'info' ] [ 'description' ] ,
source : hash [ 'provider' ] ,
role_ids : Role . signup_role_ids ,
2018-07-16 15:07:23 +00:00
updated_by_id : 1 ,
created_by_id : 1 ,
2018-10-11 12:40:12 +00:00
}
if hash [ 'info' ] [ 'first_name' ] . present? && hash [ 'info' ] [ 'last_name' ] . present?
data [ :firstname ] = hash [ 'info' ] [ 'first_name' ]
data [ :lastname ] = hash [ 'info' ] [ 'last_name' ]
end
create! ( data )
2018-07-16 15:07:23 +00:00
rescue = > e
logger . error e
raise Exceptions :: UnprocessableEntity , e . message
end
2012-04-10 14:06:46 +00:00
end
2012-04-23 06:55:16 +00:00
2013-08-17 22:10:02 +00:00
= begin
2016-08-12 16:39:09 +00:00
get all permissions of user
user = User . find ( 123 )
user . permissions
returns
{
'permission.key' = > true ,
# ...
}
= end
def permissions
Refactoring: Clarify complex Permission queries
This commit was prepared to facilitate a larger refactoring assignment
as part of the Pundit migration.
As a bonus, it includes some SQL query optimizations!
=== Why was this refactoring necessary?
It's not, strictly speaking.
But the Pundit migration involves taking complex querying logic
and moving it into Scope classes as appropriate,
and deciding where things belong is really difficult
when you can't see what they're doing.
=== So how does this refactoring fix the problem?
* It replaces raw SQL queries with Ruby-esque ActiveRecord queries.
* It replaces complex, procedural code
that's full of loops and obscure local variable assignment
with compact, cleanly-formatted code
that follows Ruby idioms and uses meaningful variable names.
In my opinion, it's much faster and easier
to understand what the code does this way.
=== What kinds of SQL query optimizations are included?
* n+1 query: user_access_token#index instantiated all active permissions
and then called current_user.permissions? on _every single one._
A fresh installation of Zammad contains 57 permissions,
so this was a lot of unnecessary queries.
The method has been rewritten to make only one query instead.
* User#permissions? used to query the DB once
for each argument it was given.
Now, it only queries the DB once, even when given many arguments.
* We had a couple SQL queries that used both #select and #pluck.
(When using #pluck, #select is redundant.)
Removing #select from these calls did not improve performance,
but it did clean up unnecessary code.
2020-07-07 11:14:58 +00:00
:: Permission . joins ( roles : :users )
. where ( users : { id : id } , roles : { active : true } , active : true )
. pluck ( :name , :preferences )
. each_with_object ( { } ) do | ( name , preferences ) , hash |
hash [ name ] = true if preferences [ 'selectable' ] != false
end
2016-08-12 16:39:09 +00:00
end
= begin
true or false for permission
user = User . find ( 123 )
user . permissions? ( 'permission.key' ) # access to certain permission.key
user . permissions? ( [ 'permission.key1' , 'permission.key2' ] ) # access to permission.key1 or permission.key2
user . permissions? ( 'permission' ) # access to all sub keys
2016-08-26 10:06:27 +00:00
user . permissions? ( 'permission.*' ) # access if one sub key access exists
2016-08-12 16:39:09 +00:00
returns
true | false
= end
Refactoring: Clarify complex Permission queries
This commit was prepared to facilitate a larger refactoring assignment
as part of the Pundit migration.
As a bonus, it includes some SQL query optimizations!
=== Why was this refactoring necessary?
It's not, strictly speaking.
But the Pundit migration involves taking complex querying logic
and moving it into Scope classes as appropriate,
and deciding where things belong is really difficult
when you can't see what they're doing.
=== So how does this refactoring fix the problem?
* It replaces raw SQL queries with Ruby-esque ActiveRecord queries.
* It replaces complex, procedural code
that's full of loops and obscure local variable assignment
with compact, cleanly-formatted code
that follows Ruby idioms and uses meaningful variable names.
In my opinion, it's much faster and easier
to understand what the code does this way.
=== What kinds of SQL query optimizations are included?
* n+1 query: user_access_token#index instantiated all active permissions
and then called current_user.permissions? on _every single one._
A fresh installation of Zammad contains 57 permissions,
so this was a lot of unnecessary queries.
The method has been rewritten to make only one query instead.
* User#permissions? used to query the DB once
for each argument it was given.
Now, it only queries the DB once, even when given many arguments.
* We had a couple SQL queries that used both #select and #pluck.
(When using #pluck, #select is redundant.)
Removing #select from these calls did not improve performance,
but it did clean up unnecessary code.
2020-07-07 11:14:58 +00:00
def permissions? ( names )
base_query = :: Permission . joins ( roles : :users )
. where ( users : { id : id } )
. where ( roles : { active : true } )
. where ( active : true )
permission_names = Array ( names ) . reject { | name | :: Permission . lookup ( name : name ) & . active == false }
verbatim_names = permission_names . flat_map { | name | :: Permission . with_parents ( name ) } . uniq
wildcard_names = permission_names . select { | name | name . end_with? ( '.*' ) }
. map { | name | name . sub ( '.*' , '.%' ) }
permissions = base_query . where ( name : verbatim_names )
wildcard_names . each do | name |
permissions = permissions . or ( base_query . where ( 'permissions.name LIKE ?' , name ) )
2017-10-01 12:25:52 +00:00
end
Refactoring: Clarify complex Permission queries
This commit was prepared to facilitate a larger refactoring assignment
as part of the Pundit migration.
As a bonus, it includes some SQL query optimizations!
=== Why was this refactoring necessary?
It's not, strictly speaking.
But the Pundit migration involves taking complex querying logic
and moving it into Scope classes as appropriate,
and deciding where things belong is really difficult
when you can't see what they're doing.
=== So how does this refactoring fix the problem?
* It replaces raw SQL queries with Ruby-esque ActiveRecord queries.
* It replaces complex, procedural code
that's full of loops and obscure local variable assignment
with compact, cleanly-formatted code
that follows Ruby idioms and uses meaningful variable names.
In my opinion, it's much faster and easier
to understand what the code does this way.
=== What kinds of SQL query optimizations are included?
* n+1 query: user_access_token#index instantiated all active permissions
and then called current_user.permissions? on _every single one._
A fresh installation of Zammad contains 57 permissions,
so this was a lot of unnecessary queries.
The method has been rewritten to make only one query instead.
* User#permissions? used to query the DB once
for each argument it was given.
Now, it only queries the DB once, even when given many arguments.
* We had a couple SQL queries that used both #select and #pluck.
(When using #pluck, #select is redundant.)
Removing #select from these calls did not improve performance,
but it did clean up unnecessary code.
2020-07-07 11:14:58 +00:00
permissions . exists?
2016-08-12 16:39:09 +00:00
end
= begin
2016-12-08 14:06:54 +00:00
returns all accessable permission ids of user
user = User . find ( 123 )
user . permissions_with_child_ids
returns
[ permission1_id , permission2_id , permission3_id ]
= end
def permissions_with_child_ids
where = ''
where_bind = [ true ]
2017-11-23 08:09:44 +00:00
permissions . each_key do | permission_name |
2016-12-08 14:06:54 +00:00
where += ' OR ' if where != ''
where += 'permissions.name = ? OR permissions.name LIKE ?'
where_bind . push permission_name
where_bind . push " #{ permission_name } .% "
2017-10-01 12:25:52 +00:00
end
2016-12-08 14:06:54 +00:00
return [ ] if where == ''
2018-10-09 06:17:41 +00:00
2017-10-18 09:13:11 +00:00
:: Permission . where ( " permissions.active = ? AND ( #{ where } ) " , * where_bind ) . pluck ( :id )
2016-12-08 14:06:54 +00:00
end
= begin
2016-08-12 16:39:09 +00:00
get all users with permission
2017-10-24 20:34:52 +00:00
users = User . with_permissions ( 'ticket.agent' )
2016-08-12 16:39:09 +00:00
get all users with permission " admin.session " or " ticket.agent "
users = User . with_permissions ( [ 'admin.session' , 'ticket.agent' ] )
returns
[ user1 , user2 , ... ]
= end
def self . with_permissions ( keys )
if keys . class != Array
keys = [ keys ]
end
total_role_ids = [ ]
permission_ids = [ ]
2017-10-01 12:25:52 +00:00
keys . each do | key |
2016-08-12 16:39:09 +00:00
role_ids = [ ]
2017-10-18 09:13:11 +00:00
:: Permission . with_parents ( key ) . each do | local_key |
permission = :: Permission . lookup ( name : local_key )
2016-08-12 16:39:09 +00:00
next if ! permission
2018-10-09 06:17:41 +00:00
2016-08-12 16:39:09 +00:00
permission_ids . push permission . id
2017-10-01 12:25:52 +00:00
end
2017-11-23 08:09:44 +00:00
next if permission_ids . blank?
2018-10-09 06:17:41 +00:00
2017-10-01 12:25:52 +00:00
Role . joins ( :roles_permissions ) . joins ( :permissions ) . where ( 'permissions_roles.permission_id IN (?) AND roles.active = ? AND permissions.active = ?' , permission_ids , true , true ) . distinct ( ) . pluck ( :id ) . each do | role_id |
2016-08-31 07:10:25 +00:00
role_ids . push role_id
2017-10-01 12:25:52 +00:00
end
2016-08-12 16:39:09 +00:00
total_role_ids . push role_ids
2017-10-01 12:25:52 +00:00
end
2017-11-23 08:09:44 +00:00
return [ ] if total_role_ids . blank?
2018-10-09 06:17:41 +00:00
2016-08-12 16:39:09 +00:00
condition = ''
2017-10-01 12:25:52 +00:00
total_role_ids . each do | _role_ids |
2016-08-12 16:39:09 +00:00
if condition != ''
condition += ' OR '
end
condition += 'roles_users.role_id IN (?)'
2017-10-01 12:25:52 +00:00
end
2016-08-30 13:01:51 +00:00
User . joins ( :users_roles ) . where ( " ( #{ condition } ) AND users.active = ? " , * total_role_ids , true ) . distinct . order ( :id )
2016-08-12 16:39:09 +00:00
end
= begin
2016-02-19 21:05:36 +00:00
generate new token for reset password
2013-08-17 22:10:02 +00:00
2016-02-19 21:05:36 +00:00
result = User . password_reset_new_token ( username )
2013-08-17 22:10:02 +00:00
returns
2016-02-19 21:05:36 +00:00
result = {
token : token ,
user : user ,
}
2013-08-17 22:10:02 +00:00
= end
2016-02-19 21:05:36 +00:00
def self . password_reset_new_token ( username )
2016-12-02 11:24:00 +00:00
return if username . blank?
2012-04-23 06:55:16 +00:00
# try to find user based on login
2018-07-16 15:07:23 +00:00
user = User . find_by ( login : username . downcase . strip , active : true )
2012-10-18 08:10:12 +00:00
2012-04-23 06:55:16 +00:00
# try second lookup with email
2018-07-16 15:07:23 +00:00
user || = User . find_by ( email : username . downcase . strip , active : true )
2012-04-23 06:55:16 +00:00
# check if email address exists
2012-09-20 12:08:02 +00:00
return if ! user
2012-04-23 06:55:16 +00:00
return if ! user . email
# generate token
2016-01-15 19:09:16 +00:00
token = Token . create ( action : 'PasswordReset' , user_id : user . id )
2012-04-23 06:55:16 +00:00
2016-02-19 21:05:36 +00:00
{
token : token ,
2018-12-19 17:31:51 +00:00
user : user ,
2012-04-23 06:55:16 +00:00
}
end
2013-08-17 22:10:02 +00:00
= begin
2017-02-24 17:27:27 +00:00
returns the User instance for a given password token if found
2013-08-17 22:10:02 +00:00
2017-02-24 17:27:27 +00:00
result = User . by_reset_token ( token )
2013-08-17 22:10:02 +00:00
returns
result = user_model # user_model if token was verified
= end
2017-02-24 17:27:27 +00:00
def self . by_reset_token ( token )
Token . check ( action : 'PasswordReset' , name : token )
2012-04-23 06:55:16 +00:00
end
2013-08-17 22:10:02 +00:00
= begin
2016-06-01 14:58:11 +00:00
reset password with token and set new password
2013-08-17 22:10:02 +00:00
result = User . password_reset_via_token ( token , password )
returns
result = user_model # user_model if token was verified
= end
2015-04-27 14:53:29 +00:00
def self . password_reset_via_token ( token , password )
2012-07-23 22:22:23 +00:00
2012-04-23 06:55:16 +00:00
# check token
2017-02-24 17:27:27 +00:00
user = by_reset_token ( token )
2013-01-03 12:00:55 +00:00
return if ! user
2012-07-23 22:22:23 +00:00
2012-04-23 06:55:16 +00:00
# reset password
2020-06-02 12:21:08 +00:00
user . update! ( password : password , verified : true )
2012-07-23 22:22:23 +00:00
2012-04-23 06:55:16 +00:00
# delete token
2016-01-15 19:09:16 +00:00
Token . find_by ( action : 'PasswordReset' , name : token ) . destroy
2014-12-30 23:51:19 +00:00
user
2012-04-23 06:55:16 +00:00
end
2013-08-17 22:10:02 +00:00
= begin
2013-10-22 06:43:49 +00:00
update last login date and reset login_failed ( is automatically done by auth and sso backend )
2013-08-17 22:10:02 +00:00
user = User . find ( 123 )
result = user . update_last_login
returns
result = new_user_model
= end
2012-10-18 08:10:12 +00:00
def update_last_login
2019-02-26 13:28:11 +00:00
# reduce DB/ES load by updating last_login every 10 minutes only
if ! last_login || last_login < 10 . minutes . ago
self . last_login = Time . zone . now
end
2013-10-22 06:43:49 +00:00
# reset login failed
self . login_failed = 0
2015-05-07 12:10:38 +00:00
save
2012-10-18 08:10:12 +00:00
end
2015-07-25 14:36:16 +00:00
= begin
2016-06-01 14:58:11 +00:00
generate new token for signup
result = User . signup_new_token ( user ) # or email
returns
result = {
token : token ,
user : user ,
}
= end
def self . signup_new_token ( user )
return if ! user
return if ! user . email
# generate token
token = Token . create ( action : 'Signup' , user_id : user . id )
{
token : token ,
2018-12-19 17:31:51 +00:00
user : user ,
2016-06-01 14:58:11 +00:00
}
end
= begin
verify signup with token
result = User . signup_verify_via_token ( token , user )
returns
result = user_model # user_model if token was verified
= end
def self . signup_verify_via_token ( token , user = nil )
# check token
local_user = Token . check ( action : 'Signup' , name : token )
return if ! local_user
# if requested user is different to current user
return if user && local_user . id != user . id
# set verified
2017-09-11 11:16:08 +00:00
local_user . update! ( verified : true )
2016-06-01 14:58:11 +00:00
# delete token
Token . find_by ( action : 'Signup' , name : token ) . destroy
local_user
end
= begin
2016-01-15 19:09:16 +00:00
merge two users to one
user = User . find ( 123 )
result = user . merge ( user_id_of_duplicate_user )
returns
result = new_user_model
= end
def merge ( user_id_of_duplicate_user )
2019-06-28 11:38:49 +00:00
# Raise an exception if the user is not found (?)
#
# (This line used to contain a useless variable assignment,
# and was changed to satisfy the linter.
# We're not certain of its original intention,
# so the User.find call has been kept
# to prevent any unexpected regressions.)
User . find ( user_id_of_duplicate_user )
2016-01-15 19:09:16 +00:00
2019-07-31 08:23:48 +00:00
# merge missing attributes
2016-01-15 19:09:16 +00:00
Models . merge ( 'User' , id , user_id_of_duplicate_user )
true
end
= begin
2015-07-25 14:36:16 +00:00
list of active users in role
2016-02-07 13:00:29 +00:00
result = User . of_role ( 'Agent' , group_ids )
2015-07-25 14:36:16 +00:00
2016-08-12 16:39:09 +00:00
result = User . of_role ( [ 'Agent' , 'Admin' ] )
2015-07-25 14:36:16 +00:00
returns
result = [ user1 , user2 ]
= end
2016-02-07 13:00:29 +00:00
def self . of_role ( role , group_ids = nil )
2016-01-15 19:09:16 +00:00
roles_ids = Role . where ( active : true , name : role ) . map ( & :id )
2016-02-07 13:00:29 +00:00
if ! group_ids
2016-04-25 23:41:38 +00:00
return User . where ( active : true ) . joins ( :users_roles ) . where ( 'roles_users.role_id IN (?)' , roles_ids ) . order ( 'users.updated_at DESC' )
2016-02-07 13:00:29 +00:00
end
2018-10-09 06:17:41 +00:00
2016-02-07 13:00:29 +00:00
User . where ( active : true )
. joins ( :users_roles )
. joins ( :users_groups )
2016-04-25 23:41:38 +00:00
. where ( 'roles_users.role_id IN (?) AND users_groups.group_ids IN (?)' , roles_ids , group_ids ) . order ( 'users.updated_at DESC' )
2015-07-25 14:36:16 +00:00
end
2016-02-08 07:12:04 +00:00
= begin
2019-07-31 08:23:48 +00:00
update / sync default preferences of users with dedicated permissions
2016-09-29 11:35:42 +00:00
result = User . update_default_preferences_by_permission ( 'ticket.agent' , force )
returns
result = true # false
= end
def self . update_default_preferences_by_permission ( permission_name , force = false )
2017-10-18 09:13:11 +00:00
permission = :: Permission . lookup ( name : permission_name )
2016-09-29 11:35:42 +00:00
return if ! permission
2018-10-09 06:17:41 +00:00
2016-09-29 11:35:42 +00:00
default = Rails . configuration . preferences_default_by_permission
return false if ! default
2018-10-09 06:17:41 +00:00
2016-09-29 11:35:42 +00:00
default . deep_stringify_keys!
2017-10-01 12:25:52 +00:00
User . with_permissions ( permission . name ) . each do | user |
2016-09-29 11:35:42 +00:00
next if ! default [ permission . name ]
2018-10-09 06:17:41 +00:00
2016-09-29 11:35:42 +00:00
has_changed = false
2017-10-01 12:25:52 +00:00
default [ permission . name ] . each do | key , value |
2016-09-29 11:35:42 +00:00
next if ! force && user . preferences [ key ]
2018-10-09 06:17:41 +00:00
2016-09-29 11:35:42 +00:00
has_changed = true
user . preferences [ key ] = value
2017-10-01 12:25:52 +00:00
end
2016-09-29 11:35:42 +00:00
if has_changed
user . save!
end
2017-10-01 12:25:52 +00:00
end
2016-09-29 11:35:42 +00:00
true
end
= begin
2019-07-31 08:23:48 +00:00
update / sync default preferences of users in a dedicated role
2016-02-08 07:12:04 +00:00
2016-09-29 11:35:42 +00:00
result = User . update_default_preferences_by_role ( 'Agent' , force )
2016-02-08 07:12:04 +00:00
returns
result = true # false
= end
2016-09-29 11:35:42 +00:00
def self . update_default_preferences_by_role ( role_name , force = false )
2016-02-08 07:12:04 +00:00
role = Role . lookup ( name : role_name )
2016-09-29 11:35:42 +00:00
return if ! role
2018-10-09 06:17:41 +00:00
2016-09-29 11:25:20 +00:00
default = Rails . configuration . preferences_default_by_permission
return false if ! default
2018-10-09 06:17:41 +00:00
2016-09-29 11:25:20 +00:00
default . deep_stringify_keys!
2017-10-01 12:25:52 +00:00
role . permissions . each do | permission |
2016-09-29 11:35:42 +00:00
User . update_default_preferences_by_permission ( permission . name , force )
2017-10-01 12:25:52 +00:00
end
2016-02-08 07:12:04 +00:00
true
end
2018-04-12 14:57:37 +00:00
def check_notifications ( other , should_save = true )
2016-09-29 11:25:20 +00:00
default = Rails . configuration . preferences_default_by_permission
2016-02-08 07:12:04 +00:00
return if ! default
2018-10-09 06:17:41 +00:00
2016-02-08 07:12:04 +00:00
default . deep_stringify_keys!
2016-09-29 11:25:20 +00:00
has_changed = false
2018-04-12 14:57:37 +00:00
other . permissions . each do | permission |
2016-09-29 11:25:20 +00:00
next if ! default [ permission . name ]
2018-10-09 06:17:41 +00:00
2017-10-01 12:25:52 +00:00
default [ permission . name ] . each do | key , value |
2016-09-29 11:25:20 +00:00
next if preferences [ key ]
2018-10-09 06:17:41 +00:00
2016-09-29 11:25:20 +00:00
preferences [ key ] = value
has_changed = true
2017-10-01 12:25:52 +00:00
end
end
2016-09-29 11:25:20 +00:00
return true if ! has_changed
2017-11-23 08:09:44 +00:00
if id && should_save
2016-09-29 11:25:20 +00:00
save!
return true
end
@preferences_default = preferences
true
2016-02-08 07:12:04 +00:00
end
def check_preferences_default
2017-06-14 15:25:45 +00:00
if @preferences_default . blank?
if id
2017-10-01 12:25:52 +00:00
roles . each do | role |
2017-06-14 15:25:45 +00:00
check_notifications ( role , false )
2017-10-01 12:25:52 +00:00
end
2017-06-14 15:25:45 +00:00
end
end
2016-12-02 11:24:00 +00:00
return if @preferences_default . blank?
2018-10-09 06:17:41 +00:00
2016-02-08 07:12:04 +00:00
preferences_tmp = @preferences_default . merge ( preferences )
self . preferences = preferences_tmp
2016-09-29 11:25:20 +00:00
@preferences_default = nil
true
2016-02-08 07:12:04 +00:00
end
2015-06-18 22:39:34 +00:00
def cache_delete
super
# delete asset caches
key = " User::authorizations:: #{ id } "
Cache . delete ( key )
2016-08-22 08:51:08 +00:00
# delete permission cache
key = " User::permissions?:local_key::: #{ id } "
Cache . delete ( key )
2015-06-18 22:39:34 +00:00
end
2018-07-16 15:07:23 +00:00
= begin
2018-05-10 12:05:34 +00:00
2018-07-16 15:07:23 +00:00
try to find correct name
2017-10-24 20:34:52 +00:00
2018-07-16 15:07:23 +00:00
[ firstname , lastname ] = User . name_guess ( 'Some Name' , 'some.name@example.com' )
2012-10-25 22:12:16 +00:00
2018-07-16 15:07:23 +00:00
= end
2012-10-25 22:12:16 +00:00
2018-07-16 15:07:23 +00:00
def self . name_guess ( string , email = nil )
return if string . blank? && email . blank?
2018-10-09 06:17:41 +00:00
2018-07-16 15:07:23 +00:00
string . strip!
firstname = ''
lastname = ''
# "Lastname, Firstname"
if string . match? ( ',' )
name = string . split ( ', ' , 2 )
2017-10-24 20:34:52 +00:00
if name . count == 2
if name [ 0 ] . present?
2018-07-16 15:07:23 +00:00
lastname = name [ 0 ] . strip
2015-01-08 14:27:44 +00:00
end
2017-10-24 20:34:52 +00:00
if name [ 1 ] . present?
2018-07-16 15:07:23 +00:00
firstname = name [ 1 ] . strip
2015-01-08 14:27:44 +00:00
end
2018-07-16 15:07:23 +00:00
return [ firstname , lastname ] if firstname . present? || lastname . present?
2013-06-12 15:59:58 +00:00
end
2018-07-16 15:07:23 +00:00
end
2012-10-25 22:12:16 +00:00
2018-07-16 15:07:23 +00:00
# "Firstname Lastname"
if string =~ / ^(((Dr \ .|Prof \ .)[[:space:]]|).+?)[[:space:]](.+?)$ /i
if $1 . present?
firstname = $1 . strip
end
if $4 . present?
lastname = $4 . strip
2015-01-08 14:27:44 +00:00
end
2018-07-16 15:07:23 +00:00
return [ firstname , lastname ] if firstname . present? || lastname . present?
end
2012-10-25 22:12:16 +00:00
2016-08-22 08:51:08 +00:00
# -no name- "firstname.lastname@example.com"
2018-07-16 15:07:23 +00:00
if string . blank? && email . present?
2020-06-08 07:17:29 +00:00
scan = email . scan ( / ^(.+?) \ .(.+?)@.+?$ / )
2018-07-16 15:07:23 +00:00
if scan [ 0 ] . present?
2017-10-24 20:34:52 +00:00
if scan [ 0 ] [ 0 ] . present?
2018-07-16 15:07:23 +00:00
firstname = scan [ 0 ] [ 0 ] . strip
2015-01-08 14:27:44 +00:00
end
2017-10-24 20:34:52 +00:00
if scan [ 0 ] [ 1 ] . present?
2018-07-16 15:07:23 +00:00
lastname = scan [ 0 ] [ 1 ] . strip
2015-01-08 14:27:44 +00:00
end
2018-07-16 15:07:23 +00:00
return [ firstname , lastname ] if firstname . present? || lastname . present?
2012-04-10 14:06:46 +00:00
end
end
2018-07-16 15:07:23 +00:00
nil
end
2018-08-30 08:39:50 +00:00
def no_name?
firstname . blank? && lastname . blank?
end
2020-01-27 09:28:17 +00:00
# get locale identifier of user or system if user's own is not set
2019-04-01 07:22:29 +00:00
def locale
2020-01-27 09:28:17 +00:00
preferences . fetch ( :locale ) { Locale . default }
2019-04-01 07:22:29 +00:00
end
2018-07-16 15:07:23 +00:00
private
def check_name
if firstname . present?
firstname . strip!
end
if lastname . present?
lastname . strip!
end
return true if firstname . present? && lastname . present?
if ( firstname . blank? && lastname . present? ) || ( firstname . present? && lastname . blank? )
used_name = firstname . presence || lastname
( local_firstname , local_lastname ) = User . name_guess ( used_name , email )
elsif firstname . blank? && lastname . blank? && email . present?
( local_firstname , local_lastname ) = User . name_guess ( '' , email )
end
self . firstname = local_firstname if local_firstname . present?
self . lastname = local_lastname if local_lastname . present?
if firstname . present? && firstname . match ( / ^[A-z]+$ / ) && ( firstname . downcase == firstname || firstname . upcase == firstname )
firstname . capitalize!
end
if lastname . present? && lastname . match ( / ^[A-z]+$ / ) && ( lastname . downcase == lastname || lastname . upcase == lastname )
lastname . capitalize!
end
2017-06-16 22:53:20 +00:00
true
2013-06-12 15:59:58 +00:00
end
2012-04-29 20:47:35 +00:00
2013-06-12 15:59:58 +00:00
def check_email
2017-06-16 22:53:20 +00:00
return true if Setting . get ( 'import_mode' )
2017-07-14 22:35:44 +00:00
return true if email . blank?
2018-10-09 06:17:41 +00:00
2016-09-14 22:56:04 +00:00
self . email = email . downcase . strip
2017-06-16 22:53:20 +00:00
return true if id == 1
2019-11-21 15:49:14 +00:00
email_address_validation = EmailAddressValidation . new ( email )
if ! email_address_validation . valid_format?
2020-01-31 21:40:55 +00:00
raise Exceptions :: UnprocessableEntity , " Invalid email ' #{ email } ' "
2019-11-21 15:49:14 +00:00
end
2018-10-09 06:17:41 +00:00
2017-06-16 22:53:20 +00:00
true
2013-06-12 15:59:58 +00:00
end
2012-04-29 20:47:35 +00:00
2013-06-12 15:59:58 +00:00
def check_login
2015-01-07 20:42:12 +00:00
# use email as login if not given
2017-06-16 22:53:20 +00:00
if login . blank?
2015-05-07 12:10:38 +00:00
self . login = email
2014-09-25 06:20:20 +00:00
end
2015-01-07 20:42:12 +00:00
# if email has changed, login is old email, change also login
2015-05-07 12:10:38 +00:00
if changes && changes [ 'email' ]
if changes [ 'email' ] [ 0 ] == login
self . login = email
2015-01-07 20:42:12 +00:00
end
end
2017-07-14 09:57:34 +00:00
# generate auto login
if login . blank?
self . login = " auto- #{ Time . zone . now . to_i } - #{ rand ( 999_999 ) } "
2016-09-14 22:56:04 +00:00
end
2015-04-30 15:25:04 +00:00
2016-09-14 22:56:04 +00:00
# check if login already exists
self . login = login . downcase . strip
2015-04-30 15:25:04 +00:00
check = true
while check
2016-01-15 19:09:16 +00:00
exists = User . find_by ( login : login )
2018-04-12 14:57:37 +00:00
if exists && exists . id != id
2017-07-14 09:57:34 +00:00
self . login = " #{ login } #{ rand ( 999 ) } "
2015-04-30 15:25:04 +00:00
else
check = false
2013-02-19 19:04:35 +00:00
end
end
2017-06-16 22:53:20 +00:00
true
2013-06-12 15:59:58 +00:00
end
2013-02-19 19:04:35 +00:00
2017-11-21 07:37:09 +00:00
def check_mail_delivery_failed
2018-08-30 08:39:50 +00:00
return if email_change . blank?
2018-10-09 06:17:41 +00:00
2017-11-21 07:37:09 +00:00
preferences . delete ( :mail_delivery_failed )
end
2017-07-12 14:41:10 +00:00
def ensure_roles
return true if role_ids . present?
2018-10-09 06:17:41 +00:00
2017-07-12 14:41:10 +00:00
self . role_ids = Role . signup_role_ids
end
2017-07-14 09:57:34 +00:00
def ensure_identifier
return true if email . present? || firstname . present? || lastname . present? || phone . present?
return true if login . present? && ! login . start_with? ( 'auto-' )
2018-10-09 06:17:41 +00:00
2017-07-14 09:57:34 +00:00
raise Exceptions :: UnprocessableEntity , 'Minimum one identifier (login, firstname, lastname, phone or email) for user is required.'
end
2017-07-14 22:35:44 +00:00
def ensure_uniq_email
return true if Setting . get ( 'user_email_multiple_use' )
return true if Setting . get ( 'import_mode' )
return true if email . blank?
return true if ! changes
return true if ! changes [ 'email' ]
2020-01-10 10:43:36 +00:00
return true if ! User . exists? ( email : email . downcase . strip )
2018-10-09 06:17:41 +00:00
2020-01-10 10:43:36 +00:00
raise Exceptions :: UnprocessableEntity , " Email address ' #{ email . downcase . strip } ' is already used for other user. "
2017-07-14 22:35:44 +00:00
end
2017-10-24 14:55:40 +00:00
def validate_roles ( role )
return true if ! role_ids # we need role_ids for checking in role_ids below, in this method
return true if role . preferences [ :not ] . blank?
2018-10-09 06:17:41 +00:00
2017-10-24 14:55:40 +00:00
role . preferences [ :not ] . each do | local_role_name |
local_role = Role . lookup ( name : local_role_name )
next if ! local_role
next if role_ids . exclude? ( local_role . id )
2018-10-09 06:17:41 +00:00
2017-10-24 14:55:40 +00:00
raise " Role #{ role . name } conflicts with #{ local_role . name } "
2017-10-01 12:25:52 +00:00
end
2017-06-16 22:53:20 +00:00
true
2016-08-12 16:39:09 +00:00
end
2017-09-05 09:49:32 +00:00
def validate_ooo
return true if out_of_office != true
raise Exceptions :: UnprocessableEntity , 'out of office start is required' if out_of_office_start_at . blank?
raise Exceptions :: UnprocessableEntity , 'out of office end is required' if out_of_office_end_at . blank?
raise Exceptions :: UnprocessableEntity , 'out of office end is before start' if out_of_office_start_at > out_of_office_end_at
raise Exceptions :: UnprocessableEntity , 'out of office replacement user is required' if out_of_office_replacement_id . blank?
raise Exceptions :: UnprocessableEntity , 'out of office no such replacement user' if ! User . find_by ( id : out_of_office_replacement_id )
2018-10-09 06:17:41 +00:00
2017-09-05 09:49:32 +00:00
true
end
2017-10-20 11:32:52 +00:00
2018-04-13 07:11:48 +00:00
def validate_preferences
return true if ! changes
return true if ! changes [ 'preferences' ]
return true if preferences . blank?
return true if ! preferences [ :notification_sound ]
return true if ! preferences [ :notification_sound ] [ :enabled ]
2018-10-09 06:17:41 +00:00
2020-07-13 12:46:08 +00:00
case preferences [ :notification_sound ] [ :enabled ]
when 'true'
2018-04-13 07:11:48 +00:00
preferences [ :notification_sound ] [ :enabled ] = true
2020-07-13 12:46:08 +00:00
when 'false'
2018-04-13 07:11:48 +00:00
preferences [ :notification_sound ] [ :enabled ] = false
end
class_name = preferences [ :notification_sound ] [ :enabled ] . class . to_s
raise Exceptions :: UnprocessableEntity , " preferences.notification_sound.enabled need to be an boolean, but it was a #{ class_name } " if class_name != 'TrueClass' && class_name != 'FalseClass'
2018-10-09 06:17:41 +00:00
2018-04-13 07:11:48 +00:00
true
end
2017-04-18 15:20:40 +00:00
= begin
2017-10-20 11:32:52 +00:00
checks if the current user is the last one with admin permissions .
2017-04-18 15:20:40 +00:00
Raises
raise 'Minimum one user need to have admin permissions'
= end
2017-10-20 11:32:52 +00:00
def last_admin_check_by_attribute
return true if ! will_save_change_to_attribute? ( 'active' )
return true if active != false
return true if ! permissions? ( [ 'admin' , 'admin.user' ] )
raise Exceptions :: UnprocessableEntity , 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
2018-10-09 06:17:41 +00:00
2017-10-20 11:32:52 +00:00
true
end
def last_admin_check_by_role ( role )
2017-06-16 22:53:20 +00:00
return true if Setting . get ( 'import_mode' )
2017-10-20 11:32:52 +00:00
return true if ! role . with_permission? ( [ 'admin' , 'admin.user' ] )
raise Exceptions :: UnprocessableEntity , 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
2018-10-09 06:17:41 +00:00
2017-10-20 11:32:52 +00:00
true
end
2017-04-24 09:55:15 +00:00
2017-10-20 11:32:52 +00:00
def last_admin_check_admin_count
admin_role_ids = Role . joins ( :permissions ) . where ( permissions : { name : [ 'admin' , 'admin.user' ] , active : true } , roles : { active : true } ) . pluck ( :id )
2017-12-13 11:17:57 +00:00
User . joins ( :roles ) . where ( roles : { id : admin_role_ids } , users : { active : true } ) . distinct ( ) . count - 1
2017-10-20 11:32:52 +00:00
end
2017-04-18 15:20:40 +00:00
2017-10-20 11:32:52 +00:00
def validate_agent_limit_by_attributes
2018-09-12 04:23:48 +00:00
return true if Setting . get ( 'system_agent_limit' ) . blank?
2017-10-20 11:32:52 +00:00
return true if ! will_save_change_to_attribute? ( 'active' )
return true if active != true
return true if ! permissions? ( 'ticket.agent' )
2018-10-09 06:17:41 +00:00
2017-10-20 11:32:52 +00:00
ticket_agent_role_ids = Role . joins ( :permissions ) . where ( permissions : { name : 'ticket.agent' , active : true } , roles : { active : true } ) . pluck ( :id )
2017-12-13 11:17:57 +00:00
count = User . joins ( :roles ) . where ( roles : { id : ticket_agent_role_ids } , users : { active : true } ) . distinct ( ) . count + 1
2018-09-12 04:23:48 +00:00
raise Exceptions :: UnprocessableEntity , 'Agent limit exceeded, please check your account settings.' if count > Setting . get ( 'system_agent_limit' ) . to_i
2018-10-09 06:17:41 +00:00
2017-06-16 22:53:20 +00:00
true
2017-04-18 15:20:40 +00:00
end
2017-10-20 11:32:52 +00:00
def validate_agent_limit_by_role ( role )
2018-09-12 04:23:48 +00:00
return true if Setting . get ( 'system_agent_limit' ) . blank?
2017-10-20 11:32:52 +00:00
return true if active != true
return true if role . active != true
return true if ! role . with_permission? ( 'ticket.agent' )
2018-10-09 06:17:41 +00:00
2017-10-20 11:32:52 +00:00
ticket_agent_role_ids = Role . joins ( :permissions ) . where ( permissions : { name : 'ticket.agent' , active : true } , roles : { active : true } ) . pluck ( :id )
2017-12-13 11:17:57 +00:00
count = User . joins ( :roles ) . where ( roles : { id : ticket_agent_role_ids } , users : { active : true } ) . distinct ( ) . count
2017-11-17 14:39:56 +00:00
# if new added role is a ticket.agent role
2017-04-18 07:38:53 +00:00
if ticket_agent_role_ids . include? ( role . id )
2017-11-17 14:39:56 +00:00
# if user already has a ticket.agent role
hint = false
role_ids . each do | locale_role_id |
next if ! ticket_agent_role_ids . include? ( locale_role_id )
2018-10-09 06:17:41 +00:00
2017-11-17 14:39:56 +00:00
hint = true
break
end
# user has not already a ticket.agent role
if hint == false
count += 1
end
2017-04-18 07:38:53 +00:00
end
2018-09-12 04:23:48 +00:00
raise Exceptions :: UnprocessableEntity , 'Agent limit exceeded, please check your account settings.' if count > Setting . get ( 'system_agent_limit' ) . to_i
2018-10-09 06:17:41 +00:00
2017-06-16 22:53:20 +00:00
true
2017-04-18 07:38:53 +00:00
end
2016-11-13 22:59:39 +00:00
def domain_based_assignment
2017-06-16 22:53:20 +00:00
return true if ! email
return true if organization_id
2018-10-09 06:17:41 +00:00
2016-11-13 22:59:39 +00:00
begin
domain = Mail :: Address . new ( email ) . domain
2017-06-16 22:53:20 +00:00
return true if ! domain
2018-10-09 06:17:41 +00:00
2016-11-13 22:59:39 +00:00
organization = Organization . find_by ( domain : domain . downcase , domain_assignment : true )
2017-06-16 22:53:20 +00:00
return true if ! organization
2018-10-09 06:17:41 +00:00
2016-11-13 22:59:39 +00:00
self . organization_id = organization . id
rescue
2017-06-16 22:53:20 +00:00
return true
2016-11-13 22:59:39 +00:00
end
2017-06-16 22:53:20 +00:00
true
2016-11-13 22:59:39 +00:00
end
2017-02-06 14:06:54 +00:00
# sets locale of the user
def set_locale
# set the user's locale to the one of the "executing" user
2017-06-16 22:53:20 +00:00
return true if ! UserInfo . current_user_id
2018-10-09 06:17:41 +00:00
2017-06-14 15:25:45 +00:00
user = User . find_by ( id : UserInfo . current_user_id )
2017-06-16 22:53:20 +00:00
return true if ! user
return true if ! user . preferences [ :locale ]
2017-02-06 14:06:54 +00:00
2017-02-06 14:20:59 +00:00
preferences [ :locale ] = user . preferences [ :locale ]
2017-06-16 22:53:20 +00:00
true
2017-02-06 14:06:54 +00:00
end
2015-07-06 18:33:37 +00:00
def avatar_for_email_check
2018-02-08 05:35:02 +00:00
return true if Setting . get ( 'import_mode' )
2017-06-16 22:53:20 +00:00
return true if email . blank?
2019-11-21 15:49:14 +00:00
email_address_validation = EmailAddressValidation . new ( email )
return true if ! email_address_validation . valid_format?
2017-09-23 06:25:55 +00:00
return true if ! saved_change_to_attribute? ( 'email' ) && updated_at > Time . zone . now - 10 . days
2013-11-02 21:32:00 +00:00
2014-12-01 07:32:35 +00:00
# save/update avatar
avatar = Avatar . auto_detection (
2018-12-19 17:31:51 +00:00
object : 'User' ,
o_id : id ,
url : email ,
source : 'app' ,
2015-05-07 12:10:38 +00:00
updated_by_id : updated_by_id ,
created_by_id : updated_by_id ,
2014-12-01 07:32:35 +00:00
)
2013-11-02 21:32:00 +00:00
2014-12-01 07:32:35 +00:00
# update user link
2017-06-16 22:53:20 +00:00
return true if ! avatar
2015-04-30 15:25:04 +00:00
2017-11-23 08:09:44 +00:00
update_column ( :image , avatar . store_hash ) # rubocop:disable Rails/SkipsModelValidations
2015-05-07 12:10:38 +00:00
cache_delete
2017-06-16 22:53:20 +00:00
true
2014-12-01 07:32:35 +00:00
end
2018-05-08 10:10:19 +00:00
def destroy_longer_required_objects
2018-08-31 10:25:06 +00:00
:: Authorization . where ( user_id : id ) . destroy_all
:: Avatar . remove ( 'User' , id )
:: Cti :: CallerId . where ( user_id : id ) . destroy_all
:: Taskbar . where ( user_id : id ) . destroy_all
:: Karma :: ActivityLog . where ( user_id : id ) . destroy_all
:: Karma :: User . where ( user_id : id ) . destroy_all
:: OnlineNotification . where ( user_id : id ) . destroy_all
:: RecentView . where ( created_by_id : id ) . destroy_all
:: UserDevice . remove ( id )
2018-09-10 12:35:12 +00:00
:: Token . where ( user_id : id ) . destroy_all
2018-10-03 06:23:22 +00:00
:: StatsStore . remove (
object : 'User' ,
2018-12-19 17:31:51 +00:00
o_id : id ,
2018-10-03 06:23:22 +00:00
)
2018-05-08 10:10:19 +00:00
true
2018-03-20 12:16:17 +00:00
end
2017-01-27 08:17:03 +00:00
def ensure_password
2019-06-27 11:51:29 +00:00
self . password = ensured_password
2017-06-16 22:53:20 +00:00
true
2017-01-27 08:17:03 +00:00
end
2012-10-18 11:42:05 +00:00
2019-06-27 11:51:29 +00:00
def ensured_password
# ensure unset password for blank values of new users
return nil if new_record? && password . blank?
2013-01-23 22:13:02 +00:00
2019-06-27 11:51:29 +00:00
# don't permit empty password update for existing users
return password_was if password . blank?
2014-12-01 07:32:35 +00:00
2019-07-31 08:23:48 +00:00
# don't re-hash passwords
2019-06-27 11:51:29 +00:00
return password if PasswordHash . crypted? ( password )
2015-04-30 15:25:04 +00:00
2019-06-27 11:51:29 +00:00
# hash the plaintext password
PasswordHash . crypt ( password )
2013-06-12 15:59:58 +00:00
end
2017-02-24 17:27:27 +00:00
# reset login_failed if password is changed
def reset_login_failed
2017-09-23 06:25:55 +00:00
return true if ! will_save_change_to_attribute? ( 'password' )
2018-10-09 06:17:41 +00:00
2017-02-24 17:27:27 +00:00
self . login_failed = 0
2017-06-16 22:53:20 +00:00
true
2017-02-24 17:27:27 +00:00
end
2018-07-23 08:28:21 +00:00
# When adding/removing a phone number from the User table,
# update caller ID table
# to adopt/orphan matching Cti::Logs accordingly
# (see https://github.com/zammad/zammad/issues/2057)
def update_caller_id
# skip if "phone" does not change, or changes like [nil, ""]
return if persisted? && ! previous_changes [ :phone ] & . any? ( & :present? )
return if destroyed? && phone . blank?
Cti :: CallerId . build ( self )
end
2015-04-27 14:15:29 +00:00
end