Kaynağa Gözat

add an option to remove chat from server pro (#20445)

* add option to remove chat from backend

* make chat default to enabled

* Check chat is enabled in chat context

---------

Co-authored-by: mserranom <mserranom@gmail.com>
GitOrigin-RevId: 7dda09df4bb74007eb4b1272d4918155b5cddaf6
Brian Gough 1 yıl önce
ebeveyn
işleme
4a32f49b3d

+ 1 - 0
services/web/app/src/Features/Project/ProjectController.js

@@ -719,6 +719,7 @@ const _ProjectController = {
           isTokenMember,
           isInvitedMember
         ),
+        chatEnabled: Features.hasFeature('chat'),
         roMirrorOnClientNoLocalStorage:
           Settings.adminOnlyLogin || project.name.startsWith('Debug: '),
         languages: Settings.languages,

+ 2 - 0
services/web/app/src/infrastructure/Features.js

@@ -58,6 +58,8 @@ const Features = {
         )
       case 'registration':
         return Boolean(Settings.overleaf)
+      case 'chat':
+        return Boolean(Settings.disableChat) === false
       case 'github-sync':
         return Boolean(Settings.enableGithubSync)
       case 'git-bridge':

+ 15 - 13
services/web/app/src/router.mjs

@@ -1139,19 +1139,21 @@ async function initialize(webRouter, privateApiRouter, publicApiRouter) {
     SpellingController.unlearn
   )
 
-  webRouter.get(
-    '/project/:project_id/messages',
-    AuthorizationMiddleware.blockRestrictedUserFromProject,
-    AuthorizationMiddleware.ensureUserCanReadProject,
-    ChatController.getMessages
-  )
-  webRouter.post(
-    '/project/:project_id/messages',
-    AuthorizationMiddleware.blockRestrictedUserFromProject,
-    AuthorizationMiddleware.ensureUserCanReadProject,
-    RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage),
-    ChatController.sendMessage
-  )
+  if (Features.hasFeature('chat')) {
+    webRouter.get(
+      '/project/:project_id/messages',
+      AuthorizationMiddleware.blockRestrictedUserFromProject,
+      AuthorizationMiddleware.ensureUserCanReadProject,
+      ChatController.getMessages
+    )
+    webRouter.post(
+      '/project/:project_id/messages',
+      AuthorizationMiddleware.blockRestrictedUserFromProject,
+      AuthorizationMiddleware.ensureUserCanReadProject,
+      RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage),
+      ChatController.sendMessage
+    )
+  }
 
   webRouter.post(
     '/project/:Project_id/references/indexAll',

+ 1 - 0
services/web/app/views/project/editor/meta.pug

@@ -9,6 +9,7 @@ meta(name="ol-isTokenMember" data-type="boolean" content=isTokenMember)
 meta(name="ol-isRestrictedTokenMember" data-type="boolean" content=isRestrictedTokenMember)
 meta(name="ol-maxDocLength" data-type="json" content=maxDocLength)
 meta(name="ol-wikiEnabled" data-type="boolean" content=settings.proxyLearn)
+meta(name="ol-chatEnabled" data-type="boolean" content=chatEnabled)
 meta(name="ol-gitBridgePublicBaseUrl" content=gitBridgePublicBaseUrl)
 meta(name="ol-gitBridgeEnabled" data-type="boolean" content=gitBridgeEnabled)
 meta(name="ol-compilesUserContentDomain" content=settings.compilesUserContentDomain)

+ 1 - 0
services/web/config/settings.defaults.js

@@ -407,6 +407,7 @@ module.exports = {
     },
   ],
 
+  disableChat: process.env.OVERLEAF_DISABLE_CHAT === 'true',
   enableSubscriptions: false,
   restrictedCountries: [],
   enableOnboardingEmails: process.env.ENABLE_ONBOARDING_EMAILS === 'true',

+ 35 - 5
services/web/frontend/js/features/chat/context/chat-context.tsx

@@ -17,6 +17,8 @@ import { appendMessage, prependMessages } from '../utils/message-list-appender'
 import useBrowserWindow from '../../../shared/hooks/use-browser-window'
 import { useLayoutContext } from '../../../shared/context/layout-context'
 import { useIdeContext } from '@/shared/context/ide-context'
