ticket_article_updates.rb 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. module Gql::Subscriptions
  3. class TicketArticleUpdates < BaseSubscription
  4. argument :ticket_id, GraphQL::Types::ID, description: 'Ticket identifier'
  5. description 'Changes to the list of ticket articles'
  6. field :add_article, Gql::Types::Ticket::ArticleType, description: 'A new article needs to be added to the list'
  7. field :update_article, Gql::Types::Ticket::ArticleType, description: 'An existing article was changed'
  8. field :remove_article_id, GraphQL::Types::ID, description: 'An article must be removed from the list'
  9. class << self
  10. # Helper methods for triggering with custom payload.
  11. def trigger_after_create(article)
  12. trigger_for_ticket(article, { article: article, event: :create })
  13. end
  14. def trigger_after_update(article)
  15. # Add information about changes to the internal flag for later processing.
  16. trigger_for_ticket(article, { article: article, event: :update, internal_changed?: article.previous_changes['internal'].present? })
  17. end
  18. def trigger_after_destroy(article)
  19. trigger_for_ticket(article, { article_id: Gql::ZammadSchema.id_from_object(article), event: :destroy })
  20. end
  21. def trigger_for_ticket(article, payload)
  22. trigger(payload, arguments: { ticket_id: Gql::ZammadSchema.id_from_object(article.ticket) })
  23. end
  24. end
  25. def authorized?(ticket_id:)
  26. Gql::ZammadSchema.authorized_object_from_id ticket_id, type: ::Ticket, user: context.current_user
  27. end
  28. # This needs to be passed a hash with the correct field name containing the article payload as root object,
  29. # as we cannot change the (graphql-ruby) function signature of update(ticket_id:).
  30. def update(ticket_id:)
  31. event = object[:event]
  32. article = object[:article]
  33. # Always send remove events.
  34. if event == :destroy
  35. return { remove_article_id: object[:article_id] }
  36. end
  37. # Send create only for articles with permission.
  38. if event == :create
  39. return article_permission? ? { add_article: article } : no_update
  40. end
  41. # For updated articles, there is a special handling if visibility changed.
  42. if article_permission?
  43. # If permission to see the article was just added, treat it as an add event.
  44. return customer_visibility_changed? ? { add_article: article } : { update_article: article }
  45. elsif customer_visibility_changed?
  46. # If permission to see the article was just removed, treat it as a remove event.
  47. return { remove_article_id: Gql::ZammadSchema.id_from_object(article) }
  48. end
  49. no_update
  50. end
  51. private
  52. def customer_visibility_changed?
  53. object[:internal_changed?] && !TicketPolicy.new(context.current_user, object[:article].ticket).agent_read_access?
  54. end
  55. # Only send updates for articles with read permission.
  56. def article_permission?
  57. Pundit.authorize context.current_user, object[:article], :show?
  58. rescue Pundit::NotAuthorizedError
  59. false
  60. end
  61. end
  62. end