user.rb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. require 'digest/sha2'
  2. class User < ApplicationModel
  3. include Gmaps
  4. before_create :check_name, :check_email, :check_login, :check_image, :check_geo, :check_password
  5. before_update :check_password, :check_image, :check_geo, :check_email, :check_login
  6. has_and_belongs_to_many :groups, :after_add => :cache_update, :after_remove => :cache_update
  7. has_and_belongs_to_many :roles, :after_add => :cache_update, :after_remove => :cache_update
  8. has_and_belongs_to_many :organizations, :after_add => :cache_update, :after_remove => :cache_update
  9. has_many :tokens, :after_add => :cache_update, :after_remove => :cache_update
  10. has_many :authorizations, :after_add => :cache_update, :after_remove => :cache_update
  11. belongs_to :organization, :class_name => 'Organization'
  12. store :preferences
  13. def fullname
  14. fullname = ''
  15. if self.firstname
  16. fullname = fullname + self.firstname
  17. end
  18. if self.lastname
  19. if fullname != ''
  20. fullname = fullname + ' '
  21. end
  22. fullname = fullname + self.lastname
  23. end
  24. return fullname
  25. end
  26. def is_role( role_name )
  27. self.roles.each { |role|
  28. return role if role.name == role_name
  29. }
  30. return false
  31. end
  32. def self.authenticate( username, password )
  33. # do not authenticate with nothing
  34. return if !username || username == ''
  35. return if !password || password == ''
  36. # try to find user based on login
  37. user = User.where( :login => username, :active => true ).first
  38. # try second lookup with email
  39. if !user
  40. user = User.where( :email => username, :active => true ).first
  41. end
  42. # no user found
  43. return nil if !user
  44. # use auth backends
  45. config = {
  46. :internal => {
  47. :adapter => 'internal',
  48. },
  49. :test => {
  50. :adapter => 'test',
  51. },
  52. :env => {
  53. :adapter => 'env',
  54. },
  55. :ldap => {
  56. :adapter => 'ldap',
  57. :host => 'somehost',
  58. :port => '3333',
  59. :base_dn => 'some base dn',
  60. :bind_user => 'some bind user',
  61. :bind_pw => 'some pw',
  62. },
  63. :otrs => {
  64. :adapter => 'otrs',
  65. :required_group => 'stats',
  66. :group_role_map => {
  67. 'admin' => 'Admin',
  68. 'stats' => 'Report',
  69. },
  70. :always_role => {
  71. 'Agent' => true,
  72. },
  73. },
  74. }
  75. config.each {|key, c|
  76. file = "auth/#{c[:adapter]}"
  77. require file
  78. user_auth = Auth.const_get("#{c[:adapter].to_s.upcase}").check( user, username, password, c )
  79. return user_auth if user_auth
  80. }
  81. # auth failed
  82. return false
  83. end
  84. def self.create_from_hash!(hash)
  85. url = ''
  86. if hash['info']['urls'] then
  87. url = hash['info']['urls']['Website'] || hash['info']['urls']['Twitter'] || ''
  88. end
  89. roles = Role.where( :name => 'Customer' )
  90. self.create(
  91. :login => hash['info']['nickname'] || hash['uid'],
  92. :firstname => hash['info']['name'],
  93. :email => hash['info']['email'],
  94. :image => hash['info']['image'],
  95. # :url => url.to_s,
  96. :note => hash['info']['description'],
  97. :source => hash['provider'],
  98. :roles => roles,
  99. :created_by_id => 1
  100. )
  101. end
  102. def self.password_reset_send(username)
  103. return if !username || username == ''
  104. # try to find user based on login
  105. user = User.where( :login => username, :active => true ).first
  106. # try second lookup with email
  107. if !user
  108. user = User.where( :email => username, :active => true ).first
  109. end
  110. # check if email address exists
  111. return if !user
  112. return if !user.email
  113. # generate token
  114. token = Token.create( :action => 'PasswordReset', :user_id => user.id )
  115. # send mail
  116. data = {}
  117. data[:subject] = 'Reset your #{config.product_name} password'
  118. data[:body] = 'Forgot your password?
  119. We received a request to reset the password for your #{config.product_name} account (#{user.login}).
  120. If you want to reset your password, click on the link below (or copy and paste the URL into your browser):
  121. #{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}
  122. This link takes you to a page where you can change your password.
  123. If you don\'t want to reset your password, please ignore this message. Your password will not be reset.
  124. Your #{config.product_name} Team
  125. '
  126. # prepare subject & body
  127. [:subject, :body].each { |key|
  128. data[key.to_sym] = NotificationFactory.build(
  129. :locale => user.locale,
  130. :string => data[key.to_sym],
  131. :objects => {
  132. :token => token,
  133. :user => user,
  134. }
  135. )
  136. }
  137. # send notification
  138. NotificationFactory.send(
  139. :recipient => user,
  140. :subject => data[:subject],
  141. :body => data[:body]
  142. )
  143. return true
  144. end
  145. # check token
  146. def self.password_reset_check(token)
  147. user = Token.check( :action => 'PasswordReset', :name => token )
  148. return user
  149. end
  150. def self.password_reset_via_token(token,password)
  151. # check token
  152. user = Token.check( :action => 'PasswordReset', :name => token )
  153. return if !user
  154. # reset password
  155. user.update_attributes( :password => password )
  156. # delete token
  157. Token.where( :action => 'PasswordReset', :name => token ).first.destroy
  158. return user
  159. end
  160. def self.find_fulldata(user_id)
  161. cache = self.cache_get(user_id, true)
  162. return cache if cache
  163. # get user
  164. user = User.find(user_id)
  165. data = user.attributes
  166. # do not show password
  167. user['password'] = ''
  168. # get linked accounts
  169. data['accounts'] = {}
  170. authorizations = user.authorizations() || []
  171. authorizations.each do | authorization |
  172. data['accounts'][authorization.provider] = {
  173. :uid => authorization[:uid],
  174. :username => authorization[:username]
  175. }
  176. end
  177. # set roles
  178. roles = []
  179. user.roles.select('id, name').where( :active => true ).each { |role|
  180. roles.push role.attributes
  181. }
  182. data['roles'] = roles
  183. data['role_ids'] = user.role_ids
  184. groups = []
  185. user.groups.select('id, name').where( :active => true ).each { |group|
  186. groups.push group.attributes
  187. }
  188. data['groups'] = groups
  189. data['group_ids'] = user.group_ids
  190. organization = user.organization
  191. if organization
  192. data['organization'] = organization.attributes
  193. end
  194. organizations = []
  195. user.organizations.select('id, name').where( :active => true ).each { |organization|
  196. organizations.push organization.attributes
  197. }
  198. data['organizations'] = organizations
  199. data['organization_ids'] = user.organization_ids
  200. self.cache_set(user.id, data, true)
  201. return data
  202. end
  203. def self.user_data_full (user_id)
  204. # get user
  205. user = User.find_fulldata(user_id)
  206. # do not show password
  207. user['password'] = ''
  208. # TEMP: compat. reasons
  209. user['preferences'] = {} if user['preferences'] == nil
  210. items = []
  211. if user['preferences'][:tickets_open].to_i > 0
  212. item = {
  213. :url => '',
  214. :name => 'open',
  215. :count => user['preferences'][:tickets_open] || 0,
  216. :title => 'Open Tickets',
  217. :class => 'user-tickets',
  218. :data => 'open'
  219. }
  220. items.push item
  221. end
  222. if user['preferences'][:tickets_closed].to_i > 0
  223. item = {
  224. :url => '',
  225. :name => 'closed',
  226. :count => user['preferences'][:tickets_closed] || 0,
  227. :title => 'Closed Tickets',
  228. :class => 'user-tickets',
  229. :data => 'closed'
  230. }
  231. items.push item
  232. end
  233. # show linked topics and items
  234. if items.count > 0
  235. topic = {
  236. :title => 'Tickets',
  237. :items => items,
  238. }
  239. user['links'] = []
  240. user['links'].push topic
  241. end
  242. return user
  243. end
  244. # update all users geo data
  245. def self.geo_update_all
  246. User.all.each { |user|
  247. user.geo_update
  248. user.save
  249. }
  250. end
  251. # update geo data of one user
  252. def geo_update
  253. address = ''
  254. location = ['street', 'zip', 'city', 'country']
  255. location.each { |item|
  256. if self[item] && self[item] != ''
  257. address = address + ',' + self[item]
  258. end
  259. }
  260. # return if no address is given
  261. return if address == ''
  262. # dp lookup
  263. latlng = Gmaps.geocode(address)
  264. if latlng
  265. self.preferences['lat'] = latlng[0]
  266. self.preferences['lng'] = latlng[1]
  267. end
  268. end
  269. def update_last_login
  270. self.last_login = Time.now
  271. self.save
  272. end
  273. private
  274. def check_geo
  275. # geo update if no user exists
  276. if !self.id
  277. self.geo_update
  278. return
  279. end
  280. location = ['street', 'zip', 'city', 'country']
  281. # get current user data
  282. current = User.where( :id => self.id ).first
  283. return if !current
  284. # check if geo update is needed
  285. current_location = {}
  286. location.each { |item|
  287. current_location[item] = current[item]
  288. }
  289. # get full address
  290. next_location = {}
  291. location.each { |item|
  292. next_location[item] = self[item]
  293. }
  294. # return if address hasn't changed and geo data is already available
  295. return if ( current_location == next_location ) && ( self.preferences['lat'] && self.preferences['lng'] )
  296. # geo update
  297. self.geo_update
  298. end
  299. def check_name
  300. if ( self.firstname && !self.firstname.empty? ) && ( !self.lastname || self.lastname.empty? )
  301. # Lastname, Firstname
  302. scan = self.firstname.scan(/, /)
  303. if scan[0]
  304. name = self.firstname.split(', ', 2)
  305. self.lastname = name[0]
  306. self.firstname = name[1]
  307. return
  308. end
  309. # Firstname Lastname
  310. name = self.firstname.split(' ', 2)
  311. self.firstname = name[0]
  312. self.lastname = name[1]
  313. return
  314. # -no name- firstname.lastname@example.com
  315. elsif ( !self.firstname || self.firstname.empty? ) && ( !self.lastname || self.lastname.empty? ) && ( self.email && !self.email.empty? )
  316. scan = self.email.scan(/^(.+?)\.(.+?)\@.+?$/)
  317. if scan[0]
  318. self.firstname = scan[0][0].capitalize
  319. self.lastname = scan[0][1].capitalize
  320. end
  321. end
  322. end
  323. def check_email
  324. if self.email
  325. self.email = self.email.downcase
  326. end
  327. end
  328. def check_login
  329. if self.login
  330. self.login = self.login.downcase
  331. end
  332. end
  333. def check_image
  334. require 'digest/md5'
  335. if !self.image || self.image == ''
  336. if self.email
  337. hash = Digest::MD5.hexdigest(self.email)
  338. self.image = "http://www.gravatar.com/avatar/#{hash}?s=48"
  339. end
  340. end
  341. end
  342. def check_password
  343. # set old password again if not given
  344. if self.password == '' || !self.password
  345. # get current record
  346. if self.id
  347. current = User.find(self.id)
  348. self.password = current.password
  349. end
  350. # create crypted password if not already crypted
  351. else
  352. if self.password !~ /^\{sha2\}/
  353. crypted = Digest::SHA2.hexdigest( self.password )
  354. self.password = "{sha2}#{crypted}"
  355. end
  356. end
  357. end
  358. end