users_controller.rb 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class UsersController < ApplicationController
  3. prepend_before_action :authentication_check, except: %i[create password_reset_send password_reset_verify image]
  4. prepend_before_action :authentication_check_only, only: [:create]
  5. # @path [GET] /users
  6. #
  7. # @summary Returns a list of User records.
  8. # @notes The requester has to be in the role 'Admin' or 'Agent' to
  9. # get a list of all Users. If the requester is in the
  10. # role 'Customer' only just the own User record will be returned.
  11. #
  12. # @response_message 200 [Array<User>] List of matching User records.
  13. # @response_message 401 Invalid session.
  14. def index
  15. offset = 0
  16. per_page = 500
  17. if params[:page] && params[:per_page]
  18. offset = (params[:page].to_i - 1) * params[:per_page].to_i
  19. per_page = params[:per_page].to_i
  20. end
  21. if per_page > 500
  22. per_page = 500
  23. end
  24. # only allow customer to fetch him self
  25. users = if !current_user.permissions?(['admin.user', 'ticket.agent'])
  26. User.where(id: current_user.id).order(id: 'ASC').offset(offset).limit(per_page)
  27. else
  28. User.all.order(id: 'ASC').offset(offset).limit(per_page)
  29. end
  30. if params[:expand]
  31. list = []
  32. users.each do |user|
  33. list.push user.attributes_with_association_names
  34. end
  35. render json: list, status: :ok
  36. return
  37. end
  38. if params[:full]
  39. assets = {}
  40. item_ids = []
  41. users.each do |item|
  42. item_ids.push item.id
  43. assets = item.assets(assets)
  44. end
  45. render json: {
  46. record_ids: item_ids,
  47. assets: assets,
  48. }, status: :ok
  49. return
  50. end
  51. users_all = []
  52. users.each do |user|
  53. users_all.push User.lookup(id: user.id).attributes_with_association_ids
  54. end
  55. render json: users_all, status: :ok
  56. end
  57. # @path [GET] /users/{id}
  58. #
  59. # @summary Returns the User record with the requested identifier.
  60. # @notes The requester has to be in the role 'Admin' or 'Agent' to
  61. # access all User records. If the requester is in the
  62. # role 'Customer' just the own User record is accessable.
  63. #
  64. # @parameter id(required) [Integer] The identifier matching the requested User.
  65. # @parameter full [Bool] If set a Asset structure with all connected Assets gets returned.
  66. #
  67. # @response_message 200 [User] User record matching the requested identifier.
  68. # @response_message 401 Invalid session.
  69. def show
  70. user = User.find(params[:id])
  71. access!(user, 'read')
  72. if params[:expand]
  73. result = user.attributes_with_association_names
  74. elsif params[:full]
  75. result = {
  76. id: params[:id],
  77. assets: user.assets({}),
  78. }
  79. else
  80. result = user.attributes_with_association_ids
  81. result.delete('password')
  82. end
  83. render json: result
  84. end
  85. # @path [POST] /users
  86. #
  87. # @summary Creates a User record with the provided attribute values.
  88. # @notes TODO.
  89. #
  90. # @parameter User(required,body) [User] The attribute value structure needed to create a User record.
  91. #
  92. # @response_message 200 [User] Created User record.
  93. # @response_message 401 Invalid session.
  94. def create
  95. clean_params = User.association_name_to_id_convert(params)
  96. clean_params = User.param_cleanup(clean_params, true)
  97. # check if it's first user, the admin user
  98. # inital admin account
  99. count = User.all.count()
  100. admin_account_exists = true
  101. if count <= 2
  102. admin_account_exists = false
  103. end
  104. # if it's a signup, add user to customer role
  105. if !current_user
  106. # check if feature is enabled
  107. if admin_account_exists && !Setting.get('user_create_account')
  108. raise Exceptions::UnprocessableEntity, 'Feature not enabled!'
  109. end
  110. # check signup option only after admin account is created
  111. if admin_account_exists && !params[:signup]
  112. raise Exceptions::UnprocessableEntity, 'Only signup with not authenticate user possible!'
  113. end
  114. # check if user already exists
  115. if clean_params[:email].blank?
  116. raise Exceptions::UnprocessableEntity, 'Attribute \'email\' required!'
  117. end
  118. # check if user already exists
  119. exists = User.find_by(email: clean_params[:email].downcase.strip)
  120. raise Exceptions::UnprocessableEntity, 'Email address is already used for other user.' if exists
  121. user = User.new(clean_params)
  122. user.associations_from_param(params)
  123. user.updated_by_id = 1
  124. user.created_by_id = 1
  125. # add first user as admin/agent and to all groups
  126. group_ids = []
  127. role_ids = []
  128. if count <= 2
  129. Role.where(name: %w[Admin Agent]).each do |role|
  130. role_ids.push role.id
  131. end
  132. Group.all().each do |group|
  133. group_ids.push group.id
  134. end
  135. # everybody else will go as customer per default
  136. else
  137. role_ids = Role.signup_role_ids
  138. end
  139. user.role_ids = role_ids
  140. user.group_ids = group_ids
  141. # remember source (in case show email verify banner)
  142. # if not inital user creation
  143. if admin_account_exists
  144. user.source = 'signup'
  145. end
  146. # else do assignment as defined
  147. else
  148. # permission check
  149. permission_check_by_permission(params)
  150. user = User.new(clean_params)
  151. user.associations_from_param(params)
  152. end
  153. user.save!
  154. # if first user was added, set system init done
  155. if !admin_account_exists
  156. Setting.set('system_init_done', true)
  157. # fetch org logo
  158. if user.email.present?
  159. Service::Image.organization_suggest(user.email)
  160. end
  161. # load calendar
  162. Calendar.init_setup(request.remote_ip)
  163. # load text modules
  164. begin
  165. TextModule.load(request.env['HTTP_ACCEPT_LANGUAGE'] || 'en-us')
  166. rescue => e
  167. logger.error "Unable to load text modules #{request.env['HTTP_ACCEPT_LANGUAGE'] || 'en-us'}: #{e.message}"
  168. end
  169. end
  170. # send inviteation if needed / only if session exists
  171. if params[:invite] && current_user
  172. token = Token.create(action: 'PasswordReset', user_id: user.id)
  173. NotificationFactory::Mailer.notification(
  174. template: 'user_invite',
  175. user: user,
  176. objects: {
  177. token: token,
  178. user: user,
  179. current_user: current_user,
  180. }
  181. )
  182. end
  183. # send email verify
  184. if params[:signup] && !current_user
  185. result = User.signup_new_token(user)
  186. NotificationFactory::Mailer.notification(
  187. template: 'signup',
  188. user: user,
  189. objects: result,
  190. )
  191. end
  192. if params[:expand]
  193. user = User.find(user.id).attributes_with_association_names
  194. render json: user, status: :created
  195. return
  196. end
  197. user_new = User.find(user.id).attributes_with_association_ids
  198. user_new.delete('password')
  199. render json: user_new, status: :created
  200. end
  201. # @path [PUT] /users/{id}
  202. #
  203. # @summary Updates the User record matching the identifier with the provided attribute values.
  204. # @notes TODO.
  205. #
  206. # @parameter id(required) [Integer] The identifier matching the requested User record.
  207. # @parameter User(required,body) [User] The attribute value structure needed to update a User record.
  208. #
  209. # @response_message 200 [User] Updated User record.
  210. # @response_message 401 Invalid session.
  211. def update
  212. permission_check_by_permission(params)
  213. user = User.find(params[:id])
  214. access!(user, 'change')
  215. # permission check
  216. permission_check_by_permission(params)
  217. user.with_lock do
  218. clean_params = User.association_name_to_id_convert(params)
  219. clean_params = User.param_cleanup(clean_params, true)
  220. user.update!(clean_params)
  221. # only allow Admin's
  222. if current_user.permissions?('admin.user') && (params[:role_ids] || params[:roles])
  223. user.associations_from_param(role_ids: params[:role_ids], roles: params[:roles])
  224. end
  225. # only allow Admin's
  226. if current_user.permissions?('admin.user') && (params[:group_ids] || params[:groups])
  227. user.associations_from_param(group_ids: params[:group_ids], groups: params[:groups])
  228. end
  229. # only allow Admin's and Agent's
  230. if current_user.permissions?(['admin.user', 'ticket.agent']) && (params[:organization_ids] || params[:organizations])
  231. user.associations_from_param(organization_ids: params[:organization_ids], organizations: params[:organizations])
  232. end
  233. if params[:expand]
  234. user = User.find(user.id).attributes_with_association_names
  235. render json: user, status: :ok
  236. return
  237. end
  238. end
  239. # get new data
  240. user_new = User.find(user.id).attributes_with_association_ids
  241. user_new.delete('password')
  242. render json: user_new, status: :ok
  243. end
  244. # @path [DELETE] /users/{id}
  245. #
  246. # @summary Deletes the User record matching the given identifier.
  247. # @notes The requester has to be in the role 'Admin' to be able to delete a User record.
  248. #
  249. # @parameter id(required) [User] The identifier matching the requested User record.
  250. #
  251. # @response_message 200 User successfully deleted.
  252. # @response_message 401 Invalid session.
  253. def destroy
  254. user = User.find(params[:id])
  255. access!(user, 'delete')
  256. model_references_check(User, params)
  257. model_destroy_render(User, params)
  258. end
  259. # @path [GET] /users/me
  260. #
  261. # @summary Returns the User record of current user.
  262. # @notes The requestor need to have a valid authentication.
  263. #
  264. # @parameter full [Bool] If set a Asset structure with all connected Assets gets returned.
  265. #
  266. # @response_message 200 [User] User record matching the requested identifier.
  267. # @response_message 401 Invalid session.
  268. def me
  269. if params[:expand]
  270. user = current_user.attributes_with_association_names
  271. render json: user, status: :ok
  272. return
  273. end
  274. if params[:full]
  275. full = User.full(current_user.id)
  276. render json: full
  277. return
  278. end
  279. user = current_user.attributes_with_association_ids
  280. user.delete('password')
  281. render json: user
  282. end
  283. # @path [GET] /users/search
  284. #
  285. # @tag Search
  286. # @tag User
  287. #
  288. # @summary Searches the User matching the given expression(s).
  289. # @notes TODO: It's possible to use the SOLR search syntax.
  290. # The requester has to be in the role 'Admin' or 'Agent' to
  291. # be able to search for User records.
  292. #
  293. # @parameter query [String] The search query.
  294. # @parameter limit [Integer] The limit of search results.
  295. # @parameter role_ids(multi) [Array<String>] A list of Role identifiers to which the Users have to be allocated to.
  296. # @parameter full [Boolean] Defines if the result should be
  297. # true: { user_ids => [1,2,...], assets => {...} }
  298. # or false: [{:id => user.id, :label => "firstname lastname <email>", :value => "firstname lastname <email>"},...].
  299. #
  300. # @response_message 200 [Array<User>] A list of User records matching the search term.
  301. # @response_message 401 Invalid session.
  302. def search
  303. if !current_user.permissions?(['ticket.agent', 'admin.user'])
  304. response_access_deny
  305. return
  306. end
  307. # set limit for pagination if needed
  308. if params[:page] && params[:per_page]
  309. params[:limit] = params[:page].to_i * params[:per_page].to_i
  310. end
  311. if params[:limit] && params[:limit].to_i > 500
  312. params[:limit] = 500
  313. end
  314. query = params[:query]
  315. if query.respond_to?(:permit!)
  316. query = query.permit!.to_h
  317. end
  318. query_params = {
  319. query: query,
  320. limit: params[:limit],
  321. current_user: current_user,
  322. }
  323. %i[role_ids permissions].each do |key|
  324. next if params[key].blank?
  325. query_params[key] = params[key]
  326. end
  327. # do query
  328. user_all = User.search(query_params)
  329. # do pagination if needed
  330. if params[:page] && params[:per_page]
  331. offset = (params[:page].to_i - 1) * params[:per_page].to_i
  332. user_all = user_all[offset, params[:per_page].to_i] || []
  333. end
  334. if params[:expand]
  335. list = []
  336. user_all.each do |user|
  337. list.push user.attributes_with_association_names
  338. end
  339. render json: list, status: :ok
  340. return
  341. end
  342. # build result list
  343. if params[:label]
  344. users = []
  345. user_all.each do |user|
  346. realname = user.firstname.to_s + ' ' + user.lastname.to_s
  347. if user.email && user.email.to_s != ''
  348. realname = realname + ' <' + user.email.to_s + '>'
  349. end
  350. a = { id: user.id, label: realname, value: realname }
  351. users.push a
  352. end
  353. # return result
  354. render json: users
  355. return
  356. end
  357. if params[:full]
  358. user_ids = []
  359. assets = {}
  360. user_all.each do |user|
  361. assets = user.assets(assets)
  362. user_ids.push user.id
  363. end
  364. # return result
  365. render json: {
  366. assets: assets,
  367. user_ids: user_ids.uniq,
  368. }
  369. return
  370. end
  371. list = []
  372. user_all.each do |user|
  373. list.push user.attributes_with_association_ids
  374. end
  375. render json: list, status: :ok
  376. end
  377. # @path [GET] /users/recent
  378. #
  379. # @tag Search
  380. # @tag User
  381. #
  382. # @summary Recent creates Users.
  383. # @notes Recent creates Users.
  384. #
  385. # @parameter limit [Integer] The limit of search results.
  386. # @parameter role_ids(multi) [Array<String>] A list of Role identifiers to which the Users have to be allocated to.
  387. # @parameter full [Boolean] Defines if the result should be
  388. # true: { user_ids => [1,2,...], assets => {...} }
  389. # or false: [{:id => user.id, :label => "firstname lastname <email>", :value => "firstname lastname <email>"},...].
  390. #
  391. # @response_message 200 [Array<User>] A list of User records matching the search term.
  392. # @response_message 401 Invalid session.
  393. def recent
  394. if !current_user.permissions?('admin.user')
  395. response_access_deny
  396. return
  397. end
  398. # do query
  399. user_all = if params[:role_ids].present?
  400. User.joins(:roles).where('roles.id' => params[:role_ids]).where('users.id != 1').order('users.created_at DESC').limit(params[:limit] || 20)
  401. else
  402. User.where('id != 1').order('created_at DESC').limit(params[:limit] || 20)
  403. end
  404. # build result list
  405. if !params[:full]
  406. users = []
  407. user_all.each do |user|
  408. realname = user.firstname.to_s + ' ' + user.lastname.to_s
  409. if user.email && user.email.to_s != ''
  410. realname = realname + ' <' + user.email.to_s + '>'
  411. end
  412. a = { id: user.id, label: realname, value: realname }
  413. users.push a
  414. end
  415. # return result
  416. render json: users
  417. return
  418. end
  419. user_ids = []
  420. assets = {}
  421. user_all.each do |user|
  422. assets = user.assets(assets)
  423. user_ids.push user.id
  424. end
  425. # return result
  426. render json: {
  427. assets: assets,
  428. user_ids: user_ids.uniq,
  429. }
  430. end
  431. # @path [GET] /users/history/{id}
  432. #
  433. # @tag History
  434. # @tag User
  435. #
  436. # @summary Returns the History records of a User record matching the given identifier.
  437. # @notes The requester has to be in the role 'Admin' or 'Agent' to
  438. # get the History records of a User record.
  439. #
  440. # @parameter id(required) [Integer] The identifier matching the requested User record.
  441. #
  442. # @response_message 200 [History] The History records of the requested User record.
  443. # @response_message 401 Invalid session.
  444. def history
  445. # permission check
  446. if !current_user.permissions?(['admin.user', 'ticket.agent'])
  447. response_access_deny
  448. return
  449. end
  450. # get user data
  451. user = User.find(params[:id])
  452. # get history of user
  453. history = user.history_get(true)
  454. # return result
  455. render json: history
  456. end
  457. =begin
  458. Resource:
  459. POST /api/v1/users/email_verify
  460. Payload:
  461. {
  462. "token": "SoMeToKeN",
  463. }
  464. Response:
  465. {
  466. :message => 'ok'
  467. }
  468. Test:
  469. curl http://localhost/api/v1/users/email_verify -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"token": "SoMeToKeN"}'
  470. =end
  471. def email_verify
  472. raise Exceptions::UnprocessableEntity, 'No token!' if !params[:token]
  473. user = User.signup_verify_via_token(params[:token], current_user)
  474. raise Exceptions::UnprocessableEntity, 'Invalid token!' if !user
  475. render json: { message: 'ok', user_email: user.email }, status: :ok
  476. end
  477. =begin
  478. Resource:
  479. POST /api/v1/users/email_verify_send
  480. Payload:
  481. {
  482. "email": "some_email@example.com"
  483. }
  484. Response:
  485. {
  486. :message => 'ok'
  487. }
  488. Test:
  489. curl http://localhost/api/v1/users/email_verify_send -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"email": "some_email@example.com"}'
  490. =end
  491. def email_verify_send
  492. raise Exceptions::UnprocessableEntity, 'No email!' if !params[:email]
  493. # check is verify is possible to send
  494. user = User.find_by(email: params[:email].downcase)
  495. raise Exceptions::UnprocessableEntity, 'No such user!' if !user
  496. #if user.verified == true
  497. # render json: { error: 'Already verified!' }, status: :unprocessable_entity
  498. # return
  499. #end
  500. token = Token.create(action: 'Signup', user_id: user.id)
  501. result = User.signup_new_token(user)
  502. if result && result[:token]
  503. user = result[:user]
  504. NotificationFactory::Mailer.notification(
  505. template: 'signup',
  506. user: user,
  507. objects: result
  508. )
  509. # only if system is in develop mode, send token back to browser for browser tests
  510. if Setting.get('developer_mode') == true
  511. render json: { message: 'ok', token: result[:token].name }, status: :ok
  512. return
  513. end
  514. # token sent to user, send ok to browser
  515. render json: { message: 'ok' }, status: :ok
  516. return
  517. end
  518. # unable to generate token
  519. render json: { message: 'failed' }, status: :ok
  520. end
  521. =begin
  522. Resource:
  523. POST /api/v1/users/password_reset
  524. Payload:
  525. {
  526. "username": "some user name"
  527. }
  528. Response:
  529. {
  530. :message => 'ok'
  531. }
  532. Test:
  533. curl http://localhost/api/v1/users/password_reset -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"username": "some_username"}'
  534. =end
  535. def password_reset_send
  536. # check if feature is enabled
  537. raise Exceptions::UnprocessableEntity, 'Feature not enabled!' if !Setting.get('user_lost_password')
  538. result = User.password_reset_new_token(params[:username])
  539. if result && result[:token]
  540. # send mail
  541. user = result[:user]
  542. NotificationFactory::Mailer.notification(
  543. template: 'password_reset',
  544. user: user,
  545. objects: result
  546. )
  547. # only if system is in develop mode, send token back to browser for browser tests
  548. if Setting.get('developer_mode') == true
  549. render json: { message: 'ok', token: result[:token].name }, status: :ok
  550. return
  551. end
  552. # token sent to user, send ok to browser
  553. render json: { message: 'ok' }, status: :ok
  554. return
  555. end
  556. # unable to generate token
  557. render json: { message: 'failed' }, status: :ok
  558. end
  559. =begin
  560. Resource:
  561. POST /api/v1/users/password_reset_verify
  562. Payload:
  563. {
  564. "token": "SoMeToKeN",
  565. "password": "new_password"
  566. }
  567. Response:
  568. {
  569. :message => 'ok'
  570. }
  571. Test:
  572. curl http://localhost/api/v1/users/password_reset_verify -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"token": "SoMeToKeN", "password" "new_password"}'
  573. =end
  574. def password_reset_verify
  575. if params[:password]
  576. # check password policy
  577. result = password_policy(params[:password])
  578. if result != true
  579. render json: { message: 'failed', notice: result }, status: :ok
  580. return
  581. end
  582. # set new password with token
  583. user = User.password_reset_via_token(params[:token], params[:password])
  584. # send mail
  585. if user
  586. NotificationFactory::Mailer.notification(
  587. template: 'password_change',
  588. user: user,
  589. objects: {
  590. user: user,
  591. current_user: current_user,
  592. }
  593. )
  594. end
  595. else
  596. user = User.by_reset_token(params[:token])
  597. end
  598. if user
  599. render json: { message: 'ok', user_login: user.login }, status: :ok
  600. else
  601. render json: { message: 'failed' }, status: :ok
  602. end
  603. end
  604. =begin
  605. Resource:
  606. POST /api/v1/users/password_change
  607. Payload:
  608. {
  609. "password_old": "some_password_old",
  610. "password_new": "some_password_new"
  611. }
  612. Response:
  613. {
  614. :message => 'ok'
  615. }
  616. Test:
  617. curl http://localhost/api/v1/users/password_change -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"password_old": "password_old", "password_new": "password_new"}'
  618. =end
  619. def password_change
  620. # check old password
  621. if !params[:password_old]
  622. render json: { message: 'failed', notice: ['Current password needed!'] }, status: :ok
  623. return
  624. end
  625. user = User.authenticate(current_user.login, params[:password_old])
  626. if !user
  627. render json: { message: 'failed', notice: ['Current password is wrong!'] }, status: :ok
  628. return
  629. end
  630. # set new password
  631. if !params[:password_new]
  632. render json: { message: 'failed', notice: ['Please supply your new password!'] }, status: :ok
  633. return
  634. end
  635. # check password policy
  636. result = password_policy(params[:password_new])
  637. if result != true
  638. render json: { message: 'failed', notice: result }, status: :ok
  639. return
  640. end
  641. user.update!(password: params[:password_new])
  642. NotificationFactory::Mailer.notification(
  643. template: 'password_change',
  644. user: user,
  645. objects: {
  646. user: user,
  647. current_user: current_user,
  648. }
  649. )
  650. render json: { message: 'ok', user_login: user.login }, status: :ok
  651. end
  652. =begin
  653. Resource:
  654. PUT /api/v1/users/preferences
  655. Payload:
  656. {
  657. "language": "de",
  658. "notification": true
  659. }
  660. Response:
  661. {
  662. :message => 'ok'
  663. }
  664. Test:
  665. curl http://localhost/api/v1/users/preferences -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"language": "de", "notifications": true}'
  666. =end
  667. def preferences
  668. raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user
  669. preferences_params = params.except(:controller, :action)
  670. if preferences_params.present?
  671. user = User.find(current_user.id)
  672. user.with_lock do
  673. preferences_params.permit!.to_h.each do |key, value|
  674. user.preferences[key.to_sym] = value
  675. end
  676. user.save!
  677. end
  678. end
  679. render json: { message: 'ok' }, status: :ok
  680. end
  681. =begin
  682. Resource:
  683. PUT /api/v1/users/out_of_office
  684. Payload:
  685. {
  686. "out_of_office": true,
  687. "out_of_office_start_at": true,
  688. "out_of_office_end_at": true,
  689. "out_of_office_replacement_id": 123,
  690. "out_of_office_text": 'honeymoon'
  691. }
  692. Response:
  693. {
  694. :message => 'ok'
  695. }
  696. Test:
  697. curl http://localhost/api/v1/users/out_of_office -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"out_of_office": true, "out_of_office_replacement_id": 123}'
  698. =end
  699. def out_of_office
  700. raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user
  701. user = User.find(current_user.id)
  702. user.with_lock do
  703. user.assign_attributes(
  704. out_of_office: params[:out_of_office],
  705. out_of_office_start_at: params[:out_of_office_start_at],
  706. out_of_office_end_at: params[:out_of_office_end_at],
  707. out_of_office_replacement_id: params[:out_of_office_replacement_id],
  708. )
  709. user.preferences[:out_of_office_text] = params[:out_of_office_text]
  710. user.save!
  711. end
  712. render json: { message: 'ok' }, status: :ok
  713. end
  714. =begin
  715. Resource:
  716. DELETE /api/v1/users/account
  717. Payload:
  718. {
  719. "provider": "twitter",
  720. "uid": 581482342942
  721. }
  722. Response:
  723. {
  724. :message => 'ok'
  725. }
  726. Test:
  727. curl http://localhost/api/v1/users/account -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"provider": "twitter", "uid": 581482342942}'
  728. =end
  729. def account_remove
  730. raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user
  731. # provider + uid to remove
  732. raise Exceptions::UnprocessableEntity, 'provider needed!' if !params[:provider]
  733. raise Exceptions::UnprocessableEntity, 'uid needed!' if !params[:uid]
  734. # remove from database
  735. record = Authorization.where(
  736. user_id: current_user.id,
  737. provider: params[:provider],
  738. uid: params[:uid],
  739. )
  740. raise Exceptions::UnprocessableEntity, 'No record found!' if !record.first
  741. record.destroy_all
  742. render json: { message: 'ok' }, status: :ok
  743. end
  744. =begin
  745. Resource:
  746. GET /api/v1/users/image/8d6cca1c6bdc226cf2ba131e264ca2c7
  747. Response:
  748. <IMAGE>
  749. Test:
  750. curl http://localhost/api/v1/users/image/8d6cca1c6bdc226cf2ba131e264ca2c7 -v -u #{login}:#{password}
  751. =end
  752. def image
  753. # cache image
  754. response.headers['Expires'] = 1.year.from_now.httpdate
  755. response.headers['Cache-Control'] = 'cache, store, max-age=31536000, must-revalidate'
  756. response.headers['Pragma'] = 'cache'
  757. file = Avatar.get_by_hash(params[:hash])
  758. if file
  759. send_data(
  760. file.content,
  761. filename: file.filename,
  762. type: file.preferences['Content-Type'] || file.preferences['Mime-Type'],
  763. disposition: 'inline'
  764. )
  765. return
  766. end
  767. # serve default image
  768. image = 'R0lGODdhMAAwAOMAAMzMzJaWlr6+vqqqqqOjo8XFxbe3t7GxsZycnAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAMAAwAAAEcxDISau9OOvNu/9gKI5kaZ5oqq5s675wLM90bd94ru98TwuAA+KQAQqJK8EAgBAgMEqmkzUgBIeSwWGZtR5XhSqAULACCoGCJGwlm1MGQrq9RqgB8fm4ZTUgDBIEcRR9fz6HiImKi4yNjo+QkZKTlJWWkBEAOw=='
  769. send_data(
  770. Base64.decode64(image),
  771. filename: 'image.gif',
  772. type: 'image/gif',
  773. disposition: 'inline'
  774. )
  775. end
  776. =begin
  777. Resource:
  778. POST /api/v1/users/avatar
  779. Payload:
  780. {
  781. "avatar_full": "base64 url",
  782. }
  783. Response:
  784. {
  785. message: 'ok'
  786. }
  787. Test:
  788. curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"avatar": "base64 url"}'
  789. =end
  790. def avatar_new
  791. return if !valid_session_with_user
  792. # get & validate image
  793. file_full = StaticAssets.data_url_attributes(params[:avatar_full])
  794. file_resize = StaticAssets.data_url_attributes(params[:avatar_resize])
  795. avatar = Avatar.add(
  796. object: 'User',
  797. o_id: current_user.id,
  798. full: {
  799. content: file_full[:content],
  800. mime_type: file_full[:mime_type],
  801. },
  802. resize: {
  803. content: file_resize[:content],
  804. mime_type: file_resize[:mime_type],
  805. },
  806. source: 'upload ' + Time.zone.now.to_s,
  807. deletable: true,
  808. )
  809. # update user link
  810. user = User.find(current_user.id)
  811. user.update!(image: avatar.store_hash)
  812. render json: { avatar: avatar }, status: :ok
  813. end
  814. def avatar_set_default
  815. return if !valid_session_with_user
  816. # get & validate image
  817. raise Exceptions::UnprocessableEntity, 'No id of avatar!' if !params[:id]
  818. # set as default
  819. avatar = Avatar.set_default('User', current_user.id, params[:id])
  820. # update user link
  821. user = User.find(current_user.id)
  822. user.update!(image: avatar.store_hash)
  823. render json: {}, status: :ok
  824. end
  825. def avatar_destroy
  826. return if !valid_session_with_user
  827. # get & validate image
  828. raise Exceptions::UnprocessableEntity, 'No id of avatar!' if !params[:id]
  829. # remove avatar
  830. Avatar.remove_one('User', current_user.id, params[:id])
  831. # update user link
  832. avatar = Avatar.get_default('User', current_user.id)
  833. user = User.find(current_user.id)
  834. user.update!(image: avatar.store_hash)
  835. render json: {}, status: :ok
  836. end
  837. def avatar_list
  838. return if !valid_session_with_user
  839. # list of avatars
  840. result = Avatar.list('User', current_user.id)
  841. render json: { avatars: result }, status: :ok
  842. end
  843. private
  844. def password_policy(password)
  845. if Setting.get('password_min_size').to_i > password.length
  846. return ["Can\'t update password, it must be at least %s characters long!", Setting.get('password_min_size')]
  847. end
  848. if Setting.get('password_need_digit').to_i == 1 && password !~ /\d/
  849. return ["Can't update password, it must contain at least 1 digit!"]
  850. end
  851. if Setting.get('password_min_2_lower_2_upper_characters').to_i == 1 && ( password !~ /[A-Z].*[A-Z]/ || password !~ /[a-z].*[a-z]/ )
  852. return ["Can't update password, it must contain at least 2 lowercase and 2 uppercase characters!"]
  853. end
  854. true
  855. end
  856. def permission_check_by_permission(params)
  857. return true if current_user.permissions?('admin.user')
  858. %i[role_ids roles].each do |key|
  859. next if !params[key]
  860. if current_user.permissions?('ticket.agent')
  861. params.delete(key)
  862. else
  863. logger.info "Role assignment is only allowed by admin! current_user_id: #{current_user.id} assigned to #{params[key].inspect}"
  864. raise Exceptions::NotAuthorized, 'This role assignment is only allowed by admin!'
  865. end
  866. end
  867. if current_user.permissions?('ticket.agent') && !params[:role_ids] && !params[:roles] && params[:id].blank?
  868. params[:role_ids] = Role.signup_role_ids
  869. end
  870. %i[group_ids groups].each do |key|
  871. next if !params[key]
  872. if current_user.permissions?('ticket.agent')
  873. params.delete(key)
  874. else
  875. logger.info "Group relation assignment is only allowed by admin! current_user_id: #{current_user.id} assigned to #{params[key].inspect}"
  876. raise Exceptions::NotAuthorized, 'Group relation is only allowed by admin!'
  877. end
  878. end
  879. return true if current_user.permissions?('ticket.agent')
  880. response_access_deny
  881. false
  882. end
  883. end