@consilioweb/payload-support 3.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +58 -14
  2. package/dist/index.cjs +673 -107
  3. package/dist/index.d.cts +40 -5
  4. package/dist/index.d.ts +40 -5
  5. package/dist/index.js +673 -107
  6. package/dist/utils/db.d.ts +34 -0
  7. package/dist/utils/readSettings.d.ts +90 -0
  8. package/dist/views/BillingView/index.js +4 -4
  9. package/dist/views/ChatView/index.js +4 -4
  10. package/dist/views/CrmView/index.js +4 -4
  11. package/dist/views/EmailTrackingView/index.js +4 -4
  12. package/dist/views/ImportConversationView/index.js +4 -4
  13. package/dist/views/LogsView/index.js +4 -2
  14. package/dist/views/NewTicketView/index.js +4 -2
  15. package/dist/views/PendingEmailsView/index.js +4 -4
  16. package/dist/views/SupportDashboardView/index.js +4 -4
  17. package/dist/views/TicketDetailView/index.js +4 -4
  18. package/dist/views/TicketInboxView/index.js +4 -2
  19. package/dist/views/TicketingSettingsView/index.js +4 -4
  20. package/dist/views/TimeDashboardView/index.js +4 -4
  21. package/dist/views/shared/viewAccess.d.ts +29 -0
  22. package/dist/views/shared/viewAccess.js +24 -0
  23. package/package.json +26 -20
  24. package/src/collections/ChatMessages.ts +59 -2
  25. package/src/collections/ClientSummaries.ts +10 -4
  26. package/src/collections/TicketMessages.ts +4 -1
  27. package/src/collections/WebhookEndpoints.ts +44 -2
  28. package/src/endpoints/admin-chat.ts +3 -3
  29. package/src/endpoints/ai-agent.ts +3 -3
  30. package/src/endpoints/ai.ts +3 -3
  31. package/src/endpoints/auth-2fa.ts +68 -11
  32. package/src/endpoints/capabilities.ts +7 -9
  33. package/src/endpoints/chat.ts +7 -5
  34. package/src/endpoints/chatbot.ts +50 -4
  35. package/src/endpoints/client-intelligence.ts +4 -4
  36. package/src/endpoints/email-stats.ts +19 -3
  37. package/src/endpoints/import-conversation.ts +3 -3
  38. package/src/endpoints/index.ts +1 -1
  39. package/src/endpoints/invite-collaborator.ts +29 -3
  40. package/src/endpoints/login.ts +28 -5
  41. package/src/endpoints/oauth-google.ts +130 -8
  42. package/src/endpoints/push.ts +14 -1
  43. package/src/endpoints/resend-notification.ts +3 -3
  44. package/src/endpoints/send-reminder.ts +3 -3
  45. package/src/endpoints/signature.ts +9 -2
  46. package/src/endpoints/statuses.ts +17 -0
  47. package/src/endpoints/ticket-synthesis.ts +3 -3
  48. package/src/endpoints/transfer-ticket.ts +28 -3
  49. package/src/endpoints/typing.ts +117 -14
  50. package/src/endpoints/user-prefs.ts +5 -2
  51. package/src/plugin.ts +12 -0
  52. package/src/portal/auth/layout.tsx +19 -1
  53. package/src/portal/auth/tickets/detail/MessageBody.tsx +88 -0
  54. package/src/portal/auth/tickets/detail/page.tsx +2 -6
  55. package/src/portal/login/page.tsx +23 -5
  56. package/src/utils/fireWebhooks.ts +4 -1
  57. package/src/utils/push.ts +22 -0
  58. package/src/utils/rateLimiter.ts +136 -4
  59. package/src/utils/readSettings.ts +124 -14
  60. package/src/utils/ticketAccess.ts +16 -1
  61. package/src/utils/twoFactorChallenge.ts +85 -0
  62. package/src/utils/urlSafety.ts +265 -0
  63. package/src/utils/webhookDispatcher.ts +5 -1
  64. package/src/views/BillingView/index.tsx +4 -4
  65. package/src/views/ChatView/index.tsx +4 -4
  66. package/src/views/CrmView/index.tsx +4 -4
  67. package/src/views/EmailTrackingView/index.tsx +4 -4
  68. package/src/views/ImportConversationView/index.tsx +4 -4
  69. package/src/views/LogsView/index.tsx +4 -2
  70. package/src/views/NewTicketView/index.tsx +4 -2
  71. package/src/views/PendingEmailsView/index.tsx +4 -4
  72. package/src/views/SupportDashboardView/index.tsx +4 -4
  73. package/src/views/TicketDetailView/index.tsx +4 -4
  74. package/src/views/TicketInboxView/index.tsx +4 -2
  75. package/src/views/TicketingSettingsView/index.tsx +4 -4
  76. package/src/views/TimeDashboardView/index.tsx +4 -4
  77. package/src/views/shared/viewAccess.ts +73 -0