+import getMeta from '@/utils/meta'
+import { debugConsole } from '@/utils/debugging'
 
 const PAGE_SIZE = 50
 
@@ -187,6 +189,8 @@ export const ChatContext = createContext<
 >(undefined)
 
 export const ChatProvider: FC = ({ children }) => {
+  const chatEnabled = getMeta('ol-chatEnabled')
+
   const clientId = useRef<string>()
   if (clientId.current === undefined) {
     clientId.current = chatClientIdGenerator.generate()
@@ -235,6 +239,10 @@ export const ChatProvider: FC = ({ children }) => {
     }
 
     function loadInitialMessages() {
+      if (!chatEnabled) {
+        debugConsole.warn(`chat is disabled, won't load initial messages`)
+        return
+      }
       if (state.initialMessagesLoaded) return
 
       dispatch({ type: 'INITIAL_FETCH_MESSAGES' })
@@ -242,11 +250,19 @@ export const ChatProvider: FC = ({ children }) => {
     }
 
     function loadMoreMessages() {
+      if (!chatEnabled) {
+        debugConsole.warn(`chat is disabled, won't load messages`)
+        return
+      }
       dispatch({ type: 'FETCH_MESSAGES' })
       fetchMessages()
     }
 
     function reset() {
+      if (!chatEnabled) {
+        debugConsole.warn(`chat is disabled, won't reset chat`)
+        return
+      }
       dispatch({ type: 'CLEAR' })
       fetchMessages()
     }
@@ -256,10 +272,20 @@ export const ChatProvider: FC = ({ children }) => {
       loadMoreMessages,
       reset,
     }
-  }, [projectId, state.atEnd, state.initialMessagesLoaded, state.lastTimestamp])
+  }, [
+    chatEnabled,
+    projectId,
+    state.atEnd,
+    state.initialMessagesLoaded,
+    state.lastTimestamp,
+  ])
 
   const sendMessage = useCallback(
     content => {
+      if (!chatEnabled) {
+        debugConsole.warn(`chat is disabled, won't send message`)
+        return
+      }
       if (!content) return
 
       dispatch({
@@ -278,17 +304,21 @@ export const ChatProvider: FC = ({ children }) => {
         })
       })
     },
