From 77405deb35cf9cfa0017cc4df3ef00a21fafe01f Mon Sep 17 00:00:00 2001 From: Sven Herrmann Date: Thu, 17 Oct 2024 14:09:56 +0200 Subject: [PATCH 01/90] Enable multipart uploads for all cloudflare uploads via uppy. this fixes upload errors with files < 100MB --- libraries/react-shared-libraries/src/helpers/uppy.upload.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/react-shared-libraries/src/helpers/uppy.upload.ts b/libraries/react-shared-libraries/src/helpers/uppy.upload.ts index 78bd6002..d8704d56 100644 --- a/libraries/react-shared-libraries/src/helpers/uppy.upload.ts +++ b/libraries/react-shared-libraries/src/helpers/uppy.upload.ts @@ -25,6 +25,9 @@ export const getUppyUploadPlugin = (provider: string, fetch: any, backendUrl: st return { plugin: AwsS3Multipart, options: { + shouldUseMultipart(file : any) { + return true; + }, createMultipartUpload: async (file: any) => { const arrayBuffer = await new Response(file.data).arrayBuffer(); const fileHash = sha256(Buffer.from(arrayBuffer)); From 2a9b9a539ccc4a241b8d55dfcd543c86a24e8e90 Mon Sep 17 00:00:00 2001 From: Sven Herrmann Date: Thu, 17 Oct 2024 15:11:39 +0200 Subject: [PATCH 02/90] Cleaning up --- libraries/react-shared-libraries/src/helpers/uppy.upload.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/react-shared-libraries/src/helpers/uppy.upload.ts b/libraries/react-shared-libraries/src/helpers/uppy.upload.ts index d8704d56..c1ec692a 100644 --- a/libraries/react-shared-libraries/src/helpers/uppy.upload.ts +++ b/libraries/react-shared-libraries/src/helpers/uppy.upload.ts @@ -25,9 +25,7 @@ export const getUppyUploadPlugin = (provider: string, fetch: any, backendUrl: st return { plugin: AwsS3Multipart, options: { - shouldUseMultipart(file : any) { - return true; - }, + shouldUseMultipart: (file : any) => true, createMultipartUpload: async (file: any) => { const arrayBuffer = await new Response(file.data).arrayBuffer(); const fileHash = sha256(Buffer.from(arrayBuffer)); From 5bc1908a593fb706e2742f859682d1262da327eb Mon Sep 17 00:00:00 2001 From: Sven Herrmann Date: Thu, 17 Oct 2024 16:01:18 +0200 Subject: [PATCH 03/90] Fix compilation error. If shouldUseMultipart is set we also have to set endpoint to avoid a type error. --- libraries/react-shared-libraries/src/helpers/uppy.upload.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/react-shared-libraries/src/helpers/uppy.upload.ts b/libraries/react-shared-libraries/src/helpers/uppy.upload.ts index c1ec692a..bc93b1e4 100644 --- a/libraries/react-shared-libraries/src/helpers/uppy.upload.ts +++ b/libraries/react-shared-libraries/src/helpers/uppy.upload.ts @@ -26,6 +26,7 @@ export const getUppyUploadPlugin = (provider: string, fetch: any, backendUrl: st plugin: AwsS3Multipart, options: { shouldUseMultipart: (file : any) => true, + endpoint: '', createMultipartUpload: async (file: any) => { const arrayBuffer = await new Response(file.data).arrayBuffer(); const fileHash = sha256(Buffer.from(arrayBuffer)); From 264eb863ecddc699814dd2eb06f99b11595bb92a Mon Sep 17 00:00:00 2001 From: Nevo David Date: Fri, 18 Oct 2024 20:39:56 +0700 Subject: [PATCH 04/90] feat: team fix --- apps/frontend/src/components/layout/settings.component.tsx | 2 +- apps/frontend/src/middleware.ts | 7 ++----- libraries/helpers/src/utils/custom.fetch.func.ts | 3 +-- .../database/prisma/organizations/organization.service.ts | 4 ++-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/frontend/src/components/layout/settings.component.tsx b/apps/frontend/src/components/layout/settings.component.tsx index 436f7fe9..f4d56eea 100644 --- a/apps/frontend/src/components/layout/settings.component.tsx +++ b/apps/frontend/src/components/layout/settings.component.tsx @@ -38,7 +38,7 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => { }, []); const url = useSearchParams(); - const showLogout = !url.get('onboarding'); + const showLogout = !url.get('onboarding') || user?.tier?.current === "FREE"; const loadProfile = useCallback(async () => { const personal = await (await fetch('/user/personal')).json(); diff --git a/apps/frontend/src/middleware.ts b/apps/frontend/src/middleware.ts index e669efb6..28e22680 100644 --- a/apps/frontend/src/middleware.ts +++ b/apps/frontend/src/middleware.ts @@ -1,7 +1,7 @@ import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; -import { fetchBackend } from '@gitroom/helpers/utils/custom.fetch.func'; import { getCookieUrlFromDomain } from '@gitroom/helpers/subdomain/subdomain.management'; +import { internalFetch } from '@gitroom/helpers/utils/internal.fetch'; // This function can be marked `async` if using `await` inside export async function middleware(request: NextRequest) { @@ -68,13 +68,10 @@ export async function middleware(request: NextRequest) { try { if (org) { const { id } = await ( - await fetchBackend('/user/join-org', { + await internalFetch('/user/join-org', { body: JSON.stringify({ org, }), - headers: { - auth: authCookie?.value!, - }, method: 'POST', }) ).json(); diff --git a/libraries/helpers/src/utils/custom.fetch.func.ts b/libraries/helpers/src/utils/custom.fetch.func.ts index f7f38c07..9daf222d 100644 --- a/libraries/helpers/src/utils/custom.fetch.func.ts +++ b/libraries/helpers/src/utils/custom.fetch.func.ts @@ -1,4 +1,3 @@ -import { loadVars } from '@gitroom/react/helpers/variable.context'; export interface Params { baseUrl: string; @@ -48,6 +47,6 @@ export const customFetch = ( export const fetchBackend = customFetch({ get baseUrl() { - return loadVars().backendUrl; + return process.env.BACKEND_URL!; }, }); diff --git a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts index db239ac3..15336c34 100644 --- a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts +++ b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts @@ -46,7 +46,7 @@ export class OrganizationService { } async inviteTeamMember(orgId: string, body: AddTeamMemberDto) { - const timeLimit = dayjs().add(15, 'minutes').format('YYYY-MM-DD HH:mm:ss'); + const timeLimit = dayjs().add(1, 'hour').format('YYYY-MM-DD HH:mm:ss'); const id = makeId(5); const url = process.env.FRONTEND_URL + @@ -55,7 +55,7 @@ export class OrganizationService { await this._notificationsService.sendEmail( body.email, 'You have been invited to join an organization', - `You have been invited to join an organization. Click here to join.
The link will expire in 15 minutes.` + `You have been invited to join an organization. Click here to join.
The link will expire in 1 hour.` ); } return { url }; From df809acb8c5dea1934409b35e5ea46ba878770f9 Mon Sep 17 00:00:00 2001 From: bilalmirza74 Date: Sun, 20 Oct 2024 10:58:11 +0530 Subject: [PATCH 05/90] Fix: removed unused variables, exported name as a property of default import --- .../src/components/analytics/chart-social.tsx | 1 - .../billing/main.billing.component.tsx | 3 --- .../src/components/launches/bot.picture.tsx | 5 +---- .../components/launches/calendar.context.tsx | 5 +++-- .../src/components/launches/calendar.tsx | 10 +++++++--- .../src/components/launches/editor.tsx | 3 +-- .../launches/generator/generator.tsx | 1 - .../launches/launches.component.tsx | 1 - .../src/components/layout/layout.context.tsx | 1 - .../src/components/layout/layout.settings.tsx | 20 +++++++++---------- .../marketplace/preview.popup.dynamic.tsx | 2 +- .../onboarding/connect.channels.tsx | 1 - .../platform-analytics/render.analytics.tsx | 2 +- 13 files changed, 24 insertions(+), 31 deletions(-) diff --git a/apps/frontend/src/components/analytics/chart-social.tsx b/apps/frontend/src/components/analytics/chart-social.tsx index f51db426..b4191ba8 100644 --- a/apps/frontend/src/components/analytics/chart-social.tsx +++ b/apps/frontend/src/components/analytics/chart-social.tsx @@ -2,7 +2,6 @@ import { FC, useEffect, useMemo, useRef } from 'react'; import DrawChart from 'chart.js/auto'; import { TotalList } from '@gitroom/frontend/components/analytics/stars.and.forks.interface'; -import dayjs from 'dayjs'; import { chunk } from 'lodash'; function mergeDataPoints(data: TotalList[], numPoints: number): TotalList[] { diff --git a/apps/frontend/src/components/billing/main.billing.component.tsx b/apps/frontend/src/components/billing/main.billing.component.tsx index fc2f88d2..71aaf7da 100644 --- a/apps/frontend/src/components/billing/main.billing.component.tsx +++ b/apps/frontend/src/components/billing/main.billing.component.tsx @@ -3,8 +3,6 @@ import { Slider } from '@gitroom/react/form/slider'; import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { Button } from '@gitroom/react/form/button'; -import { sortBy } from 'lodash'; -import { Track } from '@gitroom/react/form/track'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { Subscription } from '@prisma/client'; import { useDebouncedCallback } from 'use-debounce'; @@ -21,7 +19,6 @@ import interClass from '@gitroom/react/helpers/inter.font'; import { useRouter } from 'next/navigation'; import { useVariables } from '@gitroom/react/helpers/variable.context'; import { useModals } from '@mantine/modals'; -import { AddProviderComponent } from '@gitroom/frontend/components/launches/add.provider.component'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Textarea } from '@gitroom/react/form/textarea'; diff --git a/apps/frontend/src/components/launches/bot.picture.tsx b/apps/frontend/src/components/launches/bot.picture.tsx index fadac522..cca8f426 100644 --- a/apps/frontend/src/components/launches/bot.picture.tsx +++ b/apps/frontend/src/components/launches/bot.picture.tsx @@ -6,10 +6,7 @@ import { Input } from '@gitroom/react/form/input'; import { Button } from '@gitroom/react/form/button'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { useToaster } from '@gitroom/react/toaster/toaster'; -import { - MediaComponent, - showMediaBox, -} from '@gitroom/frontend/components/media/media.component'; +import { showMediaBox } from '@gitroom/frontend/components/media/media.component'; export const BotPicture: FC<{ integration: Integrations; diff --git a/apps/frontend/src/components/launches/calendar.context.tsx b/apps/frontend/src/components/launches/calendar.context.tsx index 03373f25..1bad55b0 100644 --- a/apps/frontend/src/components/launches/calendar.context.tsx +++ b/apps/frontend/src/components/launches/calendar.context.tsx @@ -19,8 +19,9 @@ import { useSearchParams } from 'next/navigation'; import isoWeek from 'dayjs/plugin/isoWeek'; import weekOfYear from 'dayjs/plugin/weekOfYear'; -dayjs.extend(isoWeek); -dayjs.extend(weekOfYear); +import { extend } from 'dayjs'; +extend(isoWeek); +extend(weekOfYear); export const CalendarContext = createContext({ currentDay: dayjs().day() as 0 | 1 | 2 | 3 | 4 | 5 | 6, diff --git a/apps/frontend/src/components/launches/calendar.tsx b/apps/frontend/src/components/launches/calendar.tsx index 93ea124b..6aac17c6 100644 --- a/apps/frontend/src/components/launches/calendar.tsx +++ b/apps/frontend/src/components/launches/calendar.tsx @@ -26,8 +26,9 @@ import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; import { groupBy, sortBy } from 'lodash'; import Image from 'next/image'; -dayjs.extend(isSameOrAfter); -dayjs.extend(isSameOrBefore); +import { extend } from 'dayjs'; +extend(isSameOrAfter); +extend(isSameOrBefore); export const days = [ 'Monday', @@ -499,7 +500,10 @@ export const CalendarColumn: FC<{ className={`w-full h-full rounded-[10px] hover:border hover:border-seventh flex justify-center items-center gap-[20px] opacity-30 grayscale hover:grayscale-0 hover:opacity-100`} > {integrations.map((selectedIntegrations) => ( -
+
{ const fetch = useFetch(); @@ -93,9 +94,7 @@ export const LayoutSettings = ({ children }: { children: ReactNode }) => { />
{isGeneral ? ( { )}
- {user?.orgId && (user.tier !== 'FREE' || !isGeneral || !billingEnabled) ? ( + {user?.orgId && + (user.tier !== 'FREE' || !isGeneral || !billingEnabled) ? ( ) : (
@@ -141,7 +141,7 @@ export const LayoutSettings = ({ children }: { children: ReactNode }) => {
- {(user.tier === 'FREE' && isGeneral) && billingEnabled ? ( + {user.tier === 'FREE' && isGeneral && billingEnabled ? ( <>

diff --git a/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx b/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx index c806bcd8..09c7bd0d 100644 --- a/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx +++ b/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx @@ -1,5 +1,5 @@ import 'reflect-metadata'; -import { FC, useCallback } from 'react'; +import { FC } from 'react'; import { Post as PrismaPost } from '.prisma/client'; import { Providers } from '@gitroom/frontend/components/launches/providers/show.all.providers'; diff --git a/apps/frontend/src/components/onboarding/connect.channels.tsx b/apps/frontend/src/components/onboarding/connect.channels.tsx index 65e5c7f7..a7bf5234 100644 --- a/apps/frontend/src/components/onboarding/connect.channels.tsx +++ b/apps/frontend/src/components/onboarding/connect.channels.tsx @@ -5,7 +5,6 @@ import React, { useCallback, useEffect, useMemo, - useRef, useState, } from 'react'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; diff --git a/apps/frontend/src/components/platform-analytics/render.analytics.tsx b/apps/frontend/src/components/platform-analytics/render.analytics.tsx index 6b2e2608..233af868 100644 --- a/apps/frontend/src/components/platform-analytics/render.analytics.tsx +++ b/apps/frontend/src/components/platform-analytics/render.analytics.tsx @@ -1,4 +1,4 @@ -import { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import { FC, useCallback, useMemo, useState } from 'react'; import { Integration } from '@prisma/client'; import useSWR from 'swr'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; From db0a9ad57662742aa92aeac85f69cff70f3a2306 Mon Sep 17 00:00:00 2001 From: jamesread Date: Tue, 22 Oct 2024 00:14:33 +0100 Subject: [PATCH 06/90] security: depbump 2024-10-22 --- package-lock.json | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4e18ca44..1130b5f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7772,13 +7772,14 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.4.tgz", - "integrity": "sha512-y52q1MxhbHaT3vAgWd08RgiYon0lJgtTa8U6g6gV0KI0IygwZhDQFJVxnrRDUdxQGIP5CKHmfQu3sk9gTNFoEA==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.5.tgz", + "integrity": "sha512-a629r8R8KC4skhdieQ0aIWH5vDBUFntWnWKFyDXQrll6/CllSchfWm87mWF39seaW6bXYtQtAEZY66JrngdrGA==", + "license": "MIT", "dependencies": { "body-parser": "1.20.3", "cors": "2.8.5", - "express": "4.21.0", + "express": "4.21.1", "multer": "1.4.4-lts.1", "tslib": "2.7.0" }, @@ -19759,16 +19760,17 @@ "integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==" }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -19800,9 +19802,10 @@ } }, "node_modules/express/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -31757,9 +31760,10 @@ } }, "node_modules/polotno": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/polotno/-/polotno-2.14.1.tgz", - "integrity": "sha512-lJEaROyHogUx3e+YZa18Q24pFNGiQ3VQebw94mcmgwBg6S8KPptMGCaXsq/JTpY6Wrisaxu0wSAXAYhwYV8F1Q==", + "version": "2.14.3", + "resolved": "https://registry.npmjs.org/polotno/-/polotno-2.14.3.tgz", + "integrity": "sha512-CYf5BmK12wAYpnFnHpe8gSoYksPr5RmJQXHAib00Fx09FSG47jLzVC+R/v7CpDrcOW/1CpQqONz1po0D245xjA==", + "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@blueprintjs/core": "5.12.0", "@blueprintjs/select": "5.2.3", From cc187b507d6f202f9dffb10e0c4d43548c00a2fb Mon Sep 17 00:00:00 2001 From: bilalmirza74 Date: Tue, 22 Oct 2024 05:25:35 +0530 Subject: [PATCH 07/90] , --- apps/frontend/src/components/analytics/chart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/components/analytics/chart.tsx b/apps/frontend/src/components/analytics/chart.tsx index 06ff4354..7d46d349 100644 --- a/apps/frontend/src/components/analytics/chart.tsx +++ b/apps/frontend/src/components/analytics/chart.tsx @@ -1,5 +1,5 @@ 'use client'; -import { FC, useEffect, useMemo, useRef } from 'react'; +import { FC, useEffect, useRef } from 'react'; import DrawChart from 'chart.js/auto'; import { ForksList, From 76a83d622661a22ea4916fa83afe6ad3dc7c2cc6 Mon Sep 17 00:00:00 2001 From: bilalmirza74 Date: Tue, 22 Oct 2024 05:33:46 +0530 Subject: [PATCH 08/90] Done all --- .../src/components/launches/helpers/linkedin.component.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/frontend/src/components/launches/helpers/linkedin.component.tsx b/apps/frontend/src/components/launches/helpers/linkedin.component.tsx index af1c36a2..7870013e 100644 --- a/apps/frontend/src/components/launches/helpers/linkedin.component.tsx +++ b/apps/frontend/src/components/launches/helpers/linkedin.component.tsx @@ -13,8 +13,6 @@ import { import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { Input } from '@gitroom/react/form/input'; import { Button } from '@gitroom/react/form/button'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import dayjs from 'dayjs'; const postUrlEmitter = new EventEmitter(); From 39791766cfd8c33a8687a51ead1d314e48eca299 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Wed, 23 Oct 2024 14:50:56 +0700 Subject: [PATCH 09/90] feat: tiktok url fix --- .../integrations/social/tiktok.provider.ts | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts index 6d373bd4..0d8b4f40 100644 --- a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts @@ -10,6 +10,8 @@ import { SocialAbstract, } from '@gitroom/nestjs-libraries/integrations/social.abstract'; import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto'; +import { timer } from '@gitroom/helpers/utils/timer'; +import { Integration } from '@prisma/client'; export class TiktokProvider extends SocialAbstract implements SocialProvider { identifier = 'tiktok'; @@ -166,13 +168,62 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { }; } + private async uploadedVideoSuccess( + id: string, + publishId: string, + accessToken: string + ): Promise<{ url: string; id: number }> { + // eslint-disable-next-line no-constant-condition + while (true) { + const post = await ( + await this.fetch( + 'https://open.tiktokapis.com/v2/post/publish/status/fetch/', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + Authorization: `Bearer ${accessToken}`, + }, + body: JSON.stringify({ + publish_id: publishId, + }), + } + ) + ).json(); + + const { status, publicaly_available_post_id } = post.data; + + if (status === 'PUBLISH_COMPLETE') { + return { + url: !publicaly_available_post_id + ? `https://www.tiktok.com/@${id}` + : `https://www.tiktok.com/@${id}/video/` + + publicaly_available_post_id, + id: !publicaly_available_post_id ? publishId : publicaly_available_post_id?.[0], + }; + } + + if (status === 'FAILED') { + throw new BadBody('titok-error-upload', JSON.stringify(post), { + // @ts-ignore + postDetails, + }); + } + + + await timer(3000); + } + } + async post( id: string, accessToken: string, - postDetails: PostDetails[] + postDetails: PostDetails[], + integration: Integration ): Promise { try { const [firstPost, ...comments] = postDetails; + const { data: { publish_id }, } = await ( @@ -203,11 +254,17 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { ) ).json(); + const { url, id: videoId } = await this.uploadedVideoSuccess( + integration.profile!, + publish_id, + accessToken + ); + return [ { id: firstPost.id, - releaseURL: `https://www.tiktok.com`, - postId: publish_id, + releaseURL: url, + postId: String(videoId), status: 'success', }, ]; From cea1596813ad025381f0624bf0f6d190f3b8b295 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Thu, 24 Oct 2024 23:59:57 +0700 Subject: [PATCH 10/90] feat: tiktok redirect url --- .../src/integrations/social/tiktok.provider.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts index 0d8b4f40..d969d99b 100644 --- a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts @@ -78,10 +78,10 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { `?client_key=${process.env.TIKTOK_CLIENT_ID}` + `&redirect_uri=${encodeURIComponent( `${ - process.env.NODE_ENV === 'development' || !process.env.NODE_ENV - ? `https://integration.git.sn/integrations/social/tiktok` - : `${process.env.FRONTEND_URL}/integrations/social/tiktok` - }` + process?.env?.FRONTEND_URL?.indexOf('https') === -1 + ? 'https://redirectmeto.com/' + : '' + }${process?.env?.FRONTEND_URL}/integrations/social/tiktok` )}` + `&state=${state}` + `&response_type=code` + @@ -199,7 +199,9 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { ? `https://www.tiktok.com/@${id}` : `https://www.tiktok.com/@${id}/video/` + publicaly_available_post_id, - id: !publicaly_available_post_id ? publishId : publicaly_available_post_id?.[0], + id: !publicaly_available_post_id + ? publishId + : publicaly_available_post_id?.[0], }; } @@ -210,7 +212,6 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { }); } - await timer(3000); } } From a7eda4dbd3990e2b0a8f049be78feb797d623efc Mon Sep 17 00:00:00 2001 From: jamesread Date: Thu, 24 Oct 2024 22:06:47 +0100 Subject: [PATCH 11/90] security: Denial of service in http-proxy-middleware - https://github.com/advisories/GHSA-c7qv-q95q-8v27 [skip ci] --- package-lock.json | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1130b5f1..480fe6a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22270,9 +22270,10 @@ } }, "node_modules/http-proxy-middleware": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.2.tgz", - "integrity": "sha512-fBLFpmvDzlxdckwZRjM0wWtwDZ4KBtQ8NFqhrFKoEtK4myzuiumBuNTxD+F4cVbXfOZljIbrynmvByofDzT7Ag==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz", + "integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.15", "debug": "^4.3.6", @@ -31760,9 +31761,9 @@ } }, "node_modules/polotno": { - "version": "2.14.3", - "resolved": "https://registry.npmjs.org/polotno/-/polotno-2.14.3.tgz", - "integrity": "sha512-CYf5BmK12wAYpnFnHpe8gSoYksPr5RmJQXHAib00Fx09FSG47jLzVC+R/v7CpDrcOW/1CpQqONz1po0D245xjA==", + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/polotno/-/polotno-2.14.4.tgz", + "integrity": "sha512-Wq6j1BKkBWtSCILHAv04UnJp+F3MvriIo9N65wMRniPcNbwPY1IxhkEJ9co0AaPrQHmOiu25BOl5isYhH5jc4w==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@blueprintjs/core": "5.12.0", @@ -39011,9 +39012,10 @@ } }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", From 5569763dc5323b438e7d0d37016052b34143445c Mon Sep 17 00:00:00 2001 From: Nevo David Date: Fri, 25 Oct 2024 22:43:10 +0700 Subject: [PATCH 12/90] feat: publishable key --- .../database/prisma/organizations/organization.repository.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts index 85084600..1c60b026 100644 --- a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts +++ b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts @@ -149,7 +149,7 @@ export class OrganizationRepository { }); if ( - !process.env.STRIPE_PUBLISHABLE_KEY || + process.env.STRIPE_PUBLISHABLE_KEY && checkForSubscription?.subscription?.subscriptionTier !== SubscriptionTier.PRO ) { From 98f36ec8ba3bced87488be6d24d06ed225c816bd Mon Sep 17 00:00:00 2001 From: Nevo David Date: Sat, 26 Oct 2024 21:20:26 +0700 Subject: [PATCH 13/90] feat: remove plausible --- apps/frontend/src/app/layout.tsx | 13 ++++++++++--- .../billing/main.billing.component.tsx | 3 +++ .../helpers/src/utils/use.fire.events.ts | 19 ++++++++++++------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/apps/frontend/src/app/layout.tsx b/apps/frontend/src/app/layout.tsx index df4509cd..f07744e0 100644 --- a/apps/frontend/src/app/layout.tsx +++ b/apps/frontend/src/app/layout.tsx @@ -10,10 +10,15 @@ import { Chakra_Petch } from 'next/font/google'; import PlausibleProvider from 'next-plausible'; import clsx from 'clsx'; import { VariableContextComponent } from '@gitroom/react/helpers/variable.context'; +import { Fragment } from 'react'; const chakra = Chakra_Petch({ weight: '400', subsets: ['latin'] }); export default async function AppLayout({ children }: { children: ReactNode }) { + const Plausible = !!process.env.STRIPE_PUBLISHABLE_KEY + ? PlausibleProvider + : Fragment; + return ( @@ -25,7 +30,9 @@ export default async function AppLayout({ children }: { children: ReactNode }) { - {children} - + diff --git a/apps/frontend/src/components/billing/main.billing.component.tsx b/apps/frontend/src/components/billing/main.billing.component.tsx index fc2f88d2..b2107c3a 100644 --- a/apps/frontend/src/components/billing/main.billing.component.tsx +++ b/apps/frontend/src/components/billing/main.billing.component.tsx @@ -24,6 +24,7 @@ import { useModals } from '@mantine/modals'; import { AddProviderComponent } from '@gitroom/frontend/components/launches/add.provider.component'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Textarea } from '@gitroom/react/form/textarea'; +import { useFireEvents } from '@gitroom/helpers/utils/use.fire.events'; export interface Tiers { month: Array<{ @@ -156,9 +157,11 @@ export const Features: FC<{ const Info: FC<{ proceed: (feedback: string) => void }> = (props) => { const [feedback, setFeedback] = useState(''); const modal = useModals(); + const events = useFireEvents(); const cancel = useCallback(() => { props.proceed(feedback); + events('cancel_subscription'); modal.closeAll(); }, [modal, feedback]); diff --git a/libraries/helpers/src/utils/use.fire.events.ts b/libraries/helpers/src/utils/use.fire.events.ts index 46f880b1..07141295 100644 --- a/libraries/helpers/src/utils/use.fire.events.ts +++ b/libraries/helpers/src/utils/use.fire.events.ts @@ -1,9 +1,14 @@ -import {usePlausible} from 'next-plausible' -import {useCallback} from "react"; +import { usePlausible } from 'next-plausible'; +import { useCallback } from 'react'; +import { useVariables } from '@gitroom/react/helpers/variable.context'; export const useFireEvents = () => { - const plausible = usePlausible(); - return useCallback((name: string, props?: any) => { - plausible(name, {props}); - }, []); -} \ No newline at end of file + const { billingEnabled } = useVariables(); + const plausible = usePlausible(); + return useCallback((name: string, props?: any) => { + if (!billingEnabled) { + return; + } + plausible(name, { props }); + }, []); +}; From 35c017a26f4f91b80f0c6ba75f7512b26bc6c7be Mon Sep 17 00:00:00 2001 From: Aryan Pokharkar Date: Sun, 27 Oct 2024 14:23:26 +0530 Subject: [PATCH 14/90] fix: Discord character limit changed to avoid message truncation --- .../components/launches/providers/discord/discord.provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx b/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx index 2c22647a..b3c1bb32 100644 --- a/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx +++ b/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx @@ -17,5 +17,5 @@ export default withProvider( undefined, DiscordDto, undefined, - 280 + 1980 ); From 87e7ee2ce9c8b77a4dbec2ba7ad8fe278c00c7b0 Mon Sep 17 00:00:00 2001 From: jamesread Date: Mon, 28 Oct 2024 23:20:21 +0000 Subject: [PATCH 15/90] bugfix: Console warning message instead of stacktrace if OPENAI_API_KEY is not set --- apps/backend/src/api/routes/copilot.controller.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/backend/src/api/routes/copilot.controller.ts b/apps/backend/src/api/routes/copilot.controller.ts index e66a13fd..65928b20 100644 --- a/apps/backend/src/api/routes/copilot.controller.ts +++ b/apps/backend/src/api/routes/copilot.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Post, Req, Res } from '@nestjs/common'; +import { Logger, Controller, Get, Post, Req, Res } from '@nestjs/common'; import { CopilotRuntime, OpenAIAdapter, @@ -13,6 +13,11 @@ export class CopilotController { constructor(private _subscriptionService: SubscriptionService) {} @Post('/chat') chat(@Req() req: Request, @Res() res: Response) { + if (process.env.OPENAI_API_KEY === undefined || process.env.OPENAI_API_KEY === '') { + Logger.warn('OpenAI API key not set, chat functionality will not work'); + return + } + const copilotRuntimeHandler = copilotRuntimeNestEndpoint({ endpoint: '/copilot/chat', runtime: new CopilotRuntime(), From fab0b524b76ec7d6b4622a880a9a731502787e66 Mon Sep 17 00:00:00 2001 From: jamesread Date: Mon, 28 Oct 2024 23:34:22 +0000 Subject: [PATCH 16/90] bugfix: #394 Bluesky posts now support "richtext" (URLs, tags, etc) --- .../src/integrations/social/bluesky.provider.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts index 9870bb73..f7ce1309 100644 --- a/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts @@ -6,7 +6,7 @@ import { } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface'; import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract'; -import { BskyAgent } from '@atproto/api'; +import { BskyAgent, RichText } from '@atproto/api'; import dayjs from 'dayjs'; import { Integration } from '@prisma/client'; import { AuthService } from '@gitroom/helpers/auth/auth.service'; @@ -132,9 +132,16 @@ export class BlueskyProvider extends SocialAbstract implements SocialProvider { }) || [] ); + const rt = new RichText({ + text: post.message, + }) + + await rt.detectFacets(agent) + // @ts-ignore const { cid, uri, commit } = await agent.post({ - text: post.message, + text: rt.text, + facets: rt.facets, createdAt: new Date().toISOString(), ...(images.length ? { From 68cae755697b205c1761c7c0265ea38f4a622d04 Mon Sep 17 00:00:00 2001 From: jamesread Date: Mon, 28 Oct 2024 23:42:03 +0000 Subject: [PATCH 17/90] bugfix: 300 character limit in Bluesky --- .../components/launches/providers/bluesky/bluesky.provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx b/apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx index 2cf549c1..c505774f 100644 --- a/apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx +++ b/apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx @@ -6,4 +6,4 @@ export default withProvider(null, undefined, undefined, async (posts) => { } return true; -}); +}, 300); From c0140614fc2913b40e82e5425c3a15820df3f37c Mon Sep 17 00:00:00 2001 From: Nevo David Date: Tue, 29 Oct 2024 12:37:44 +0700 Subject: [PATCH 18/90] feat: fixed refresh vulnerabilities and menu opening --- .../src/api/routes/integrations.controller.ts | 16 +++++++--------- .../social/[provider]/continue/page.tsx | 7 ++++--- .../components/launches/launches.component.tsx | 4 ++-- .../src/components/launches/menu/menu.tsx | 5 +++-- .../integrations/integration.missing.scopes.ts | 2 +- .../src/integrations/social.abstract.ts | 4 +++- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/apps/backend/src/api/routes/integrations.controller.ts b/apps/backend/src/api/routes/integrations.controller.ts index f7c4ad74..a394fe51 100644 --- a/apps/backend/src/api/routes/integrations.controller.ts +++ b/apps/backend/src/api/routes/integrations.controller.ts @@ -1,12 +1,5 @@ import { - Body, - Controller, - Delete, - Get, - Param, - Post, - Query, - UseFilters, + Body, Controller, Delete, Get, Param, Post, Query, UseFilters } from '@nestjs/common'; import { ioRedis } from '@gitroom/nestjs-libraries/redis/redis.service'; import { ConnectIntegrationDto } from '@gitroom/nestjs-libraries/dtos/integrations/connect.integration.dto'; @@ -29,6 +22,7 @@ import { PostsService } from '@gitroom/nestjs-libraries/database/prisma/posts/po import { IntegrationTimeDto } from '@gitroom/nestjs-libraries/dtos/integrations/integration.time.dto'; import { AuthService } from '@gitroom/helpers/auth/auth.service'; import { AuthTokenDetails } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface'; +import { NotEnoughScopes } from '@gitroom/nestjs-libraries/integrations/social.abstract'; @ApiTags('Integrations') @Controller('/integrations') @@ -354,7 +348,11 @@ export class IntegrationsController { }); if (!id) { - throw new Error('Invalid api key'); + throw new NotEnoughScopes('Invalid API key'); + } + + if (refresh && id !== refresh) { + throw new NotEnoughScopes('Please refresh the channel that needs to be refreshed'); } return this._integrationService.createOrUpdateIntegration( diff --git a/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx b/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx index 8a06e542..97244c00 100644 --- a/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx +++ b/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx @@ -28,7 +28,8 @@ export default async function Page({ }); if (data.status === HttpStatusCode.NotAcceptable) { - return redirect(`/launches?scope=missing`); + const { msg } = await data.json(); + return redirect(`/launches?msg=${msg}`); } if ( @@ -50,8 +51,8 @@ export default async function Page({ const { inBetweenSteps, id } = await data.json(); if (inBetweenSteps && !searchParams.refresh) { - return redirect(`/launches?added=${provider}&continue=${id}`); + return redirect(`/launches?msg=Channel Refreshed&added=${provider}&continue=${id}`); } - return redirect(`/launches?added=${provider}`); + return redirect(`/launches?added=${provider}&msg=Channel Added`); } diff --git a/apps/frontend/src/components/launches/launches.component.tsx b/apps/frontend/src/components/launches/launches.component.tsx index 8134d4e6..29666236 100644 --- a/apps/frontend/src/components/launches/launches.component.tsx +++ b/apps/frontend/src/components/launches/launches.component.tsx @@ -96,8 +96,8 @@ export const LaunchesComponent = () => { if (typeof window === 'undefined') { return; } - if (search.get('scope') === 'missing') { - toast.show('You have to approve all the channel permissions', 'warning'); + if (search.get('msg')) { + toast.show(search.get('msg')!, 'warning'); } if (search.get('added')) { fireEvents('channel_added'); diff --git a/apps/frontend/src/components/launches/menu/menu.tsx b/apps/frontend/src/components/launches/menu/menu.tsx index c31930ec..d6f6b227 100644 --- a/apps/frontend/src/components/launches/menu/menu.tsx +++ b/apps/frontend/src/components/launches/menu/menu.tsx @@ -1,4 +1,4 @@ -import { FC, useCallback, useState } from 'react'; +import { FC, MouseEventHandler, useCallback, useState } from 'react'; import { useClickOutside } from '@mantine/hooks'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; @@ -36,7 +36,8 @@ export const Menu: FC<{ setShow(false); }); - const changeShow = useCallback(() => { + const changeShow: MouseEventHandler = useCallback((e) => { + e.stopPropagation(); setShow(!show); }, [show]); diff --git a/libraries/nestjs-libraries/src/integrations/integration.missing.scopes.ts b/libraries/nestjs-libraries/src/integrations/integration.missing.scopes.ts index f3c55ec1..998aba86 100644 --- a/libraries/nestjs-libraries/src/integrations/integration.missing.scopes.ts +++ b/libraries/nestjs-libraries/src/integrations/integration.missing.scopes.ts @@ -9,6 +9,6 @@ export class NotEnoughScopesFilter implements ExceptionFilter { const ctx = host.switchToHttp(); const response = ctx.getResponse(); - response.status(HttpStatusCode.NotAcceptable).json({ invalid: true }); + response.status(HttpStatusCode.NotAcceptable).json({ msg: exception.message }); } } diff --git a/libraries/nestjs-libraries/src/integrations/social.abstract.ts b/libraries/nestjs-libraries/src/integrations/social.abstract.ts index cc300272..b30497f6 100644 --- a/libraries/nestjs-libraries/src/integrations/social.abstract.ts +++ b/libraries/nestjs-libraries/src/integrations/social.abstract.ts @@ -13,7 +13,9 @@ export class BadBody { ) {} } -export class NotEnoughScopes {} +export class NotEnoughScopes { + constructor(public message = 'Not enough scopes') {} +} export abstract class SocialAbstract { async fetch(url: string, options: RequestInit = {}, identifier = '') { From 64695706c13e67ce0422fef00f0c26432bc4f8fd Mon Sep 17 00:00:00 2001 From: Nevo David Date: Tue, 29 Oct 2024 12:43:20 +0700 Subject: [PATCH 19/90] feat: quick fix for messageing in refresh --- .../(site)/integrations/social/[provider]/continue/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx b/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx index 97244c00..5beb10e0 100644 --- a/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx +++ b/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx @@ -51,8 +51,8 @@ export default async function Page({ const { inBetweenSteps, id } = await data.json(); if (inBetweenSteps && !searchParams.refresh) { - return redirect(`/launches?msg=Channel Refreshed&added=${provider}&continue=${id}`); + return redirect(`/launches?added=${provider}&continue=${id}`); } - return redirect(`/launches?added=${provider}&msg=Channel Added`); + return redirect(`/launches?added=${provider}&msg=Channel Updated`); } From d9827f7306e306f9bc46e5d7f61bb9f3471ddf75 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Tue, 29 Oct 2024 20:30:47 +0700 Subject: [PATCH 20/90] feat: fix agencies --- .../src/database/prisma/agencies/agencies.service.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts index ff89757b..c2ca4fab 100644 --- a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts +++ b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts @@ -2,13 +2,13 @@ import { Injectable } from '@nestjs/common'; import { AgenciesRepository } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.repository'; import { User } from '@prisma/client'; import { CreateAgencyDto } from '@gitroom/nestjs-libraries/dtos/agencies/create.agency.dto'; -import { EmailService } from '@gitroom/nestjs-libraries/services/email.service'; +import { NotificationService } from '@gitroom/nestjs-libraries/database/prisma/notifications/notification.service'; @Injectable() export class AgenciesService { constructor( private _agenciesRepository: AgenciesRepository, - private _emailService: EmailService + private _notificationService: NotificationService ) {} getAgencyByUser(user: User) { return this._agenciesRepository.getAgencyByUser(user); @@ -35,7 +35,7 @@ export class AgenciesService { const agency = await this._agenciesRepository.getAgencyById(id); if (action === 'approve') { - await this._emailService.sendEmail( + await this._notificationService.sendEmail( agency?.user?.email!, 'Your Agency has been approved and added to Postiz 🚀', ` @@ -59,7 +59,7 @@ export class AgenciesService { return; } - await this._emailService.sendEmail( + await this._notificationService.sendEmail( agency?.user?.email!, 'Your Agency has been declined 😔', ` @@ -84,7 +84,7 @@ export class AgenciesService { async createAgency(user: User, body: CreateAgencyDto) { const agency = await this._agenciesRepository.createAgency(user, body); - await this._emailService.sendEmail( + await this._notificationService.sendEmail( 'nevo@postiz.com', 'New agency created', ` From 792fa7fba0d0a5c492423ae73a542eaecda4b940 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Wed, 30 Oct 2024 22:16:08 +0700 Subject: [PATCH 21/90] feat: posthog --- apps/frontend/src/app/layout.tsx | 8 ++++- .../helpers/src/utils/use.fire.events.ts | 5 +++ .../src/helpers/posthog.tsx | 28 ++++++++++++++++ package-lock.json | 32 +++++++++++++++++++ package.json | 1 + 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 libraries/react-shared-libraries/src/helpers/posthog.tsx diff --git a/apps/frontend/src/app/layout.tsx b/apps/frontend/src/app/layout.tsx index f07744e0..4f48fed8 100644 --- a/apps/frontend/src/app/layout.tsx +++ b/apps/frontend/src/app/layout.tsx @@ -11,6 +11,7 @@ import PlausibleProvider from 'next-plausible'; import clsx from 'clsx'; import { VariableContextComponent } from '@gitroom/react/helpers/variable.context'; import { Fragment } from 'react'; +import { PHProvider } from '@gitroom/react/helpers/posthog'; const chakra = Chakra_Petch({ weight: '400', subsets: ['latin'] }); @@ -44,7 +45,12 @@ export default async function AppLayout({ children }: { children: ReactNode }) { - {children} + + {children} + diff --git a/libraries/helpers/src/utils/use.fire.events.ts b/libraries/helpers/src/utils/use.fire.events.ts index 07141295..b23a2e86 100644 --- a/libraries/helpers/src/utils/use.fire.events.ts +++ b/libraries/helpers/src/utils/use.fire.events.ts @@ -1,14 +1,19 @@ import { usePlausible } from 'next-plausible'; import { useCallback } from 'react'; import { useVariables } from '@gitroom/react/helpers/variable.context'; +import { usePostHog } from 'posthog-js/react'; export const useFireEvents = () => { const { billingEnabled } = useVariables(); const plausible = usePlausible(); + const posthog = usePostHog(); + return useCallback((name: string, props?: any) => { if (!billingEnabled) { return; } + + posthog.capture(name, props); plausible(name, { props }); }, []); }; diff --git a/libraries/react-shared-libraries/src/helpers/posthog.tsx b/libraries/react-shared-libraries/src/helpers/posthog.tsx new file mode 100644 index 00000000..18164ed7 --- /dev/null +++ b/libraries/react-shared-libraries/src/helpers/posthog.tsx @@ -0,0 +1,28 @@ +'use client'; + +import posthog from 'posthog-js'; +import { PostHogProvider } from 'posthog-js/react'; +import { FC, ReactNode, useEffect } from 'react'; + +export const PHProvider: FC<{ + children: ReactNode; + key?: string; + host?: string; +}> = ({ children, key, host }) => { + useEffect(() => { + if (!key || !host) { + return; + } + + posthog.init(key, { + api_host: host, + person_profiles: 'identified_only', + capture_pageview: false, // Disable automatic pageview capture, as we capture manually + }); + }, []); + + if (!key || !host) { + return <>{children}; + } + return {children}; +}; diff --git a/package-lock.json b/package-lock.json index 480fe6a7..f32c0339 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,6 +99,7 @@ "nx": "19.7.2", "openai": "^4.47.1", "polotno": "^2.10.5", + "posthog-js": "^1.178.0", "react": "18.3.1", "react-colorful": "^5.6.1", "react-dnd": "^16.0.1", @@ -17001,6 +17002,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/core-js": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-compat": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", @@ -32488,6 +32499,22 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/posthog-js": { + "version": "1.178.0", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.178.0.tgz", + "integrity": "sha512-ILD4flNh72d5dycc4ZouKORlaVr+pDzl5TlZr1JgP0NBAoduHjhE7XZYwk7zdYkry7u0qAIpfv2306zJCW2vGg==", + "dependencies": { + "core-js": "^3.38.1", + "fflate": "^0.4.8", + "preact": "^10.19.3", + "web-vitals": "^4.2.0" + } + }, + "node_modules/posthog-js/node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + }, "node_modules/preact": { "version": "10.24.2", "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.2.tgz", @@ -38817,6 +38844,11 @@ "node": ">= 8" } }, + "node_modules/web-vitals": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", + "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==" + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", diff --git a/package.json b/package.json index 8b356af5..00b17a30 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "nx": "19.7.2", "openai": "^4.47.1", "polotno": "^2.10.5", + "posthog-js": "^1.178.0", "react": "18.3.1", "react-colorful": "^5.6.1", "react-dnd": "^16.0.1", From 605c3457ff9239816cbb60f159dc31a80415ee34 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Wed, 30 Oct 2024 22:59:37 +0700 Subject: [PATCH 22/90] feat: fix posthog --- apps/frontend/src/app/layout.tsx | 2 +- .../react-shared-libraries/src/helpers/posthog.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/frontend/src/app/layout.tsx b/apps/frontend/src/app/layout.tsx index 4f48fed8..c645acad 100644 --- a/apps/frontend/src/app/layout.tsx +++ b/apps/frontend/src/app/layout.tsx @@ -46,7 +46,7 @@ export default async function AppLayout({ children }: { children: ReactNode }) { domain={!!process.env.IS_GENERAL ? 'postiz.com' : 'gitroom.com'} > {children} diff --git a/libraries/react-shared-libraries/src/helpers/posthog.tsx b/libraries/react-shared-libraries/src/helpers/posthog.tsx index 18164ed7..08e4e9f8 100644 --- a/libraries/react-shared-libraries/src/helpers/posthog.tsx +++ b/libraries/react-shared-libraries/src/helpers/posthog.tsx @@ -6,22 +6,22 @@ import { FC, ReactNode, useEffect } from 'react'; export const PHProvider: FC<{ children: ReactNode; - key?: string; + phkey?: string; host?: string; -}> = ({ children, key, host }) => { +}> = ({ children, phkey, host }) => { useEffect(() => { - if (!key || !host) { + if (!phkey || !host) { return; } - posthog.init(key, { + posthog.init(phkey, { api_host: host, person_profiles: 'identified_only', capture_pageview: false, // Disable automatic pageview capture, as we capture manually }); }, []); - if (!key || !host) { + if (!phkey || !host) { return <>{children}; } return {children}; From 8a4a397d0a7dbdcae30ba75346235bbd3ae4b6e5 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Thu, 31 Oct 2024 11:53:24 +0700 Subject: [PATCH 23/90] feat: variables --- .../helpers/src/utils/use.fire.events.ts | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/libraries/helpers/src/utils/use.fire.events.ts b/libraries/helpers/src/utils/use.fire.events.ts index b23a2e86..2f39fd56 100644 --- a/libraries/helpers/src/utils/use.fire.events.ts +++ b/libraries/helpers/src/utils/use.fire.events.ts @@ -1,19 +1,28 @@ import { usePlausible } from 'next-plausible'; import { useCallback } from 'react'; -import { useVariables } from '@gitroom/react/helpers/variable.context'; import { usePostHog } from 'posthog-js/react'; +import { useVariables } from '@gitroom/react/helpers/variable.context'; +import { useUser } from '@gitroom/frontend/components/layout/user.context'; export const useFireEvents = () => { const { billingEnabled } = useVariables(); const plausible = usePlausible(); const posthog = usePostHog(); + const user = useUser(); - return useCallback((name: string, props?: any) => { - if (!billingEnabled) { - return; - } + return useCallback( + (name: string, props?: any) => { + if (!billingEnabled) { + return; + } - posthog.capture(name, props); - plausible(name, { props }); - }, []); + if (user) { + posthog.identify(user.id, { email: user.email, name: user.name }); + } + + posthog.capture(name, props); + plausible(name, { props }); + }, + [user] + ); }; From 31e78a8c1ceedd210fbc3aa0f790d35a96703370 Mon Sep 17 00:00:00 2001 From: jamesread Date: Sun, 3 Nov 2024 21:21:57 +0000 Subject: [PATCH 24/90] bugfix: Ignore cloudflare in config checker, as it is no longer needed. --- .../helpers/src/configuration/configuration.checker.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libraries/helpers/src/configuration/configuration.checker.ts b/libraries/helpers/src/configuration/configuration.checker.ts index 425de8ad..7703b666 100644 --- a/libraries/helpers/src/configuration/configuration.checker.ts +++ b/libraries/helpers/src/configuration/configuration.checker.ts @@ -30,12 +30,7 @@ export class ConfigurationChecker { this.checkIsValidUrl('FRONTEND_URL') this.checkIsValidUrl('NEXT_PUBLIC_BACKEND_URL') this.checkIsValidUrl('BACKEND_INTERNAL_URL') - this.checkNonEmpty('CLOUDFLARE_ACCOUNT_ID', 'Needed to setup providers.') - this.checkNonEmpty('CLOUDFLARE_ACCESS_KEY', 'Needed to setup providers.') - this.checkNonEmpty('CLOUDFLARE_SECRET_ACCESS_KEY', 'Needed to setup providers.') - this.checkNonEmpty('CLOUDFLARE_BUCKETNAME', 'Needed to setup providers.') - this.checkNonEmpty('CLOUDFLARE_BUCKET_URL', 'Needed to setup providers.') - this.checkNonEmpty('CLOUDFLARE_REGION', 'Needed to setup providers.') + this.checkNonEmpty('STORAGE_PROVIDER', 'Needed to setup storage.') } checkNonEmpty (key: string, description?: string): boolean { From 39b1a67119f778a584756eabd96c3b569f6f285a Mon Sep 17 00:00:00 2001 From: jamesread Date: Mon, 4 Nov 2024 01:16:45 +0000 Subject: [PATCH 25/90] feature: Responsive launches UI --- apps/frontend/src/app/global.scss | 1 - .../components/launches/add.edit.model.tsx | 13 +- .../src/components/launches/filters.tsx | 140 +++++++++--------- .../launches/general.preview.component.tsx | 2 +- .../launches/launches.component.tsx | 4 +- .../src/components/layout/impersonate.tsx | 2 +- .../src/components/layout/layout.settings.tsx | 12 +- .../src/components/layout/top.menu.tsx | 6 +- .../notifications/notification.component.tsx | 2 +- 9 files changed, 93 insertions(+), 89 deletions(-) diff --git a/apps/frontend/src/app/global.scss b/apps/frontend/src/app/global.scss index da791348..ac18deaa 100644 --- a/apps/frontend/src/app/global.scss +++ b/apps/frontend/src/app/global.scss @@ -10,7 +10,6 @@ html { } .box { position: relative; - padding: 8px 24px; } .box span { position: relative; diff --git a/apps/frontend/src/components/launches/add.edit.model.tsx b/apps/frontend/src/components/launches/add.edit.model.tsx index 966a2db8..8b2389fc 100644 --- a/apps/frontend/src/components/launches/add.edit.model.tsx +++ b/apps/frontend/src/components/launches/add.edit.model.tsx @@ -385,14 +385,15 @@ export const AddEditModal: FC<{ instructions="You are an assistant that help the user to schedule their social media posts, everytime somebody write something, try to use a function call, if not prompt the user that the request is invalid and you are here to assists with social media posts" /> )} -
@@ -540,10 +541,10 @@ export const AddEditModal: FC<{ ) : null}
-
-
+
+
+
+
{plug.description}
+
+ {plug.fields.map((field) => ( +
+ {field.type === 'richtext' ? ( +