2016-10-19 03:11:36 +00:00
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
2012-04-16 08:04:49 +00:00
class User < ApplicationModel
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
2017-06-16 20:43:09 +00:00
include HasGroups
include HasRoles
2017-01-31 17:13:45 +00:00
2018-04-26 08:55:53 +00:00
include User :: ChecksAccess
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 :roles , after_add : % i [ cache_update check_notifications ] , after_remove : :cache_update , before_add : % i [ validate_agent_limit_by_role validate_roles ] , before_remove : :last_admin_check_by_role , class_name : 'Role'
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
belongs_to :organization , inverse_of : :members
2017-11-21 07:37:09 +00:00
before_validation :check_name , :check_email , :check_login , :check_mail_delivery_failed , :ensure_uniq_email , :ensure_password , :ensure_roles , :ensure_identifier
2018-04-13 07:11:48 +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
2015-07-06 18:33:37 +00:00
after_create :avatar_for_email_check
after_update :avatar_for_email_check
2018-07-23 08:28:21 +00:00
after_commit :update_caller_id
2018-05-08 10:10:19 +00:00
before_destroy :destroy_longer_required_objects
2012-04-10 14:06:46 +00:00
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
2017-01-31 17:13:45 +00:00
def ignore_search_indexing? ( _action )
# ignore internal user
return true if id == 1
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?
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?
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
authenticate user agains sso
result = User . sso ( sso_params )
returns
result = user_model # user model if authentication was successfully
= end
2013-02-17 18:28:32 +00:00
def self . sso ( params )
# try to login against configure auth backends
2016-01-15 19:09:16 +00:00
user_auth = Sso . check ( params )
2013-08-17 21:48:01 +00:00
return if ! user_auth
2013-02-17 18:28:32 +00:00
2014-12-30 23:51:19 +00:00
user_auth
2013-02-17 18:28:32 +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
2016-08-12 16:39:09 +00:00
role_ids = Role . signup_role_ids
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?
url = local_url
2012-04-10 14:06:46 +00:00
end
2018-07-16 15:07:23 +00:00
begin
create! (
login : hash [ 'info' ] [ 'nickname' ] || hash [ 'uid' ] ,
firstname : hash [ 'info' ] [ '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_ids ,
updated_by_id : 1 ,
created_by_id : 1 ,
)
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
list = { }
2017-10-18 09:13:11 +00:00
:: Permission . select ( 'permissions.name, permissions.preferences' ) . joins ( :roles ) . where ( 'roles.id IN (?) AND permissions.active = ?' , role_ids , true ) . pluck ( :name , :preferences ) . each do | permission |
2016-08-31 07:10:25 +00:00
next if permission [ 1 ] [ 'selectable' ] == false
list [ permission [ 0 ] ] = true
2017-10-01 12:25:52 +00:00
end
2016-08-12 16:39:09 +00:00
list
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
def permissions? ( key )
keys = key
names = [ ]
if key . class == String
keys = [ key ]
end
2017-10-01 12:25:52 +00:00
keys . each do | local_key |
2016-08-26 10:06:27 +00:00
list = [ ]
2017-11-23 08:09:44 +00:00
if local_key . match? ( / \ . \ *$ / )
2016-08-26 10:06:27 +00:00
local_key . sub! ( '.*' , '.%' )
2017-10-18 09:13:11 +00:00
permissions = :: Permission . with_parents ( local_key )
list = :: Permission . select ( 'preferences' ) . joins ( :roles ) . where ( 'roles.id IN (?) AND roles.active = ? AND (permissions.name IN (?) OR permissions.name LIKE ?) AND permissions.active = ?' , role_ids , true , permissions , local_key , true ) . pluck ( :preferences )
2016-08-26 10:06:27 +00:00
else
2017-10-18 09:13:11 +00:00
permission = :: Permission . lookup ( name : local_key )
2017-11-23 08:09:44 +00:00
break if permission & . active == false
2017-10-18 09:13:11 +00:00
permissions = :: Permission . with_parents ( local_key )
list = :: Permission . select ( 'preferences' ) . joins ( :roles ) . where ( 'roles.id IN (?) AND roles.active = ? AND permissions.name IN (?) AND permissions.active = ?' , role_ids , true , permissions , true ) . pluck ( :preferences )
2017-10-01 12:25:52 +00:00
end
2017-10-18 09:13:11 +00:00
return true if list . present?
2017-10-01 12:25:52 +00:00
end
2016-08-12 16:39:09 +00:00
false
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 == ''
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
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?
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?
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 ,
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
2017-09-11 11:16:08 +00:00
user . update! ( password : password )
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
2015-05-08 10:20:33 +00:00
self . last_login = Time . zone . now
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 ,
user : user ,
}
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 )
# find email addresses and move them to primary user
duplicate_user = User . find ( user_id_of_duplicate_user )
# merge missing attibutes
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
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
2016-09-29 11:35:42 +00:00
update / sync default preferences of users in a dedecated permissions
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
default = Rails . configuration . preferences_default_by_permission
return false if ! default
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 ]
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 ]
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
2016-02-08 07:12:04 +00:00
update / sync default preferences of users in a dedecated role
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
2016-09-29 11:25:20 +00:00
default = Rails . configuration . preferences_default_by_permission
return false if ! default
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
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 ]
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 ]
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?
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?
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?
2015-05-07 12:10:38 +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
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?
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
2016-09-14 22:56:04 +00:00
raise Exceptions :: UnprocessableEntity , 'Invalid email' if email !~ / @ /
2017-11-23 08:09:44 +00:00
raise Exceptions :: UnprocessableEntity , 'Invalid email' if email . match? ( / \ s / )
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
return true if ! changes || ! changes [ 'email' ]
preferences . delete ( :mail_delivery_failed )
true
end
2017-07-12 14:41:10 +00:00
def ensure_roles
return true if role_ids . present?
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-' )
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' ]
return true if ! User . find_by ( email : email . downcase . strip )
raise Exceptions :: UnprocessableEntity , 'Email address is already used for other user.'
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?
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 )
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 )
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 ]
if preferences [ :notification_sound ] [ :enabled ] == 'true'
preferences [ :notification_sound ] [ :enabled ] = true
elsif preferences [ :notification_sound ] [ :enabled ] == 'false'
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'
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
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
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
return true if ! Setting . get ( 'system_agent_limit' )
return true if ! will_save_change_to_attribute? ( 'active' )
return true if active != true
return true if ! permissions? ( 'ticket.agent' )
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
2017-10-20 11:32:52 +00:00
raise Exceptions :: UnprocessableEntity , 'Agent limit exceeded, please check your account settings.' if count > Setting . get ( 'system_agent_limit' )
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 )
2017-06-16 22:53:20 +00:00
return true if ! Setting . get ( 'system_agent_limit' )
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' )
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 )
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
raise Exceptions :: UnprocessableEntity , 'Agent limit exceeded, please check your account settings.' if count > Setting . get ( 'system_agent_limit' )
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
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
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
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
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?
return true if email !~ / @ /
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 (
2015-04-27 13:42:53 +00:00
object : 'User' ,
2015-05-07 12:10:38 +00:00
o_id : id ,
url : email ,
2015-04-27 13:42:53 +00:00
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
Authorization . where ( user_id : id ) . destroy_all
2016-01-15 19:09:16 +00:00
Avatar . remove ( 'User' , id )
2018-03-20 12:16:17 +00:00
Cti :: CallerId . where ( user_id : id ) . destroy_all
Taskbar . where ( user_id : id ) . destroy_all
2018-05-08 10:10:19 +00:00
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 )
true
2018-03-20 12:16:17 +00:00
end
2017-01-27 08:17:03 +00:00
def ensure_password
2017-06-16 22:53:20 +00:00
return true if password_empty?
return true if PasswordHash . crypted? ( password )
2017-01-27 08:17:03 +00:00
self . password = PasswordHash . crypt ( 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
2017-01-27 08:17:03 +00:00
def password_empty?
2013-06-12 15:59:58 +00:00
# set old password again if not given
2017-01-27 08:17:03 +00:00
return if password . present?
2013-01-23 22:13:02 +00:00
2017-01-27 08:17:03 +00:00
# skip if it's not desired to set a password (yet)
return true if ! password
2014-12-01 07:32:35 +00:00
2017-01-27 08:17:03 +00:00
# get current record
return if ! id
2015-04-30 15:25:04 +00:00
2017-01-27 08:17:03 +00:00
self . password = password_was
true
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' )
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