search.rb 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Organization
  3. module Search
  4. extend ActiveSupport::Concern
  5. # methods defined here are going to extend the class, not the instance of it
  6. class_methods do
  7. =begin
  8. search organizations preferences
  9. result = Organization.search_preferences(user_model)
  10. returns if user has permissions to search
  11. result = {
  12. prio: 1000,
  13. direct_search_index: true
  14. }
  15. returns if user has no permissions to search
  16. result = false
  17. =end
  18. def search_preferences(current_user)
  19. return false if !current_user.permissions?(['ticket.agent', 'ticket.customer', 'admin.organization'])
  20. {
  21. prio: 1500,
  22. direct_search_index: !customer_only?(current_user),
  23. }
  24. end
  25. def customer_only?(current_user)
  26. return true if current_user.permissions?('ticket.customer') && !current_user.permissions?(['admin.organization', 'ticket.agent'])
  27. false
  28. end
  29. =begin
  30. search organizations
  31. result = Organization.search(
  32. current_user: User.find(123),
  33. query: 'search something',
  34. limit: 15,
  35. offset: 100,
  36. # sort single column
  37. sort_by: 'created_at',
  38. order_by: 'asc',
  39. # sort multiple columns
  40. sort_by: [ 'created_at', 'updated_at' ],
  41. order_by: [ 'asc', 'desc' ],
  42. )
  43. returns
  44. result = [organization_model1, organization_model2]
  45. =end
  46. def search(params)
  47. # get params
  48. query = params[:query]
  49. limit = params[:limit] || 10
  50. offset = params[:offset] || 0
  51. current_user = params[:current_user]
  52. sql_helper = ::SqlHelper.new(object: self)
  53. # check sort - positions related to order by
  54. sort_by = sql_helper.get_sort_by(params, %w[active updated_at])
  55. # check order - positions related to sort by
  56. order_by = sql_helper.get_order_by(params, %w[desc desc])
  57. # enable search only for permitted users
  58. return [] if !search_preferences(current_user)
  59. # make sure customers always only can search their own organizations
  60. if customer_only?(current_user)
  61. params[:ids] = current_user.all_organization_ids
  62. end
  63. # try search index backend
  64. if SearchIndexBackend.enabled?
  65. items = SearchIndexBackend.search(query, 'Organization', limit: limit,
  66. from: offset,
  67. sort_by: sort_by,
  68. order_by: order_by,
  69. ids: params[:ids])
  70. organizations = []
  71. items.each do |item|
  72. organization = Organization.lookup(id: item[:id])
  73. next if !organization
  74. organizations.push organization
  75. end
  76. return organizations
  77. end
  78. order_select_sql = sql_helper.get_order_select(sort_by, order_by, 'organizations.updated_at')
  79. order_sql = sql_helper.get_order(sort_by, order_by, 'organizations.updated_at ASC')
  80. # fallback do sql query
  81. # - stip out * we already search for *query* -
  82. query.delete! '*'
  83. organizations = Organization.where_or_cis(%i[name note], "%#{query}%")
  84. .reorder(Arel.sql(order_sql))
  85. .offset(offset)
  86. .limit(limit)
  87. if params[:ids].present?
  88. organizations = organizations.where(id: params[:ids])
  89. end
  90. organizations = organizations.to_a
  91. # use result independent of size if an explicit offset is given
  92. # this is the case for e.g. paginated searches
  93. return organizations if params[:offset].present?
  94. return organizations if organizations.length > 3
  95. # if only a few organizations are found, search for names of users
  96. organizations_by_user = Organization.select("DISTINCT(organizations.id), #{order_select_sql}")
  97. .joins('LEFT OUTER JOIN users ON users.organization_id = organizations.id')
  98. .where(User.or_cis(%i[firstname lastname email], "%#{query}%"))
  99. .reorder(Arel.sql(order_sql))
  100. .limit(limit)
  101. if params[:ids].present?
  102. organizations_by_user = organizations_by_user.where(id: params[:ids])
  103. end
  104. organizations_by_user.each do |organization_by_user|
  105. organization_exists = false
  106. organizations.each do |organization|
  107. next if organization.id != organization_by_user.id
  108. organization_exists = true
  109. break
  110. end
  111. # get model with full data
  112. next if organization_exists
  113. organizations.push Organization.find(organization_by_user.id)
  114. end
  115. organizations
  116. end
  117. end
  118. end
  119. end