-    [projectId, user]
+    [chatEnabled, projectId, user]
   )
 
   const markMessagesAsRead = useCallback(() => {
+    if (!chatEnabled) {
+      debugConsole.warn(`chat is disabled, won't mark messages as read`)
+      return
+    }
     dispatch({ type: 'MARK_MESSAGES_AS_READ' })
-  }, [])
+  }, [chatEnabled])
 
   // Handling receiving messages over the socket
   const { socket } = useIdeContext()
   useEffect(() => {
-    if (!socket) return
+    if (!chatEnabled || !socket) return
 
     function receivedMessage(message: any) {
       // If the message is from the current client id, then we are receiving the sent message back from the socket.
@@ -304,7 +334,7 @@ export const ChatProvider: FC = ({ children }) => {
 
       socket.removeListener('new-chat-message', receivedMessage)
     }
-  }, [socket])
+  }, [chatEnabled, socket])
 
   // Handle unread messages
   useEffect(() => {

+ 3 - 1
services/web/frontend/js/features/editor-navigation-toolbar/components/toolbar-header.jsx

@@ -51,6 +51,8 @@ const ToolbarHeader = React.memo(function ToolbarHeader({
   openShareModal,
   trackChangesVisible,
 }) {
+  const chatEnabled = getMeta('ol-chatEnabled')
+
   const { t } = useTranslation()
   const shouldDisplayPublishButton = hasPublishPermissions && PublishButton
 
@@ -123,7 +125,7 @@ const ToolbarHeader = React.memo(function ToolbarHeader({
 
             <LayoutDropdownButton />
 
-            {chatVisible && (
+            {chatEnabled && chatVisible && (
               <ChatToggleButton
                 chatIsOpen={chatIsOpen}
                 onClick={toggleChatOpen}

+ 27 - 20
services/web/frontend/js/features/ide-react/components/layout/main-layout.tsx

@@ -13,6 +13,7 @@ import { useSidebarPane } from '@/features/ide-react/hooks/use-sidebar-pane'
 import { useChatPane } from '@/features/ide-react/hooks/use-chat-pane'
 import { EditorAndPdf } from '@/features/ide-react/components/editor-and-pdf'
 import HistoryContainer from '@/features/ide-react/components/history-container'
+import getMeta from '@/utils/meta'
 
 export const MainLayout: FC = () => {
   const { view } = useLayoutContext()
@@ -38,6 +39,8 @@ export const MainLayout: FC = () => {
     handlePaneExpand: handleChatExpand,
   } = useChatPane()
 
+  const chatEnabled = getMeta('ol-chatEnabled')
+
   const { t } = useTranslation()
 
   return (
@@ -90,27 +93,31 @@ export const MainLayout: FC = () => {
                 <EditorAndPdf />
               </Panel>
 
-              <HorizontalResizeHandle
-                onDoubleClick={toggleChat}
-                resizable={chatIsOpen}
-                onDragging={setChatResizing}
-                hitAreaMargins={{ coarse: 0, fine: 0 }}
-              />
+              {chatEnabled && (
+                <>
+                  <HorizontalResizeHandle
+                    onDoubleClick={toggleChat}
+                    resizable={chatIsOpen}
+                    onDragging={setChatResizing}
+                    hitAreaMargins={{ coarse: 0, fine: 0 }}
+                  />
 
-              {/* chat */}
-              <Panel
-                ref={chatPanelRef}
-                id="panel-chat"
-                order={2}
-                defaultSize={20}
-                minSize={5}
-                maxSize={30}
-                collapsible
-                onCollapse={handleChatCollapse}
-                onExpand={handleChatExpand}
-              >
-                <ChatPane />
-              </Panel>
+                  {/* chat */}
+                  <Panel
+                    ref={chatPanelRef}
+                    id="panel-chat"
+                    order={2}
+                    defaultSize={20}
+                    minSize={5}
+                    maxSize={30}
+                    collapsible
+                    onCollapse={handleChatCollapse}
+                    onExpand={handleChatExpand}
+                  >
+                    <ChatPane />
+                  </Panel>
+                </>
+              )}
             </PanelGroup>
           </Panel>
         </PanelGroup>

+ 1 - 0
services/web/frontend/js/utils/meta.ts

@@ -69,6 +69,7 @@ export interface Meta {
   'ol-cannot-link-other-third-party-sso': boolean
   'ol-cannot-reactivate-subscription': boolean
   'ol-cannot-use-ai': boolean
+  'ol-chatEnabled': boolean
   'ol-countryCode': PricingFormState['country']
   'ol-couponCode': PricingFormState['coupon']
   'ol-createdAt': Date

+ 1 - 0
services/web/test/frontend/features/chat/components/chat-pane.test.jsx

@@ -22,6 +22,7 @@ describe('<ChatPane />', function () {
 
   beforeEach(function () {
     window.metaAttributesCache.set('ol-user', user)
+    window.metaAttributesCache.set('ol-chatEnabled', true)
   })
 
   afterEach(function () {

+ 1 - 0
services/web/test/frontend/features/chat/context/chat-context.test.jsx

@@ -29,6 +29,7 @@ describe('ChatContext', function () {
     stubMathJax()
 
     window.metaAttributesCache.set('ol-user', user)
+    window.metaAttributesCache.set('ol-chatEnabled', true)
 
     this.stub = sinon.stub(chatClientIdGenerator, 'generate').returns(uuidValue)
   })

+ 4 - 0
services/web/test/frontend/features/editor-navigation-toolbar/components/toolbar-header.test.jsx

@@ -26,6 +26,10 @@ describe('<ToolbarHeader />', function () {
     detach: () => {},
   }
 
+  beforeEach(function () {
+    window.metaAttributesCache.set('ol-chatEnabled', true)
+  })
+
   describe('cobranding logo', function () {
     it('is not displayed by default', function () {
       renderWithEditorContext(<ToolbarHeader {...defaultProps} />)