@@ -0,0 +1,73 @@
1
+ import type { AdminViewServerProps } from 'payload'
2
+ import { formatAdminURL } from 'payload/shared'
3
+ import { SUPPORT_STAFF_SLUG_CONFIG_KEY } from '../../utils/readSettings.js'
4
+
5
+ /**
6
+ * Where a custom admin view must send a caller it refuses, or `null` to render.
7
+ *
8
+ * Payload does NOT gate custom admin views. `RootPage` skips its own
9
+ * `canAccessAdmin` redirect as soon as `isCustomAdminView()` matches, and that
10
+ * helper only compares the request path against the registered `view.path` —
11
+ * it reads no visibility flag, despite what its docblock claims. Authorising a
12
+ * custom view is therefore the view's own job, and every view registered by
13
+ * this plugin sits at a custom path (`/support/inbox`, `/support/ticket`, …).
14
+ *
15
+ * `!req.user` alone is not that check. A single `payload-token` cookie serves
16
+ * every auth collection of the host app, so an ordinary front-office account —
17
+ * a `customers`, `members` or `subscribers` signup — carries one on `/admin`
18
+ * routes too. Such a caller reached `DefaultTemplate` and received the admin
19
+ * chrome together with the client config Payload builds for any authenticated
20
+ * request: the field schema of every collection and global, `admin.hidden`
21
+ * ones included, plus an unfiltered `visibleEntities`.
22
+ *
23
+ * The ticket data itself never travelled — the client components fetch through
24
+ * `/api/support/*`, which `requireAdmin` has guarded all along — but the shape
25
+ * of the whole CMS did.
26
+ *
27
+ * The gate mirrors `requireAdmin` (utils/auth.ts): membership of the staff
28
+ * collection. It additionally honours `canAccessAdmin`, so an account the host
29
+ * disabled through its own `access.admin` is refused here too, and it fails
30
+ * closed on anything it cannot resolve.
31
+ */
32
+ export function supportViewRedirectTarget(
33
+ initPageResult: AdminViewServerProps['initPageResult'],
34
+ ): string | null {
35
+ const req = initPageResult?.req
36
+ const config = req?.payload?.config
37
+ const adminRoute = config?.routes?.admin ?? '/admin'
38
+ const routes = config?.admin?.routes
39
+
40
+ const to = (route: string | undefined, fallback: string) =>
41
+ formatAdminURL({ adminRoute, path: (route ?? fallback) as `/${string}` })
42
+
43
+ if (!req?.user) return to(routes?.login, '/login')
44
+
45
+ // `sanitizePermissions` deletes the key when it is false, so an explicit
46
+ // `false` is a denial while `undefined` simply means "not computed here".
47
+ if (initPageResult?.permissions?.canAccessAdmin === false) {
48
+ return to(routes?.unauthorized, '/unauthorized')
49
+ }
50
+
51
+ // Same source of truth as the write path: the slug `plugin.ts` publishes on
52
+ // `config.custom`, NOT `config.admin.user` — Payload defaults the latter to
53
+ // the app's first auth collection, which on a host declaring a front office
54
+ // first is precisely the collection we are trying to keep out.
55
+ //
56
+ // `resolveStaffPrefSlug` is deliberately NOT used here. Its last-resort
57
+ // fallback is the literal `'users'`, which is the right call on a read path
58
+ // (a wrong scope returns no settings) and the wrong one on an authorisation
59
+ // path: it would admit whoever happens to sit in a collection named `users`
60
+ // on a host where neither source resolved. A gate with nothing to compare
61
+ // against refuses.
62
+ const custom = config?.custom as Record<string, unknown> | undefined
63
+ const registered = custom?.[SUPPORT_STAFF_SLUG_CONFIG_KEY]
64
+ const staffSlug =
65
+ (typeof registered === 'string' && registered) || config?.admin?.user || null
66
+
67
+ const collection = (req.user as { collection?: string }).collection
68
+ if (!staffSlug || !collection || collection !== staffSlug) {
69
+ return to(routes?.unauthorized, '/unauthorized')
70
+ }
71
+
72
+ return null
73
+ }