token.rb 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. class Token < ApplicationModel
  3. include CanBeAuthorized
  4. before_create :generate_token
  5. belongs_to :user, optional: true
  6. store :preferences
  7. =begin
  8. create new token
  9. token = Token.create(action: 'PasswordReset', user_id: user.id)
  10. returns
  11. the token
  12. create new persistent token
  13. token = Token.create(
  14. action: 'api',
  15. persistent: true,
  16. user_id: user.id,
  17. preferences: {
  18. permission: {
  19. 'user_preferences.calendar' => true,
  20. }
  21. }
  22. )
  23. in case if you use it via an controller, e. g. you can verify via "curl -H "Authorization: Token token=33562a00d7eda2a7c2fb639b91c6bcb8422067b6" http://...
  24. returns
  25. the token
  26. =end
  27. =begin
  28. check token
  29. user = Token.check(action: 'PasswordReset', name: '123abc12qweads')
  30. check api token with permissions
  31. user = Token.check(action: 'api', name: '123abc12qweads', permission: 'admin.session')
  32. user = Token.check(action: 'api', name: '123abc12qweads', permission: ['admin.session', 'ticket.agent'])
  33. returns
  34. user for who this token was created
  35. =end
  36. def self.check(data)
  37. # fetch token
  38. token = Token.find_by(action: data[:action], name: data[:name])
  39. return if !token
  40. # check if token is still valid
  41. if !token.persistent &&
  42. token.created_at < 1.day.ago
  43. # delete token
  44. token.delete
  45. token.save
  46. return
  47. end
  48. user = token.user
  49. # persistent token not valid if user is inactive
  50. return if !data[:inactive_user] && token.persistent && user.active == false
  51. # add permission check
  52. return if data[:permission] && !token.permissions?(data[:permission])
  53. # return token user
  54. user
  55. end
  56. =begin
  57. cleanup old token
  58. Token.cleanup
  59. =end
  60. def self.cleanup
  61. Token.where('persistent IS ? AND created_at < ?', nil, 30.days.ago).delete_all
  62. true
  63. end
  64. def permissions
  65. Permission.where(
  66. name: Array(preferences[:permission]),
  67. active: true,
  68. )
  69. end
  70. def permissions?(names)
  71. return false if !effective_user.permissions?(names)
  72. super(names)
  73. end
  74. # allows to evaluate token permissions in context of given user instead of owner
  75. # @param [User] user to use as context for the given block
  76. # @param block to evaluate in given context
  77. def with_context(user:, &block)
  78. @effective_user = user
  79. instance_eval(&block) if block
  80. ensure
  81. @effective_user = nil
  82. end
  83. private
  84. def generate_token
  85. loop do
  86. self.name = SecureRandom.urlsafe_base64(48)
  87. break if !Token.exists?(name: name)
  88. end
  89. true
  90. end
  91. # token owner or user set by #with_context
  92. def effective_user
  93. @effective_user || user
  94. end
  95. end