2021-06-01 12:20:20 +00:00
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
2012-04-16 08:04:49 +00:00
class User < ApplicationModel
2020-08-14 11:12:41 +00:00
include CanBeAuthorized
2019-01-28 06:04:05 +00:00
include CanBeImported
2017-05-02 15:21:13 +00:00
include HasActivityStreamLog
include ChecksClientNotification
2021-08-25 12:24:42 +00:00
include ChecksCoreWorkflow
2017-05-02 15:21:13 +00:00
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
2021-08-17 16:37:16 +00:00
include HasObjectManagerAttributes
2021-06-23 11:35:27 +00:00
include :: HasTicketCreateScreenImpact
2020-09-08 15:06:23 +00:00
include HasTaskbars
2020-02-20 13:34:03 +00:00
include User :: HasTicketCreateScreenImpact
2013-08-19 06:29:49 +00:00
include User :: Assets
2021-04-12 14:03:51 +00:00
include User :: Avatar
2018-04-26 08:55:53 +00:00
include User :: Search
2016-07-06 06:13:44 +00:00
include User :: SearchIndex
2021-03-01 08:18:40 +00:00
include User :: TouchesOrganization
include User :: PerformsGeoLookup
include User :: UpdatesTicketOrganization
2013-08-19 06:29:49 +00:00
2021-05-20 06:59:02 +00:00
include HasTransactionDispatcher
2020-09-08 15:06:23 +00:00
has_and_belongs_to_many :organizations , after_add : :cache_update , after_remove : :cache_update , class_name : 'Organization'
2020-10-15 06:37:21 +00:00
has_and_belongs_to_many :overviews , dependent : :nullify
2020-09-08 15:06:23 +00:00
has_many :tokens , after_add : :cache_update , after_remove : :cache_update , dependent : :destroy
has_many :authorizations , after_add : :cache_update , after_remove : :cache_update , dependent : :destroy
has_many :online_notifications , dependent : :destroy
has_many :taskbars , dependent : :destroy
has_many :user_devices , dependent : :destroy
has_one :chat_agent_created_by , class_name : 'Chat::Agent' , foreign_key : :created_by_id , dependent : :destroy , inverse_of : :created_by
has_one :chat_agent_updated_by , class_name : 'Chat::Agent' , foreign_key : :updated_by_id , dependent : :destroy , inverse_of : :updated_by
has_many :chat_sessions , class_name : 'Chat::Session' , dependent : :destroy
has_many :karma_user , class_name : 'Karma::User' , dependent : :destroy
2021-03-16 08:59:32 +00:00
has_many :mentions , dependent : :destroy
2020-09-08 15:06:23 +00:00
has_many :karma_activity_logs , class_name : 'Karma::ActivityLog' , dependent : :destroy
has_many :cti_caller_ids , class_name : 'Cti::CallerId' , dependent : :destroy
has_many :customer_tickets , class_name : 'Ticket' , foreign_key : :customer_id , dependent : :destroy , inverse_of : :customer
has_many :owner_tickets , class_name : 'Ticket' , foreign_key : :owner_id , inverse_of : :owner
has_many :created_recent_views , class_name : 'RecentView' , foreign_key : :created_by_id , dependent : :destroy , inverse_of : :created_by
has_many :permissions , - > { where ( roles : { active : true } , active : true ) } , through : :roles
has_many :data_privacy_tasks , as : :deletable
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
2021-08-05 08:11:35 +00:00
before_update :check_preferences_default , :validate_preferences , :validate_ooo , :reset_login_failed_after_password_change , :validate_agent_limit_by_attributes , :last_admin_check_by_attribute
2020-09-08 15:06:23 +00:00
before_destroy :destroy_longer_required_objects , :destroy_move_dependency_ownership
2020-09-30 09:07:01 +00:00
after_commit :update_caller_id
2018-11-06 05:42:52 +00:00
2018-04-12 14:57:37 +00:00
store :preferences
2012-04-14 15:53:00 +00:00
2021-03-16 08:59:32 +00:00
association_attributes_ignored :online_notifications , :templates , :taskbars , :user_devices , :chat_sessions , :karma_activity_logs , :cti_caller_ids , :text_modules , :customer_tickets , :owner_tickets , :created_recent_views , :chat_agents , :data_privacy_tasks , :overviews , :mentions
2020-09-08 15:06:23 +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
2020-08-14 11:12:41 +00:00
association_attributes_ignored :permissions
2017-01-31 17:13:45 +00:00
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
2021-08-02 13:38:11 +00:00
Time . use_zone ( Setting . get ( 'timezone_default' ) . presence ) do
start = out_of_office_start_at . beginning_of_day
finish = out_of_office_end_at . end_of_day
Time . zone . now . between? start , finish
end
2017-09-05 09:49:32 +00:00
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
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 )
2021-08-16 06:49:32 +00:00
return if identifier . blank?
2017-04-19 10:09:54 +00:00
# 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-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 ]
2020-08-14 11:12:41 +00:00
permissions . pluck ( :name ) . each 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
2021-07-16 13:29:38 +00:00
Role . joins ( :permissions_roles ) . 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
2021-06-23 11:35:27 +00:00
User . joins ( :roles_users ) . 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
2021-06-23 11:35:27 +00:00
return User . where ( active : true ) . joins ( :roles_users ) . where ( 'roles_users.role_id' = > 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 )
2021-06-23 11:35:27 +00:00
. joins ( :roles_users )
2016-02-07 13:00:29 +00:00
. 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
2020-09-30 09:07:01 +00:00
if @preferences_default . blank? && id
roles . each do | role |
check_notifications ( role , false )
2017-06-14 15:25:45 +00:00
end
end
2020-09-30 09:07:01 +00:00
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"
2021-05-12 11:37:44 +00:00
if string =~ %r{ ^(((Dr \ .|Prof \ .)[[:space:]]|).+?)[[:space:]](.+?)$ }i
2018-07-16 15:07:23 +00:00
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?
2021-05-12 11:37:44 +00:00
scan = email . scan ( %r{ ^(.+?) \ .(.+?)@.+?$ } )
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?
2021-05-12 11:37:44 +00:00
if firstname . present? && firstname . match ( %r{ ^[A-z]+$ } ) && ( firstname . downcase == firstname || firstname . upcase == firstname )
2018-07-16 15:07:23 +00:00
firstname . capitalize!
end
2021-05-12 11:37:44 +00:00
if lastname . present? && lastname . match ( %r{ ^[A-z]+$ } ) && ( lastname . downcase == lastname || lastname . upcase == lastname )
2018-07-16 15:07:23 +00:00
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
2020-09-30 09:07:01 +00:00
if changes && changes [ 'email' ] && changes [ 'email' ] [ 0 ] == login
self . login = email
2015-01-07 20:42:12 +00:00
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?
2020-08-03 08:35:43 +00:00
raise Exceptions :: UnprocessableEntity , 'out of office no such replacement user' if ! User . exists? ( 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 )
2021-07-16 13:29:38 +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 )
2021-07-16 13:29:38 +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 )
2021-07-16 13:29:38 +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 |
2020-09-30 09:07:01 +00:00
next if ticket_agent_role_ids . exclude? ( 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
2018-05-08 10:10:19 +00:00
def destroy_longer_required_objects
2020-09-08 15:06:23 +00:00
:: Avatar . remove ( self . class . to_s , id )
2018-08-31 10:25:06 +00:00
:: UserDevice . remove ( id )
2020-10-06 13:13:50 +00:00
:: StatsStore . where ( stats_storable : self ) . destroy_all
2020-09-08 15:06:23 +00:00
end
def destroy_move_dependency_ownership
result = Models . references ( self . class . to_s , id )
2021-06-02 10:25:12 +00:00
user_columns = %w[ created_by_id updated_by_id out_of_office_replacement_id origin_by_id owner_id archived_by_id published_by_id internal_by_id ]
2020-09-08 15:06:23 +00:00
result . each do | class_name , references |
next if class_name . blank?
next if references . blank?
2021-03-02 11:03:21 +00:00
ref_class = class_name . constantize
ref_update_columns = [ ]
2020-09-08 15:06:23 +00:00
references . each do | column , reference_found |
next if ! reference_found
2020-09-30 09:07:01 +00:00
if user_columns . include? ( column )
2021-03-02 11:03:21 +00:00
ref_update_columns << column
2020-09-08 15:06:23 +00:00
elsif ref_class . exists? ( column = > id )
raise " Failed deleting references! Check logic for #{ class_name } -> #{ column } . "
end
end
2021-03-02 11:03:21 +00:00
next if ref_update_columns . blank?
where_sql = ref_update_columns . map { | column | " #{ column } = #{ id } " } . join ( ' OR ' )
ref_class . where ( where_sql ) . find_in_batches ( batch_size : 1000 ) do | batch_list |
batch_list . each do | record |
ref_update_columns . each do | column |
next if record [ column ] != id
record [ column ] = 1
end
record . save!
rescue = > e
Rails . logger . error e
end
end
2020-09-08 15:06:23 +00:00
end
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
2021-08-05 08:11:35 +00:00
def reset_login_failed_after_password_change
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