base.rb 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Sessions::Event::Base
  3. def initialize(params)
  4. params.each do |key, value|
  5. instance_variable_set :"@#{key}", value
  6. end
  7. @is_web_socket = false
  8. return if !@clients[@client_id]
  9. @is_web_socket = true
  10. return if !self.class.instance_variable_get(:@database_connection)
  11. if ActiveRecord::Base.connected?
  12. @reused_connection = true
  13. else
  14. @reused_connection = false
  15. ActiveRecord::Base.establish_connection
  16. end
  17. session_user_info
  18. end
  19. def session_user_info
  20. return if !@session
  21. return if !@session['id']
  22. user = User.lookup(id: @session['id'])
  23. return if user.blank?
  24. UserInfo.current_user_id = user.id
  25. end
  26. def self.inherited(subclass)
  27. super
  28. subclass.instance_variable_set(:@database_connection, @database_connection)
  29. end
  30. def websocket_send(recipient_client_id, data)
  31. msg = if data.instance_of?(Array)
  32. data.to_json
  33. else
  34. "[#{data.to_json}]"
  35. end
  36. if @clients[recipient_client_id]
  37. log 'debug', "ws send #{msg}", recipient_client_id
  38. @clients[recipient_client_id][:websocket].send(msg)
  39. else
  40. log 'debug', "fs send #{msg}", recipient_client_id
  41. Sessions.send(recipient_client_id, data)
  42. end
  43. end
  44. def valid_session?
  45. if !@session
  46. error = {
  47. event: 'error',
  48. data: {
  49. state: 'no_session',
  50. },
  51. }
  52. Sessions.send(@client_id, error)
  53. return
  54. end
  55. if !@session['id']
  56. error = {
  57. event: 'error',
  58. data: {
  59. state: 'no_session_user_id',
  60. },
  61. }
  62. Sessions.send(@client_id, error)
  63. return
  64. end
  65. true
  66. end
  67. def current_user_id
  68. if !@session
  69. error = {
  70. event: "#{@event}_error",
  71. data: {
  72. state: 'no_session',
  73. },
  74. }
  75. Sessions.send(@client_id, error)
  76. return
  77. end
  78. if @session['id'].blank?
  79. error = {
  80. event: "#{@event}_error",
  81. data: {
  82. state: 'no_session_user_id',
  83. },
  84. }
  85. Sessions.send(@client_id, error)
  86. return
  87. end
  88. @session['id']
  89. end
  90. def current_user
  91. user_id = current_user_id
  92. return if !user_id
  93. user = User.find_by(id: user_id)
  94. if !user
  95. error = {
  96. event: "#{event}_error",
  97. data: {
  98. state: 'no_such_user',
  99. },
  100. }
  101. Sessions.send(@client_id, error)
  102. return
  103. end
  104. user
  105. end
  106. def remote_ip
  107. # Basic implementation of the algorithm recommended by
  108. # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For#selecting_an_ip_address
  109. # because we cannot use Rails' request.remote_ip here (as it runs from websocket server without rack).
  110. raw_header = @headers&.dig('X-Forwarded-For').presence
  111. return if !raw_header
  112. raw_header
  113. .split(',')
  114. .map(&:strip)
  115. .difference(Rails.application.config.action_dispatch.trusted_proxies)
  116. .last
  117. end
  118. def origin
  119. @headers&.fetch('Origin', nil).presence
  120. end
  121. def permission_check(key, event)
  122. user = current_user
  123. return if !user
  124. if !user.permissions?(key)
  125. error = {
  126. event: "#{event}_error",
  127. data: {
  128. state: 'no_permission',
  129. },
  130. }
  131. Sessions.send(@client_id, error)
  132. return
  133. end
  134. true
  135. end
  136. def log(level, data, client_id = nil)
  137. return if !@options[:v] && level == 'debug'
  138. if !client_id
  139. client_id = @client_id
  140. end
  141. # rubocop:disable Rails/Output
  142. puts "#{Time.now.utc.iso8601}:client(#{client_id}) #{data}"
  143. # puts "#{Time.now.utc.iso8601}:#{ level }:client(#{ client_id }) #{ data }"
  144. # rubocop:enable Rails/Output
  145. # Rails.logger.info "#{Time.now.utc.iso8601}:client(#{client_id}) #{data}"
  146. end
  147. def self.database_connection_required
  148. @database_connection = true
  149. end
  150. def destroy
  151. return if !@is_web_socket
  152. return if !self.class.instance_variable_get(:@database_connection)
  153. return if @reused_connection
  154. ActiveRecord::Base.remove_connection
  155. end
  156. end