user.rb 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  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, :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: [:cache_update, :check_notifications], after_remove: :cache_update, before_add: [: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. if hash['info']['urls']
  261. hash['info']['urls'].each do |_name, local_url|
  262. next if !local_url
  263. next if local_url.empty?
  264. url = local_url
  265. end
  266. end
  267. create(
  268. login: hash['info']['nickname'] || hash['uid'],
  269. firstname: hash['info']['name'],
  270. email: hash['info']['email'],
  271. image_source: hash['info']['image'],
  272. web: url,
  273. address: hash['info']['location'],
  274. note: hash['info']['description'],
  275. source: hash['provider'],
  276. role_ids: role_ids,
  277. updated_by_id: 1,
  278. created_by_id: 1,
  279. )
  280. end
  281. =begin
  282. get all permissions of user
  283. user = User.find(123)
  284. user.permissions
  285. returns
  286. {
  287. 'permission.key' => true,
  288. # ...
  289. }
  290. =end
  291. def permissions
  292. list = {}
  293. ::Permission.select('permissions.name, permissions.preferences').joins(:roles).where('roles.id IN (?) AND permissions.active = ?', role_ids, true).pluck(:name, :preferences).each do |permission|
  294. next if permission[1]['selectable'] == false
  295. list[permission[0]] = true
  296. end
  297. list
  298. end
  299. =begin
  300. true or false for permission
  301. user = User.find(123)
  302. user.permissions?('permission.key') # access to certain permission.key
  303. user.permissions?(['permission.key1', 'permission.key2']) # access to permission.key1 or permission.key2
  304. user.permissions?('permission') # access to all sub keys
  305. user.permissions?('permission.*') # access if one sub key access exists
  306. returns
  307. true|false
  308. =end
  309. def permissions?(key)
  310. keys = key
  311. names = []
  312. if key.class == String
  313. keys = [key]
  314. end
  315. keys.each do |local_key|
  316. list = []
  317. if local_key =~ /\.\*$/
  318. local_key.sub!('.*', '.%')
  319. permissions = ::Permission.with_parents(local_key)
  320. 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)
  321. else
  322. permission = ::Permission.lookup(name: local_key)
  323. break if permission && permission.active == false
  324. permissions = ::Permission.with_parents(local_key)
  325. 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)
  326. end
  327. return true if list.present?
  328. end
  329. false
  330. end
  331. =begin
  332. returns all accessable permission ids of user
  333. user = User.find(123)
  334. user.permissions_with_child_ids
  335. returns
  336. [permission1_id, permission2_id, permission3_id]
  337. =end
  338. def permissions_with_child_ids
  339. where = ''
  340. where_bind = [true]
  341. permissions.each do |permission_name, _value|
  342. where += ' OR ' if where != ''
  343. where += 'permissions.name = ? OR permissions.name LIKE ?'
  344. where_bind.push permission_name
  345. where_bind.push "#{permission_name}.%"
  346. end
  347. return [] if where == ''
  348. ::Permission.where("permissions.active = ? AND (#{where})", *where_bind).pluck(:id)
  349. end
  350. =begin
  351. get all users with permission
  352. users = User.with_permissions('ticket.agent')
  353. get all users with permission "admin.session" or "ticket.agent"
  354. users = User.with_permissions(['admin.session', 'ticket.agent'])
  355. returns
  356. [user1, user2, ...]
  357. =end
  358. def self.with_permissions(keys)
  359. if keys.class != Array
  360. keys = [keys]
  361. end
  362. total_role_ids = []
  363. permission_ids = []
  364. keys.each do |key|
  365. role_ids = []
  366. ::Permission.with_parents(key).each do |local_key|
  367. permission = ::Permission.lookup(name: local_key)
  368. next if !permission
  369. permission_ids.push permission.id
  370. end
  371. next if permission_ids.empty?
  372. 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|
  373. role_ids.push role_id
  374. end
  375. total_role_ids.push role_ids
  376. end
  377. return [] if total_role_ids.empty?
  378. condition = ''
  379. total_role_ids.each do |_role_ids|
  380. if condition != ''
  381. condition += ' OR '
  382. end
  383. condition += 'roles_users.role_id IN (?)'
  384. end
  385. User.joins(:users_roles).where("(#{condition}) AND users.active = ?", *total_role_ids, true).distinct.order(:id)
  386. end
  387. =begin
  388. generate new token for reset password
  389. result = User.password_reset_new_token(username)
  390. returns
  391. result = {
  392. token: token,
  393. user: user,
  394. }
  395. =end
  396. def self.password_reset_new_token(username)
  397. return if username.blank?
  398. # try to find user based on login
  399. user = User.find_by(login: username.downcase, active: true)
  400. # try second lookup with email
  401. user ||= User.find_by(email: username.downcase, active: true)
  402. # check if email address exists
  403. return if !user
  404. return if !user.email
  405. # generate token
  406. token = Token.create(action: 'PasswordReset', user_id: user.id)
  407. {
  408. token: token,
  409. user: user,
  410. }
  411. end
  412. =begin
  413. returns the User instance for a given password token if found
  414. result = User.by_reset_token(token)
  415. returns
  416. result = user_model # user_model if token was verified
  417. =end
  418. def self.by_reset_token(token)
  419. Token.check(action: 'PasswordReset', name: token)
  420. end
  421. =begin
  422. reset password with token and set new password
  423. result = User.password_reset_via_token(token,password)
  424. returns
  425. result = user_model # user_model if token was verified
  426. =end
  427. def self.password_reset_via_token(token, password)
  428. # check token
  429. user = by_reset_token(token)
  430. return if !user
  431. # reset password
  432. user.update!(password: password)
  433. # delete token
  434. Token.find_by(action: 'PasswordReset', name: token).destroy
  435. user
  436. end
  437. =begin
  438. update last login date and reset login_failed (is automatically done by auth and sso backend)
  439. user = User.find(123)
  440. result = user.update_last_login
  441. returns
  442. result = new_user_model
  443. =end
  444. def update_last_login
  445. self.last_login = Time.zone.now
  446. # reset login failed
  447. self.login_failed = 0
  448. save
  449. end
  450. =begin
  451. generate new token for signup
  452. result = User.signup_new_token(user) # or email
  453. returns
  454. result = {
  455. token: token,
  456. user: user,
  457. }
  458. =end
  459. def self.signup_new_token(user)
  460. return if !user
  461. return if !user.email
  462. # generate token
  463. token = Token.create(action: 'Signup', user_id: user.id)
  464. {
  465. token: token,
  466. user: user,
  467. }
  468. end
  469. =begin
  470. verify signup with token
  471. result = User.signup_verify_via_token(token, user)
  472. returns
  473. result = user_model # user_model if token was verified
  474. =end
  475. def self.signup_verify_via_token(token, user = nil)
  476. # check token
  477. local_user = Token.check(action: 'Signup', name: token)
  478. return if !local_user
  479. # if requested user is different to current user
  480. return if user && local_user.id != user.id
  481. # set verified
  482. local_user.update!(verified: true)
  483. # delete token
  484. Token.find_by(action: 'Signup', name: token).destroy
  485. local_user
  486. end
  487. =begin
  488. merge two users to one
  489. user = User.find(123)
  490. result = user.merge(user_id_of_duplicate_user)
  491. returns
  492. result = new_user_model
  493. =end
  494. def merge(user_id_of_duplicate_user)
  495. # find email addresses and move them to primary user
  496. duplicate_user = User.find(user_id_of_duplicate_user)
  497. # merge missing attibutes
  498. Models.merge('User', id, user_id_of_duplicate_user)
  499. true
  500. end
  501. =begin
  502. list of active users in role
  503. result = User.of_role('Agent', group_ids)
  504. result = User.of_role(['Agent', 'Admin'])
  505. returns
  506. result = [user1, user2]
  507. =end
  508. def self.of_role(role, group_ids = nil)
  509. roles_ids = Role.where(active: true, name: role).map(&:id)
  510. if !group_ids
  511. return User.where(active: true).joins(:users_roles).where('roles_users.role_id IN (?)', roles_ids).order('users.updated_at DESC')
  512. end
  513. User.where(active: true)
  514. .joins(:users_roles)
  515. .joins(:users_groups)
  516. .where('roles_users.role_id IN (?) AND users_groups.group_ids IN (?)', roles_ids, group_ids).order('users.updated_at DESC')
  517. end
  518. =begin
  519. update/sync default preferences of users in a dedecated permissions
  520. result = User.update_default_preferences_by_permission('ticket.agent', force)
  521. returns
  522. result = true # false
  523. =end
  524. def self.update_default_preferences_by_permission(permission_name, force = false)
  525. permission = ::Permission.lookup(name: permission_name)
  526. return if !permission
  527. default = Rails.configuration.preferences_default_by_permission
  528. return false if !default
  529. default.deep_stringify_keys!
  530. User.with_permissions(permission.name).each do |user|
  531. next if !default[permission.name]
  532. has_changed = false
  533. default[permission.name].each do |key, value|
  534. next if !force && user.preferences[key]
  535. has_changed = true
  536. user.preferences[key] = value
  537. end
  538. if has_changed
  539. user.save!
  540. end
  541. end
  542. true
  543. end
  544. =begin
  545. update/sync default preferences of users in a dedecated role
  546. result = User.update_default_preferences_by_role('Agent', force)
  547. returns
  548. result = true # false
  549. =end
  550. def self.update_default_preferences_by_role(role_name, force = false)
  551. role = Role.lookup(name: role_name)
  552. return if !role
  553. default = Rails.configuration.preferences_default_by_permission
  554. return false if !default
  555. default.deep_stringify_keys!
  556. role.permissions.each do |permission|
  557. User.update_default_preferences_by_permission(permission.name, force)
  558. end
  559. true
  560. end
  561. def check_notifications(o, shouldSave = true)
  562. default = Rails.configuration.preferences_default_by_permission
  563. return if !default
  564. default.deep_stringify_keys!
  565. has_changed = false
  566. o.permissions.each do |permission|
  567. next if !default[permission.name]
  568. default[permission.name].each do |key, value|
  569. next if preferences[key]
  570. preferences[key] = value
  571. has_changed = true
  572. end
  573. end
  574. return true if !has_changed
  575. if id && shouldSave
  576. save!
  577. return true
  578. end
  579. @preferences_default = preferences
  580. true
  581. end
  582. def check_preferences_default
  583. if @preferences_default.blank?
  584. if id
  585. roles.each do |role|
  586. check_notifications(role, false)
  587. end
  588. end
  589. end
  590. return if @preferences_default.blank?
  591. preferences_tmp = @preferences_default.merge(preferences)
  592. self.preferences = preferences_tmp
  593. @preferences_default = nil
  594. true
  595. end
  596. private
  597. def cache_delete
  598. super
  599. # delete asset caches
  600. key = "User::authorizations::#{id}"
  601. Cache.delete(key)
  602. # delete permission cache
  603. key = "User::permissions?:local_key:::#{id}"
  604. Cache.delete(key)
  605. end
  606. def check_name
  607. if firstname.present?
  608. firstname.strip!
  609. end
  610. if lastname.present?
  611. lastname.strip!
  612. end
  613. return true if firstname.present? && lastname.present?
  614. if (firstname.blank? && lastname.present?) || (firstname.present? && lastname.blank?)
  615. # "Lastname, Firstname"
  616. used_name = if firstname.blank?
  617. lastname
  618. else
  619. firstname
  620. end
  621. name = used_name.split(', ', 2)
  622. if name.count == 2
  623. if name[0].present?
  624. self.lastname = name[0]
  625. end
  626. if name[1].present?
  627. self.firstname = name[1]
  628. end
  629. return true
  630. end
  631. # "Firstname Lastname"
  632. name = used_name.split(' ', 2)
  633. if name.count == 2
  634. if name[0].present?
  635. self.firstname = name[0]
  636. end
  637. if name[1].present?
  638. self.lastname = name[1]
  639. end
  640. return true
  641. end
  642. # -no name- "firstname.lastname@example.com"
  643. elsif firstname.blank? && lastname.blank? && email.present?
  644. scan = email.scan(/^(.+?)\.(.+?)\@.+?$/)
  645. if scan[0]
  646. if scan[0][0].present?
  647. self.firstname = scan[0][0].capitalize
  648. end
  649. if scan[0][1].present?
  650. self.lastname = scan[0][1].capitalize
  651. end
  652. end
  653. end
  654. true
  655. end
  656. def check_email
  657. return true if Setting.get('import_mode')
  658. return true if email.blank?
  659. self.email = email.downcase.strip
  660. return true if id == 1
  661. raise Exceptions::UnprocessableEntity, 'Invalid email' if email !~ /@/
  662. raise Exceptions::UnprocessableEntity, 'Invalid email' if email =~ /\s/
  663. true
  664. end
  665. def check_login
  666. # use email as login if not given
  667. if login.blank?
  668. self.login = email
  669. end
  670. # if email has changed, login is old email, change also login
  671. if changes && changes['email']
  672. if changes['email'][0] == login
  673. self.login = email
  674. end
  675. end
  676. # generate auto login
  677. if login.blank?
  678. self.login = "auto-#{Time.zone.now.to_i}-#{rand(999_999)}"
  679. end
  680. # check if login already exists
  681. self.login = login.downcase.strip
  682. check = true
  683. while check
  684. exists = User.find_by(login: login)
  685. if exists && exists.id != id
  686. self.login = "#{login}#{rand(999)}"
  687. else
  688. check = false
  689. end
  690. end
  691. true
  692. end
  693. def ensure_roles
  694. return true if role_ids.present?
  695. self.role_ids = Role.signup_role_ids
  696. end
  697. def ensure_identifier
  698. return true if email.present? || firstname.present? || lastname.present? || phone.present?
  699. return true if login.present? && !login.start_with?('auto-')
  700. raise Exceptions::UnprocessableEntity, 'Minimum one identifier (login, firstname, lastname, phone or email) for user is required.'
  701. end
  702. def ensure_uniq_email
  703. return true if Setting.get('user_email_multiple_use')
  704. return true if Setting.get('import_mode')
  705. return true if email.blank?
  706. return true if !changes
  707. return true if !changes['email']
  708. return true if !User.find_by(email: email.downcase.strip)
  709. raise Exceptions::UnprocessableEntity, 'Email address is already used for other user.'
  710. end
  711. def validate_roles(role)
  712. return true if !role_ids # we need role_ids for checking in role_ids below, in this method
  713. return true if role.preferences[:not].blank?
  714. role.preferences[:not].each do |local_role_name|
  715. local_role = Role.lookup(name: local_role_name)
  716. next if !local_role
  717. next if role_ids.exclude?(local_role.id)
  718. raise "Role #{role.name} conflicts with #{local_role.name}"
  719. end
  720. true
  721. end
  722. def validate_ooo
  723. return true if out_of_office != true
  724. raise Exceptions::UnprocessableEntity, 'out of office start is required' if out_of_office_start_at.blank?
  725. raise Exceptions::UnprocessableEntity, 'out of office end is required' if out_of_office_end_at.blank?
  726. raise Exceptions::UnprocessableEntity, 'out of office end is before start' if out_of_office_start_at > out_of_office_end_at
  727. raise Exceptions::UnprocessableEntity, 'out of office replacement user is required' if out_of_office_replacement_id.blank?
  728. raise Exceptions::UnprocessableEntity, 'out of office no such replacement user' if !User.find_by(id: out_of_office_replacement_id)
  729. true
  730. end
  731. =begin
  732. checks if the current user is the last one with admin permissions.
  733. Raises
  734. raise 'Minimum one user need to have admin permissions'
  735. =end
  736. def last_admin_check_by_attribute
  737. return true if !will_save_change_to_attribute?('active')
  738. return true if active != false
  739. return true if !permissions?(['admin', 'admin.user'])
  740. raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
  741. true
  742. end
  743. def last_admin_check_by_role(role)
  744. return true if Setting.get('import_mode')
  745. return true if !role.with_permission?(['admin', 'admin.user'])
  746. raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
  747. true
  748. end
  749. def last_admin_check_admin_count
  750. admin_role_ids = Role.joins(:permissions).where(permissions: { name: ['admin', 'admin.user'], active: true }, roles: { active: true }).pluck(:id)
  751. User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).count - 1
  752. end
  753. def validate_agent_limit_by_attributes
  754. return true if !Setting.get('system_agent_limit')
  755. return true if !will_save_change_to_attribute?('active')
  756. return true if active != true
  757. return true if !permissions?('ticket.agent')
  758. ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
  759. count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).count + 1
  760. raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
  761. true
  762. end
  763. def validate_agent_limit_by_role(role)
  764. return true if !Setting.get('system_agent_limit')
  765. return true if active != true
  766. return true if role.active != true
  767. return true if !role.with_permission?('ticket.agent')
  768. ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
  769. count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).count
  770. if ticket_agent_role_ids.include?(role.id)
  771. count += 1
  772. end
  773. raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
  774. true
  775. end
  776. def domain_based_assignment
  777. return true if !email
  778. return true if organization_id
  779. begin
  780. domain = Mail::Address.new(email).domain
  781. return true if !domain
  782. organization = Organization.find_by(domain: domain.downcase, domain_assignment: true)
  783. return true if !organization
  784. self.organization_id = organization.id
  785. rescue
  786. return true
  787. end
  788. true
  789. end
  790. # sets locale of the user
  791. def set_locale
  792. # set the user's locale to the one of the "executing" user
  793. return true if !UserInfo.current_user_id
  794. user = User.find_by(id: UserInfo.current_user_id)
  795. return true if !user
  796. return true if !user.preferences[:locale]
  797. preferences[:locale] = user.preferences[:locale]
  798. true
  799. end
  800. def avatar_for_email_check
  801. return true if email.blank?
  802. return true if email !~ /@/
  803. return true if !saved_change_to_attribute?('email') && updated_at > Time.zone.now - 10.days
  804. # save/update avatar
  805. avatar = Avatar.auto_detection(
  806. object: 'User',
  807. o_id: id,
  808. url: email,
  809. source: 'app',
  810. updated_by_id: updated_by_id,
  811. created_by_id: updated_by_id,
  812. )
  813. # update user link
  814. return true if !avatar
  815. update_column(:image, avatar.store_hash)
  816. cache_delete
  817. true
  818. end
  819. def avatar_destroy
  820. Avatar.remove('User', id)
  821. end
  822. def user_device_destroy
  823. UserDevice.remove(id)
  824. end
  825. def ensure_password
  826. return true if password_empty?
  827. return true if PasswordHash.crypted?(password)
  828. self.password = PasswordHash.crypt(password)
  829. true
  830. end
  831. def password_empty?
  832. # set old password again if not given
  833. return if password.present?
  834. # skip if it's not desired to set a password (yet)
  835. return true if !password
  836. # get current record
  837. return if !id
  838. self.password = password_was
  839. true
  840. end
  841. # reset login_failed if password is changed
  842. def reset_login_failed
  843. return true if !will_save_change_to_attribute?('password')
  844. self.login_failed = 0
  845. true
  846. end
  847. end