users_controller.rb 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
  2. class UsersController < ApplicationController
  3. before_filter :authentication_check, :except => [:create, :password_reset_send, :password_reset_verify]
  4. # @path [GET] /users
  5. #
  6. # @summary Returns a list of User records.
  7. # @notes The requester has to be in the role 'Admin' or 'Agent' to
  8. # get a list of all Users. If the requester is in the
  9. # role 'Customer' only just the own User record will be returned.
  10. #
  11. # @response_message 200 [Array<User>] List of matching User records.
  12. # @response_message 401 Invalid session.
  13. def index
  14. # only allow customer to fetch him self
  15. if is_role('Customer') && !is_role('Admin') && !is_role('Agent')
  16. users = User.where( :id => current_user.id )
  17. else
  18. users = User.all
  19. end
  20. users_all = []
  21. users.each {|user|
  22. users_all.push User.lookup( :id => user.id ).attributes_with_associations
  23. }
  24. render :json => users_all, :status => :ok
  25. end
  26. # @path [GET] /users/{id}
  27. #
  28. # @summary Returns the User record with the requested identifier.
  29. # @notes The requester has to be in the role 'Admin' or 'Agent' to
  30. # access all User records. If the requester is in the
  31. # role 'Customer' just the own User record is accessable.
  32. #
  33. # @parameter id(required) [Integer] The identifier matching the requested User.
  34. # @parameter full [Bool] If set a Asset structure with all connected Assets gets returned.
  35. #
  36. # @response_message 200 [User] User record matching the requested identifier.
  37. # @response_message 401 Invalid session.
  38. def show
  39. # access deny
  40. return if !permission_check
  41. if params[:full]
  42. full = User.full( params[:id] )
  43. render :json => full
  44. return
  45. end
  46. user = User.find( params[:id] )
  47. render :json => user
  48. end
  49. # @path [POST] /users
  50. #
  51. # @summary Creates a User record with the provided attribute values.
  52. # @notes TODO.
  53. #
  54. # @parameter User(required,body) [User] The attribute value structure needed to create a User record.
  55. #
  56. # @response_message 200 [User] Created User record.
  57. # @response_message 401 Invalid session.
  58. def create
  59. user = User.new( User.param_cleanup(params) )
  60. begin
  61. # check if it's first user
  62. count = User.all.count()
  63. # if it's a signup, add user to customer role
  64. if !current_user
  65. user.updated_by_id = 1
  66. user.created_by_id = 1
  67. # check if feature is enabled
  68. if !Setting.get('user_create_account')
  69. render :json => { :error => 'Feature not enabled!' }, :status => :unprocessable_entity
  70. return
  71. end
  72. # add first user as admin/agent and to all groups
  73. group_ids = []
  74. role_ids = []
  75. if count <= 2
  76. Role.where( :name => [ 'Admin', 'Agent'] ).each { |role|
  77. role_ids.push role.id
  78. }
  79. Group.all().each { |group|
  80. group_ids.push group.id
  81. }
  82. # everybody else will go as customer per default
  83. else
  84. role_ids.push Role.where( :name => 'Customer' ).first.id
  85. end
  86. user.role_ids = role_ids
  87. user.group_ids = group_ids
  88. # else do assignment as defined
  89. else
  90. # permission check by role
  91. return if !permission_check_by_role
  92. if params[:role_ids]
  93. user.role_ids = params[:role_ids]
  94. end
  95. if params[:group_ids]
  96. user.group_ids = params[:group_ids]
  97. end
  98. end
  99. # check if user already exists
  100. if user.email
  101. exists = User.where( :email => user.email ).first
  102. if exists
  103. render :json => { :error => 'User already exists!' }, :status => :unprocessable_entity
  104. return
  105. end
  106. end
  107. user.save
  108. # if first user was added, set system init done
  109. if count <= 2
  110. Setting.set( 'system_init_done', true )
  111. end
  112. # send inviteation if needed / only if session exists
  113. if params[:invite] && current_user
  114. # generate token
  115. token = Token.create( :action => 'PasswordReset', :user_id => user.id )
  116. # send mail
  117. data = {}
  118. data[:subject] = 'Invitation to #{config.product_name} at #{config.fqdn}'
  119. data[:body] = 'Hi #{user.firstname},
  120. I (#{current_user.firstname} #{current_user.lastname}) invite you to #{config.product_name} - the customer support / ticket system platform.
  121. Click on the following link and set your password:
  122. #{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}
  123. Enjoy,
  124. #{current_user.firstname} #{current_user.lastname}
  125. Your #{config.product_name} Team
  126. '
  127. # prepare subject & body
  128. [:subject, :body].each { |key|
  129. data[key.to_sym] = NotificationFactory.build(
  130. :locale => user.locale,
  131. :string => data[key.to_sym],
  132. :objects => {
  133. :token => token,
  134. :user => user,
  135. :current_user => current_user,
  136. }
  137. )
  138. }
  139. # send notification
  140. NotificationFactory.send(
  141. :recipient => user,
  142. :subject => data[:subject],
  143. :body => data[:body]
  144. )
  145. end
  146. user_new = User.find( user.id )
  147. render :json => user_new, :status => :created
  148. rescue Exception => e
  149. render :json => { :error => e.message }, :status => :unprocessable_entity
  150. end
  151. end
  152. # @path [PUT] /users/{id}
  153. #
  154. # @summary Updates the User record matching the identifier with the provided attribute values.
  155. # @notes TODO.
  156. #
  157. # @parameter id(required) [Integer] The identifier matching the requested User record.
  158. # @parameter User(required,body) [User] The attribute value structure needed to update a User record.
  159. #
  160. # @response_message 200 [User] Updated User record.
  161. # @response_message 401 Invalid session.
  162. def update
  163. # access deny
  164. return if !permission_check
  165. user = User.find( params[:id] )
  166. begin
  167. user.update_attributes( User.param_cleanup(params) )
  168. # only allow Admin's and Agent's
  169. if is_role('Admin') && is_role('Agent') && params[:role_ids]
  170. user.role_ids = params[:role_ids]
  171. end
  172. # only allow Admin's
  173. if is_role('Admin') && params[:group_ids]
  174. user.group_ids = params[:group_ids]
  175. end
  176. # only allow Admin's and Agent's
  177. if is_role('Admin') && is_role('Agent') && params[:organization_ids]
  178. user.organization_ids = params[:organization_ids]
  179. end
  180. # get new data
  181. user_new = User.find( params[:id] )
  182. render :json => user_new, :status => :ok
  183. rescue Exception => e
  184. render :json => { :error => e.message }, :status => :unprocessable_entity
  185. end
  186. end
  187. # @path [DELETE] /users/{id}
  188. #
  189. # @summary Deletes the User record matching the given identifier.
  190. # @notes The requester has to be in the role 'Admin' to be able to delete a User record.
  191. #
  192. # @parameter id(required) [User] The identifier matching the requested User record.
  193. #
  194. # @response_message 200 User successfully deleted.
  195. # @response_message 401 Invalid session.
  196. def destroy
  197. return if deny_if_not_role('Admin')
  198. model_destory_render(User, params)
  199. end
  200. # @path [GET] /users/search
  201. #
  202. # @tag Search
  203. # @tag User
  204. #
  205. # @summary Searches the User matching the given expression(s).
  206. # @notes TODO: It's possible to use the SOLR search syntax.
  207. # The requester has to be in the role 'Admin' or 'Agent' to
  208. # be able to search for User records.
  209. #
  210. # @parameter term [String] The search term.
  211. # @parameter limit [Integer] The limit of search results.
  212. # @parameter role_ids(multi) [Array<String>] A list of Role identifiers to which the Users have to be allocated to.
  213. # @parameter full [Boolean] Defines if the result should be
  214. # true: { user_ids => [1,2,...], assets => {...} }
  215. # or false: [{:id => user.id, :label => "firstname lastname <email>", :value => "firstname lastname <email>"},...].
  216. #
  217. # @response_message 200 [Array<User>] A list of User records matching the search term.
  218. # @response_message 401 Invalid session.
  219. def search
  220. if is_role('Customer') && !is_role('Admin') && !is_role('Agent')
  221. response_access_deny
  222. return
  223. end
  224. query_params = {
  225. :query => params[:term],
  226. :limit => params[:limit],
  227. :current_user => current_user,
  228. }
  229. if params[:role_ids] && !params[:role_ids].empty?
  230. query_params[:role_ids] = params[:role_ids]
  231. end
  232. # do query
  233. user_all = User.search(query_params)
  234. # build result list
  235. if !params[:full]
  236. users = []
  237. user_all.each { |user|
  238. realname = user.firstname.to_s + ' ' + user.lastname.to_s
  239. if user.email && user.email.to_s != ''
  240. realname = realname + ' <' + user.email.to_s + '>'
  241. end
  242. a = { :id => user.id, :label => realname, :value => realname }
  243. users.push a
  244. }
  245. # return result
  246. render :json => users
  247. return
  248. end
  249. user_ids = []
  250. assets = {}
  251. user_all.each { |user|
  252. assets = user.assets(assets)
  253. user_ids.push user.id
  254. }
  255. # return result
  256. render :json => {
  257. :assets => assets,
  258. :user_ids => user_ids.uniq,
  259. }
  260. end
  261. # @path [GET] /users/history/{id}
  262. #
  263. # @tag History
  264. # @tag User
  265. #
  266. # @summary Returns the History records of a User record matching the given identifier.
  267. # @notes The requester has to be in the role 'Admin' or 'Agent' to
  268. # get the History records of a User record.
  269. #
  270. # @parameter id(required) [Integer] The identifier matching the requested User record.
  271. #
  272. # @response_message 200 [History] The History records of the requested User record.
  273. # @response_message 401 Invalid session.
  274. def history
  275. # permissin check
  276. if !is_role('Admin') && !is_role('Agent')
  277. response_access_deny
  278. return
  279. end
  280. # get user data
  281. user = User.find( params[:id] )
  282. # get history of user
  283. history = user.history_get(true)
  284. # return result
  285. render :json => history
  286. end
  287. =begin
  288. Resource:
  289. POST /api/v1/users/password_reset
  290. Payload:
  291. {
  292. "username": "some user name"
  293. }
  294. Response:
  295. {
  296. :message => 'ok'
  297. }
  298. Test:
  299. curl http://localhost/api/v1/users/password_reset.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"username": "some_username"}'
  300. =end
  301. def password_reset_send
  302. # check if feature is enabled
  303. if !Setting.get('user_lost_password')
  304. render :json => { :error => 'Feature not enabled!' }, :status => :unprocessable_entity
  305. return
  306. end
  307. success = User.password_reset_send( params[:username] )
  308. if success
  309. render :json => { :message => 'ok' }, :status => :ok
  310. else
  311. render :json => { :message => 'failed' }, :status => :unprocessable_entity
  312. end
  313. end
  314. =begin
  315. Resource:
  316. POST /api/v1/users/password_reset_verify
  317. Payload:
  318. {
  319. "token": "SoMeToKeN",
  320. "password": "new_password"
  321. }
  322. Response:
  323. {
  324. :message => 'ok'
  325. }
  326. Test:
  327. curl http://localhost/api/v1/users/password_reset_verify.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"token": "SoMeToKeN", "password" "new_password"}'
  328. =end
  329. def password_reset_verify
  330. if params[:password]
  331. # check password policy
  332. result = password_policy(params[:password])
  333. if result != true
  334. render :json => { :message => 'failed', :notice => result }, :status => :ok
  335. return
  336. end
  337. # set new password with token
  338. user = User.password_reset_via_token( params[:token], params[:password] )
  339. else
  340. user = User.password_reset_check( params[:token] )
  341. end
  342. if user
  343. render :json => { :message => 'ok', :user_login => user.login }, :status => :ok
  344. else
  345. render :json => { :message => 'failed' }, :status => :ok
  346. end
  347. end
  348. =begin
  349. Resource:
  350. POST /api/v1/users/password_change
  351. Payload:
  352. {
  353. "password_old": "some_password_old",
  354. "password_new": "some_password_new"
  355. }
  356. Response:
  357. {
  358. :message => 'ok'
  359. }
  360. Test:
  361. curl http://localhost/api/v1/users/password_change.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"password_old": "password_old", "password_new": "password_new"}'
  362. =end
  363. def password_change
  364. # check old password
  365. if !params[:password_old]
  366. render :json => { :message => 'failed', :notice => ['Old password needed!'] }, :status => :ok
  367. return
  368. end
  369. user = User.authenticate( current_user.login, params[:password_old] )
  370. if !user
  371. render :json => { :message => 'failed', :notice => ['Old password is wrong!'] }, :status => :ok
  372. return
  373. end
  374. # set new password
  375. if !params[:password_new]
  376. render :json => { :message => 'failed', :notice => ['Please supply your new password!'] }, :status => :ok
  377. return
  378. end
  379. # check password policy
  380. result = password_policy(params[:password_new])
  381. if result != true
  382. render :json => { :message => 'failed', :notice => result }, :status => :ok
  383. return
  384. end
  385. user.update_attributes( :password => params[:password_new] )
  386. render :json => { :message => 'ok', :user_login => user.login }, :status => :ok
  387. end
  388. =begin
  389. Resource:
  390. PUT /api/v1/users/preferences.json
  391. Payload:
  392. {
  393. "language": "de",
  394. "notification": true
  395. }
  396. Response:
  397. {
  398. :message => 'ok'
  399. }
  400. Test:
  401. curl http://localhost/api/v1/users/preferences.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"language": "de", "notifications": true}'
  402. =end
  403. def preferences
  404. if !current_user
  405. render :json => { :message => 'No current user!' }, :status => :unprocessable_entity
  406. return
  407. end
  408. if params[:user]
  409. params[:user].each {|key, value|
  410. current_user.preferences[key.to_sym] = value
  411. }
  412. end
  413. current_user.save
  414. render :json => { :message => 'ok' }, :status => :ok
  415. end
  416. =begin
  417. Resource:
  418. DELETE /api/v1/users/account.json
  419. Payload:
  420. {
  421. "provider": "twitter",
  422. "uid": 581482342942
  423. }
  424. Response:
  425. {
  426. :message => 'ok'
  427. }
  428. Test:
  429. curl http://localhost/api/v1/users/account.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"provider": "twitter", "uid": 581482342942}'
  430. =end
  431. def account_remove
  432. if !current_user
  433. render :json => { :message => 'No current user!' }, :status => :unprocessable_entity
  434. return
  435. end
  436. # provider + uid to remove
  437. if !params[:provider]
  438. render :json => { :message => 'provider needed!' }, :status => :unprocessable_entity
  439. return
  440. end
  441. if !params[:uid]
  442. render :json => { :message => 'uid needed!' }, :status => :unprocessable_entity
  443. return
  444. end
  445. # remove from database
  446. record = Authorization.where(
  447. :user_id => current_user.id,
  448. :provider => params[:provider],
  449. :uid => params[:uid],
  450. )
  451. if !record.first
  452. render :json => { :message => 'No record found!' }, :status => :unprocessable_entity
  453. return
  454. end
  455. record.destroy_all
  456. render :json => { :message => 'ok' }, :status => :ok
  457. end
  458. =begin
  459. Resource:
  460. GET /api/v1/users/image/8d6cca1c6bdc226cf2ba131e264ca2c7
  461. Response:
  462. <IMAGE>
  463. Test:
  464. curl http://localhost/api/v1/users/image/8d6cca1c6bdc226cf2ba131e264ca2c7 -v -u #{login}:#{password}
  465. =end
  466. def image
  467. # cache image
  468. response.headers['Expires'] = 1.year.from_now.httpdate
  469. response.headers['Cache-Control'] = 'cache, store, max-age=31536000, must-revalidate'
  470. response.headers['Pragma'] = 'cache'
  471. file = Avatar.get_by_hash( params[:hash] )
  472. if file
  473. send_data(
  474. file.content,
  475. :filename => file.filename,
  476. :type => file.preferences['Content-Type'] || file.preferences['Mime-Type'],
  477. :disposition => 'inline'
  478. )
  479. return
  480. end
  481. # serve default image
  482. image = 'R0lGODdhMAAwAOMAAMzMzJaWlr6+vqqqqqOjo8XFxbe3t7GxsZycnAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAMAAwAAAEcxDISau9OOvNu/9gKI5kaZ5oqq5s675wLM90bd94ru98TwuAA+KQAQqJK8EAgBAgMEqmkzUgBIeSwWGZtR5XhSqAULACCoGCJGwlm1MGQrq9RqgB8fm4ZTUgDBIEcRR9fz6HiImKi4yNjo+QkZKTlJWWkBEAOw=='
  483. send_data(
  484. Base64.decode64(image),
  485. :filename => 'image.gif',
  486. :type => 'image/gif',
  487. :disposition => 'inline'
  488. )
  489. end
  490. =begin
  491. Resource:
  492. POST /api/v1/users/avatar
  493. Payload:
  494. {
  495. "avatar_full": "base64 url",
  496. }
  497. Response:
  498. {
  499. :message => 'ok'
  500. }
  501. Test:
  502. curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"avatar": "base64 url"}'
  503. =end
  504. def avatar_new
  505. return if !valid_session_with_user
  506. # get & validate image
  507. file_full = StaticAssets.data_url_attributes( params[:avatar_full] )
  508. file_resize = StaticAssets.data_url_attributes( params[:avatar_resize] )
  509. avatar = Avatar.add(
  510. :object => 'User',
  511. :o_id => current_user.id,
  512. :full => {
  513. :content => file_full[:content],
  514. :mime_type => file_full[:mime_type],
  515. },
  516. :resize => {
  517. :content => file_resize[:content],
  518. :mime_type => file_resize[:mime_type],
  519. },
  520. :source => 'upload ' + Time.now.to_s,
  521. :deletable => true,
  522. )
  523. # update user link
  524. current_user.update_attributes( :image => avatar.store_hash )
  525. render :json => { :avatar => avatar }, :status => :ok
  526. end
  527. def avatar_set_default
  528. return if !valid_session_with_user
  529. # get & validate image
  530. if !params[:id]
  531. render :json => { :message => 'No id of avatar!' }, :status => :unprocessable_entity
  532. return
  533. end
  534. # set as default
  535. avatar = Avatar.set_default( 'User', current_user.id, params[:id] )
  536. # update user link
  537. current_user.update_attributes( :image => avatar.store_hash )
  538. render :json => {}, :status => :ok
  539. end
  540. def avatar_destroy
  541. return if !valid_session_with_user
  542. # get & validate image
  543. if !params[:id]
  544. render :json => { :message => 'No id of avatar!' }, :status => :unprocessable_entity
  545. return
  546. end
  547. # remove avatar
  548. Avatar.remove_one( 'User', current_user.id, params[:id] )
  549. # update user link
  550. avatar = Avatar.get_default( 'User', current_user.id )
  551. current_user.update_attributes( :image => avatar.store_hash )
  552. render :json => {}, :status => :ok
  553. end
  554. def avatar_list
  555. return if !valid_session_with_user
  556. # list of avatars
  557. result = Avatar.list( 'User', current_user.id )
  558. render :json => { :avatars => result }, :status => :ok
  559. end
  560. private
  561. def password_policy(password)
  562. if Setting.get('password_min_size') > password.length
  563. return ["Can\'t update password, it must be at least %s characters long!", Setting.get('password_min_size')]
  564. end
  565. if Setting.get('password_need_digit').to_i == 1 && password !~ /\d/
  566. return ["Can't update password, it must contain at least 1 digit!"]
  567. end
  568. if Setting.get('password_min_2_lower_2_upper_characters').to_i == 1 && ( password !~ /[A-Z].*[A-Z]/ || password !~ /[a-z].*[a-z]/ )
  569. return ["Can't update password, it must contain at least 2 lowercase and 2 uppercase characters!"]
  570. end
  571. true
  572. end
  573. def permission_check_by_role
  574. return true if is_role('Admin')
  575. return true if is_role('Agent')
  576. response_access_deny
  577. return false
  578. end
  579. def permission_check
  580. return true if is_role('Admin')
  581. return true if is_role('Agent')
  582. # allow to update customer by him self
  583. return true if is_role('Customer') && params[:id].to_i == current_user.id
  584. response_access_deny
  585. return false
  586. end
  587. end