user.rb 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. # Copyright (C) 2012-2014 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 User::Permission
  26. load 'user/assets.rb'
  27. include User::Assets
  28. extend User::Search
  29. include User::SearchIndex
  30. before_create :check_name, :check_email, :check_login, :check_password
  31. before_update :check_password, :check_email, :check_login
  32. after_create :avatar_check, :notify_clients_after_create
  33. after_update :avatar_check, :notify_clients_after_update
  34. after_destroy :avatar_destroy, :notify_clients_after_destroy
  35. has_and_belongs_to_many :groups, :after_add => :cache_update, :after_remove => :cache_update
  36. has_and_belongs_to_many :roles, :after_add => :cache_update, :after_remove => :cache_update
  37. has_and_belongs_to_many :organizations, :after_add => :cache_update, :after_remove => :cache_update
  38. has_many :tokens, :after_add => :cache_update, :after_remove => :cache_update
  39. has_many :authorizations, :after_add => :cache_update, :after_remove => :cache_update
  40. belongs_to :organization, :class_name => 'Organization'
  41. store :preferences
  42. activity_stream_support(
  43. :role => 'Admin',
  44. :ignore_attributes => {
  45. :last_login => true,
  46. :image => true,
  47. :image_source => true,
  48. }
  49. )
  50. history_support(
  51. :ignore_attributes => {
  52. :password => true,
  53. :image => true,
  54. :image_source => true,
  55. }
  56. )
  57. search_index_support(
  58. :ignore_attributes => {
  59. :password => true,
  60. :image => true,
  61. :image_source => true,
  62. :source => true,
  63. :login_failed => true,
  64. :preferences => true,
  65. }
  66. )
  67. =begin
  68. fullname of user
  69. user = User.find(123)
  70. result = user.fulename
  71. returns
  72. result = "Bob Smith"
  73. =end
  74. def fullname
  75. fullname = ''
  76. if self.firstname && !self.firstname.empty?
  77. fullname = fullname + self.firstname
  78. end
  79. if self.lastname && !self.lastname.empty?
  80. if fullname != ''
  81. fullname = fullname + ' '
  82. end
  83. fullname = fullname + self.lastname
  84. end
  85. if fullname == '' && self.email
  86. fullname = self.email
  87. end
  88. fullname
  89. end
  90. =begin
  91. check if user is in role
  92. user = User.find(123)
  93. result = user.is_role('Customer')
  94. returns
  95. result = true|false
  96. =end
  97. def is_role( role_name )
  98. self.roles.each { |role|
  99. return role if role.name == role_name
  100. }
  101. false
  102. end
  103. =begin
  104. get users activity stream
  105. user = User.find(123)
  106. result = user.activity_stream( 20 )
  107. returns
  108. result = [
  109. {
  110. :id => 2,
  111. :o_id => 2,
  112. :created_by_id => 3,
  113. :created_at => '2013-09-28 00:57:21',
  114. :object => "User",
  115. :type => "created",
  116. },
  117. {
  118. :id => 2,
  119. :o_id => 2,
  120. :created_by_id => 3,
  121. :created_at => '2013-09-28 00:59:21',
  122. :object => "User",
  123. :type => "updated",
  124. },
  125. ]
  126. =end
  127. def activity_stream( limit, fulldata = false )
  128. activity_stream = ActivityStream.list( self, limit )
  129. return activity_stream if !fulldata
  130. # get related objects
  131. assets = ApplicationModel.assets_of_object_list(activity_stream)
  132. return {
  133. :activity_stream => activity_stream,
  134. :assets => assets,
  135. }
  136. end
  137. =begin
  138. authenticate user
  139. result = User.authenticate(username, password)
  140. returns
  141. result = user_model # user model if authentication was successfully
  142. =end
  143. def self.authenticate( username, password )
  144. # do not authenticate with nothing
  145. return if !username || username == ''
  146. return if !password || password == ''
  147. # try to find user based on login
  148. user = User.where( :login => username.downcase, :active => true ).first
  149. # try second lookup with email
  150. if !user
  151. user = User.where( :email => username.downcase, :active => true ).first
  152. end
  153. # check failed logins
  154. max_login_failed = Setting.get('password_max_login_failed') || 10
  155. if user && user.login_failed > max_login_failed
  156. return false
  157. end
  158. user_auth = Auth.check( username, password, user )
  159. # set login failed +1
  160. if !user_auth && user
  161. sleep 1
  162. user.login_failed = user.login_failed + 1
  163. user.save
  164. end
  165. # auth ok
  166. user_auth
  167. end
  168. =begin
  169. authenticate user agains sso
  170. result = User.sso(sso_params)
  171. returns
  172. result = user_model # user model if authentication was successfully
  173. =end
  174. def self.sso(params)
  175. # try to login against configure auth backends
  176. user_auth = Sso.check( params )
  177. return if !user_auth
  178. user_auth
  179. end
  180. =begin
  181. create user from from omni auth hash
  182. result = User.create_from_hash!(hash)
  183. returns
  184. result = user_model # user model if create was successfully
  185. =end
  186. def self.create_from_hash!(hash)
  187. url = ''
  188. if hash['info']['urls'] then
  189. url = hash['info']['urls']['Website'] || hash['info']['urls']['Twitter'] || ''
  190. end
  191. roles = Role.where( :name => 'Customer' )
  192. self.create(
  193. :login => hash['info']['nickname'] || hash['uid'],
  194. :firstname => hash['info']['name'],
  195. :email => hash['info']['email'],
  196. :image => hash['info']['image'],
  197. # :url => url.to_s,
  198. :note => hash['info']['description'],
  199. :source => hash['provider'],
  200. :roles => roles,
  201. :updated_by_id => 1,
  202. :created_by_id => 1,
  203. )
  204. end
  205. =begin
  206. send reset password email with token to user
  207. result = User.password_reset_send(username)
  208. returns
  209. result = token
  210. =end
  211. def self.password_reset_send(username)
  212. return if !username || username == ''
  213. # try to find user based on login
  214. user = User.where( :login => username.downcase, :active => true ).first
  215. # try second lookup with email
  216. if !user
  217. user = User.where( :email => username.downcase, :active => true ).first
  218. end
  219. # check if email address exists
  220. return if !user
  221. return if !user.email
  222. # generate token
  223. token = Token.create( :action => 'PasswordReset', :user_id => user.id )
  224. # send mail
  225. data = {}
  226. data[:subject] = 'Reset your #{config.product_name} password'
  227. data[:body] = 'Forgot your password?
  228. We received a request to reset the password for your #{config.product_name} account (#{user.login}).
  229. If you want to reset your password, click on the link below (or copy and paste the URL into your browser):
  230. #{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}
  231. This link takes you to a page where you can change your password.
  232. If you don\'t want to reset your password, please ignore this message. Your password will not be reset.
  233. Your #{config.product_name} Team'
  234. # prepare subject & body
  235. [:subject, :body].each { |key|
  236. data[key.to_sym] = NotificationFactory.build(
  237. :locale => user.preferences[:locale],
  238. :string => data[key.to_sym],
  239. :objects => {
  240. :token => token,
  241. :user => user,
  242. }
  243. )
  244. }
  245. # send notification
  246. NotificationFactory.send(
  247. :recipient => user,
  248. :subject => data[:subject],
  249. :body => data[:body]
  250. )
  251. token
  252. end
  253. =begin
  254. check reset password token
  255. result = User.password_reset_check(token)
  256. returns
  257. result = user_model # user_model if token was verified
  258. =end
  259. def self.password_reset_check(token)
  260. user = Token.check( :action => 'PasswordReset', :name => token )
  261. # reset login failed if token is valid
  262. if user
  263. user.login_failed = 0
  264. user.save
  265. end
  266. user
  267. end
  268. =begin
  269. reset reset password with token and set new password
  270. result = User.password_reset_via_token(token,password)
  271. returns
  272. result = user_model # user_model if token was verified
  273. =end
  274. def self.password_reset_via_token(token,password)
  275. # check token
  276. user = Token.check( :action => 'PasswordReset', :name => token )
  277. return if !user
  278. # reset password
  279. user.update_attributes( :password => password )
  280. # delete token
  281. Token.where( :action => 'PasswordReset', :name => token ).first.destroy
  282. user
  283. end
  284. =begin
  285. update last login date and reset login_failed (is automatically done by auth and sso backend)
  286. user = User.find(123)
  287. result = user.update_last_login
  288. returns
  289. result = new_user_model
  290. =end
  291. def update_last_login
  292. self.last_login = Time.now
  293. # reset login failed
  294. self.login_failed = 0
  295. # set updated by user
  296. self.updated_by_id = self.id
  297. self.save
  298. end
  299. private
  300. def check_name
  301. if ( self.firstname && !self.firstname.empty? ) && ( !self.lastname || self.lastname.empty? )
  302. # Lastname, Firstname
  303. scan = self.firstname.scan(/, /)
  304. if scan[0]
  305. name = self.firstname.split(', ', 2)
  306. if name[0] != nil
  307. self.lastname = name[0]
  308. end
  309. if name[1] != nil
  310. self.firstname = name[1]
  311. end
  312. return
  313. end
  314. # Firstname Lastname
  315. name = self.firstname.split(' ', 2)
  316. if name[0] != nil
  317. self.firstname = name[0]
  318. end
  319. if name[1] != nil
  320. self.lastname = name[1]
  321. end
  322. return
  323. # -no name- firstname.lastname@example.com
  324. elsif ( !self.firstname || self.firstname.empty? ) && ( !self.lastname || self.lastname.empty? ) && ( self.email && !self.email.empty? )
  325. scan = self.email.scan(/^(.+?)\.(.+?)\@.+?$/)
  326. if scan[0]
  327. if scan[0][0] != nil
  328. self.firstname = scan[0][0].capitalize
  329. end
  330. if scan[0][1] != nil
  331. self.lastname = scan[0][1].capitalize
  332. end
  333. end
  334. end
  335. end
  336. def check_email
  337. if self.email
  338. self.email = self.email.downcase
  339. end
  340. end
  341. def check_login
  342. # use email as login if not given
  343. if !self.login && self.email
  344. self.login = self.email
  345. end
  346. # if email has changed, login is old email, change also login
  347. if self.changes && self.changes['email']
  348. if self.changes['email'][0] == self.login
  349. self.login = self.email
  350. end
  351. end
  352. # check if login already exists
  353. if self.login
  354. self.login = self.login.downcase
  355. check = true
  356. while check
  357. exists = User.where( :login => self.login ).first
  358. if exists && exists.id != self.id
  359. self.login = self.login + rand(999).to_s
  360. else
  361. check = false
  362. end
  363. end
  364. end
  365. end
  366. def avatar_check
  367. return if !self.email
  368. return if self.email.empty?
  369. # save/update avatar
  370. avatar = Avatar.auto_detection(
  371. :object => 'User',
  372. :o_id => self.id,
  373. :url => self.email,
  374. :source => 'app',
  375. :updated_by_id => self.updated_by_id,
  376. :created_by_id => self.updated_by_id,
  377. )
  378. # update user link
  379. if avatar
  380. self.update_column( :image, avatar.store_hash )
  381. self.cache_delete
  382. end
  383. end
  384. def avatar_destroy
  385. Avatar.remove( 'User', self.id )
  386. end
  387. def check_password
  388. # set old password again if not given
  389. if self.password == '' || !self.password
  390. # get current record
  391. if self.id
  392. #current = User.find(self.id)
  393. #self.password = current.password
  394. self.password = self.password_was
  395. end
  396. end
  397. # crypt password if not already crypted
  398. if self.password && self.password !~ /^\{sha2\}/
  399. crypted = Digest::SHA2.hexdigest( self.password )
  400. self.password = "{sha2}#{crypted}"
  401. end
  402. end
  403. end