diff --git a/plugins/slack/server/api/hooks.ts b/plugins/slack/server/api/hooks.ts
index bdafc20eb..977372685 100644
--- a/plugins/slack/server/api/hooks.ts
+++ b/plugins/slack/server/api/hooks.ts
@@ -1,8 +1,10 @@
import { t } from "i18next";
import Router from "koa-router";
import escapeRegExp from "lodash/escapeRegExp";
+import queryString from "query-string";
import { z } from "zod";
import { IntegrationService, IntegrationType } from "@shared/types";
+import parseDocumentSlug from "@shared/utils/parseDocumentSlug";
import {
AuthenticationError,
InvalidRequestError,
@@ -19,8 +21,10 @@ import {
Integration,
IntegrationAuthentication,
AuthenticationProvider,
+ Comment,
} from "@server/models";
import SearchHelper from "@server/models/helpers/SearchHelper";
+import { can } from "@server/policies";
import { APIContext } from "@server/types";
import { safeEqual } from "@server/utils/crypto";
import { opts } from "@server/utils/i18n";
@@ -78,16 +82,38 @@ router.post(
const unfurls = {};
for (const link of event.links) {
- const id = link.url.slice(link.url.lastIndexOf("/") + 1);
- const doc = await Document.findByPk(id);
- if (!doc || doc.teamId !== user.teamId) {
- continue;
+ const documentId = parseDocumentSlug(link.url);
+ if (documentId) {
+ const doc = await Document.findByPk(documentId, { userId: user.id });
+
+ if (doc && can(user, "read", doc)) {
+ const commentId = queryString.parse(
+ link.url.split("?")[1]
+ )?.commentId;
+
+ if (commentId) {
+ const comment = await Comment.findByPk(commentId as string);
+ if (!comment) {
+ continue;
+ }
+
+ unfurls[link.url] = {
+ title: t(`Comment by {{ author }} on "{{ title }}"`, {
+ author: comment.createdBy.name,
+ title: doc.title,
+ ...opts(user),
+ }),
+ text: comment.toPlainText(),
+ };
+ } else {
+ unfurls[link.url] = {
+ title: doc.title,
+ text: doc.getSummary(),
+ color: doc.collection?.color,
+ };
+ }
+ }
}
- unfurls[link.url] = {
- title: doc.title,
- text: doc.getSummary(),
- color: doc.collection?.color,
- };
}
await Slack.post("chat.unfurl", {
diff --git a/server/models/Comment.ts b/server/models/Comment.ts
index 710df1aeb..4dd5e85c9 100644
--- a/server/models/Comment.ts
+++ b/server/models/Comment.ts
@@ -1,3 +1,4 @@
+import { Node } from "prosemirror-model";
import { InferAttributes, InferCreationAttributes } from "sequelize";
import {
DataType,
@@ -9,7 +10,9 @@ import {
DefaultScope,
} from "sequelize-typescript";
import type { ProsemirrorData } from "@shared/types";
+import ProsemirrorHelper from "@shared/utils/ProsemirrorHelper";
import { CommentValidation } from "@shared/validations";
+import { schema } from "@server/editor";
import Document from "./Document";
import User from "./User";
import ParanoidModel from "./base/ParanoidModel";
@@ -71,6 +74,11 @@ class Comment extends ParanoidModel<
@ForeignKey(() => Comment)
@Column(DataType.UUID)
parentCommentId: string;
+
+ public toPlainText() {
+ const node = Node.fromJSON(schema, this.data);
+ return ProsemirrorHelper.toPlainText(node, schema);
+ }
}
export default Comment;
diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json
index e84140e5c..9ef1b0ff8 100644
--- a/shared/i18n/locales/en_US/translation.json
+++ b/shared/i18n/locales/en_US/translation.json
@@ -970,6 +970,7 @@
"Get rich previews of {{ appName }} links shared in Slack and use the {{ command }} slash command to search for documents without leaving your chat.": "Get rich previews of {{ appName }} links shared in Slack and use the {{ command }} slash command to search for documents without leaving your chat.",
"This will remove the Outline slash command from your Slack workspace. Are you sure?": "This will remove the Outline slash command from your Slack workspace. Are you sure?",
"Connect {{appName}} collections to Slack channels. Messages will be automatically posted to Slack when documents are published or updated.": "Connect {{appName}} collections to Slack channels. Messages will be automatically posted to Slack when documents are published or updated.",
+ "Comment by {{ author }} on \"{{ title }}\"": "Comment by {{ author }} on \"{{ title }}\"",
"How to use {{ command }}": "How to use {{ command }}",
"To search your workspace use {{ command }}. \nType {{ command2 }} help to display this help text.": "To search your workspace use {{ command }}. \nType {{ command2 }} help to display this help text.",
"Post to Channel": "Post to Channel",