Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/frontend/src/components/launches/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { groupBy, sortBy } from 'lodash';
import Image from 'next/image';
import { extend } from 'dayjs';
import { isUSCitizen } from './helpers/isuscitizen.utils';
import removeMd from 'remove-markdown';
extend(isSameOrAfter);
extend(isSameOrBefore);

Expand Down Expand Up @@ -604,7 +605,7 @@ const CalendarItem: FC<{
</div>
<div className="whitespace-pre-wrap line-clamp-3">
{state === 'DRAFT' ? 'Draft: ' : ''}
{post.content}
{removeMd(post.content).replace(/\n/g, ' ')}
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory';
import { useFormatting } from '@gitroom/frontend/components/launches/helpers/use.formatting';
import clsx from 'clsx';
import { VideoOrImage } from '@gitroom/react/helpers/video.or.image';
import { Chakra_Petch } from 'next/font/google';
import { FC } from 'react';
import { textSlicer } from '@gitroom/helpers/utils/count.length';
const chakra = Chakra_Petch({ weight: '400', subsets: ['latin'] });
import interClass from '@gitroom/react/helpers/inter.font';

export const GeneralPreviewComponent: FC<{maximumCharacters?: number}> = (props) => {
const { value: topValue, integration } = useIntegration();
Expand Down Expand Up @@ -64,7 +63,7 @@ export const GeneralPreviewComponent: FC<{maximumCharacters?: number}> = (props)
{integration?.display || '@username'}
</div>
</div>
<pre className={clsx('text-wrap', chakra.className)} dangerouslySetInnerHTML={{__html: value.text}} />
<pre className={clsx('text-wrap', interClass)} dangerouslySetInnerHTML={{__html: value.text}} />
{!!value?.images?.length && (
<div className={clsx("w-full rounded-[16px] overflow-hidden mt-[12px]", value?.images?.length > 3 ? 'grid grid-cols-2 gap-[4px]' : 'flex gap-[4px]')}>
{value.images.map((image, index) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import { Input } from '@gitroom/react/form/input';
import { Button } from '@gitroom/react/form/button';
import { useToaster } from '@gitroom/react/toaster/toaster';

const postUrlEmitter = new EventEmitter();

Expand Down Expand Up @@ -76,26 +77,32 @@ export const LinkedinCompany: FC<{
const { onClose, onSelect, id } = props;
const fetch = useFetch();
const [company, setCompany] = useState<any>(null);
const toast = useToaster();

const getCompany = async () => {
if (!company) {
return ;
return;
}

try {
const { options } = await (
await fetch('/integrations/function', {
method: 'POST',
body: JSON.stringify({
id,
name: 'company',
data: {
url: company,
},
}),
})
).json();

onSelect(options.value);
onClose();
} catch (e) {
toast.show('Failed to load profile', 'warning');
}
const {options} = await (
await fetch('/integrations/function', {
method: 'POST',
body: JSON.stringify({
id,
name: 'company',
data: {
url: company,
},
}),
})
).json();

onSelect(options.value);
onClose();
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export const useFormatting = (
if (params.removeMarkdown) {
newText = removeMd(newText);
}
newText = newText.replace(/@\w{1,15}/g, function(match) {
return `<strong>${match}</strong>`;
});
if (params.saveBreaklines) {
newText = newText.replace('𝔫𝔢𝔴𝔩𝔦𝔫𝔢', '\n');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@ import { newImage } from '@gitroom/frontend/components/launches/helpers/new.imag
import { postSelector } from '@gitroom/frontend/components/post-url-selector/post.url.selector';
import { UpDownArrow } from '@gitroom/frontend/components/launches/up.down.arrow';
import { arrayMoveImmutable } from 'array-move';
import { linkedinCompany } from '@gitroom/frontend/components/launches/helpers/linkedin.component';
import {
LinkedinCompany,
linkedinCompany,
} from '@gitroom/frontend/components/launches/helpers/linkedin.component';
import { Editor } from '@gitroom/frontend/components/launches/editor';
import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core';
import { AddPostButton } from '@gitroom/frontend/components/launches/add.post.button';
import { GeneralPreviewComponent } from '@gitroom/frontend/components/launches/general.preview.component';
import { capitalize } from 'lodash';
import { useModals } from '@mantine/modals';

// Simple component to change back to settings on after changing tab
export const SetTab: FC<{ changeTab: () => void }> = (props) => {
Expand Down Expand Up @@ -69,8 +73,8 @@ export const EditorWrapper: FC<{ children: ReactNode }> = ({ children }) => {
};

export const withProvider = function <T extends object>(
SettingsComponent: FC<{values?: any}> | null,
CustomPreviewComponent?: FC<{maximumCharacters?: number}>,
SettingsComponent: FC<{ values?: any }> | null,
CustomPreviewComponent?: FC<{ maximumCharacters?: number }>,
dto?: any,
checkValidity?: (
value: Array<Array<{ path: string }>>,
Expand All @@ -91,6 +95,8 @@ export const withProvider = function <T extends object>(
}) => {
const existingData = useExistingData();
const { integration, date } = useIntegration();
const [showLinkedinPopUp, setShowLinkedinPopUp] = useState<any>(false);

useCopilotReadable({
description:
integration?.type === 'social'
Expand Down Expand Up @@ -255,6 +261,21 @@ export const withProvider = function <T extends object>(
},
});

const tagPersonOrCompany = useCallback(
(integration: string, editor: (value: string) => void) => () => {
setShowLinkedinPopUp(
<LinkedinCompany
onSelect={(tag) => {
editor(tag);
}}
id={integration}
onClose={() => setShowLinkedinPopUp(false)}
/>
);
},
[]
);

// this is a trick to prevent the data from being deleted, yet we don't render the elements
if (!props.show) {
return null;
Expand All @@ -263,6 +284,7 @@ export const withProvider = function <T extends object>(
return (
<FormProvider {...form}>
<SetTab changeTab={() => setShowTab(0)} />
{showLinkedinPopUp ? showLinkedinPopUp : null}
<div className="mt-[15px] w-full flex flex-col flex-1">
{!props.hideMenu && (
<div className="flex gap-[4px]">
Expand Down Expand Up @@ -319,6 +341,20 @@ export const withProvider = function <T extends object>(
<div>
<div className="flex gap-[4px]">
<div className="flex-1 text-textColor editor">
{integration?.identifier === 'linkedin' && (
<Button
className="mb-[5px]"
onClick={tagPersonOrCompany(
integration.id,
(newValue: string) =>
changeValue(index)(
val.content + newValue
)
)}
>
Tag a company
</Button>
)}
<Editor
order={index}
height={InPlaceValue.length > 1 ? 200 : 250}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
async company(token: string, data: { url: string }) {
const { url } = data;
const getCompanyVanity = url.match(
/^https?:\/\/?www\.?linkedin\.com\/company\/([^/]+)\/$/
/^https?:\/\/(?:www\.)?linkedin\.com\/company\/([^/]+)\/?$/
);
if (!getCompanyVanity || !getCompanyVanity?.length) {
throw new Error('Invalid LinkedIn company URL');
Expand Down Expand Up @@ -282,6 +282,32 @@
}
}

private fixText(text: string) {
const pattern = /@\[.+?]\(urn:li:organization.+?\)/g;
const matches = text.match(pattern) || [];
const splitAll = text.split(pattern);
const splitTextReformat = splitAll.map((p) => {
return p
.replace(/\*/g, '\\*')
Comment on lines +290 to +291

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.
.replace(/\(/g, '\\(')
Comment on lines +290 to +292

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI about 1 year ago

To fix the problem, we should use a regular expression with the g flag to ensure that all occurrences of the special characters are replaced. This will make the escaping process more reliable and less error-prone. We will update the replace calls in the fixText function to use regular expressions with the g flag.

Suggested changeset 1
libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
--- a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
@@ -294,3 +294,3 @@
         .replace(/\{/g, '\\{')
-        .replace(/}/g, '\\}')
+        .replace(/\}/g, '\\}')
         .replace(/@/g, '\\@');
EOF
@@ -294,3 +294,3 @@
.replace(/\{/g, '\\{')
.replace(/}/g, '\\}')
.replace(/\}/g, '\\}')
.replace(/@/g, '\\@');
Copilot is powered by AI and may make mistakes. Always verify output.
.replace(/\)/g, '\\)')
Comment on lines +290 to +293

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI about 1 year ago

To fix the problem, we should use a well-tested sanitization library to handle the escaping of special characters. This will ensure that all edge cases are covered and reduce the risk of injection attacks or other issues related to incomplete escaping.

In this case, we can use the escape-string-regexp library, which is designed to escape special characters in a string for use in a regular expression. This library is well-tested and widely used, making it a reliable choice for our needs.

We will:

  1. Install the escape-string-regexp library.
  2. Import the library in the file.
  3. Use the library to escape the special characters in the fixText function.
Suggested changeset 2
libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
--- a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
@@ -16,2 +16,3 @@
 import { Integration } from '@prisma/client';
+import escapeStringRegexp from 'escape-string-regexp';
 
@@ -289,9 +290,3 @@
     const splitTextReformat = splitAll.map((p) => {
-      return p
-        .replace(/\*/g, '\\*')
-        .replace(/\(/g, '\\(')
-        .replace(/\)/g, '\\)')
-        .replace(/\{/g, '\\{')
-        .replace(/}/g, '\\}')
-        .replace(/@/g, '\\@');
+      return escapeStringRegexp(p);
     });
EOF
@@ -16,2 +16,3 @@
import { Integration } from '@prisma/client';
import escapeStringRegexp from 'escape-string-regexp';

@@ -289,9 +290,3 @@
const splitTextReformat = splitAll.map((p) => {
return p
.replace(/\*/g, '\\*')
.replace(/\(/g, '\\(')
.replace(/\)/g, '\\)')
.replace(/\{/g, '\\{')
.replace(/}/g, '\\}')
.replace(/@/g, '\\@');
return escapeStringRegexp(p);
});
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -155,3 +155,4 @@
     "yargs": "^17.7.2",
-    "yup": "^1.4.0"
+    "yup": "^1.4.0",
+    "escape-string-regexp": "^5.0.0"
   },
EOF
@@ -155,3 +155,4 @@
"yargs": "^17.7.2",
"yup": "^1.4.0"
"yup": "^1.4.0",
"escape-string-regexp": "^5.0.0"
},
This fix introduces these dependencies
Package Version Security advisories
escape-string-regexp (npm) 5.0.0 None
Copilot is powered by AI and may make mistakes. Always verify output.
.replace(/\{/g, '\\{')
Comment on lines +290 to +294

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI about 1 year ago

To fix the problem, we should replace the custom escaping logic in the fixText function with a well-tested sanitization library. This will ensure that all special characters are properly escaped and reduce the risk of injection attacks or other issues.

The escape-string-regexp library is a well-known library that can be used to escape special characters in a string. We will use this library to replace the custom escaping logic in the fixText function.

Suggested changeset 2
libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
--- a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
@@ -16,2 +16,3 @@
 import { Integration } from '@prisma/client';
+import escapeStringRegexp from 'escape-string-regexp';
 
@@ -289,9 +290,3 @@
     const splitTextReformat = splitAll.map((p) => {
-      return p
-        .replace(/\*/g, '\\*')
-        .replace(/\(/g, '\\(')
-        .replace(/\)/g, '\\)')
-        .replace(/\{/g, '\\{')
-        .replace(/}/g, '\\}')
-        .replace(/@/g, '\\@');
+      return escapeStringRegexp(p);
     });
EOF
@@ -16,2 +16,3 @@
import { Integration } from '@prisma/client';
import escapeStringRegexp from 'escape-string-regexp';

@@ -289,9 +290,3 @@
const splitTextReformat = splitAll.map((p) => {
return p
.replace(/\*/g, '\\*')
.replace(/\(/g, '\\(')
.replace(/\)/g, '\\)')
.replace(/\{/g, '\\{')
.replace(/}/g, '\\}')
.replace(/@/g, '\\@');
return escapeStringRegexp(p);
});
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -155,3 +155,4 @@
     "yargs": "^17.7.2",
-    "yup": "^1.4.0"
+    "yup": "^1.4.0",
+    "escape-string-regexp": "^5.0.0"
   },
EOF
@@ -155,3 +155,4 @@
"yargs": "^17.7.2",
"yup": "^1.4.0"
"yup": "^1.4.0",
"escape-string-regexp": "^5.0.0"
},
This fix introduces these dependencies
Package Version Security advisories
escape-string-regexp (npm) 5.0.0 None
Copilot is powered by AI and may make mistakes. Always verify output.
.replace(/}/g, '\\}')
Comment on lines +290 to +295

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.
.replace(/@/g, '\\@');
Comment on lines +290 to +296

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI about 1 year ago

To fix the problem, we need to ensure that all occurrences of the characters being escaped are replaced. This can be achieved by using regular expressions with the global flag (g). This ensures that every instance of the character in the string is replaced, not just the first one.

We will modify the fixText function to use regular expressions with the global flag for each character that needs to be escaped.

Suggested changeset 1
libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
--- a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
@@ -294,3 +294,3 @@
         .replace(/\{/g, '\\{')
-        .replace(/}/g, '\\}')
+        .replace(/\}/g, '\\}')
         .replace(/@/g, '\\@');
EOF
@@ -294,3 +294,3 @@
.replace(/\{/g, '\\{')
.replace(/}/g, '\\}')
.replace(/\}/g, '\\}')
.replace(/@/g, '\\@');
Copilot is powered by AI and may make mistakes. Always verify output.
});

const connectAll = splitTextReformat.reduce((all, current) => {
const match = matches.shift();
all.push(current);
if (match) {
all.push(match);
}
return all;
}, [] as string[]);

return connectAll.join('');
}

async post(
id: string,
accessToken: string,
Expand Down Expand Up @@ -340,12 +366,7 @@
type === 'personal'
? `urn:li:person:${id}`
: `urn:li:organization:${id}`,
commentary: firstPost.message
.replace(/\*/g, '\\*')
.replace(/\(/g, '\\(')
.replace(/\)/g, '\\)')
.replace(/\{/g, '\\{')
.replace(/}/g, '\\}'),
commentary: this.fixText(firstPost.message),
visibility: 'PUBLIC',
distribution: {
feedDistribution: 'MAIN_FEED',
Expand Down Expand Up @@ -410,12 +431,7 @@
? `urn:li:person:${id}`
: `urn:li:organization:${id}`,
object: topPostId,
message: post.message
.replace(/\*/g, '\\*')
.replace(/\(/g, '\\(')
.replace(/\)/g, '\\)')
.replace(/\{/g, '\\{')
.replace(/}/g, '\\}'),
message: this.fixText(post.message),
}),
}
)
Expand Down
Loading