permissions-context.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { createContext, useContext, useEffect } from 'react'
  2. import { useConnectionContext } from '@/features/ide-react/context/connection-context'
  3. import { useEditorContext } from '@/shared/context/editor-context'
  4. import getMeta from '@/utils/meta'
  5. import {
  6. Permissions,
  7. PermissionsLevel,
  8. } from '@/features/ide-react/types/permissions'
  9. import useScopeValue from '@/shared/hooks/use-scope-value'
  10. import { DeepReadonly } from '../../../../../types/utils'
  11. import useViewerPermissions from '@/shared/hooks/use-viewer-permissions'
  12. import { useProjectContext } from '@/shared/context/project-context'
  13. export const PermissionsContext = createContext<Permissions | undefined>(
  14. undefined
  15. )
  16. const permissionsMap: DeepReadonly<Record<PermissionsLevel, Permissions>> = {
  17. readOnly: {
  18. read: true,
  19. comment: true,
  20. resolveOwnComments: false,
  21. resolveAllComments: false,
  22. trackedWrite: false,
  23. write: false,
  24. admin: false,
  25. labelVersion: false,
  26. },
  27. review: {
  28. read: true,
  29. comment: true,
  30. resolveOwnComments: true,
  31. resolveAllComments: false,
  32. trackedWrite: true,
  33. write: false,
  34. admin: false,
  35. labelVersion: true,
  36. },
  37. readAndWrite: {
  38. read: true,
  39. comment: true,
  40. resolveOwnComments: true,
  41. resolveAllComments: true,
  42. trackedWrite: true,
  43. write: true,
  44. admin: false,
  45. labelVersion: true,
  46. },
  47. owner: {
  48. read: true,
  49. comment: true,
  50. resolveOwnComments: true,
  51. resolveAllComments: true,
  52. trackedWrite: true,
  53. write: true,
  54. admin: true,
  55. labelVersion: true,
  56. },
  57. }
  58. const anonymousPermissionsMap: typeof permissionsMap = {
  59. readOnly: { ...permissionsMap.readOnly, comment: false },
  60. readAndWrite: { ...permissionsMap.readAndWrite, comment: false },
  61. review: { ...permissionsMap.review, comment: false },
  62. owner: { ...permissionsMap.owner, comment: false },
  63. }
  64. const linkSharingWarningPermissionsMap: typeof permissionsMap = {
  65. readOnly: { ...permissionsMap.readOnly, comment: false },
  66. readAndWrite: permissionsMap.readAndWrite,
  67. review: permissionsMap.review,
  68. owner: permissionsMap.owner,
  69. }
  70. const noTrackChangesPermissionsMap: typeof permissionsMap = {
  71. readOnly: permissionsMap.readOnly,
  72. readAndWrite: permissionsMap.readAndWrite,
  73. review: { ...permissionsMap.review, trackedWrite: false },
  74. owner: permissionsMap.owner,
  75. }
  76. export const PermissionsProvider: React.FC<React.PropsWithChildren> = ({
  77. children,
  78. }) => {
  79. const [permissions, setPermissions] =
  80. useScopeValue<Readonly<Permissions>>('permissions')
  81. const { connectionState } = useConnectionContext()
  82. const { permissionsLevel } = useEditorContext() as {
  83. permissionsLevel: PermissionsLevel
  84. }
  85. const hasViewerPermissions = useViewerPermissions()
  86. const anonymous = getMeta('ol-anonymous')
  87. const project = useProjectContext()
  88. useEffect(() => {
  89. let activePermissionsMap
  90. if (hasViewerPermissions) {
  91. activePermissionsMap = linkSharingWarningPermissionsMap
  92. } else if (anonymous) {
  93. activePermissionsMap = anonymousPermissionsMap
  94. } else if (!project.features.trackChanges) {
  95. activePermissionsMap = noTrackChangesPermissionsMap
  96. } else {
  97. activePermissionsMap = permissionsMap
  98. }
  99. setPermissions(activePermissionsMap[permissionsLevel])
  100. }, [
  101. anonymous,
  102. permissionsLevel,
  103. setPermissions,
  104. hasViewerPermissions,
  105. project.features.trackChanges,
  106. ])
  107. useEffect(() => {
  108. if (connectionState.forceDisconnected) {
  109. setPermissions(prevState => ({ ...prevState, write: false }))
  110. }
  111. }, [connectionState.forceDisconnected, setPermissions])
  112. return (
  113. <PermissionsContext.Provider value={permissions}>
  114. {children}
  115. </PermissionsContext.Provider>
  116. )
  117. }
  118. export function usePermissionsContext() {
  119. const context = useContext(PermissionsContext)
  120. if (!context) {
  121. throw new Error(
  122. 'usePermissionsContext is only available inside PermissionsProvider'
  123. )
  124. }
  125. return context
  126. }