user.rb 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. require 'digest/md5'
  3. # @model User
  4. #
  5. # @property id(required) [Integer] The identifier for the User.
  6. # @property login(required) [String] The login of the User used for authentication.
  7. # @property firstname [String] The firstname of the User.
  8. # @property lastname [String] The lastname of the User.
  9. # @property email [String] The email of the User.
  10. # @property image [String] The Image used as the User avatar (TODO: Image model?).
  11. # @property web [String] The website/URL of the User.
  12. # @property password [String] The password of the User.
  13. # @property phone [String] The phone number of the User.
  14. # @property fax [String] The fax number of the User.
  15. # @property mobile [String] The mobile number of the User.
  16. # @property department [String] The department the User is working at.
  17. # @property street [String] The street the User lives in.
  18. # @property zip [Integer] The zip postal code of the User city.
  19. # @property city [String] The city the User lives in.
  20. # @property country [String] The country the User lives in.
  21. # @property verified [Boolean] The flag that shows the verified state of the User.
  22. # @property active [Boolean] The flag that shows the active state of the User.
  23. # @property note [String] The note or comment stored to the User.
  24. class User < ApplicationModel
  25. include HasActivityStreamLog
  26. include ChecksClientNotification
  27. include HasHistory
  28. include HasSearchIndexBackend
  29. include HasGroups
  30. include HasRoles
  31. include User::ChecksAccess
  32. load 'user/assets.rb'
  33. include User::Assets
  34. extend User::Search
  35. load 'user/search_index.rb'
  36. include User::SearchIndex
  37. before_validation :check_name, :check_email, :check_login, :check_mail_delivery_failed, :ensure_uniq_email, :ensure_password, :ensure_roles, :ensure_identifier
  38. before_create :check_preferences_default, :validate_ooo, :domain_based_assignment, :set_locale
  39. before_update :check_preferences_default, :validate_ooo, :reset_login_failed, :validate_agent_limit_by_attributes, :last_admin_check_by_attribute
  40. after_create :avatar_for_email_check
  41. after_update :avatar_for_email_check
  42. after_destroy :avatar_destroy, :user_device_destroy
  43. 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'
  44. has_and_belongs_to_many :organizations, after_add: :cache_update, after_remove: :cache_update, class_name: 'Organization'
  45. #has_many :permissions, class_name: 'Permission', through: :roles, class_name: 'Role'
  46. has_many :tokens, after_add: :cache_update, after_remove: :cache_update
  47. has_many :authorizations, after_add: :cache_update, after_remove: :cache_update
  48. belongs_to :organization, class_name: 'Organization'
  49. store :preferences
  50. activity_stream_permission 'admin.user'
  51. activity_stream_attributes_ignored :last_login,
  52. :login_failed,
  53. :image,
  54. :image_source,
  55. :preferences
  56. history_attributes_ignored :password,
  57. :last_login,
  58. :image,
  59. :image_source,
  60. :preferences
  61. search_index_attributes_ignored :password,
  62. :image,
  63. :image_source,
  64. :source,
  65. :login_failed,
  66. :preferences
  67. def ignore_search_indexing?(_action)
  68. # ignore internal user
  69. return true if id == 1
  70. false
  71. end
  72. =begin
  73. fullname of user
  74. user = User.find(123)
  75. result = user.fullname
  76. returns
  77. result = "Bob Smith"
  78. =end
  79. def fullname
  80. name = ''
  81. if firstname.present?
  82. name = firstname
  83. end
  84. if lastname.present?
  85. if name != ''
  86. name += ' '
  87. end
  88. name += lastname
  89. end
  90. if name.blank? && email.present?
  91. name = email
  92. end
  93. name
  94. end
  95. =begin
  96. longname of user
  97. user = User.find(123)
  98. result = user.longname
  99. returns
  100. result = "Bob Smith"
  101. or with org
  102. result = "Bob Smith (Org ABC)"
  103. =end
  104. def longname
  105. name = fullname
  106. if organization_id
  107. organization = Organization.lookup(id: organization_id)
  108. if organization
  109. name += " (#{organization.name})"
  110. end
  111. end
  112. name
  113. end
  114. =begin
  115. check if user is in role
  116. user = User.find(123)
  117. result = user.role?('Customer')
  118. result = user.role?(['Agent', 'Admin'])
  119. returns
  120. result = true|false
  121. =end
  122. def role?(role_name)
  123. roles.where(name: role_name).any?
  124. end
  125. =begin
  126. check if user is in role
  127. user = User.find(123)
  128. result = user.out_of_office?
  129. returns
  130. result = true|false
  131. =end
  132. def out_of_office?
  133. return false if out_of_office != true
  134. return false if out_of_office_start_at.blank?
  135. return false if out_of_office_end_at.blank?
  136. Time.zone.today.between?(out_of_office_start_at, out_of_office_end_at)
  137. end
  138. =begin
  139. check if user is in role
  140. user = User.find(123)
  141. result = user.out_of_office_agent
  142. returns
  143. result = user_model
  144. =end
  145. def out_of_office_agent
  146. return if !out_of_office?
  147. return if out_of_office_replacement_id.blank?
  148. User.find_by(id: out_of_office_replacement_id)
  149. end
  150. =begin
  151. gets users where user is replacement
  152. user = User.find(123)
  153. result = user.out_of_office_agent_of
  154. returns
  155. result = [user_model1, user_model2]
  156. =end
  157. def out_of_office_agent_of
  158. 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)
  159. end
  160. =begin
  161. get users activity stream
  162. user = User.find(123)
  163. result = user.activity_stream(20)
  164. returns
  165. result = [
  166. {
  167. id: 2,
  168. o_id: 2,
  169. created_by_id: 3,
  170. created_at: '2013-09-28 00:57:21',
  171. object: "User",
  172. type: "created",
  173. },
  174. {
  175. id: 2,
  176. o_id: 2,
  177. created_by_id: 3,
  178. created_at: '2013-09-28 00:59:21',
  179. object: "User",
  180. type: "updated",
  181. },
  182. ]
  183. =end
  184. def activity_stream(limit, fulldata = false)
  185. activity_stream = ActivityStream.list(self, limit)
  186. return activity_stream if !fulldata
  187. # get related objects
  188. assets = ApplicationModel.assets_of_object_list(activity_stream)
  189. {
  190. activity_stream: activity_stream,
  191. assets: assets,
  192. }
  193. end
  194. =begin
  195. authenticate user
  196. result = User.authenticate(username, password)
  197. returns
  198. result = user_model # user model if authentication was successfully
  199. =end
  200. def self.authenticate(username, password)
  201. # do not authenticate with nothing
  202. return if username.blank? || password.blank?
  203. user = User.identify(username)
  204. return if !user
  205. return if !Auth.can_login?(user)
  206. return user if Auth.valid?(user, password)
  207. sleep 1
  208. user.login_failed += 1
  209. user.save!
  210. nil
  211. end
  212. =begin
  213. checks if a user has reached the maximum of failed login tries
  214. user = User.find(123)
  215. result = user.max_login_failed?
  216. returns
  217. result = true | false
  218. =end
  219. def max_login_failed?
  220. max_login_failed = Setting.get('password_max_login_failed').to_i || 10
  221. login_failed > max_login_failed
  222. end
  223. =begin
  224. tries to find the matching instance by the given identifier. Currently email and login is supported.
  225. user = User.indentify('User123')
  226. # or
  227. user = User.indentify('user-123@example.com')
  228. returns
  229. # User instance
  230. user.login # 'user123'
  231. =end
  232. def self.identify(identifier)
  233. # try to find user based on login
  234. user = User.find_by(login: identifier.downcase)
  235. return user if user
  236. # try second lookup with email
  237. User.find_by(email: identifier.downcase)
  238. end
  239. =begin
  240. authenticate user agains sso
  241. result = User.sso(sso_params)
  242. returns
  243. result = user_model # user model if authentication was successfully
  244. =end
  245. def self.sso(params)
  246. # try to login against configure auth backends
  247. user_auth = Sso.check(params)
  248. return if !user_auth
  249. user_auth
  250. end
  251. =begin
  252. create user from from omni auth hash
  253. result = User.create_from_hash!(hash)
  254. returns
  255. result = user_model # user model if create was successfully
  256. =end
  257. def self.create_from_hash!(hash)
  258. role_ids = Role.signup_role_ids
  259. url = ''
  260. hash['info']['urls']&.each_value do |local_url|
  261. next if local_url.blank?
  262. url = local_url
  263. end
  264. create(
  265. login: hash['info']['nickname'] || hash['uid'],
  266. firstname: hash['info']['name'],
  267. email: hash['info']['email'],
  268. image_source: hash['info']['image'],
  269. web: url,
  270. address: hash['info']['location'],
  271. note: hash['info']['description'],
  272. source: hash['provider'],
  273. role_ids: role_ids,
  274. updated_by_id: 1,
  275. created_by_id: 1,
  276. )
  277. end
  278. =begin
  279. get all permissions of user
  280. user = User.find(123)
  281. user.permissions
  282. returns
  283. {
  284. 'permission.key' => true,
  285. # ...
  286. }
  287. =end
  288. def permissions
  289. list = {}
  290. ::Permission.select('permissions.name, permissions.preferences').joins(:roles).where('roles.id IN (?) AND permissions.active = ?', role_ids, true).pluck(:name, :preferences).each do |permission|
  291. next if permission[1]['selectable'] == false
  292. list[permission[0]] = true
  293. end
  294. list
  295. end
  296. =begin
  297. true or false for permission
  298. user = User.find(123)
  299. user.permissions?('permission.key') # access to certain permission.key
  300. user.permissions?(['permission.key1', 'permission.key2']) # access to permission.key1 or permission.key2
  301. user.permissions?('permission') # access to all sub keys
  302. user.permissions?('permission.*') # access if one sub key access exists
  303. returns
  304. true|false
  305. =end
  306. def permissions?(key)
  307. keys = key
  308. names = []
  309. if key.class == String
  310. keys = [key]
  311. end
  312. keys.each do |local_key|
  313. list = []
  314. if local_key.match?(/\.\*$/)
  315. local_key.sub!('.*', '.%')
  316. permissions = ::Permission.with_parents(local_key)
  317. 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)
  318. else
  319. permission = ::Permission.lookup(name: local_key)
  320. break if permission&.active == false
  321. permissions = ::Permission.with_parents(local_key)
  322. 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)
  323. end
  324. return true if list.present?
  325. end
  326. false
  327. end
  328. =begin
  329. returns all accessable permission ids of user
  330. user = User.find(123)
  331. user.permissions_with_child_ids
  332. returns
  333. [permission1_id, permission2_id, permission3_id]
  334. =end
  335. def permissions_with_child_ids
  336. where = ''
  337. where_bind = [true]
  338. permissions.each_key do |permission_name|
  339. where += ' OR ' if where != ''
  340. where += 'permissions.name = ? OR permissions.name LIKE ?'
  341. where_bind.push permission_name
  342. where_bind.push "#{permission_name}.%"
  343. end
  344. return [] if where == ''
  345. ::Permission.where("permissions.active = ? AND (#{where})", *where_bind).pluck(:id)
  346. end
  347. =begin
  348. get all users with permission
  349. users = User.with_permissions('ticket.agent')
  350. get all users with permission "admin.session" or "ticket.agent"
  351. users = User.with_permissions(['admin.session', 'ticket.agent'])
  352. returns
  353. [user1, user2, ...]
  354. =end
  355. def self.with_permissions(keys)
  356. if keys.class != Array
  357. keys = [keys]
  358. end
  359. total_role_ids = []
  360. permission_ids = []
  361. keys.each do |key|
  362. role_ids = []
  363. ::Permission.with_parents(key).each do |local_key|
  364. permission = ::Permission.lookup(name: local_key)
  365. next if !permission
  366. permission_ids.push permission.id
  367. end
  368. next if permission_ids.blank?
  369. 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|
  370. role_ids.push role_id
  371. end
  372. total_role_ids.push role_ids
  373. end
  374. return [] if total_role_ids.blank?
  375. condition = ''
  376. total_role_ids.each do |_role_ids|
  377. if condition != ''
  378. condition += ' OR '
  379. end
  380. condition += 'roles_users.role_id IN (?)'
  381. end
  382. User.joins(:users_roles).where("(#{condition}) AND users.active = ?", *total_role_ids, true).distinct.order(:id)
  383. end
  384. =begin
  385. generate new token for reset password
  386. result = User.password_reset_new_token(username)
  387. returns
  388. result = {
  389. token: token,
  390. user: user,
  391. }
  392. =end
  393. def self.password_reset_new_token(username)
  394. return if username.blank?
  395. # try to find user based on login
  396. user = User.find_by(login: username.downcase, active: true)
  397. # try second lookup with email
  398. user ||= User.find_by(email: username.downcase, active: true)
  399. # check if email address exists
  400. return if !user
  401. return if !user.email
  402. # generate token
  403. token = Token.create(action: 'PasswordReset', user_id: user.id)
  404. {
  405. token: token,
  406. user: user,
  407. }
  408. end
  409. =begin
  410. returns the User instance for a given password token if found
  411. result = User.by_reset_token(token)
  412. returns
  413. result = user_model # user_model if token was verified
  414. =end
  415. def self.by_reset_token(token)
  416. Token.check(action: 'PasswordReset', name: token)
  417. end
  418. =begin
  419. reset password with token and set new password
  420. result = User.password_reset_via_token(token,password)
  421. returns
  422. result = user_model # user_model if token was verified
  423. =end
  424. def self.password_reset_via_token(token, password)
  425. # check token
  426. user = by_reset_token(token)
  427. return if !user
  428. # reset password
  429. user.update!(password: password)
  430. # delete token
  431. Token.find_by(action: 'PasswordReset', name: token).destroy
  432. user
  433. end
  434. =begin
  435. update last login date and reset login_failed (is automatically done by auth and sso backend)
  436. user = User.find(123)
  437. result = user.update_last_login
  438. returns
  439. result = new_user_model
  440. =end
  441. def update_last_login
  442. self.last_login = Time.zone.now
  443. # reset login failed
  444. self.login_failed = 0
  445. save
  446. end
  447. =begin
  448. generate new token for signup
  449. result = User.signup_new_token(user) # or email
  450. returns
  451. result = {
  452. token: token,
  453. user: user,
  454. }
  455. =end
  456. def self.signup_new_token(user)
  457. return if !user
  458. return if !user.email
  459. # generate token
  460. token = Token.create(action: 'Signup', user_id: user.id)
  461. {
  462. token: token,
  463. user: user,
  464. }
  465. end
  466. =begin
  467. verify signup with token
  468. result = User.signup_verify_via_token(token, user)
  469. returns
  470. result = user_model # user_model if token was verified
  471. =end
  472. def self.signup_verify_via_token(token, user = nil)
  473. # check token
  474. local_user = Token.check(action: 'Signup', name: token)
  475. return if !local_user
  476. # if requested user is different to current user
  477. return if user && local_user.id != user.id
  478. # set verified
  479. local_user.update!(verified: true)
  480. # delete token
  481. Token.find_by(action: 'Signup', name: token).destroy
  482. local_user
  483. end
  484. =begin
  485. merge two users to one
  486. user = User.find(123)
  487. result = user.merge(user_id_of_duplicate_user)
  488. returns
  489. result = new_user_model
  490. =end
  491. def merge(user_id_of_duplicate_user)
  492. # find email addresses and move them to primary user
  493. duplicate_user = User.find(user_id_of_duplicate_user)
  494. # merge missing attibutes
  495. Models.merge('User', id, user_id_of_duplicate_user)
  496. true
  497. end
  498. =begin
  499. list of active users in role
  500. result = User.of_role('Agent', group_ids)
  501. result = User.of_role(['Agent', 'Admin'])
  502. returns
  503. result = [user1, user2]
  504. =end
  505. def self.of_role(role, group_ids = nil)
  506. roles_ids = Role.where(active: true, name: role).map(&:id)
  507. if !group_ids
  508. return User.where(active: true).joins(:users_roles).where('roles_users.role_id IN (?)', roles_ids).order('users.updated_at DESC')
  509. end
  510. User.where(active: true)
  511. .joins(:users_roles)
  512. .joins(:users_groups)
  513. .where('roles_users.role_id IN (?) AND users_groups.group_ids IN (?)', roles_ids, group_ids).order('users.updated_at DESC')
  514. end
  515. =begin
  516. update/sync default preferences of users in a dedecated permissions
  517. result = User.update_default_preferences_by_permission('ticket.agent', force)
  518. returns
  519. result = true # false
  520. =end
  521. def self.update_default_preferences_by_permission(permission_name, force = false)
  522. permission = ::Permission.lookup(name: permission_name)
  523. return if !permission
  524. default = Rails.configuration.preferences_default_by_permission
  525. return false if !default
  526. default.deep_stringify_keys!
  527. User.with_permissions(permission.name).each do |user|
  528. next if !default[permission.name]
  529. has_changed = false
  530. default[permission.name].each do |key, value|
  531. next if !force && user.preferences[key]
  532. has_changed = true
  533. user.preferences[key] = value
  534. end
  535. if has_changed
  536. user.save!
  537. end
  538. end
  539. true
  540. end
  541. =begin
  542. update/sync default preferences of users in a dedecated role
  543. result = User.update_default_preferences_by_role('Agent', force)
  544. returns
  545. result = true # false
  546. =end
  547. def self.update_default_preferences_by_role(role_name, force = false)
  548. role = Role.lookup(name: role_name)
  549. return if !role
  550. default = Rails.configuration.preferences_default_by_permission
  551. return false if !default
  552. default.deep_stringify_keys!
  553. role.permissions.each do |permission|
  554. User.update_default_preferences_by_permission(permission.name, force)
  555. end
  556. true
  557. end
  558. def check_notifications(o, should_save = true)
  559. default = Rails.configuration.preferences_default_by_permission
  560. return if !default
  561. default.deep_stringify_keys!
  562. has_changed = false
  563. o.permissions.each do |permission|
  564. next if !default[permission.name]
  565. default[permission.name].each do |key, value|
  566. next if preferences[key]
  567. preferences[key] = value
  568. has_changed = true
  569. end
  570. end
  571. return true if !has_changed
  572. if id && should_save
  573. save!
  574. return true
  575. end
  576. @preferences_default = preferences
  577. true
  578. end
  579. def check_preferences_default
  580. if @preferences_default.blank?
  581. if id
  582. roles.each do |role|
  583. check_notifications(role, false)
  584. end
  585. end
  586. end
  587. return if @preferences_default.blank?
  588. preferences_tmp = @preferences_default.merge(preferences)
  589. self.preferences = preferences_tmp
  590. @preferences_default = nil
  591. true
  592. end
  593. private
  594. def cache_delete
  595. super
  596. # delete asset caches
  597. key = "User::authorizations::#{id}"
  598. Cache.delete(key)
  599. # delete permission cache
  600. key = "User::permissions?:local_key:::#{id}"
  601. Cache.delete(key)
  602. end
  603. def check_name
  604. if firstname.present?
  605. firstname.strip!
  606. end
  607. if lastname.present?
  608. lastname.strip!
  609. end
  610. return true if firstname.present? && lastname.present?
  611. if (firstname.blank? && lastname.present?) || (firstname.present? && lastname.blank?)
  612. # "Lastname, Firstname"
  613. used_name = if firstname.blank?
  614. lastname
  615. else
  616. firstname
  617. end
  618. name = used_name.split(', ', 2)
  619. if name.count == 2
  620. if name[0].present?
  621. self.lastname = name[0]
  622. end
  623. if name[1].present?
  624. self.firstname = name[1]
  625. end
  626. return true
  627. end
  628. # "Firstname Lastname"
  629. name = used_name.split(' ', 2)
  630. if name.count == 2
  631. if name[0].present?
  632. self.firstname = name[0]
  633. end
  634. if name[1].present?
  635. self.lastname = name[1]
  636. end
  637. return true
  638. end
  639. # -no name- "firstname.lastname@example.com"
  640. elsif firstname.blank? && lastname.blank? && email.present?
  641. scan = email.scan(/^(.+?)\.(.+?)\@.+?$/)
  642. if scan[0]
  643. if scan[0][0].present?
  644. self.firstname = scan[0][0].capitalize
  645. end
  646. if scan[0][1].present?
  647. self.lastname = scan[0][1].capitalize
  648. end
  649. end
  650. end
  651. true
  652. end
  653. def check_email
  654. return true if Setting.get('import_mode')
  655. return true if email.blank?
  656. self.email = email.downcase.strip
  657. return true if id == 1
  658. raise Exceptions::UnprocessableEntity, 'Invalid email' if email !~ /@/
  659. raise Exceptions::UnprocessableEntity, 'Invalid email' if email.match?(/\s/)
  660. true
  661. end
  662. def check_login
  663. # use email as login if not given
  664. if login.blank?
  665. self.login = email
  666. end
  667. # if email has changed, login is old email, change also login
  668. if changes && changes['email']
  669. if changes['email'][0] == login
  670. self.login = email
  671. end
  672. end
  673. # generate auto login
  674. if login.blank?
  675. self.login = "auto-#{Time.zone.now.to_i}-#{rand(999_999)}"
  676. end
  677. # check if login already exists
  678. self.login = login.downcase.strip
  679. check = true
  680. while check
  681. exists = User.find_by(login: login)
  682. if exists && exists.id != id # rubocop:disable Style/SafeNavigation
  683. self.login = "#{login}#{rand(999)}"
  684. else
  685. check = false
  686. end
  687. end
  688. true
  689. end
  690. def check_mail_delivery_failed
  691. return true if !changes || !changes['email']
  692. preferences.delete(:mail_delivery_failed)
  693. true
  694. end
  695. def ensure_roles
  696. return true if role_ids.present?
  697. self.role_ids = Role.signup_role_ids
  698. end
  699. def ensure_identifier
  700. return true if email.present? || firstname.present? || lastname.present? || phone.present?
  701. return true if login.present? && !login.start_with?('auto-')
  702. raise Exceptions::UnprocessableEntity, 'Minimum one identifier (login, firstname, lastname, phone or email) for user is required.'
  703. end
  704. def ensure_uniq_email
  705. return true if Setting.get('user_email_multiple_use')
  706. return true if Setting.get('import_mode')
  707. return true if email.blank?
  708. return true if !changes
  709. return true if !changes['email']
  710. return true if !User.find_by(email: email.downcase.strip)
  711. raise Exceptions::UnprocessableEntity, 'Email address is already used for other user.'
  712. end
  713. def validate_roles(role)
  714. return true if !role_ids # we need role_ids for checking in role_ids below, in this method
  715. return true if role.preferences[:not].blank?
  716. role.preferences[:not].each do |local_role_name|
  717. local_role = Role.lookup(name: local_role_name)
  718. next if !local_role
  719. next if role_ids.exclude?(local_role.id)
  720. raise "Role #{role.name} conflicts with #{local_role.name}"
  721. end
  722. true
  723. end
  724. def validate_ooo
  725. return true if out_of_office != true
  726. raise Exceptions::UnprocessableEntity, 'out of office start is required' if out_of_office_start_at.blank?
  727. raise Exceptions::UnprocessableEntity, 'out of office end is required' if out_of_office_end_at.blank?
  728. raise Exceptions::UnprocessableEntity, 'out of office end is before start' if out_of_office_start_at > out_of_office_end_at
  729. raise Exceptions::UnprocessableEntity, 'out of office replacement user is required' if out_of_office_replacement_id.blank?
  730. raise Exceptions::UnprocessableEntity, 'out of office no such replacement user' if !User.find_by(id: out_of_office_replacement_id)
  731. true
  732. end
  733. =begin
  734. checks if the current user is the last one with admin permissions.
  735. Raises
  736. raise 'Minimum one user need to have admin permissions'
  737. =end
  738. def last_admin_check_by_attribute
  739. return true if !will_save_change_to_attribute?('active')
  740. return true if active != false
  741. return true if !permissions?(['admin', 'admin.user'])
  742. raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
  743. true
  744. end
  745. def last_admin_check_by_role(role)
  746. return true if Setting.get('import_mode')
  747. return true if !role.with_permission?(['admin', 'admin.user'])
  748. raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
  749. true
  750. end
  751. def last_admin_check_admin_count
  752. admin_role_ids = Role.joins(:permissions).where(permissions: { name: ['admin', 'admin.user'], active: true }, roles: { active: true }).pluck(:id)
  753. User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).distinct().count - 1
  754. end
  755. def validate_agent_limit_by_attributes
  756. return true if !Setting.get('system_agent_limit')
  757. return true if !will_save_change_to_attribute?('active')
  758. return true if active != true
  759. return true if !permissions?('ticket.agent')
  760. ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
  761. count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().count + 1
  762. raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
  763. true
  764. end
  765. def validate_agent_limit_by_role(role)
  766. return true if !Setting.get('system_agent_limit')
  767. return true if active != true
  768. return true if role.active != true
  769. return true if !role.with_permission?('ticket.agent')
  770. ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
  771. count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().count
  772. # if new added role is a ticket.agent role
  773. if ticket_agent_role_ids.include?(role.id)
  774. # if user already has a ticket.agent role
  775. hint = false
  776. role_ids.each do |locale_role_id|
  777. next if !ticket_agent_role_ids.include?(locale_role_id)
  778. hint = true
  779. break
  780. end
  781. # user has not already a ticket.agent role
  782. if hint == false
  783. count += 1
  784. end
  785. end
  786. raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
  787. true
  788. end
  789. def domain_based_assignment
  790. return true if !email
  791. return true if organization_id
  792. begin
  793. domain = Mail::Address.new(email).domain
  794. return true if !domain
  795. organization = Organization.find_by(domain: domain.downcase, domain_assignment: true)
  796. return true if !organization
  797. self.organization_id = organization.id
  798. rescue
  799. return true
  800. end
  801. true
  802. end
  803. # sets locale of the user
  804. def set_locale
  805. # set the user's locale to the one of the "executing" user
  806. return true if !UserInfo.current_user_id
  807. user = User.find_by(id: UserInfo.current_user_id)
  808. return true if !user
  809. return true if !user.preferences[:locale]
  810. preferences[:locale] = user.preferences[:locale]
  811. true
  812. end
  813. def avatar_for_email_check
  814. return true if email.blank?
  815. return true if email !~ /@/
  816. return true if !saved_change_to_attribute?('email') && updated_at > Time.zone.now - 10.days
  817. # save/update avatar
  818. avatar = Avatar.auto_detection(
  819. object: 'User',
  820. o_id: id,
  821. url: email,
  822. source: 'app',
  823. updated_by_id: updated_by_id,
  824. created_by_id: updated_by_id,
  825. )
  826. # update user link
  827. return true if !avatar
  828. update_column(:image, avatar.store_hash) # rubocop:disable Rails/SkipsModelValidations
  829. cache_delete
  830. true
  831. end
  832. def avatar_destroy
  833. Avatar.remove('User', id)
  834. end
  835. def user_device_destroy
  836. UserDevice.remove(id)
  837. end
  838. def ensure_password
  839. return true if password_empty?
  840. return true if PasswordHash.crypted?(password)
  841. self.password = PasswordHash.crypt(password)
  842. true
  843. end
  844. def password_empty?
  845. # set old password again if not given
  846. return if password.present?
  847. # skip if it's not desired to set a password (yet)
  848. return true if !password
  849. # get current record
  850. return if !id
  851. self.password = password_was
  852. true
  853. end
  854. # reset login_failed if password is changed
  855. def reset_login_failed
  856. return true if !will_save_change_to_attribute?('password')
  857. self.login_failed = 0
  858. true
  859. end
  860. end