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