From f560afe0b990cef205596788256d2e2409be3b9d Mon Sep 17 00:00:00 2001
From: Kristina <kristin.fefelova@gmail.com>
Date: Mon, 13 May 2024 17:32:13 +0400
Subject: [PATCH] Add user to public document space on mention (#5587)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
---
 models/server-activity/src/index.ts           |  3 ++-
 .../activity-resources/src/references.ts      | 25 +++++++++++++------
 server/middleware/src/spaceSecurity.ts        | 14 ++++++++---
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/models/server-activity/src/index.ts b/models/server-activity/src/index.ts
index 9e5f65f36a..c1e4fef72d 100644
--- a/models/server-activity/src/index.ts
+++ b/models/server-activity/src/index.ts
@@ -27,7 +27,8 @@ export function createModel (builder: Builder): void {
     txMatch: {
       collection: 'reactions',
       _class: core.class.TxCollectionCUD
-    }
+    },
+    isAsync: true
   })
 
   builder.createDoc(serverCore.class.Trigger, core.space.Model, {
diff --git a/server-plugins/activity-resources/src/references.ts b/server-plugins/activity-resources/src/references.ts
index 8b402926e8..cbda69e526 100644
--- a/server-plugins/activity-resources/src/references.ts
+++ b/server-plugins/activity-resources/src/references.ts
@@ -107,13 +107,13 @@ export async function getPersonNotificationTxes (
     return []
   }
 
-  const isAvailable = await isSpaceAvailable(receiver, space, control)
+  const res: Tx[] = []
+  const isAvailable = await checkSpace(receiver, space, control, res)
 
   if (!isAvailable) {
     return []
   }
 
-  const res: Tx[] = []
   const doc = (await control.findAll(reference.srcDocClass, { _id: reference.srcDocId }))[0]
 
   const collaboratorsTx = await getCollaboratorsTxes(reference, control, receiver, doc)
@@ -215,14 +215,25 @@ export async function getPersonNotificationTxes (
   return res
 }
 
-async function isSpaceAvailable (user: PersonAccount, spaceId: Ref<Space>, control: TriggerControl): Promise<boolean> {
+async function checkSpace (
+  user: PersonAccount,
+  spaceId: Ref<Space>,
+  control: TriggerControl,
+  res: Tx[]
+): Promise<boolean> {
   const space = (await control.findAll<Space>(core.class.Space, { _id: spaceId }))[0]
-
-  if (!space?.private) {
-    return true
+  const isMember = space.members.includes(user._id)
+  if (space.private) {
+    return isMember
   }
 
-  return space.members.includes(user._id)
+  if (!isMember) {
+    res.push(
+      control.txFactory.createTxUpdateDoc(space._class, space.space, space._id, { $push: { members: user._id } })
+    )
+  }
+
+  return true
 }
 
 async function getCollaboratorsTxes (
diff --git a/server/middleware/src/spaceSecurity.ts b/server/middleware/src/spaceSecurity.ts
index 437d405a2e..052f3aef96 100644
--- a/server/middleware/src/spaceSecurity.ts
+++ b/server/middleware/src/spaceSecurity.ts
@@ -326,14 +326,20 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar
       if (tx.objectSpace === (account._id as string)) {
         targets = [account.email, systemAccountEmail]
       } else {
+        const cudTx = tx as TxCUD<Doc>
+        const isSpace = h.isDerived(cudTx.objectClass, core.class.Space)
+
+        if (isSpace) {
+          return undefined
+        }
+
         const space = this.spacesMap.get(tx.objectSpace)
+
         if (space !== undefined) {
           targets = await this.getTargets(space.members)
           if (!isOwner(account, ctx)) {
-            const cudTx = tx as TxCUD<Doc>
-            const isSpace = h.isDerived(cudTx.objectClass, core.class.Space)
-            const allowed = this.getAllAllowedSpaces(account, !isSpace)
-            if (allowed === undefined || !allowed.includes(isSpace ? (cudTx.objectId as Ref<Space>) : tx.objectSpace)) {
+            const allowed = this.getAllAllowedSpaces(account, true)
+            if (allowed === undefined || !allowed.includes(tx.objectSpace)) {
               throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))
             }
           } else if (!targets.includes(account.email)) {