From a60106ff24c7aa4e1e02b536a88beff43afd4df6 Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Thu, 24 Oct 2024 14:56:18 -0700 Subject: [PATCH 01/19] fix: small bugs found in datadog logs (#10414) Signed-off-by: Matt Krick --- codegen.json | 3 + .../client/components/NotificationPicker.tsx | 7 +++ .../TeamsLimitExceededNotification.tsx | 59 +++++++++++++++++++ .../server/dataloader/customLoaderMakers.ts | 5 ++ .../mutations/helpers/inviteToTeamHelper.ts | 3 + ...ntegrationProviderAuthStrategyEnum.graphql | 1 + .../public/typeDefs/NotificationEnum.graphql | 1 + .../graphql/public/types/EstimateStage.ts | 3 +- .../graphql/public/types/NewMeetingStage.ts | 15 ++--- .../public/types/NotifyTeamsLimitExceeded.ts | 11 ++++ packages/server/graphql/public/types/User.ts | 5 +- .../server/graphql/types/NotificationEnum.ts | 34 ----------- packages/server/utils/atlassian/jiraImages.ts | 2 +- 13 files changed, 103 insertions(+), 46 deletions(-) create mode 100644 packages/client/components/TeamsLimitExceededNotification.tsx create mode 100644 packages/server/graphql/public/types/NotifyTeamsLimitExceeded.ts delete mode 100644 packages/server/graphql/types/NotificationEnum.ts diff --git a/codegen.json b/codegen.json index 46391d55abc..53c0d8bdd28 100644 --- a/codegen.json +++ b/codegen.json @@ -142,6 +142,9 @@ "NotifyResponseReplied": "../../postgres/types/Notification.d#ResponseRepliedNotification as ResponseRepliedNotificationDB", "NotifyTaskInvolves": "../../postgres/types/Notification.d#TaskInvolvesNotification as TaskInvolvesNotificationDB", "NotifyTeamArchived": "../../postgres/types/Notification.d#TeamArchivedNotification as TeamArchivedNotificationDB", + "NotifyTeamsLimitReminder": "../../postgres/types/Notification.d#TeamsLimitReminderNotification as TeamsLimitReminderNotificationDB", + "NotifyTeamsLimitExceeded": "../../postgres/types/Notification.d#TeamsLimitExceededNotification as TeamsLimitExceededNotificationDB", + "NotifyPromptToJoinOrg": "../../postgres/types/Notification.d#PromptToJoinOrgNotification as PromptToJoinOrgNotificationDB", "Organization": "../../postgres/types/index#Organization as OrganizationDB", "TemplateScaleValue": "./types/TemplateScaleValue#TemplateScaleValueSource as TemplateScaleValueSourceDB", "SuggestedAction": "../../postgres/types/index#SuggestedAction as SuggestedActionDB", diff --git a/packages/client/components/NotificationPicker.tsx b/packages/client/components/NotificationPicker.tsx index bcf634f2b7d..6df1f86dd52 100644 --- a/packages/client/components/NotificationPicker.tsx +++ b/packages/client/components/NotificationPicker.tsx @@ -25,6 +25,12 @@ const typePicker: Record> = { /* webpackChunkName: 'TeamsLimitReminderNotification' */ './TeamsLimitReminderNotification' ) ), + TEAMS_LIMIT_EXCEEDED: lazyPreload( + () => + import( + /* webpackChunkName: 'TeamsLimitExceededNotification' */ './TeamsLimitExceededNotification' + ) + ), PROMPT_TO_JOIN_ORG: lazyPreload( () => import(/* webpackChunkName: 'PromptToJoinOrgNotification' */ './PromptToJoinOrgNotification') @@ -74,6 +80,7 @@ const NotificationPicker = (props: Props) => { ...Mentioned_notification ...ResponseReplied_notification ...TeamsLimitReminderNotification_notification + ...TeamsLimitExceededNotification_notification ...PromptToJoinOrgNotification_notification ...RequestToJoinOrgNotification_notification } diff --git a/packages/client/components/TeamsLimitExceededNotification.tsx b/packages/client/components/TeamsLimitExceededNotification.tsx new file mode 100644 index 00000000000..3ee4aa6f7fa --- /dev/null +++ b/packages/client/components/TeamsLimitExceededNotification.tsx @@ -0,0 +1,59 @@ +import graphql from 'babel-plugin-relay/macro' +import React, {useEffect} from 'react' +import {useFragment} from 'react-relay' +import {TeamsLimitExceededNotification_notification$key} from '~/__generated__/TeamsLimitExceededNotification_notification.graphql' +import useRouter from '~/hooks/useRouter' +import defaultOrgAvatar from '~/styles/theme/images/avatar-organization.svg' +import useAtmosphere from '../hooks/useAtmosphere' +import {Threshold} from '../types/constEnums' +import SendClientSideEvent from '../utils/SendClientSideEvent' +import NotificationAction from './NotificationAction' +import NotificationTemplate from './NotificationTemplate' + +interface Props { + notification: TeamsLimitExceededNotification_notification$key +} + +const TeamsLimitExceededNotification = (props: Props) => { + const {notification: notificationRef} = props + const atmosphere = useAtmosphere() + const notification = useFragment( + graphql` + fragment TeamsLimitExceededNotification_notification on NotifyTeamsLimitExceeded { + ...NotificationTemplate_notification + id + orgId + orgName + orgPicture + } + `, + notificationRef + ) + const {history} = useRouter() + const {orgId, orgName, orgPicture} = notification + + useEffect(() => { + SendClientSideEvent(atmosphere, 'Upgrade CTA Viewed', { + upgradeCTALocation: 'teamsLimitExceededNotification', + orgId + }) + }, []) + + const onActionClick = () => { + SendClientSideEvent(atmosphere, 'Upgrade CTA Clicked', { + upgradeCTALocation: 'teamsLimitExceededNotification' + }) + history.push(`/me/organizations/${orgId}`) + } + + return ( + } + notification={notification} + /> + ) +} + +export default TeamsLimitExceededNotification diff --git a/packages/server/dataloader/customLoaderMakers.ts b/packages/server/dataloader/customLoaderMakers.ts index 30c05ca1d68..02ed0349832 100644 --- a/packages/server/dataloader/customLoaderMakers.ts +++ b/packages/server/dataloader/customLoaderMakers.ts @@ -154,6 +154,11 @@ export const userTasks = (parent: RootDataLoader, dependsOn: RegisterDependsOn) filterQuery, includeUnassigned } = key + if (teamIds.length === 0) + return { + key: serializeUserTasksKey(key), + data: [] + } const hasUserIds = userIds?.length > 0 const hasStatusFilters = statusFilters ? statusFilters.length > 0 : false const teamTasks = await selectTasks() diff --git a/packages/server/graphql/mutations/helpers/inviteToTeamHelper.ts b/packages/server/graphql/mutations/helpers/inviteToTeamHelper.ts index 319c90e78fd..85510155c21 100644 --- a/packages/server/graphql/mutations/helpers/inviteToTeamHelper.ts +++ b/packages/server/graphql/mutations/helpers/inviteToTeamHelper.ts @@ -112,6 +112,9 @@ const inviteToTeamHelper = async ( return approvalErrors[idx] instanceof Error ? undefined : invitee }) .filter(isNotNull) + if (newAllowedInvitees.length === 0) { + return {error: {message: 'Email is not approved by organization'}} + } const tokens = await Promise.all( newAllowedInvitees.map(async () => (await randomBytes(48)).toString('hex')) ) diff --git a/packages/server/graphql/public/typeDefs/IntegrationProviderAuthStrategyEnum.graphql b/packages/server/graphql/public/typeDefs/IntegrationProviderAuthStrategyEnum.graphql index aa45386bd63..3b49419c94c 100644 --- a/packages/server/graphql/public/typeDefs/IntegrationProviderAuthStrategyEnum.graphql +++ b/packages/server/graphql/public/typeDefs/IntegrationProviderAuthStrategyEnum.graphql @@ -6,4 +6,5 @@ enum IntegrationProviderAuthStrategyEnum { oauth2 pat webhook + sharedSecret } diff --git a/packages/server/graphql/public/typeDefs/NotificationEnum.graphql b/packages/server/graphql/public/typeDefs/NotificationEnum.graphql index b76b1447ab7..35d2333059c 100644 --- a/packages/server/graphql/public/typeDefs/NotificationEnum.graphql +++ b/packages/server/graphql/public/typeDefs/NotificationEnum.graphql @@ -16,4 +16,5 @@ enum NotificationEnum { TEAMS_LIMIT_REMINDER PROMPT_TO_JOIN_ORG REQUEST_TO_JOIN_ORG + TEAMS_LIMIT_EXCEEDED } diff --git a/packages/server/graphql/public/types/EstimateStage.ts b/packages/server/graphql/public/types/EstimateStage.ts index a601b2228ad..9d6d95880d2 100644 --- a/packages/server/graphql/public/types/EstimateStage.ts +++ b/packages/server/graphql/public/types/EstimateStage.ts @@ -217,7 +217,8 @@ const EstimateStage: EstimateStageResolvers = { }, task: async ({taskId}, _args, {dataLoader}) => { - return dataLoader.get('tasks').loadNonNull(taskId) + const task = await dataLoader.get('tasks').load(taskId) + return task ?? null } } diff --git a/packages/server/graphql/public/types/NewMeetingStage.ts b/packages/server/graphql/public/types/NewMeetingStage.ts index 9950e3cb878..90cd0751ad9 100644 --- a/packages/server/graphql/public/types/NewMeetingStage.ts +++ b/packages/server/graphql/public/types/NewMeetingStage.ts @@ -1,3 +1,4 @@ +import isValidDate from '../../../../client/utils/isValidDate' import GenericMeetingStage from '../../../database/types/GenericMeetingStage' import {Logger} from '../../../utils/Logger' import {getUserId} from '../../../utils/authorization' @@ -33,15 +34,11 @@ const NewMeetingStage: NewMeetingStageResolvers = { return readyToAdvance.filter((userId: string) => userId !== facilitatorUserId).length }, - timeRemaining: ({scheduledEndTime, id, meetingId}) => { - if (scheduledEndTime) { - if (!(scheduledEndTime instanceof Date)) { - console.log('ENDTIME NOT DATE', scheduledEndTime, id, meetingId) - return null - } - return scheduledEndTime.getTime() - Date.now() - } - return null + timeRemaining: ({scheduledEndTime}) => { + if (!scheduledEndTime) return null + const coercedDate = new Date(scheduledEndTime) + if (!isValidDate(coercedDate)) return null + return coercedDate.getTime() - Date.now() } } diff --git a/packages/server/graphql/public/types/NotifyTeamsLimitExceeded.ts b/packages/server/graphql/public/types/NotifyTeamsLimitExceeded.ts new file mode 100644 index 00000000000..f0c9cc9a0b6 --- /dev/null +++ b/packages/server/graphql/public/types/NotifyTeamsLimitExceeded.ts @@ -0,0 +1,11 @@ +import {NotifyTeamsLimitExceededResolvers} from '../resolverTypes' + +const NotifyTeamsLimitExceeded: NotifyTeamsLimitExceededResolvers = { + __isTypeOf: ({type}) => type === 'TEAMS_LIMIT_EXCEEDED', + orgPicture: async ({orgPicture}, _args, {dataLoader}) => { + if (!orgPicture) return null + return dataLoader.get('fileStoreAsset').load(orgPicture) + } +} + +export default NotifyTeamsLimitExceeded diff --git a/packages/server/graphql/public/types/User.ts b/packages/server/graphql/public/types/User.ts index 6cf83e0eb6d..8b9f51b9cee 100644 --- a/packages/server/graphql/public/types/User.ts +++ b/packages/server/graphql/public/types/User.ts @@ -332,6 +332,8 @@ const User: ReqResolvers<'User'> = { const validTeamIds = teamIds ? teamIds.filter((teamId: string) => accessibleTeamIds.includes(teamId)) : accessibleTeamIds + if (validTeamIds.length === 0) + return {error: 'No teams', pageInfo: {hasNextPage: false, hasPreviousPage: false}, edges: []} if (viewerId !== id && !isSuperUser(authToken)) return {error: 'Not user', pageInfo: {hasNextPage: false, hasPreviousPage: false}, edges: []} @@ -339,6 +341,7 @@ const User: ReqResolvers<'User'> = { const minVal = new Date(0) const pg = getKysely() + const hasEventTypes = eventTypes ? eventTypes.length > 0 : false const events = await pg .selectFrom('TimelineEvent') .selectAll() @@ -346,7 +349,7 @@ const User: ReqResolvers<'User'> = { .where((eb) => eb.between('createdAt', minVal, dbAfter)) .where('isActive', '=', true) .where('teamId', 'in', validTeamIds) - .$if(!!eventTypes, (db) => db.where('type', 'in', eventTypes!)) + .$if(hasEventTypes, (db) => db.where('type', 'in', eventTypes!)) .orderBy('createdAt', 'desc') .limit(first + 1) .execute() diff --git a/packages/server/graphql/types/NotificationEnum.ts b/packages/server/graphql/types/NotificationEnum.ts deleted file mode 100644 index df78dcedcb3..00000000000 --- a/packages/server/graphql/types/NotificationEnum.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {GraphQLEnumType} from 'graphql' - -export type NotificationEnumType = - | 'KICKED_OUT' - | 'PAYMENT_REJECTED' - | 'TASK_INVOLVES' - | 'PROMOTE_TO_BILLING_LEADER' - | 'TEAM_ARCHIVED' - | 'TEAM_INVITATION' - | 'MEETING_STAGE_TIME_LIMIT_END' - | 'TEAMS_LIMIT_EXCEEDED' - | 'TEAMS_LIMIT_REMINDER' - | 'PROMPT_TO_JOIN_ORG' - | 'REQUEST_TO_JOIN_ORG' - -const NotificationEnum = new GraphQLEnumType({ - name: 'NotificationEnum', - description: 'The kind of notification', - values: { - KICKED_OUT: {}, - PAYMENT_REJECTED: {}, - PROMOTE_TO_BILLING_LEADER: {}, - TEAM_INVITATION: {}, - TEAM_ARCHIVED: {}, - TASK_INVOLVES: {}, - MEETING_STAGE_TIME_LIMIT_END: {}, - TEAMS_LIMIT_EXCEEDED: {}, - TEAMS_LIMIT_REMINDER: {}, - PROMPT_TO_JOIN_ORG: {}, - REQUEST_TO_JOIN_ORG: {} - } -}) - -export default NotificationEnum diff --git a/packages/server/utils/atlassian/jiraImages.ts b/packages/server/utils/atlassian/jiraImages.ts index ae45f812280..d781075e0e6 100644 --- a/packages/server/utils/atlassian/jiraImages.ts +++ b/packages/server/utils/atlassian/jiraImages.ts @@ -23,7 +23,7 @@ if (!serverSecret) { export const updateJiraImageUrls = (cloudId: string, descriptionHTML: string) => { const imageUrlToHash = {} as Record const projectBaseUrl = `https://api.atlassian.com/ex/jira/${cloudId}` - + if (!descriptionHTML) return {updatedDescription: descriptionHTML, imageUrlToHash} const $ = cheerio.load(descriptionHTML) $('body') .find('img') From 55c8a808cb7d0cceb740465352eda4ce3d901683 Mon Sep 17 00:00:00 2001 From: "parabol-release-bot[bot]" <150284312+parabol-release-bot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:05:53 -0700 Subject: [PATCH 02/19] chore(release): release v8.1.0 (#10408) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 17 +++++++++++++++++ package.json | 2 +- packages/chronos/package.json | 4 ++-- packages/client/package.json | 2 +- packages/embedder/package.json | 2 +- packages/gql-executor/package.json | 6 +++--- packages/integration-tests/package.json | 2 +- packages/server/package.json | 4 ++-- 9 files changed, 29 insertions(+), 12 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c2430e7ade9..529b133fdee 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "8.0.1" + ".": "8.1.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 98040029099..2620e4b8141 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,23 @@ This project adheres to [Semantic Versioning](http://semver.org/). This CHANGELOG follows conventions [outlined here](http://keepachangelog.com/). +## [8.1.0](https://github.com/ParabolInc/parabol/compare/v8.0.1...v8.1.0) (2024-10-24) + + +### Added + +* show insights by default ([#10405](https://github.com/ParabolInc/parabol/issues/10405)) ([f67328f](https://github.com/ParabolInc/parabol/commit/f67328fe06dc936dd24ad32d8101712807f175c5)) + + +### Fixed + +* small bugs found in datadog logs ([#10414](https://github.com/ParabolInc/parabol/issues/10414)) ([a60106f](https://github.com/ParabolInc/parabol/commit/a60106ff24c7aa4e1e02b536a88beff43afd4df6)) + + +### Changed + +* Add Mattermost Plugin IntegrationProvider ([#10361](https://github.com/ParabolInc/parabol/issues/10361)) ([b5bd2b4](https://github.com/ParabolInc/parabol/commit/b5bd2b46d88df1e13d5a12a925642b9e47b1b5a1)) + ## [8.0.1](https://github.com/ParabolInc/parabol/compare/v8.0.0...v8.0.1) (2024-10-23) diff --git a/package.json b/package.json index 83676d38836..e8d163d2d59 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.0.1", + "version": "8.1.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/chronos/package.json b/packages/chronos/package.json index 707d00afc11..ea6e5dca2ce 100644 --- a/packages/chronos/package.json +++ b/packages/chronos/package.json @@ -1,6 +1,6 @@ { "name": "chronos", - "version": "8.0.1", + "version": "8.1.0", "description": "A cron job scheduler", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/chronos#readme", @@ -25,6 +25,6 @@ }, "dependencies": { "cron": "^2.3.1", - "parabol-server": "8.0.1" + "parabol-server": "8.1.0" } } diff --git a/packages/client/package.json b/packages/client/package.json index 2e9dbdffb59..1198a57b908 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.0.1", + "version": "8.1.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/embedder/package.json b/packages/embedder/package.json index f78315e23cf..8d5cbfbb96a 100644 --- a/packages/embedder/package.json +++ b/packages/embedder/package.json @@ -1,6 +1,6 @@ { "name": "parabol-embedder", - "version": "8.0.1", + "version": "8.1.0", "description": "A service that computes embedding vectors from Parabol objects", "author": "Jordan Husney ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/embedder#readme", diff --git a/packages/gql-executor/package.json b/packages/gql-executor/package.json index dc980294d53..f8747e8ea4a 100644 --- a/packages/gql-executor/package.json +++ b/packages/gql-executor/package.json @@ -1,6 +1,6 @@ { "name": "gql-executor", - "version": "8.0.1", + "version": "8.1.0", "description": "A Stateless GraphQL Executor", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/gqlExecutor#readme", @@ -26,8 +26,8 @@ }, "dependencies": { "dd-trace": "^5.0.0", - "parabol-client": "8.0.1", - "parabol-server": "8.0.1", + "parabol-client": "8.1.0", + "parabol-server": "8.1.0", "undici": "^5.26.2" } } diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index 6560c7e0be1..65bce2923a5 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -2,7 +2,7 @@ "name": "integration-tests", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.0.1", + "version": "8.1.0", "description": "", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index aba0525b8fa..2c42bf27cd3 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.0.1", + "version": "8.1.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" @@ -120,7 +120,7 @@ "oauth-1.0a": "^2.2.6", "openai": "^4.53.0", "oy-vey": "^0.12.1", - "parabol-client": "8.0.1", + "parabol-client": "8.1.0", "pg": "^8.5.1", "react": "^17.0.2", "react-dom": "^17.0.2", From 2c49dce82d0b9a8f7b20762bcc2cd903fcc966b0 Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Thu, 24 Oct 2024 15:30:26 -0700 Subject: [PATCH 03/19] fix: increase URL col length for IntegrationProvider Signed-off-by: Matt Krick --- ...024-10-24T22:26:35.877Z_integrationProviderUrls.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 packages/server/postgres/migrations/2024-10-24T22:26:35.877Z_integrationProviderUrls.ts diff --git a/packages/server/postgres/migrations/2024-10-24T22:26:35.877Z_integrationProviderUrls.ts b/packages/server/postgres/migrations/2024-10-24T22:26:35.877Z_integrationProviderUrls.ts new file mode 100644 index 00000000000..94a99109905 --- /dev/null +++ b/packages/server/postgres/migrations/2024-10-24T22:26:35.877Z_integrationProviderUrls.ts @@ -0,0 +1,11 @@ +import type {Kysely} from 'kysely' + +export async function up(db: Kysely): Promise { + await db.schema + .alterTable('IntegrationProvider') + .alterColumn('webhookUrl', (ac) => ac.setDataType('varchar(2056)')) + .alterColumn('serverBaseUrl', (ac) => ac.setDataType('varchar(2056)')) + .execute() +} + +export async function down(db: Kysely): Promise {} From c101e30350a70056d470d293de9c88cdb18e8f88 Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Fri, 25 Oct 2024 11:31:23 -0700 Subject: [PATCH 04/19] fix: index on discussionTopicId (#10423) Signed-off-by: Matt Krick --- ...4-10-25T17:36:31.231Z_indexDiscussionTopicId.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 packages/server/postgres/migrations/2024-10-25T17:36:31.231Z_indexDiscussionTopicId.ts diff --git a/packages/server/postgres/migrations/2024-10-25T17:36:31.231Z_indexDiscussionTopicId.ts b/packages/server/postgres/migrations/2024-10-25T17:36:31.231Z_indexDiscussionTopicId.ts new file mode 100644 index 00000000000..e97ab8562cd --- /dev/null +++ b/packages/server/postgres/migrations/2024-10-25T17:36:31.231Z_indexDiscussionTopicId.ts @@ -0,0 +1,14 @@ +import type {Kysely} from 'kysely' + +export async function up(db: Kysely): Promise { + await db.schema + .createIndex('idx_Discussion_discussionTopicId') + .ifNotExists() + .on('Discussion') + .column('discussionTopicId') + .execute() +} + +export async function down(db: Kysely): Promise { + await db.schema.dropIndex('idx_Discussion_discussionTopicId').ifExists().execute() +} From 47c900df79ed5b4aeb0947079580e03a7281ebfb Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Mon, 28 Oct 2024 13:04:07 -0700 Subject: [PATCH 05/19] [Snyk] Upgrade @radix-ui/react-alert-dialog from 1.1.1 to 1.1.2 (#10407) Co-authored-by: snyk-bot Co-authored-by: GitHub Action --- packages/client/package.json | 2 +- yarn.lock | 115 +++++++++++++++++++++-------------- 2 files changed, 71 insertions(+), 46 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index 1198a57b908..f7c72e0401a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -73,7 +73,7 @@ "@mui/icons-material": "^5.8.4", "@mui/material": "^5.9.2", "@mui/x-date-pickers": "^6.3.1", - "@radix-ui/react-alert-dialog": "1.1.1", + "@radix-ui/react-alert-dialog": "1.1.2", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.4", diff --git a/yarn.lock b/yarn.lock index 434ba9a4105..3e85252abe0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6820,15 +6820,15 @@ resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== -"@radix-ui/react-alert-dialog@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.1.tgz#f49c987b9e4f2bf37005b3864933e2b3beac907a" - integrity sha512-wmCoJwj7byuVuiLKqDLlX7ClSUU0vd9sdCeM+2Ls+uf13+cpSJoMgwysHq1SGVVkJj5Xn0XWi1NoRCdkMpr6Mw== +"@radix-ui/react-alert-dialog@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.2.tgz#ac3bb7f71f5cbb595d3d0949bb12b598c2a99981" + integrity sha512-eGSlLzPhKO+TErxkiGcCZGuvbVMnLA1MTnyBksGOeGRGkxHiiJUujsjmNTdWTm4iHVSRaUao9/4Ur671auMghQ== dependencies: "@radix-ui/primitive" "1.1.0" "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-context" "1.1.0" - "@radix-ui/react-dialog" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dialog" "1.1.2" "@radix-ui/react-primitive" "2.0.0" "@radix-ui/react-slot" "1.1.0" @@ -6921,30 +6921,30 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-context@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" - integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== - -"@radix-ui/react-dialog@1.1.1": +"@radix-ui/react-context@1.1.1": version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz#4906507f7b4ad31e22d7dad69d9330c87c431d44" - integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg== + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" + integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== + +"@radix-ui/react-dialog@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz#d9345575211d6f2d13e209e84aec9a8584b54d6c" + integrity sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA== dependencies: "@radix-ui/primitive" "1.1.0" "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-context" "1.1.0" - "@radix-ui/react-dismissable-layer" "1.1.0" - "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.1" + "@radix-ui/react-focus-guards" "1.1.1" "@radix-ui/react-focus-scope" "1.1.0" "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-portal" "1.1.1" - "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-portal" "1.1.2" + "@radix-ui/react-presence" "1.1.1" "@radix-ui/react-primitive" "2.0.0" "@radix-ui/react-slot" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" aria-hidden "^1.1.1" - react-remove-scroll "2.5.7" + react-remove-scroll "2.6.0" "@radix-ui/react-dialog@^1.0.4": version "1.0.4" @@ -7005,10 +7005,10 @@ "@radix-ui/react-use-callback-ref" "1.0.1" "@radix-ui/react-use-escape-keydown" "1.0.3" -"@radix-ui/react-dismissable-layer@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz#2cd0a49a732372513733754e6032d3fb7988834e" - integrity sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig== +"@radix-ui/react-dismissable-layer@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz#cbdcb739c5403382bdde5f9243042ba643883396" + integrity sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ== dependencies: "@radix-ui/primitive" "1.1.0" "@radix-ui/react-compose-refs" "1.1.0" @@ -7051,10 +7051,10 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-focus-guards@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz#8e9abb472a9a394f59a1b45f3dd26cfe3fc6da13" - integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw== +"@radix-ui/react-focus-guards@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" + integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== "@radix-ui/react-focus-scope@1.0.3": version "1.0.3" @@ -7208,10 +7208,10 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" -"@radix-ui/react-portal@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.1.tgz#1957f1eb2e1aedfb4a5475bd6867d67b50b1d15f" - integrity sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g== +"@radix-ui/react-portal@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.2.tgz#51eb46dae7505074b306ebcb985bf65cc547d74e" + integrity sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg== dependencies: "@radix-ui/react-primitive" "2.0.0" "@radix-ui/react-use-layout-effect" "1.1.0" @@ -7234,10 +7234,10 @@ "@radix-ui/react-compose-refs" "1.0.1" "@radix-ui/react-use-layout-effect" "1.0.1" -"@radix-ui/react-presence@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" - integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== +"@radix-ui/react-presence@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.1.tgz#98aba423dba5e0c687a782c0669dcd99de17f9b1" + integrity sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A== dependencies: "@radix-ui/react-compose-refs" "1.1.0" "@radix-ui/react-use-layout-effect" "1.1.0" @@ -20264,7 +20264,7 @@ react-remove-scroll-bar@^2.3.3: react-style-singleton "^2.2.1" tslib "^2.0.0" -react-remove-scroll-bar@^2.3.4: +react-remove-scroll-bar@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c" integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g== @@ -20283,12 +20283,12 @@ react-remove-scroll@2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-remove-scroll@2.5.7: - version "2.5.7" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" - integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== +react-remove-scroll@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz#fb03a0845d7768a4f1519a99fdb84983b793dc07" + integrity sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ== dependencies: - react-remove-scroll-bar "^2.3.4" + react-remove-scroll-bar "^2.3.6" react-style-singleton "^2.2.1" tslib "^2.1.0" use-callback-ref "^1.3.0" @@ -21941,7 +21941,7 @@ string-similarity@^3.0.0: resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-3.0.0.tgz#07b0bc69fae200ad88ceef4983878d03793847c7" integrity sha512-7kS7LyTp56OqOI2BDWQNVnLX/rCxIQn+/5M0op1WV6P8Xx6TZNdajpuqQdiJ7Xx+p1C5CsWMvdiBp9ApMhxzEQ== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -21959,6 +21959,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.0.tgz#5ab00980cfb29f43e736b113a120a73a0fb569d3" @@ -22030,7 +22039,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -22044,6 +22053,13 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -23894,7 +23910,7 @@ workbox-window@6.5.4: "@types/trusted-types" "^2.0.2" workbox-core "6.5.4" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -23912,6 +23928,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From e96336930c4852af0bcdfd70707bd4a8a57ce75e Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Mon, 28 Oct 2024 13:07:36 -0700 Subject: [PATCH 06/19] fix: support pg tracing in dd-trace-js (#10424) Signed-off-by: Matt Krick --- .gitignore | 2 +- package.json | 2 +- ...addEmbeddingsMetadataForMeetingTemplate.ts | 2 +- ...MetadataForRetrospectiveDiscussionTopic.ts | 2 +- .../ai_models/AbstractEmbeddingsModel.ts | 2 +- packages/embedder/custom.d.ts | 2 +- .../indexing/createEmbeddingTextFrom.ts | 2 +- .../server/billing/helpers/adjustUserCount.ts | 2 +- .../server/database/types/MeetingTemplate.ts | 2 +- .../__tests__/isOrgVerified.test.ts | 2 +- .../server/dataloader/customLoaderMakers.ts | 2 +- .../dataloader/integrationAuthLoaders.ts | 2 +- .../server/graphql/mutations/createTask.ts | 2 +- .../helpers/addAIGeneratedContentToThreads.ts | 2 +- .../helpers/createNewMeetingPhases.ts | 2 +- .../notifications/MattermostNotifier.ts | 2 +- .../mutations/helpers/removeScheduledJobs.ts | 2 +- .../server/graphql/mutations/joinMeeting.ts | 2 +- .../graphql/mutations/updatePokerScope.ts | 4 ++-- .../private/mutations/runScheduledJobs.ts | 2 +- .../public/types/RetroReflectionGroup.ts | 2 +- packages/server/graphql/public/types/SAML.ts | 2 +- packages/server/postgres/getKysely.ts | 2 +- packages/server/postgres/getPg.ts | 16 +++++++++++--- packages/server/postgres/pg.ts | 2 ++ packages/server/postgres/types/Meeting.d.ts | 2 +- .../server/postgres/types/Notification.d.ts | 2 +- packages/server/postgres/types/index.d.ts | 14 ++++++------- .../safeMutations/removeSuggestedAction.ts | 2 +- .../isRequestToJoinDomainAllowed.test.ts | 2 +- scripts/prod.js | 2 ++ scripts/webpack/prod.servers.config.js | 21 +++++++++++++++++-- 32 files changed, 71 insertions(+), 40 deletions(-) create mode 100644 packages/server/postgres/pg.ts diff --git a/.gitignore b/.gitignore index 27e25baedc9..17e64e722f4 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ dist/ dump.rdb node_modules/ package-lock.json -packages/server/postgres/pg.d.ts +packages/server/postgres/types/pg.d.ts packages/server/postgres/queries/generated packages/server/types/githubTypes.ts packages/server/types/gitlabTypes.ts diff --git a/package.json b/package.json index e8d163d2d59..adc3fe3024e 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "clean": "git clean -fdx -e .env", "codegen": "node scripts/codegenGraphQL.js", "pg:build": "pgtyped -c ./packages/server/postgres/pgtypedConfig.js", - "pg:generate": "export $(grep ^POSTGRES_ .env | tr -d \"'\"); yarn kysely-codegen --exclude-pattern \"(PgMigrations|StripeQuantityMismatchLogging)\" --out-file ./packages/server/postgres/pg.d.ts --dialect postgres --url postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB && prettier --write ./packages/server/postgres/pg.d.ts", + "pg:generate": "export $(grep ^POSTGRES_ .env | tr -d \"'\"); yarn kysely-codegen --exclude-pattern \"(PgMigrations|StripeQuantityMismatchLogging)\" --out-file ./packages/server/postgres/types/pg.d.ts --dialect postgres --url postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB && prettier --write ./packages/server/postgres/types/pg.d.ts", "pg:restore": "node ./scripts/toolbox/pgRestore.js", "db:start": "docker compose -f docker/stacks/development/docker-compose.yml up -d", "db:stop": "docker compose -f docker/stacks/development/docker-compose.yml down", diff --git a/packages/embedder/addEmbeddingsMetadataForMeetingTemplate.ts b/packages/embedder/addEmbeddingsMetadataForMeetingTemplate.ts index e333f1764b4..531e303cc69 100644 --- a/packages/embedder/addEmbeddingsMetadataForMeetingTemplate.ts +++ b/packages/embedder/addEmbeddingsMetadataForMeetingTemplate.ts @@ -1,5 +1,5 @@ import {ExpressionOrFactory, SqlBool, sql} from 'kysely' -import {DB} from 'parabol-server/postgres/pg' +import {DB} from 'parabol-server/postgres/types/pg' import {Logger} from 'parabol-server/utils/Logger' import getKysely from '../server/postgres/getKysely' import {AddEmbeddingsMetadataParams} from './addEmbeddingsMetadata' diff --git a/packages/embedder/addEmbeddingsMetadataForRetrospectiveDiscussionTopic.ts b/packages/embedder/addEmbeddingsMetadataForRetrospectiveDiscussionTopic.ts index 8c4f5b6cd10..dc6c359cfd0 100644 --- a/packages/embedder/addEmbeddingsMetadataForRetrospectiveDiscussionTopic.ts +++ b/packages/embedder/addEmbeddingsMetadataForRetrospectiveDiscussionTopic.ts @@ -1,5 +1,5 @@ import {ExpressionOrFactory, SqlBool, sql} from 'kysely' -import {DB} from 'parabol-server/postgres/pg' +import {DB} from 'parabol-server/postgres/types/pg' import {Logger} from 'parabol-server/utils/Logger' import getKysely from '../server/postgres/getKysely' import {AddEmbeddingsMetadataParams} from './addEmbeddingsMetadata' diff --git a/packages/embedder/ai_models/AbstractEmbeddingsModel.ts b/packages/embedder/ai_models/AbstractEmbeddingsModel.ts index 78bd6e47a3e..838b83dc24e 100644 --- a/packages/embedder/ai_models/AbstractEmbeddingsModel.ts +++ b/packages/embedder/ai_models/AbstractEmbeddingsModel.ts @@ -1,6 +1,6 @@ import {sql} from 'kysely' import getKysely from 'parabol-server/postgres/getKysely' -import {DB} from 'parabol-server/postgres/pg' +import {DB} from 'parabol-server/postgres/types/pg' import isValid from '../../server/graphql/isValid' import {Logger} from '../../server/utils/Logger' import {getEmbedderPriority} from '../getEmbedderPriority' diff --git a/packages/embedder/custom.d.ts b/packages/embedder/custom.d.ts index b051eb3e4b3..3badb7d8d39 100644 --- a/packages/embedder/custom.d.ts +++ b/packages/embedder/custom.d.ts @@ -1,5 +1,5 @@ import {DataLoaderInstance} from '../server/dataloader/RootDataLoader' -import type {DB} from '../server/postgres/pg' +import type {DB} from '../server/postgres/types/pg' import {JobQueueError} from './JobQueueError' export type EmbeddingObjectType = DB['EmbeddingsMetadata']['objectType'] diff --git a/packages/embedder/indexing/createEmbeddingTextFrom.ts b/packages/embedder/indexing/createEmbeddingTextFrom.ts index 83560d35e18..e3a65da6537 100644 --- a/packages/embedder/indexing/createEmbeddingTextFrom.ts +++ b/packages/embedder/indexing/createEmbeddingTextFrom.ts @@ -1,5 +1,5 @@ import {Selectable} from 'kysely' -import {DB} from 'parabol-server/postgres/pg' +import {DB} from 'parabol-server/postgres/types/pg' import {DataLoaderInstance} from '../../server/dataloader/RootDataLoader' import {createTextFromMeetingTemplate} from './meetingTemplate' diff --git a/packages/server/billing/helpers/adjustUserCount.ts b/packages/server/billing/helpers/adjustUserCount.ts index 68dc6174de8..36623042be4 100644 --- a/packages/server/billing/helpers/adjustUserCount.ts +++ b/packages/server/billing/helpers/adjustUserCount.ts @@ -4,9 +4,9 @@ import generateUID from '../../generateUID' import {DataLoaderWorker} from '../../graphql/graphql' import isValid from '../../graphql/isValid' import getKysely from '../../postgres/getKysely' -import {OrganizationUserAudit} from '../../postgres/pg' import {getUserById} from '../../postgres/queries/getUsersByIds' import IUser from '../../postgres/types/IUser' +import {OrganizationUserAudit} from '../../postgres/types/pg' import {Logger} from '../../utils/Logger' import {analytics} from '../../utils/analytics/analytics' import getActiveDomainForOrgId from '../../utils/getActiveDomainForOrgId' diff --git a/packages/server/database/types/MeetingTemplate.ts b/packages/server/database/types/MeetingTemplate.ts index ebe903bca4f..6a71fa25d77 100644 --- a/packages/server/database/types/MeetingTemplate.ts +++ b/packages/server/database/types/MeetingTemplate.ts @@ -1,7 +1,7 @@ import {Insertable} from 'kysely' import generateUID from '../../generateUID' -import {MeetingTemplate as MeetingTemplateDB} from '../../postgres/pg' import {MeetingTypeEnum} from '../../postgres/types/Meeting' +import {MeetingTemplate as MeetingTemplateDB} from '../../postgres/types/pg' export type SharingScopeEnum = 'ORGANIZATION' | 'PUBLIC' | 'TEAM' | 'USER' diff --git a/packages/server/dataloader/__tests__/isOrgVerified.test.ts b/packages/server/dataloader/__tests__/isOrgVerified.test.ts index 59a304c92ee..f49e31f2de2 100644 --- a/packages/server/dataloader/__tests__/isOrgVerified.test.ts +++ b/packages/server/dataloader/__tests__/isOrgVerified.test.ts @@ -3,8 +3,8 @@ import {Insertable} from 'kysely' import {createPGTables, truncatePGTables} from '../../__tests__/common' import generateUID from '../../generateUID' import getKysely from '../../postgres/getKysely' -import {User} from '../../postgres/pg' import {OrganizationUser} from '../../postgres/types' +import {User} from '../../postgres/types/pg' import RootDataLoader from '../RootDataLoader' const TEST_DB = 'getVerifiedOrgIdsTest' diff --git a/packages/server/dataloader/customLoaderMakers.ts b/packages/server/dataloader/customLoaderMakers.ts index 02ed0349832..e7df1f4a523 100644 --- a/packages/server/dataloader/customLoaderMakers.ts +++ b/packages/server/dataloader/customLoaderMakers.ts @@ -6,7 +6,6 @@ import getFileStoreManager from '../fileStorage/getFileStoreManager' import {ReactableEnum} from '../graphql/public/resolverTypes' import {SAMLSource} from '../graphql/public/types/SAML' import getKysely from '../postgres/getKysely' -import {TeamMeetingTemplate} from '../postgres/pg.d' import {IGetLatestTaskEstimatesQueryResult} from '../postgres/queries/generated/getLatestTaskEstimatesQuery' import getGitHubAuthByUserIdTeamId, { GitHubAuth @@ -29,6 +28,7 @@ import { } from '../postgres/select' import {Insight, MeetingSettings, OrganizationUser, Task, Team} from '../postgres/types' import {AnyMeeting, MeetingTypeEnum} from '../postgres/types/Meeting' +import {TeamMeetingTemplate} from '../postgres/types/pg' import {Logger} from '../utils/Logger' import getRedis from '../utils/getRedis' import isUserVerified from '../utils/isUserVerified' diff --git a/packages/server/dataloader/integrationAuthLoaders.ts b/packages/server/dataloader/integrationAuthLoaders.ts index 04b40f24ea2..8d97ecd77c0 100644 --- a/packages/server/dataloader/integrationAuthLoaders.ts +++ b/packages/server/dataloader/integrationAuthLoaders.ts @@ -3,7 +3,6 @@ import TeamMemberIntegrationAuthId from '../../client/shared/gqlIds/TeamMemberIn import errorFilter from '../graphql/errorFilter' import isValid from '../graphql/isValid' import getKysely from '../postgres/getKysely' -import {TeamMemberIntegrationAuth} from '../postgres/pg' import {IGetBestTeamIntegrationAuthQueryResult} from '../postgres/queries/generated/getBestTeamIntegrationAuthQuery' import {IntegrationProviderServiceEnum} from '../postgres/queries/generated/getIntegrationProvidersByIdsQuery' import {IGetTeamMemberIntegrationAuthQueryResult} from '../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' @@ -14,6 +13,7 @@ import getIntegrationProvidersByIds, { import getTeamMemberIntegrationAuth from '../postgres/queries/getTeamMemberIntegrationAuth' import {selectSlackNotifications} from '../postgres/select' import {SlackAuth, SlackNotification} from '../postgres/types' +import {TeamMemberIntegrationAuth} from '../postgres/types/pg' import NullableDataLoader from './NullableDataLoader' import RootDataLoader from './RootDataLoader' diff --git a/packages/server/graphql/mutations/createTask.ts b/packages/server/graphql/mutations/createTask.ts index 98958388cd4..d0d3f485000 100644 --- a/packages/server/graphql/mutations/createTask.ts +++ b/packages/server/graphql/mutations/createTask.ts @@ -11,8 +11,8 @@ import getTagsFromEntityMap from '../../../client/utils/draftjs/getTagsFromEntit import generateUID from '../../generateUID' import updatePrevUsedRepoIntegrationsCache from '../../integrations/updatePrevUsedRepoIntegrationsCache' import getKysely from '../../postgres/getKysely' -import {Notification} from '../../postgres/pg' import {Task, TaskTag} from '../../postgres/types/index.d' +import {Notification} from '../../postgres/types/pg' import {TaskServiceEnum} from '../../postgres/types/TaskIntegration' import {analytics} from '../../utils/analytics/analytics' import {getUserId, isTeamMember} from '../../utils/authorization' diff --git a/packages/server/graphql/mutations/helpers/addAIGeneratedContentToThreads.ts b/packages/server/graphql/mutations/helpers/addAIGeneratedContentToThreads.ts index 6b18a33ff8b..35237177bec 100644 --- a/packages/server/graphql/mutations/helpers/addAIGeneratedContentToThreads.ts +++ b/packages/server/graphql/mutations/helpers/addAIGeneratedContentToThreads.ts @@ -4,7 +4,7 @@ import extractTextFromDraftString from '../../../../client/utils/draftjs/extract import DiscussStage from '../../../database/types/DiscussStage' import generateUID from '../../../generateUID' import getKysely from '../../../postgres/getKysely' -import {Comment} from '../../../postgres/pg' +import {Comment} from '../../../postgres/types/pg' import {convertHtmlToTaskContent} from '../../../utils/draftjs/convertHtmlToTaskContent' import {DataLoaderWorker} from '../../graphql' diff --git a/packages/server/graphql/mutations/helpers/createNewMeetingPhases.ts b/packages/server/graphql/mutations/helpers/createNewMeetingPhases.ts index f5f7a2e1def..b4523783a84 100644 --- a/packages/server/graphql/mutations/helpers/createNewMeetingPhases.ts +++ b/packages/server/graphql/mutations/helpers/createNewMeetingPhases.ts @@ -24,9 +24,9 @@ import UpdatesPhase from '../../../database/types/UpdatesPhase' import UpdatesStage from '../../../database/types/UpdatesStage' import {DataLoaderInstance} from '../../../dataloader/RootDataLoader' import getKysely from '../../../postgres/getKysely' -import {DB} from '../../../postgres/pg' import {MeetingTypeEnum} from '../../../postgres/types/Meeting' import {NewMeetingPhase, NewMeetingStages} from '../../../postgres/types/NewMeetingPhase' +import {DB} from '../../../postgres/types/pg' import isPhaseAvailable from '../../../utils/isPhaseAvailable' import {DataLoaderWorker} from '../../graphql' import {getFeatureTier} from '../../types/helpers/getFeatureTier' diff --git a/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts b/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts index b0fc2afd35d..65f728d863d 100644 --- a/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts +++ b/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts @@ -4,11 +4,11 @@ import makeAppURL from 'parabol-client/utils/makeAppURL' import findStageById from 'parabol-client/utils/meetings/findStageById' import {phaseLabelLookup} from 'parabol-client/utils/meetings/lookups' import appOrigin from '../../../../appOrigin' -import {TeamMemberIntegrationAuth} from '../../../../postgres/pg' import {IntegrationProviderMattermost} from '../../../../postgres/queries/getIntegrationProvidersByIds' import {SlackNotification, Team} from '../../../../postgres/types' import IUser from '../../../../postgres/types/IUser' import {AnyMeeting, MeetingTypeEnum} from '../../../../postgres/types/Meeting' +import {TeamMemberIntegrationAuth} from '../../../../postgres/types/pg' import MattermostServerManager from '../../../../utils/MattermostServerManager' import {analytics} from '../../../../utils/analytics/analytics' import {toEpochSeconds} from '../../../../utils/epochTime' diff --git a/packages/server/graphql/mutations/helpers/removeScheduledJobs.ts b/packages/server/graphql/mutations/helpers/removeScheduledJobs.ts index 475480467e1..817c965f8ad 100644 --- a/packages/server/graphql/mutations/helpers/removeScheduledJobs.ts +++ b/packages/server/graphql/mutations/helpers/removeScheduledJobs.ts @@ -1,6 +1,6 @@ import {Updateable} from 'kysely' import getKysely from '../../../postgres/getKysely' -import {DB} from '../../../postgres/pg' +import {DB} from '../../../postgres/types/pg' type FilterType = Omit, 'runAt'> diff --git a/packages/server/graphql/mutations/joinMeeting.ts b/packages/server/graphql/mutations/joinMeeting.ts index d904089a878..246b3899e1d 100644 --- a/packages/server/graphql/mutations/joinMeeting.ts +++ b/packages/server/graphql/mutations/joinMeeting.ts @@ -7,10 +7,10 @@ import CheckInStage from '../../database/types/CheckInStage' import TeamPromptResponseStage from '../../database/types/TeamPromptResponseStage' import UpdatesStage from '../../database/types/UpdatesStage' import getKysely from '../../postgres/getKysely' -import {MeetingMember} from '../../postgres/pg' import {TeamMember} from '../../postgres/types' import {AnyMeeting} from '../../postgres/types/Meeting' import {NewMeetingPhase, NewMeetingStages} from '../../postgres/types/NewMeetingPhase' +import {MeetingMember} from '../../postgres/types/pg' import {analytics} from '../../utils/analytics/analytics' import {getUserId, isTeamMember} from '../../utils/authorization' import getPhase from '../../utils/getPhase' diff --git a/packages/server/graphql/mutations/updatePokerScope.ts b/packages/server/graphql/mutations/updatePokerScope.ts index a80913a9d47..cb5ca3d1cac 100644 --- a/packages/server/graphql/mutations/updatePokerScope.ts +++ b/packages/server/graphql/mutations/updatePokerScope.ts @@ -4,13 +4,13 @@ import {SubscriptionChannel, Threshold} from 'parabol-client/types/constEnums' import {ESTIMATE_TASK_SORT_ORDER} from '../../../client/utils/constants' import EstimateStage from '../../database/types/EstimateStage' import getKysely from '../../postgres/getKysely' -import {Discussion} from '../../postgres/pg' +import {Discussion} from '../../postgres/types/pg' import {TaskServiceEnum} from '../../postgres/types/TaskIntegration' -import RedisLockQueue from '../../utils/RedisLockQueue' import {getUserId, isTeamMember} from '../../utils/authorization' import getPhase from '../../utils/getPhase' import getRedis from '../../utils/getRedis' import publish from '../../utils/publish' +import RedisLockQueue from '../../utils/RedisLockQueue' import {GQLContext} from '../graphql' import UpdatePokerScopeItemInput from '../types/UpdatePokerScopeItemInput' import UpdatePokerScopePayload from '../types/UpdatePokerScopePayload' diff --git a/packages/server/graphql/private/mutations/runScheduledJobs.ts b/packages/server/graphql/private/mutations/runScheduledJobs.ts index 465f13bb2df..c579b942c6f 100644 --- a/packages/server/graphql/private/mutations/runScheduledJobs.ts +++ b/packages/server/graphql/private/mutations/runScheduledJobs.ts @@ -5,7 +5,7 @@ import ScheduledTeamLimitsJob from '../../../database/types/ScheduledTeamLimitsJ import processTeamsLimitsJob from '../../../database/types/processTeamsLimitsJob' import generateUID from '../../../generateUID' import getKysely from '../../../postgres/getKysely' -import {DB} from '../../../postgres/pg' +import {DB} from '../../../postgres/types/pg' import {Logger} from '../../../utils/Logger' import publish from '../../../utils/publish' import {DataLoaderWorker} from '../../graphql' diff --git a/packages/server/graphql/public/types/RetroReflectionGroup.ts b/packages/server/graphql/public/types/RetroReflectionGroup.ts index 8a262b491d5..b71ebb39e22 100644 --- a/packages/server/graphql/public/types/RetroReflectionGroup.ts +++ b/packages/server/graphql/public/types/RetroReflectionGroup.ts @@ -1,5 +1,5 @@ import {Selectable} from 'kysely' -import {RetroReflectionGroup as TRetroReflectionGroup} from '../../../postgres/pg' +import {RetroReflectionGroup as TRetroReflectionGroup} from '../../../postgres/types/pg' import {getUserId} from '../../../utils/authorization' import {RetroReflectionGroupResolvers} from '../resolverTypes' diff --git a/packages/server/graphql/public/types/SAML.ts b/packages/server/graphql/public/types/SAML.ts index 24312a433d4..1949f276451 100644 --- a/packages/server/graphql/public/types/SAML.ts +++ b/packages/server/graphql/public/types/SAML.ts @@ -1,5 +1,5 @@ import {Selectable} from 'kysely' -import {SAML as TSAML} from '../../../postgres/pg.d' +import {SAML as TSAML} from '../../../postgres/types/pg' import {SamlResolvers} from '../resolverTypes' export interface SAMLSource extends Selectable { diff --git a/packages/server/postgres/getKysely.ts b/packages/server/postgres/getKysely.ts index c7c02a59d16..ff0caa60e71 100644 --- a/packages/server/postgres/getKysely.ts +++ b/packages/server/postgres/getKysely.ts @@ -1,6 +1,6 @@ import {Kysely, PostgresDialect} from 'kysely' import getPg from './getPg' -import {DB} from './pg.d' +import {DB} from './types/pg' let kysely: Kysely | undefined diff --git a/packages/server/postgres/getPg.ts b/packages/server/postgres/getPg.ts index 0e82891eeb7..7ce41879e57 100644 --- a/packages/server/postgres/getPg.ts +++ b/packages/server/postgres/getPg.ts @@ -1,7 +1,17 @@ -import {Pool} from 'pg' +import type {Pool as PGPool} from 'pg' import sleep from '../../client/utils/sleep' import getPgConfig from './getPgConfig' +/* +Force a native `require` so dd-trace-js can monkeypatch the require statement. +In development, the require statement requires `./pg.ts` since require resolves packages by first looking in the same dir +In production, the require statement will resolve to the node_modules found in /dist +*/ +// when used outside of webpack, e.g. kysely.config.js, go vanilla +declare let __non_webpack_require__: typeof require +const pg = + typeof __non_webpack_require__ === 'undefined' ? require('pg') : __non_webpack_require__('pg') +const {Pool} = pg const config = getPgConfig() const graceFullyReconnect = async () => { @@ -21,10 +31,10 @@ const graceFullyReconnect = async () => { } } -let pool: Pool | undefined +let pool: PGPool | undefined const getPg = (schema?: string) => { if (!pool) { - pool = new Pool(config) + pool = new Pool(config) as PGPool pool.on('error', graceFullyReconnect) if (schema) { pool.on('connect', (client) => { diff --git a/packages/server/postgres/pg.ts b/packages/server/postgres/pg.ts new file mode 100644 index 00000000000..51dd6b37a40 --- /dev/null +++ b/packages/server/postgres/pg.ts @@ -0,0 +1,2 @@ +// webpack entrypoint forcing pg & all dependencies to get bundled into a standalone file +export {Client, Pool} from 'pg' diff --git a/packages/server/postgres/types/Meeting.d.ts b/packages/server/postgres/types/Meeting.d.ts index 4dfa0d3e4f5..c54aed1dedd 100644 --- a/packages/server/postgres/types/Meeting.d.ts +++ b/packages/server/postgres/types/Meeting.d.ts @@ -1,6 +1,5 @@ import {Selectable} from 'kysely' import {NonNullableProps} from '../../../client/types/generics' -import {NewMeeting as NewMeetingPG} from '../pg.d' import {AutogroupReflectionGroupType, UsedReactjis} from './index.d' import { CheckInMeetingPhase, @@ -9,6 +8,7 @@ import { RetroMeetingPhase, TeamPromptPhase } from './NewMeetingPhase' +import {NewMeeting as NewMeetingPG} from './pg' type NewMeeting = Selectable export type MeetingTypeEnum = NewMeeting['meetingType'] diff --git a/packages/server/postgres/types/Notification.d.ts b/packages/server/postgres/types/Notification.d.ts index 14a71b0700d..08eec0eac1d 100644 --- a/packages/server/postgres/types/Notification.d.ts +++ b/packages/server/postgres/types/Notification.d.ts @@ -1,4 +1,4 @@ -import type {Notification} from '../pg.d' +import type {Notification} from './pg' interface BaseNotification { id: string diff --git a/packages/server/postgres/types/index.d.ts b/packages/server/postgres/types/index.d.ts index a6cf8481192..df219711932 100644 --- a/packages/server/postgres/types/index.d.ts +++ b/packages/server/postgres/types/index.d.ts @@ -1,11 +1,4 @@ import {SelectQueryBuilder, Selectable} from 'kysely' -import { - Discussion as DiscussionPG, - Insight as InsightPG, - OrganizationUser as OrganizationUserPG, - TaskEstimate as TaskEstimatePG, - TeamMember as TeamMemberPG -} from '../pg.d' import { selectAgendaItems, selectComments, @@ -25,6 +18,13 @@ import { selectTemplateScale, selectTemplateScaleRef } from '../select' +import { + Discussion as DiscussionPG, + Insight as InsightPG, + OrganizationUser as OrganizationUserPG, + TaskEstimate as TaskEstimatePG, + TeamMember as TeamMemberPG +} from './pg' type ExtractTypeFromQueryBuilderSelect any> = ReturnType extends SelectQueryBuilder<_, _, infer X> ? X : never diff --git a/packages/server/safeMutations/removeSuggestedAction.ts b/packages/server/safeMutations/removeSuggestedAction.ts index a8481af1f95..efda8b66e27 100644 --- a/packages/server/safeMutations/removeSuggestedAction.ts +++ b/packages/server/safeMutations/removeSuggestedAction.ts @@ -1,6 +1,6 @@ import {sql} from 'kysely' import getKysely from '../postgres/getKysely' -import {SuggestedAction} from '../postgres/pg' +import {SuggestedAction} from '../postgres/types/pg' const removeSuggestedAction = async (userId: string, type: SuggestedAction['type']) => { const removedAction = await getKysely() diff --git a/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts b/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts index d518a0ad301..d74fac3d40d 100644 --- a/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts +++ b/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts @@ -5,8 +5,8 @@ import RootDataLoader from '../../dataloader/RootDataLoader' import generateUID from '../../generateUID' import {TierEnum} from '../../graphql/public/resolverTypes' import getKysely from '../../postgres/getKysely' -import {User} from '../../postgres/pg' import {OrganizationUser} from '../../postgres/types' +import {User} from '../../postgres/types/pg' import getRedis from '../getRedis' import {getEligibleOrgIdsByDomain} from '../isRequestToJoinDomainAllowed' diff --git a/scripts/prod.js b/scripts/prod.js index bfb8dea036f..58776184dc1 100644 --- a/scripts/prod.js +++ b/scripts/prod.js @@ -13,6 +13,8 @@ const runChild = (cmd) => { } }) build.stderr.pipe(process.stderr) + // enable this for debugging webpack scripts + // build.stdout.pipe(process.stdout) }) } diff --git a/scripts/webpack/prod.servers.config.js b/scripts/webpack/prod.servers.config.js index dd1679a6b4d..4b39f42f4d2 100644 --- a/scripts/webpack/prod.servers.config.js +++ b/scripts/webpack/prod.servers.config.js @@ -44,10 +44,21 @@ module.exports = (config) => { ], pushToCDN: [DOTENV, path.join(PROJECT_ROOT, 'scripts/toolboxSrc/pushToCDN.ts')], migrate: [DOTENV, path.join(PROJECT_ROOT, 'scripts/toolboxSrc/standaloneMigrations.ts')], - assignSURole: [DOTENV, path.join(PROJECT_ROOT, 'scripts/toolboxSrc/assignSURole.ts')] + assignSURole: [DOTENV, path.join(PROJECT_ROOT, 'scripts/toolboxSrc/assignSURole.ts')], + pg: { + // bundle pg with all its dependencies into a single file + // so dd-trace-js can monkeypatch require('pg') + import: [path.join(SERVER_ROOT, 'postgres/pg.ts')], + library: { + type: 'commonjs2' + } + } }, output: { - filename: '[name].js', + filename: (pathData) => { + // trick dd-trace-js into thinking our standalone pg file is a node_module + return pathData.chunk.name === 'pg' ? 'node_modules/pg/lib/index.js' : '[name].js' + }, path: distPath }, resolve: { @@ -104,6 +115,12 @@ module.exports = (config) => { // copy sharp's libvips to the output from: path.resolve(PROJECT_ROOT, 'node_modules', 'sharp', 'vendor'), to: 'vendor' + }, + { + // dd-trace-js has a lookup table for hooks, which includes the key `pg` + // In order for `pg` to get parsed as `pg` and not `pg.js`, we need a package.json to provide the name `pg` + from: path.resolve(PROJECT_ROOT, 'node_modules', 'pg', 'package.json'), + to: 'node_modules/pg/package.json' } ] }) From 2ce40680dedee99a941d362cc3ab8a8f655bda27 Mon Sep 17 00:00:00 2001 From: "parabol-release-bot[bot]" <150284312+parabol-release-bot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:16:41 -0700 Subject: [PATCH 07/19] chore(release): release v8.1.1 (#10416) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ package.json | 2 +- packages/chronos/package.json | 4 ++-- packages/client/package.json | 2 +- packages/embedder/package.json | 2 +- packages/gql-executor/package.json | 6 +++--- packages/integration-tests/package.json | 2 +- packages/server/package.json | 4 ++-- 9 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 529b133fdee..54736c81642 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "8.1.0" + ".": "8.1.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 2620e4b8141..0667de7666f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ This project adheres to [Semantic Versioning](http://semver.org/). This CHANGELOG follows conventions [outlined here](http://keepachangelog.com/). +## [8.1.1](https://github.com/ParabolInc/parabol/compare/v8.1.0...v8.1.1) (2024-10-28) + + +### Fixed + +* increase URL col length for IntegrationProvider ([2c49dce](https://github.com/ParabolInc/parabol/commit/2c49dce82d0b9a8f7b20762bcc2cd903fcc966b0)) +* index on discussionTopicId ([#10423](https://github.com/ParabolInc/parabol/issues/10423)) ([c101e30](https://github.com/ParabolInc/parabol/commit/c101e30350a70056d470d293de9c88cdb18e8f88)) +* support pg tracing in dd-trace-js ([#10424](https://github.com/ParabolInc/parabol/issues/10424)) ([e963369](https://github.com/ParabolInc/parabol/commit/e96336930c4852af0bcdfd70707bd4a8a57ce75e)) + ## [8.1.0](https://github.com/ParabolInc/parabol/compare/v8.0.1...v8.1.0) (2024-10-24) diff --git a/package.json b/package.json index adc3fe3024e..668193a8594 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.0", + "version": "8.1.1", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/chronos/package.json b/packages/chronos/package.json index ea6e5dca2ce..13299544d6a 100644 --- a/packages/chronos/package.json +++ b/packages/chronos/package.json @@ -1,6 +1,6 @@ { "name": "chronos", - "version": "8.1.0", + "version": "8.1.1", "description": "A cron job scheduler", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/chronos#readme", @@ -25,6 +25,6 @@ }, "dependencies": { "cron": "^2.3.1", - "parabol-server": "8.1.0" + "parabol-server": "8.1.1" } } diff --git a/packages/client/package.json b/packages/client/package.json index f7c72e0401a..edc42595ba0 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.0", + "version": "8.1.1", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/embedder/package.json b/packages/embedder/package.json index 8d5cbfbb96a..284beb71fe2 100644 --- a/packages/embedder/package.json +++ b/packages/embedder/package.json @@ -1,6 +1,6 @@ { "name": "parabol-embedder", - "version": "8.1.0", + "version": "8.1.1", "description": "A service that computes embedding vectors from Parabol objects", "author": "Jordan Husney ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/embedder#readme", diff --git a/packages/gql-executor/package.json b/packages/gql-executor/package.json index f8747e8ea4a..f5934b11b4b 100644 --- a/packages/gql-executor/package.json +++ b/packages/gql-executor/package.json @@ -1,6 +1,6 @@ { "name": "gql-executor", - "version": "8.1.0", + "version": "8.1.1", "description": "A Stateless GraphQL Executor", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/gqlExecutor#readme", @@ -26,8 +26,8 @@ }, "dependencies": { "dd-trace": "^5.0.0", - "parabol-client": "8.1.0", - "parabol-server": "8.1.0", + "parabol-client": "8.1.1", + "parabol-server": "8.1.1", "undici": "^5.26.2" } } diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index 65bce2923a5..9a942908a83 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -2,7 +2,7 @@ "name": "integration-tests", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.0", + "version": "8.1.1", "description": "", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index 2c42bf27cd3..a803ca55381 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.0", + "version": "8.1.1", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" @@ -120,7 +120,7 @@ "oauth-1.0a": "^2.2.6", "openai": "^4.53.0", "oy-vey": "^0.12.1", - "parabol-client": "8.1.0", + "parabol-client": "8.1.1", "pg": "^8.5.1", "react": "^17.0.2", "react-dom": "^17.0.2", From 88fec61c90412745ffee4c6d565d9d0cf9296550 Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Mon, 28 Oct 2024 15:19:34 -0700 Subject: [PATCH 08/19] fix: TeamMemberIntegrationAuth single fetch (#10426) Signed-off-by: Matt Krick --- packages/embedder/embedder.ts | 3 +- .../server/dataloader/azureDevOpsLoaders.ts | 10 +++---- packages/server/dataloader/gcalLoaders.ts | 10 ++----- packages/server/dataloader/gitlabLoaders.ts | 10 ++----- .../dataloader/integrationAuthLoaders.ts | 28 +++++++++++-------- .../mutations/helpers/createAzureTask.ts | 4 +-- .../mutations/helpers/createGitLabTask.ts | 4 +-- .../notifications/MattermostNotifier.ts | 3 +- .../gitlab/GitLabServerManager.ts | 6 ++-- .../jiraServer/JiraServerRestManager.ts | 9 ++---- .../queries/getTeamMemberIntegrationAuth.ts | 18 ------------ .../src/getTeamMemberIntegrationAuthQuery.sql | 8 ------ packages/server/postgres/select.ts | 3 ++ packages/server/postgres/types/index.d.ts | 4 ++- .../server/utils/AzureDevOpsServerManager.ts | 6 ++-- 15 files changed, 50 insertions(+), 76 deletions(-) delete mode 100644 packages/server/postgres/queries/getTeamMemberIntegrationAuth.ts delete mode 100644 packages/server/postgres/queries/src/getTeamMemberIntegrationAuthQuery.sql diff --git a/packages/embedder/embedder.ts b/packages/embedder/embedder.ts index fa02616b1de..5e92dd6cf6b 100644 --- a/packages/embedder/embedder.ts +++ b/packages/embedder/embedder.ts @@ -18,7 +18,8 @@ tracer.init({ plugins: false, version: process.env.npm_package_version }) -tracer.use('pg') +// The embedder queue is in PG & gets hits non-stop, which dirties up the logs. Ignore the polling query before enabling pg +// tracer.use('pg') const run = async () => { const SERVER_ID = process.env.SERVER_ID diff --git a/packages/server/dataloader/azureDevOpsLoaders.ts b/packages/server/dataloader/azureDevOpsLoaders.ts index 3bf4e889b3f..101004c6cf7 100644 --- a/packages/server/dataloader/azureDevOpsLoaders.ts +++ b/packages/server/dataloader/azureDevOpsLoaders.ts @@ -1,11 +1,11 @@ import DataLoader from 'dataloader' import {decode} from 'jsonwebtoken' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' import getAzureDevOpsDimensionFieldMaps from '../postgres/queries/getAzureDevOpsDimensionFieldMaps' import {IntegrationProviderAzureDevOps} from '../postgres/queries/getIntegrationProvidersByIds' import insertTaskEstimate from '../postgres/queries/insertTaskEstimate' import removeTeamMemberIntegrationAuthQuery from '../postgres/queries/removeTeamMemberIntegrationAuth' import upsertTeamMemberIntegrationAuth from '../postgres/queries/upsertTeamMemberIntegrationAuth' +import {TeamMemberIntegrationAuth} from '../postgres/types' import AzureDevOpsServerManager, { ProjectRes, Resource, @@ -133,16 +133,16 @@ export interface AzureProject extends ProjectRes { export const freshAzureDevOpsAuth = ( parent: RootDataLoader -): DataLoader => { - return new DataLoader( +): DataLoader => { + return new DataLoader( async (keys) => { const results = await Promise.allSettled( keys.map(async ({userId, teamId}) => { - const azureDevOpsAuthToRefresh = (await parent.get('teamMemberIntegrationAuths').load({ + const azureDevOpsAuthToRefresh = await parent.get('teamMemberIntegrationAuths').load({ service: 'azureDevOps', teamId, userId - })) as IGetTeamMemberIntegrationAuthQueryResult | null + }) if (azureDevOpsAuthToRefresh === null) { return null } diff --git a/packages/server/dataloader/gcalLoaders.ts b/packages/server/dataloader/gcalLoaders.ts index 392d9081c32..758b7f40a56 100644 --- a/packages/server/dataloader/gcalLoaders.ts +++ b/packages/server/dataloader/gcalLoaders.ts @@ -1,16 +1,12 @@ import DataLoader from 'dataloader' import GcalOAuth2Manager from '../integrations/gcal/GcalOAuth2Manager' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' import upsertTeamMemberIntegrationAuth from '../postgres/queries/upsertTeamMemberIntegrationAuth' +import {TeamMemberIntegrationAuth} from '../postgres/types' import sendToSentry from '../utils/sendToSentry' import RootDataLoader from './RootDataLoader' export const freshGcalAuth = (parent: RootDataLoader) => { - return new DataLoader< - {teamId: string; userId: string}, - IGetTeamMemberIntegrationAuthQueryResult | null, - string - >( + return new DataLoader<{teamId: string; userId: string}, TeamMemberIntegrationAuth | null, string>( async (keys) => { const results = await Promise.allSettled( keys.map(async ({teamId, userId}) => { @@ -48,7 +44,7 @@ export const freshGcalAuth = (parent: RootDataLoader) => { await upsertTeamMemberIntegrationAuth(newGcalAuth) return newGcalAuth } - return gcalAuth as IGetTeamMemberIntegrationAuthQueryResult + return gcalAuth }) ) const vals = results.map((result) => (result.status === 'fulfilled' ? result.value : null)) diff --git a/packages/server/dataloader/gitlabLoaders.ts b/packages/server/dataloader/gitlabLoaders.ts index 1dceb5a60b3..68435fd7245 100644 --- a/packages/server/dataloader/gitlabLoaders.ts +++ b/packages/server/dataloader/gitlabLoaders.ts @@ -1,16 +1,12 @@ import DataLoader from 'dataloader' import GitLabOAuth2Manager from '../integrations/gitlab/GitLabOAuth2Manager' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' import upsertTeamMemberIntegrationAuth from '../postgres/queries/upsertTeamMemberIntegrationAuth' +import {TeamMemberIntegrationAuth} from '../postgres/types' import sendToSentry from '../utils/sendToSentry' import RootDataLoader from './RootDataLoader' export const freshGitlabAuth = (parent: RootDataLoader) => { - return new DataLoader< - {teamId: string; userId: string}, - IGetTeamMemberIntegrationAuthQueryResult | null, - string - >( + return new DataLoader<{teamId: string; userId: string}, TeamMemberIntegrationAuth | null, string>( async (keys) => { const results = await Promise.allSettled( keys.map(async ({teamId, userId}) => { @@ -45,7 +41,7 @@ export const freshGitlabAuth = (parent: RootDataLoader) => { await upsertTeamMemberIntegrationAuth(newGitlabAuth) return newGitlabAuth } - return gitlabAuth as IGetTeamMemberIntegrationAuthQueryResult + return gitlabAuth }) ) const vals = results.map((result) => (result.status === 'fulfilled' ? result.value : null)) diff --git a/packages/server/dataloader/integrationAuthLoaders.ts b/packages/server/dataloader/integrationAuthLoaders.ts index 8d97ecd77c0..a8f5d5cb21e 100644 --- a/packages/server/dataloader/integrationAuthLoaders.ts +++ b/packages/server/dataloader/integrationAuthLoaders.ts @@ -5,15 +5,12 @@ import isValid from '../graphql/isValid' import getKysely from '../postgres/getKysely' import {IGetBestTeamIntegrationAuthQueryResult} from '../postgres/queries/generated/getBestTeamIntegrationAuthQuery' import {IntegrationProviderServiceEnum} from '../postgres/queries/generated/getIntegrationProvidersByIdsQuery' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' import getBestTeamIntegrationAuth from '../postgres/queries/getBestTeamIntegrationAuth' import getIntegrationProvidersByIds, { TIntegrationProvider } from '../postgres/queries/getIntegrationProvidersByIds' -import getTeamMemberIntegrationAuth from '../postgres/queries/getTeamMemberIntegrationAuth' -import {selectSlackNotifications} from '../postgres/select' -import {SlackAuth, SlackNotification} from '../postgres/types' -import {TeamMemberIntegrationAuth} from '../postgres/types/pg' +import {selectSlackNotifications, selectTeamMemberIntegrationAuth} from '../postgres/select' +import {SlackAuth, SlackNotification, TeamMemberIntegrationAuth} from '../postgres/types' import NullableDataLoader from './NullableDataLoader' import RootDataLoader from './RootDataLoader' @@ -124,17 +121,26 @@ export const bestTeamIntegrationProviders = (parent: RootDataLoader) => { export const teamMemberIntegrationAuths = (parent: RootDataLoader) => { return new DataLoader< TeamMemberIntegrationAuthPrimaryKey, - IGetTeamMemberIntegrationAuthQueryResult | null, + TeamMemberIntegrationAuth | null, string >( async (keys) => { - const results = await Promise.allSettled( - keys.map(async ({service, teamId, userId}) => - getTeamMemberIntegrationAuth(service, teamId, userId) + const results = await selectTeamMemberIntegrationAuth() + .where(({eb, refTuple, tuple}) => + eb( + refTuple('teamId', 'userId', 'service'), + 'in', + keys.map((key) => tuple(key.teamId, key.userId, key.service)) + ) ) + .execute() + return keys.map( + (key) => + results.find( + ({teamId, userId, service}) => + key.teamId === teamId && key.userId === userId && key.service === service + ) || null ) - const vals = results.map((result) => (result.status === 'fulfilled' ? result.value : null)) - return vals }, { ...parent.dataLoaderOptions, diff --git a/packages/server/graphql/mutations/helpers/createAzureTask.ts b/packages/server/graphql/mutations/helpers/createAzureTask.ts index 80442b8e2fb..a8e8c8e06df 100644 --- a/packages/server/graphql/mutations/helpers/createAzureTask.ts +++ b/packages/server/graphql/mutations/helpers/createAzureTask.ts @@ -1,12 +1,12 @@ import {DataLoaderWorker} from '../../../graphql/graphql' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../../../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' import {IntegrationProviderAzureDevOps} from '../../../postgres/queries/getIntegrationProvidersByIds' +import {TeamMemberIntegrationAuth} from '../../../postgres/types' import AzureDevOpsServerManager from '../../../utils/AzureDevOpsServerManager' const createAzureTask = async ( rawContentStr: string, serviceProjectHash: string, - azureAuth: IGetTeamMemberIntegrationAuthQueryResult, + azureAuth: TeamMemberIntegrationAuth, dataLoader: DataLoaderWorker ) => { const provider = await dataLoader.get('integrationProviders').loadNonNull(azureAuth.providerId) diff --git a/packages/server/graphql/mutations/helpers/createGitLabTask.ts b/packages/server/graphql/mutations/helpers/createGitLabTask.ts index 3b07706a81c..69c5ce4d93c 100644 --- a/packages/server/graphql/mutations/helpers/createGitLabTask.ts +++ b/packages/server/graphql/mutations/helpers/createGitLabTask.ts @@ -2,13 +2,13 @@ import {stateToMarkdown} from 'draft-js-export-markdown' import {GraphQLResolveInfo} from 'graphql' import splitDraftContent from 'parabol-client/utils/draftjs/splitDraftContent' import GitLabServerManager from '../../../integrations/gitlab/GitLabServerManager' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../../../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' +import {TeamMemberIntegrationAuth} from '../../../postgres/types' import {DataLoaderWorker, GQLContext} from '../../graphql' const createGitLabTask = async ( rawContent: string, fullPath: string, - gitlabAuth: IGetTeamMemberIntegrationAuthQueryResult, + gitlabAuth: TeamMemberIntegrationAuth, context: GQLContext, info: GraphQLResolveInfo, dataLoader: DataLoaderWorker diff --git a/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts b/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts index 65f728d863d..c4caa787d90 100644 --- a/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts +++ b/packages/server/graphql/mutations/helpers/notifications/MattermostNotifier.ts @@ -5,10 +5,9 @@ import findStageById from 'parabol-client/utils/meetings/findStageById' import {phaseLabelLookup} from 'parabol-client/utils/meetings/lookups' import appOrigin from '../../../../appOrigin' import {IntegrationProviderMattermost} from '../../../../postgres/queries/getIntegrationProvidersByIds' -import {SlackNotification, Team} from '../../../../postgres/types' +import {SlackNotification, Team, TeamMemberIntegrationAuth} from '../../../../postgres/types' import IUser from '../../../../postgres/types/IUser' import {AnyMeeting, MeetingTypeEnum} from '../../../../postgres/types/Meeting' -import {TeamMemberIntegrationAuth} from '../../../../postgres/types/pg' import MattermostServerManager from '../../../../utils/MattermostServerManager' import {analytics} from '../../../../utils/analytics/analytics' import {toEpochSeconds} from '../../../../utils/epochTime' diff --git a/packages/server/integrations/gitlab/GitLabServerManager.ts b/packages/server/integrations/gitlab/GitLabServerManager.ts index dd44a3a5525..5a1aa1ca578 100644 --- a/packages/server/integrations/gitlab/GitLabServerManager.ts +++ b/packages/server/integrations/gitlab/GitLabServerManager.ts @@ -9,7 +9,7 @@ import getIssue from '../../graphql/nestedSchema/GitLab/queries/getIssue.graphql import getProfile from '../../graphql/nestedSchema/GitLab/queries/getProfile.graphql' import getProjectIssues from '../../graphql/nestedSchema/GitLab/queries/getProjectIssues.graphql' import getProjects from '../../graphql/nestedSchema/GitLab/queries/getProjects.graphql' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' +import {TeamMemberIntegrationAuth} from '../../postgres/types' import {RootSchema} from '../../types/custom' import { CreateIssueMutation, @@ -25,13 +25,13 @@ import {CreateTaskResponse, TaskIntegrationManager} from '../TaskIntegrationMana class GitLabServerManager implements TaskIntegrationManager { public title = 'GitLab' - private readonly auth: IGetTeamMemberIntegrationAuthQueryResult + private readonly auth: TeamMemberIntegrationAuth private readonly context: GQLContext private readonly info: GraphQLResolveInfo private readonly serverBaseUrl: string constructor( - auth: IGetTeamMemberIntegrationAuthQueryResult, + auth: TeamMemberIntegrationAuth, context: GQLContext, info: GraphQLResolveInfo, serverBaseUrl: string diff --git a/packages/server/integrations/jiraServer/JiraServerRestManager.ts b/packages/server/integrations/jiraServer/JiraServerRestManager.ts index 36b024379a1..daae367d1ed 100644 --- a/packages/server/integrations/jiraServer/JiraServerRestManager.ts +++ b/packages/server/integrations/jiraServer/JiraServerRestManager.ts @@ -5,8 +5,8 @@ import JiraServerIssueId from '~/shared/gqlIds/JiraServerIssueId' import {ExternalLinks} from '~/types/constEnums' import composeJQL from '~/utils/composeJQL' import splitDraftContent from '~/utils/draftjs/splitDraftContent' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' import {IntegrationProviderJiraServer} from '../../postgres/queries/getIntegrationProvidersByIds' +import {TeamMemberIntegrationAuth} from '../../postgres/types' import {CreateTaskResponse, TaskIntegrationManager} from '../TaskIntegrationManagerFactory' const MAX_PAGINATION_RESULTS = 5000 @@ -97,16 +97,13 @@ interface JiraServerIssuesResponse { export default class JiraServerRestManager implements TaskIntegrationManager { public title = 'Jira Server' - private readonly auth: IGetTeamMemberIntegrationAuthQueryResult + private readonly auth: TeamMemberIntegrationAuth private readonly provider: IntegrationProviderJiraServer private readonly serverBaseUrl: string private readonly oauth: OAuth private readonly token: OAuth.Token - constructor( - auth: IGetTeamMemberIntegrationAuthQueryResult, - provider: IntegrationProviderJiraServer - ) { + constructor(auth: TeamMemberIntegrationAuth, provider: IntegrationProviderJiraServer) { this.auth = auth this.provider = provider diff --git a/packages/server/postgres/queries/getTeamMemberIntegrationAuth.ts b/packages/server/postgres/queries/getTeamMemberIntegrationAuth.ts deleted file mode 100644 index 932f98a0ff2..00000000000 --- a/packages/server/postgres/queries/getTeamMemberIntegrationAuth.ts +++ /dev/null @@ -1,18 +0,0 @@ -import getPg from '../getPg' -import {IntegrationProviderServiceEnum} from './generated/getIntegrationProvidersByIdsQuery' -import { - getTeamMemberIntegrationAuthQuery, - IGetTeamMemberIntegrationAuthQueryResult -} from './generated/getTeamMemberIntegrationAuthQuery' - -export type TeamMemberIntegrationAuth = IGetTeamMemberIntegrationAuthQueryResult - -const getTeamMemberIntegrationAuth = async ( - service: IntegrationProviderServiceEnum, - teamId: string, - userId: string -) => { - const [res] = await getTeamMemberIntegrationAuthQuery.run({service, teamId, userId}, getPg()) - return res ?? null -} -export default getTeamMemberIntegrationAuth diff --git a/packages/server/postgres/queries/src/getTeamMemberIntegrationAuthQuery.sql b/packages/server/postgres/queries/src/getTeamMemberIntegrationAuthQuery.sql deleted file mode 100644 index be6de15f9e4..00000000000 --- a/packages/server/postgres/queries/src/getTeamMemberIntegrationAuthQuery.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - @name getTeamMemberIntegrationAuthQuery - */ -SELECT * FROM "TeamMemberIntegrationAuth" -WHERE "teamId" = :teamId -AND "userId" = :userId -AND "service" = :service -AND "isActive" = TRUE; diff --git a/packages/server/postgres/select.ts b/packages/server/postgres/select.ts index 1e4d550ca7a..bb22dce175c 100644 --- a/packages/server/postgres/select.ts +++ b/packages/server/postgres/select.ts @@ -18,6 +18,9 @@ export const selectTimelineEvent = () => { >() } +export const selectTeamMemberIntegrationAuth = () => { + return getKysely().selectFrom('TeamMemberIntegrationAuth').selectAll() +} export const selectTemplateScaleRef = () => { return getKysely() .selectFrom([ diff --git a/packages/server/postgres/types/index.d.ts b/packages/server/postgres/types/index.d.ts index df219711932..2cf883166e1 100644 --- a/packages/server/postgres/types/index.d.ts +++ b/packages/server/postgres/types/index.d.ts @@ -13,6 +13,7 @@ import { selectSuggestedAction, selectTasks, selectTeamInvitations, + selectTeamMemberIntegrationAuth, selectTeamPromptResponses, selectTeams, selectTemplateScale, @@ -58,7 +59,8 @@ export type SuggestedAction = ExtractTypeFromQueryBuilderSelect {} export type TeamMember = Selectable - +export interface TeamMemberIntegrationAuth + extends ExtractTypeFromQueryBuilderSelect {} export type TeamPromptResponse = ExtractTypeFromQueryBuilderSelect export type TemplateScale = ExtractTypeFromQueryBuilderSelect diff --git a/packages/server/utils/AzureDevOpsServerManager.ts b/packages/server/utils/AzureDevOpsServerManager.ts index ff4df7c0c67..0436ff3b676 100644 --- a/packages/server/utils/AzureDevOpsServerManager.ts +++ b/packages/server/utils/AzureDevOpsServerManager.ts @@ -15,8 +15,8 @@ import { TaskIntegrationManager } from '../integrations/TaskIntegrationManagerFactory' import {authorizeOAuth2} from '../integrations/helpers/authorizeOAuth2' -import {IGetTeamMemberIntegrationAuthQueryResult} from '../postgres/queries/generated/getTeamMemberIntegrationAuthQuery' import {IntegrationProviderAzureDevOps} from '../postgres/queries/getIntegrationProvidersByIds' +import {TeamMemberIntegrationAuth} from '../postgres/types' import makeCreateAzureTaskComment from './makeCreateAzureTaskComment' export interface AzureDevOpsUser { @@ -254,7 +254,7 @@ class AzureDevOpsServerManager implements TaskIntegrationManager { Accept: 'application/json' as const, 'Content-Type': 'application/json' } - private readonly auth: IGetTeamMemberIntegrationAuthQueryResult | null + private readonly auth: TeamMemberIntegrationAuth | null async init(code: string, codeVerifier: string | null) { if (!codeVerifier) { @@ -273,7 +273,7 @@ class AzureDevOpsServerManager implements TaskIntegrationManager { private readonly provider: IntegrationProviderAzureDevOps | undefined constructor( - auth: IGetTeamMemberIntegrationAuthQueryResult | null, + auth: TeamMemberIntegrationAuth | null, provider: IntegrationProviderAzureDevOps | null ) { if (!!auth && !!auth.accessToken) { From 96a827b20e0fb7a29b6858a3dc651d5e612526e6 Mon Sep 17 00:00:00 2001 From: Nick O'Ferrall Date: Mon, 28 Oct 2024 22:20:34 +0000 Subject: [PATCH 09/19] feat: add featureFlags migration (#10375) --- ...4-10-28T15:49:33.276Z_add-feature-flags.ts | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 packages/server/postgres/migrations/2024-10-28T15:49:33.276Z_add-feature-flags.ts diff --git a/packages/server/postgres/migrations/2024-10-28T15:49:33.276Z_add-feature-flags.ts b/packages/server/postgres/migrations/2024-10-28T15:49:33.276Z_add-feature-flags.ts new file mode 100644 index 00000000000..7c615d4e587 --- /dev/null +++ b/packages/server/postgres/migrations/2024-10-28T15:49:33.276Z_add-feature-flags.ts @@ -0,0 +1,53 @@ +import {Kysely} from 'kysely' + +export async function up(db: Kysely): Promise { + await db + .insertInto('FeatureFlag') + .values([ + { + featureName: 'insights', + description: 'Whether the team has access to an AI summary of their wins and challenges', + expiresAt: new Date('2025-01-31T00:00:00.000Z'), + scope: 'Team' + }, + { + featureName: 'publicTeams', + description: 'Whether users can see teams they are not a member of in an org', + expiresAt: new Date('2025-01-31T00:00:00.000Z'), + scope: 'Organization' + }, + { + featureName: 'relatedDiscussions', + description: + 'A comment in a retro discussion thread that uses AI to show similar conversations in the past', + expiresAt: new Date('2025-01-31T00:00:00.000Z'), + scope: 'Organization' + }, + { + featureName: 'standupAISummary', + description: 'Whether the standup UI has an AI meeting Summary or not', + expiresAt: new Date('2025-01-31T00:00:00.000Z'), + scope: 'Organization' + }, + { + featureName: 'suggestGroups', + description: 'Auto-group reflections using AI', + expiresAt: new Date('2025-01-31T00:00:00.000Z'), + scope: 'Organization' + } + ]) + .execute() +} + +export async function down(db: Kysely): Promise { + await db + .deleteFrom('FeatureFlag') + .where('featureName', 'in', [ + 'insights', + 'publicTeams', + 'relatedDiscussions', + 'standupAISummary', + 'suggestGroups' + ]) + .execute() +} From 27ff2dcb6edd685d2784bf142db565a2142e3953 Mon Sep 17 00:00:00 2001 From: "parabol-release-bot[bot]" <150284312+parabol-release-bot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:28:16 -0700 Subject: [PATCH 10/19] chore(release): release v8.2.0 (#10427) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- packages/chronos/package.json | 4 ++-- packages/client/package.json | 2 +- packages/embedder/package.json | 2 +- packages/gql-executor/package.json | 6 +++--- packages/integration-tests/package.json | 2 +- packages/server/package.json | 4 ++-- 9 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 54736c81642..f59c11ca844 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "8.1.1" + ".": "8.2.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0667de7666f..6d50ff4024c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](http://semver.org/). This CHANGELOG follows conventions [outlined here](http://keepachangelog.com/). +## [8.2.0](https://github.com/ParabolInc/parabol/compare/v8.1.1...v8.2.0) (2024-10-28) + + +### Added + +* add featureFlags migration ([#10375](https://github.com/ParabolInc/parabol/issues/10375)) ([96a827b](https://github.com/ParabolInc/parabol/commit/96a827b20e0fb7a29b6858a3dc651d5e612526e6)) + + +### Fixed + +* TeamMemberIntegrationAuth single fetch ([#10426](https://github.com/ParabolInc/parabol/issues/10426)) ([88fec61](https://github.com/ParabolInc/parabol/commit/88fec61c90412745ffee4c6d565d9d0cf9296550)) + ## [8.1.1](https://github.com/ParabolInc/parabol/compare/v8.1.0...v8.1.1) (2024-10-28) diff --git a/package.json b/package.json index 668193a8594..19b1dc47e79 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.1", + "version": "8.2.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/chronos/package.json b/packages/chronos/package.json index 13299544d6a..af3175a1432 100644 --- a/packages/chronos/package.json +++ b/packages/chronos/package.json @@ -1,6 +1,6 @@ { "name": "chronos", - "version": "8.1.1", + "version": "8.2.0", "description": "A cron job scheduler", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/chronos#readme", @@ -25,6 +25,6 @@ }, "dependencies": { "cron": "^2.3.1", - "parabol-server": "8.1.1" + "parabol-server": "8.2.0" } } diff --git a/packages/client/package.json b/packages/client/package.json index edc42595ba0..888d9563e55 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.1", + "version": "8.2.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/embedder/package.json b/packages/embedder/package.json index 284beb71fe2..5a2edf1d852 100644 --- a/packages/embedder/package.json +++ b/packages/embedder/package.json @@ -1,6 +1,6 @@ { "name": "parabol-embedder", - "version": "8.1.1", + "version": "8.2.0", "description": "A service that computes embedding vectors from Parabol objects", "author": "Jordan Husney ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/embedder#readme", diff --git a/packages/gql-executor/package.json b/packages/gql-executor/package.json index f5934b11b4b..773dd26b3f7 100644 --- a/packages/gql-executor/package.json +++ b/packages/gql-executor/package.json @@ -1,6 +1,6 @@ { "name": "gql-executor", - "version": "8.1.1", + "version": "8.2.0", "description": "A Stateless GraphQL Executor", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/gqlExecutor#readme", @@ -26,8 +26,8 @@ }, "dependencies": { "dd-trace": "^5.0.0", - "parabol-client": "8.1.1", - "parabol-server": "8.1.1", + "parabol-client": "8.2.0", + "parabol-server": "8.2.0", "undici": "^5.26.2" } } diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index 9a942908a83..f8b41436793 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -2,7 +2,7 @@ "name": "integration-tests", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.1", + "version": "8.2.0", "description": "", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index a803ca55381..f54349f51cc 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.1.1", + "version": "8.2.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" @@ -120,7 +120,7 @@ "oauth-1.0a": "^2.2.6", "openai": "^4.53.0", "oy-vey": "^0.12.1", - "parabol-client": "8.1.1", + "parabol-client": "8.2.0", "pg": "^8.5.1", "react": "^17.0.2", "react-dom": "^17.0.2", From 1b36b181874d56dd59b531c100d3b56e102699ae Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Tue, 29 Oct 2024 14:55:37 -0700 Subject: [PATCH 11/19] fix: latestMeeting query (#10429) Signed-off-by: Matt Krick --- .../server/dataloader/customLoaderMakers.ts | 34 +++++++++++++------ packages/server/postgres/select.ts | 14 ++------ packages/server/postgres/types/index.d.ts | 10 ++++++ 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/packages/server/dataloader/customLoaderMakers.ts b/packages/server/dataloader/customLoaderMakers.ts index e7df1f4a523..da562a0416c 100644 --- a/packages/server/dataloader/customLoaderMakers.ts +++ b/packages/server/dataloader/customLoaderMakers.ts @@ -3,6 +3,7 @@ import {Selectable, SqlBool, sql} from 'kysely' import {PARABOL_AI_USER_ID} from '../../client/utils/constants' import MeetingTemplate from '../database/types/MeetingTemplate' import getFileStoreManager from '../fileStorage/getFileStoreManager' +import isValid from '../graphql/isValid' import {ReactableEnum} from '../graphql/public/resolverTypes' import {SAMLSource} from '../graphql/public/types/SAML' import getKysely from '../postgres/getKysely' @@ -35,6 +36,7 @@ import isUserVerified from '../utils/isUserVerified' import NullableDataLoader from './NullableDataLoader' import RootDataLoader, {RegisterDependsOn} from './RootDataLoader' import normalizeArrayResults from './normalizeArrayResults' +import normalizeResults from './normalizeResults' export interface MeetingSettingsKey { teamId: string meetingType: MeetingTypeEnum @@ -584,16 +586,28 @@ export const lastMeetingByMeetingSeriesId = ( dependsOn('newMeetings') return new DataLoader( async (keys) => { - return await Promise.all( - keys.map(async (key) => { - const latestMeeting = await selectNewMeetings() - .where('meetingSeriesId', '=', key) - .orderBy('createdAt desc') - .limit(1) - .executeTakeFirst() - return latestMeeting || null - }) - ) + const meetingIdRes = await getKysely() + .with('LastMeetings', (qc) => + qc + .selectFrom('NewMeeting') + .select([ + 'id', + 'meetingSeriesId', + 'createdAt', + sql`ROW_NUMBER() OVER (PARTITION BY "meetingSeriesId" ORDER BY "createdAt" DESC)`.as( + 'rn' + ) + ]) + .where('meetingSeriesId', 'in', keys) + ) + .selectFrom('LastMeetings') + .select('id') + .where('rn', '=', 1) + .execute() + + const meetingIds = meetingIdRes.map(({id}) => id) + const meetings = (await parent.get('newMeetings').loadMany(meetingIds)).filter(isValid) + return normalizeResults(keys, meetings, 'meetingSeriesId') }, { ...parent.dataLoaderOptions diff --git a/packages/server/postgres/select.ts b/packages/server/postgres/select.ts index bb22dce175c..efae11cccfb 100644 --- a/packages/server/postgres/select.ts +++ b/packages/server/postgres/select.ts @@ -2,7 +2,7 @@ import type {JSONContent} from '@tiptap/core' import {NotNull, sql} from 'kysely' import {NewMeetingPhaseTypeEnum} from '../graphql/public/resolverTypes' import getKysely from './getKysely' -import {ReactjiDB, TaskTag} from './types' +import {JiraDimensionField, ReactjiDB, TaskTag} from './types' import {AnyMeeting, AnyMeetingMember} from './types/Meeting' import {AnyNotification} from './types/Notification' import {AnyTaskIntegration} from './types/TaskIntegration' @@ -90,17 +90,7 @@ export const selectTeams = () => 'updatedAt' ]) .select(({fn}) => [ - fn< - { - dimensionName: string - cloudId: string - projectKey: string - issueKey: string - fieldName: string - fieldType: string - fieldId: string - }[] - >('to_json', ['jiraDimensionFields']).as('jiraDimensionFields') + fn('to_json', ['jiraDimensionFields']).as('jiraDimensionFields') ]) export const selectRetroReflections = () => diff --git a/packages/server/postgres/types/index.d.ts b/packages/server/postgres/types/index.d.ts index 2cf883166e1..a91a82d3101 100644 --- a/packages/server/postgres/types/index.d.ts +++ b/packages/server/postgres/types/index.d.ts @@ -33,6 +33,16 @@ type ExtractTypeFromQueryBuilderSelect any> = export type Discussion = Selectable export type ReactjiDB = {id: string; userId: string} +export type JiraDimensionField = { + dimensionName: string + cloudId: string + projectKey: string + issueKey: string + fieldName: string + fieldType: string + fieldId: string +} + export type UsedReactjis = Record export type TranscriptBlock = { speaker: string From 62b610a63e05fb5004473c0cbef0ddda8d42b471 Mon Sep 17 00:00:00 2001 From: Bruce Tian Date: Wed, 30 Oct 2024 09:45:47 -0700 Subject: [PATCH 12/19] chore(metrics): add metrics to identify who attempte to upgrade organization (#10432) --- .../graphql/public/mutations/createStripeSubscription.ts | 2 ++ packages/server/utils/analytics/analytics.ts | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/packages/server/graphql/public/mutations/createStripeSubscription.ts b/packages/server/graphql/public/mutations/createStripeSubscription.ts index 6b65428c4b2..c3754c0d2eb 100644 --- a/packages/server/graphql/public/mutations/createStripeSubscription.ts +++ b/packages/server/graphql/public/mutations/createStripeSubscription.ts @@ -1,4 +1,5 @@ import Stripe from 'stripe' +import {analytics} from '../../../utils/analytics/analytics' import {getUserId} from '../../../utils/authorization' import standardError from '../../../utils/standardError' import {getStripeManager} from '../../../utils/stripe' @@ -50,6 +51,7 @@ const createStripeSubscription: MutationResolvers['createStripeSubscription'] = const paymentIntent = latestInvoice.payment_intent as Stripe.PaymentIntent const clientSecret = paymentIntent.client_secret + analytics.organizationUpgradeAttempted(viewer, orgId) const data = {stripeSubscriptionClientSecret: clientSecret} return data } diff --git a/packages/server/utils/analytics/analytics.ts b/packages/server/utils/analytics/analytics.ts index 765e16efc66..28ff7432ab0 100644 --- a/packages/server/utils/analytics/analytics.ts +++ b/packages/server/utils/analytics/analytics.ts @@ -132,6 +132,7 @@ export type AnalyticsEvent = | 'Notification Email Sent' // org | 'Upgrade CTA Clicked' + | 'Organization Upgrade Attempted' | 'Organization Upgraded' | 'Downgrade Clicked' | 'Downgrade Continue Clicked' @@ -506,6 +507,10 @@ class Analytics { this.track(user, 'Upgrade CTA Clicked', {upgradeCTALocation}) } + organizationUpgradeAttempted = (user: AnalyticsUser, orgId: string) => { + this.track(user, 'Organization Upgrade Attempted', {orgId}) + } + organizationUpgraded = ( user: AnalyticsUser, upgradeEventProperties: OrgTierChangeEventProperties From 4f515eaa9f32d2dc038923a58f43216de583188a Mon Sep 17 00:00:00 2001 From: Bruce Tian Date: Wed, 30 Oct 2024 10:01:46 -0700 Subject: [PATCH 13/19] feat(orgAdmins): show total user & team counts (#10396) --- .../OrgBilling/OrgPlansAndBilling.tsx | 3 + .../components/OrgBilling/OrgUsage.tsx | 64 +++++++++++++++++++ .../OrganizationRow/OrganizationRow.tsx | 3 +- 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 packages/client/modules/userDashboard/components/OrgBilling/OrgUsage.tsx diff --git a/packages/client/modules/userDashboard/components/OrgBilling/OrgPlansAndBilling.tsx b/packages/client/modules/userDashboard/components/OrgBilling/OrgPlansAndBilling.tsx index 72a921ee61c..dee6eb069aa 100644 --- a/packages/client/modules/userDashboard/components/OrgBilling/OrgPlansAndBilling.tsx +++ b/packages/client/modules/userDashboard/components/OrgBilling/OrgPlansAndBilling.tsx @@ -12,6 +12,7 @@ import OrgBillingInvoices from './OrgBillingInvoices' import OrgPlanDrawer from './OrgPlanDrawer' import OrgPlans from './OrgPlans' import OrgPlansAndBillingHeading from './OrgPlansAndBillingHeading' +import OrgUsage from './OrgUsage' import PaymentDetails from './PaymentDetails' type Props = { @@ -50,6 +51,7 @@ const OrgPlansAndBilling = (props: Props) => { ...BillingLeaders_organization ...PaymentDetails_organization ...OrgPlanDrawer_organization + ...OrgUsage_organization id billingTier isBillingLeader @@ -92,6 +94,7 @@ const OrgPlansAndBilling = (props: Props) => {
+ {billingTier === 'enterprise' && } {isBillingLeader && billingTier === 'team' && ( <> diff --git a/packages/client/modules/userDashboard/components/OrgBilling/OrgUsage.tsx b/packages/client/modules/userDashboard/components/OrgBilling/OrgUsage.tsx new file mode 100644 index 00000000000..86034698525 --- /dev/null +++ b/packages/client/modules/userDashboard/components/OrgBilling/OrgUsage.tsx @@ -0,0 +1,64 @@ +import graphql from 'babel-plugin-relay/macro' +import React from 'react' +import {useFragment} from 'react-relay' +import {OrgUsage_organization$key} from '../../../../__generated__/OrgUsage_organization.graphql' +import Panel from '../../../../components/Panel/Panel' +import useRouter from '../../../../hooks/useRouter' + +interface Props { + organizationRef: OrgUsage_organization$key +} + +const OrgUsage = (props: Props) => { + const {organizationRef} = props + const organization = useFragment( + graphql` + fragment OrgUsage_organization on Organization { + id + allTeamsCount + orgUserCount { + activeUserCount + inactiveUserCount + } + } + `, + organizationRef + ) + + const {id: orgId, allTeamsCount, orgUserCount} = organization + const totalUserCount = orgUserCount.activeUserCount + orgUserCount.inactiveUserCount + const {history} = useRouter() + + return ( + + + + ) +} + +export default OrgUsage diff --git a/packages/client/modules/userDashboard/components/OrganizationRow/OrganizationRow.tsx b/packages/client/modules/userDashboard/components/OrganizationRow/OrganizationRow.tsx index 2032ba8a87c..c3cf18a3a59 100644 --- a/packages/client/modules/userDashboard/components/OrganizationRow/OrganizationRow.tsx +++ b/packages/client/modules/userDashboard/components/OrganizationRow/OrganizationRow.tsx @@ -140,7 +140,8 @@ const OrganizationRow = (props: Props) => { )} - {`${totalUsers} ${plural(totalUsers, 'User')} (${activeUserCount} Active)`} + {`${totalUsers} ${plural(totalUsers, 'User')}`} + {billingTier !== 'enterprise' && ` (${activeUserCount} Active)`} From f10b58e661a5bc04a67d36c78ade68fde472bf47 Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Thu, 31 Oct 2024 09:02:22 -0700 Subject: [PATCH 14/19] fix: reset retro group safely (#10431) Signed-off-by: Matt Krick --- .../mutations/resetRetroMeetingToGroupStage.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/server/graphql/mutations/resetRetroMeetingToGroupStage.ts b/packages/server/graphql/mutations/resetRetroMeetingToGroupStage.ts index 5a52a2f05e8..498b8fb592a 100644 --- a/packages/server/graphql/mutations/resetRetroMeetingToGroupStage.ts +++ b/packages/server/graphql/mutations/resetRetroMeetingToGroupStage.ts @@ -110,13 +110,14 @@ const resetRetroMeetingToGroupStage = { .where('discussionId', 'in', discussionIdsToDelete) .execute() } + if (reflectionGroupIds.length > 0) { + await pg + .updateTable('RetroReflectionGroup') + .set({voterIds: [], discussionPromptQuestion: null}) + .where('id', 'in', reflectionGroupIds) + .execute() + } await pg - .with('ResetGroups', (qb) => - qb - .updateTable('RetroReflectionGroup') - .set({voterIds: [], discussionPromptQuestion: null}) - .where('id', 'in', reflectionGroupIds) - ) .with('ResetMeetingMember', (qb) => qb .updateTable('MeetingMember') From 90403c63a962b560cfe76ba864859abb25613b21 Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Thu, 31 Oct 2024 09:59:21 -0700 Subject: [PATCH 15/19] fix: throw on migration error (#10439) Signed-off-by: Matt Krick --- scripts/toolboxSrc/preDeploy.ts | 16 +++++++++++----- scripts/toolboxSrc/standaloneMigrations.ts | 13 +++++++------ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/scripts/toolboxSrc/preDeploy.ts b/scripts/toolboxSrc/preDeploy.ts index 68f34ee0430..4941efe88fb 100644 --- a/scripts/toolboxSrc/preDeploy.ts +++ b/scripts/toolboxSrc/preDeploy.ts @@ -1,6 +1,7 @@ import dotenv from 'dotenv' import dotenvExpand from 'dotenv-expand' import getKysely from 'parabol-server/postgres/getKysely' +import {Logger} from 'parabol-server/utils/Logger' import path from 'path' import queryMap from '../../queryMap.json' import getProjectRoot from '../webpack/utils/getProjectRoot' @@ -12,7 +13,7 @@ import standaloneMigrations from './standaloneMigrations' const PROJECT_ROOT = getProjectRoot() const storePersistedQueries = async () => { - console.log('🔗 QueryMap Persistence Started') + Logger.log('🔗 QueryMap Persistence Started') const hashes = Object.keys(queryMap) const now = new Date() const records = hashes.map((hash) => ({ @@ -22,8 +23,13 @@ const storePersistedQueries = async () => { })) const pg = getKysely() - const res = await pg.insertInto('QueryMap').values(records).onConflict((oc) => oc.doNothing()).returning('id').execute() - console.log(`🔗 QueryMap Persistence Complete: ${res.length} records added`) + const res = await pg + .insertInto('QueryMap') + .values(records) + .onConflict((oc) => oc.doNothing()) + .returning('id') + .execute() + Logger.log(`🔗 QueryMap Persistence Complete: ${res.length} records added`) } const preDeploy = async () => { @@ -31,14 +37,14 @@ const preDeploy = async () => { const envPath = path.join(PROJECT_ROOT, '.env') const myEnv = dotenv.config({path: envPath}) dotenvExpand(myEnv) - console.log(`🚀 Predeploy Started v${__APP_VERSION__} sha:${__COMMIT_HASH__}`) + Logger.log(`🚀 Predeploy Started v${__APP_VERSION__} sha:${__COMMIT_HASH__}`) // first we migrate DBs & add env vars to client assets await Promise.all([standaloneMigrations(), applyEnvVarsToClientAssets()]) // The we can prime the DB & CDN await Promise.all([storePersistedQueries(), primeIntegrations(), pushToCDN()]) await getKysely().destroy() - console.log(`🚀 Predeploy Complete`) + Logger.log(`🚀 Predeploy Complete`) process.exit() } diff --git a/scripts/toolboxSrc/standaloneMigrations.ts b/scripts/toolboxSrc/standaloneMigrations.ts index ca7b1f7eddc..88b9559a1d6 100644 --- a/scripts/toolboxSrc/standaloneMigrations.ts +++ b/scripts/toolboxSrc/standaloneMigrations.ts @@ -2,6 +2,7 @@ // This file is bundled by webpack into a small migrate.js file which includes all migration files & their deps // It is used by PPMIs who are only provided with the bundles import {Migrator} from 'kysely' +import {Logger} from 'parabol-server/utils/Logger' import path from 'path' import {migrations} from '../../.config/kyselyMigrations' import getKysely from '../../packages/server/postgres/getKysely' @@ -9,7 +10,7 @@ import '../webpack/utils/dotenv' import pgEnsureExtensions from './pgEnsureExtensions' const migratePG = async () => { - console.log('🐘 Postgres Migration Started') + Logger.log('🐘 Postgres Migration Started') await pgEnsureExtensions() // pgm uses a dynamic require statement, which doesn't work with webpack // if we ignore that dynamic require, we'd still have to include the migrations directory AND any dependencies it might have @@ -38,17 +39,17 @@ const migratePG = async () => { results?.forEach((it) => { if (it.status === 'Success') { - console.log(` ✅ Migration: ${it.migrationName}`) + Logger.log(` ✅ Migration: ${it.migrationName}`) } else if (it.status === 'Error') { - console.error(` ⛔️ Migration: ${it.migrationName}`) + Logger.error(` ⛔️ Migration: ${it.migrationName}`) } }) if (error) { - console.log('🐘 Postgres Migration Failed') - console.error(error) + Logger.log('🐘 Postgres Migration Failed') + throw error } else { - console.log('🐘 Postgres Migration Complete') + Logger.log('🐘 Postgres Migration Complete') } } From 28705932785072e5bfac4e49b1101bd31392416c Mon Sep 17 00:00:00 2001 From: "parabol-release-bot[bot]" <150284312+parabol-release-bot[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:03:06 -0700 Subject: [PATCH 16/19] chore(release): release v8.3.0 (#10430) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 19 +++++++++++++++++++ package.json | 2 +- packages/chronos/package.json | 4 ++-- packages/client/package.json | 2 +- packages/embedder/package.json | 2 +- packages/gql-executor/package.json | 6 +++--- packages/integration-tests/package.json | 2 +- packages/server/package.json | 4 ++-- 9 files changed, 31 insertions(+), 12 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f59c11ca844..8d48393bbc6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "8.2.0" + ".": "8.3.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d50ff4024c..ed0125fea71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,25 @@ This project adheres to [Semantic Versioning](http://semver.org/). This CHANGELOG follows conventions [outlined here](http://keepachangelog.com/). +## [8.3.0](https://github.com/ParabolInc/parabol/compare/v8.2.0...v8.3.0) (2024-10-31) + + +### Added + +* **orgAdmins:** show total user & team counts ([#10396](https://github.com/ParabolInc/parabol/issues/10396)) ([4f515ea](https://github.com/ParabolInc/parabol/commit/4f515eaa9f32d2dc038923a58f43216de583188a)) + + +### Fixed + +* latestMeeting query ([#10429](https://github.com/ParabolInc/parabol/issues/10429)) ([1b36b18](https://github.com/ParabolInc/parabol/commit/1b36b181874d56dd59b531c100d3b56e102699ae)) +* reset retro group safely ([#10431](https://github.com/ParabolInc/parabol/issues/10431)) ([f10b58e](https://github.com/ParabolInc/parabol/commit/f10b58e661a5bc04a67d36c78ade68fde472bf47)) +* throw on migration error ([#10439](https://github.com/ParabolInc/parabol/issues/10439)) ([90403c6](https://github.com/ParabolInc/parabol/commit/90403c63a962b560cfe76ba864859abb25613b21)) + + +### Changed + +* **metrics:** add metrics to identify who attempte to upgrade organization ([#10432](https://github.com/ParabolInc/parabol/issues/10432)) ([62b610a](https://github.com/ParabolInc/parabol/commit/62b610a63e05fb5004473c0cbef0ddda8d42b471)) + ## [8.2.0](https://github.com/ParabolInc/parabol/compare/v8.1.1...v8.2.0) (2024-10-28) diff --git a/package.json b/package.json index 19b1dc47e79..e7e93708b9e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.2.0", + "version": "8.3.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/chronos/package.json b/packages/chronos/package.json index af3175a1432..6941b6534e0 100644 --- a/packages/chronos/package.json +++ b/packages/chronos/package.json @@ -1,6 +1,6 @@ { "name": "chronos", - "version": "8.2.0", + "version": "8.3.0", "description": "A cron job scheduler", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/chronos#readme", @@ -25,6 +25,6 @@ }, "dependencies": { "cron": "^2.3.1", - "parabol-server": "8.2.0" + "parabol-server": "8.3.0" } } diff --git a/packages/client/package.json b/packages/client/package.json index 888d9563e55..1c8be883a55 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.2.0", + "version": "8.3.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/embedder/package.json b/packages/embedder/package.json index 5a2edf1d852..d4b9c6589fe 100644 --- a/packages/embedder/package.json +++ b/packages/embedder/package.json @@ -1,6 +1,6 @@ { "name": "parabol-embedder", - "version": "8.2.0", + "version": "8.3.0", "description": "A service that computes embedding vectors from Parabol objects", "author": "Jordan Husney ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/embedder#readme", diff --git a/packages/gql-executor/package.json b/packages/gql-executor/package.json index 773dd26b3f7..33ae1a57e9c 100644 --- a/packages/gql-executor/package.json +++ b/packages/gql-executor/package.json @@ -1,6 +1,6 @@ { "name": "gql-executor", - "version": "8.2.0", + "version": "8.3.0", "description": "A Stateless GraphQL Executor", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/gqlExecutor#readme", @@ -26,8 +26,8 @@ }, "dependencies": { "dd-trace": "^5.0.0", - "parabol-client": "8.2.0", - "parabol-server": "8.2.0", + "parabol-client": "8.3.0", + "parabol-server": "8.3.0", "undici": "^5.26.2" } } diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index f8b41436793..d8606caa5b6 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -2,7 +2,7 @@ "name": "integration-tests", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.2.0", + "version": "8.3.0", "description": "", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index f54349f51cc..ea334220899 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.2.0", + "version": "8.3.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" @@ -120,7 +120,7 @@ "oauth-1.0a": "^2.2.6", "openai": "^4.53.0", "oy-vey": "^0.12.1", - "parabol-client": "8.2.0", + "parabol-client": "8.3.0", "pg": "^8.5.1", "react": "^17.0.2", "react-dom": "^17.0.2", From f50e32f5f740c42b722d2581c02c7467dfa9ff2e Mon Sep 17 00:00:00 2001 From: Georg Bremer Date: Mon, 4 Nov 2024 09:30:14 +0100 Subject: [PATCH 17/19] chore: Add Mattermost webhook handler (#10237) --- .env.example | 1 + .../typeDefs/PokerMeetingSettings.graphql | 2 +- .../mattermost/mattermostWebhookHandler.ts | 384 ++++++++++++++++++ packages/server/package.json | 3 + packages/server/server.ts | 2 + .../toolboxSrc/applyEnvVarsToClientAssets.ts | 2 +- scripts/webpack/dev.client.config.js | 2 +- yarn.lock | 51 ++- 8 files changed, 443 insertions(+), 4 deletions(-) create mode 100644 packages/server/integrations/mattermost/mattermostWebhookHandler.ts diff --git a/.env.example b/.env.example index b18b4544081..257d9c3b5a0 100644 --- a/.env.example +++ b/.env.example @@ -123,6 +123,7 @@ REDIS_URL='redis://localhost:6379' # STRIPE_PUBLISHABLE_KEY='' # STRIPE_WEBHOOK_SECRET='' # MATTERMOST_DISABLED='false' +# MATTERMOST_SECRET='' # MSTEAMS_DISABLED='false' # MAIL diff --git a/packages/server/graphql/public/typeDefs/PokerMeetingSettings.graphql b/packages/server/graphql/public/typeDefs/PokerMeetingSettings.graphql index abfd95c3fbc..92bb55a5f17 100644 --- a/packages/server/graphql/public/typeDefs/PokerMeetingSettings.graphql +++ b/packages/server/graphql/public/typeDefs/PokerMeetingSettings.graphql @@ -1,5 +1,5 @@ """ -The retro-specific meeting settings +The poker-specific meeting settings """ type PokerMeetingSettings implements TeamMeetingSettings { id: ID! diff --git a/packages/server/integrations/mattermost/mattermostWebhookHandler.ts b/packages/server/integrations/mattermost/mattermostWebhookHandler.ts new file mode 100644 index 00000000000..97b1749cf25 --- /dev/null +++ b/packages/server/integrations/mattermost/mattermostWebhookHandler.ts @@ -0,0 +1,384 @@ +import {createVerifier, httpbis} from 'http-message-signatures' +import {markdownToDraft} from 'markdown-draft-js' +import {Variables} from 'relay-runtime' +import {HttpRequest, HttpResponse} from 'uWebSockets.js' +import AuthToken from '../../database/types/AuthToken' +import uWSAsyncHandler from '../../graphql/uWSAsyncHandler' +import parseBody from '../../parseBody' +import getKysely from '../../postgres/getKysely' +import getGraphQLExecutor from '../../utils/getGraphQLExecutor' +import sendToSentry from '../../utils/sendToSentry' + +const MATTERMOST_SECRET = process.env.MATTERMOST_SECRET +const PORT = __PRODUCTION__ ? process.env.PORT : process.env.SOCKET_PORT +const HOST = process.env.HOST +const PORT_SUFFIX = HOST !== 'localhost' ? '' : `:${PORT}` +const ORIGIN = `${process.env.PROTO}://${HOST}${PORT_SUFFIX}` + +const markdownToDraftJS = (markdown: string) => { + const rawObject = markdownToDraft(markdown) + return JSON.stringify(rawObject) +} + +const eventLookup: Record< + string, + { + query: string + convertResult?: (data: any) => any + convertInput?: (input: any) => any + } +> = { + meetingTemplates: { + query: ` + query MeetingTemplates { + viewer { + availableTemplates(first: 2000) { + edges { + node { + id + name + type + illustrationUrl + orgId + teamId + scope + } + } + } + teams { + id + name + orgId + retroSettings: meetingSettings(meetingType: retrospective) { + id + phaseTypes + ...on RetrospectiveMeetingSettings { + disableAnonymity + } + } + pokerSettings: meetingSettings(meetingType: poker) { + id + phaseTypes + } + actionSettings: meetingSettings(meetingType: action) { + id + phaseTypes + } + } + } + } + `, + convertResult: (data: any) => { + const restructured = { + availableTemplates: data.viewer.availableTemplates.edges.map((edge: any) => edge.node), + teams: data.viewer.teams + } + return restructured + } + }, + startRetrospective: { + query: ` + mutation StartRetrospective( + $teamId: ID! + $templateId: ID! + ) { + selectTemplate(selectedTemplateId: $templateId, teamId: $teamId) { + meetingSettings { + id + } + } + startRetrospective(teamId: $teamId) { + ... on ErrorPayload { + error { + message + } + } + } + } + ` + }, + startCheckIn: { + query: ` + mutation StartCheckIn($teamId: ID!) { + startCheckIn(teamId: $teamId) { + ... on ErrorPayload { + error { + message + } + } + ... on StartCheckInSuccess { + meeting { + id + } + } + } + } + ` + }, + startSprintPoker: { + query: ` + mutation StartSprintPokerMutation( + $teamId: ID! + $templateId: ID! + ) { + selectTemplate(selectedTemplateId: $templateId, teamId: $teamId) { + meetingSettings { + id + } + } + startSprintPoker(teamId: $teamId) { + ... on ErrorPayload { + error { + message + } + } + ... on StartSprintPokerSuccess { + meeting { + id + } + } + } + } + ` + }, + startTeamPrompt: { + query: ` + mutation StartTeamPromptMutation( + $teamId: ID! + ) { + startTeamPrompt(teamId: $teamId) { + ... on ErrorPayload { + error { + message + } + } + ...on StartTeamPromptSuccess { + meeting { + id + } + } + } + } + ` + }, + getMeetingSettings: { + query: ` + query GetMeetingSettings($teamId: ID!, $meetingType: MeetingTypeEnum!) { + viewer { + team(teamId: $teamId) { + meetingSettings(meetingType: $meetingType) { + id + phaseTypes + ...on RetrospectiveMeetingSettings { + disableAnonymity + } + } + } + } + } + `, + convertResult: (data: any) => { + const {meetingSettings} = data.viewer.team + return { + id: meetingSettings.id, + checkinEnabled: meetingSettings.phaseTypes.includes('checkin'), + teamHealthEnabled: meetingSettings.phaseTypes.includes('TEAM_HEALTH'), + disableAnonymity: meetingSettings.disableAnonymity + } + } + }, + setMeetingSettings: { + query: ` + mutation SetMeetingSettings( + $id: ID! + $checkinEnabled: Boolean + $teamHealthEnabled: Boolean + $disableAnonymity: Boolean + ) { + setMeetingSettings( + settingsId: $id + checkinEnabled: $checkinEnabled + teamHealthEnabled: $teamHealthEnabled + disableAnonymity: $disableAnonymity + ) { + settings { + id + phaseTypes + ... on RetrospectiveMeetingSettings { + disableAnonymity + } + } + } + } + `, + convertResult: (data: any) => { + const {settings: meetingSettings} = data.setMeetingSettings + return { + id: meetingSettings.id, + checkinEnabled: meetingSettings.phaseTypes.includes('checkin'), + teamHealthEnabled: meetingSettings.phaseTypes.includes('TEAM_HEALTH'), + disableAnonymity: meetingSettings.disableAnonymity + } + } + }, + getActiveMeetings: { + query: ` + query Meetings { + viewer { + teams { + activeMeetings { + id + teamId + name + meetingType + ...on RetrospectiveMeeting { + phases { + ...on ReflectPhase { + reflectPrompts { + id + question + description + } + stages { + isComplete + } + } + } + templateId + } + } + } + } + } + `, + convertResult: (data: any) => { + const activeMeetings = data.viewer.teams.flatMap((team: any) => team.activeMeetings) + return activeMeetings.map((meeting: any) => { + const {phases, ...rest} = meeting + const reflectPhase = phases?.find((phase: any) => 'reflectPrompts' in phase) + if (!reflectPhase) return rest + const isComplete = !reflectPhase.stages.some((stage: any) => !stage.isComplete) + return { + ...rest, + reflectPrompts: reflectPhase.reflectPrompts, + isComplete + } + }) + } + }, + createReflection: { + convertInput: (variables: any) => { + const {content, ...rest} = variables + return { + input: { + content: markdownToDraftJS(content), + ...rest + } + } + }, + query: ` + mutation CreateReflectionMutation($input: CreateReflectionInput!) { + createReflection(input: $input) { + reflectionId + } + } + ` + } +} + +const publishWebhookGQL = async ( + query: string, + variables: Variables, + email: string +) => { + const pg = getKysely() + const user = await pg + .selectFrom('User') + .selectAll() + .where('email', '=', email) + .executeTakeFirstOrThrow() + try { + const authToken = new AuthToken({sub: user.id, tms: user.tms}) + return await getGraphQLExecutor().publish({ + authToken, + query, + variables, + isPrivate: false + }) + } catch (e) { + const error = e instanceof Error ? e : new Error('GQL executor failed to publish') + sendToSentry(error, {tags: {query: query.slice(0, 50)}}) + return undefined + } +} + +const mattermostWebhookHandler = uWSAsyncHandler(async (res: HttpResponse, req: HttpRequest) => { + if (!MATTERMOST_SECRET) { + res.writeStatus('404').end() + return + } + const headers = { + 'content-type': req.getHeader('content-type'), + 'content-digest': req.getHeader('content-digest'), + 'content-length': req.getHeader('content-length'), + signature: req.getHeader('signature'), + 'signature-input': req.getHeader('signature-input') + } + + const verified = await httpbis.verifyMessage( + { + async keyLookup(_: any) { + // TODO When we support multiple Parabol - Mattermost connections, we should look up the key from IntegrationProvider + // const keyId = params.keyid; + return { + id: '', + algs: ['hmac-sha256'], + verify: createVerifier(MATTERMOST_SECRET, 'hmac-sha256') + } + } + }, + { + method: req.getMethod(), + url: ORIGIN + req.getUrl(), + headers + } + ) + if (!verified) { + res.writeStatus('401').end() + return + } + + const body = await parseBody<{query: string; variables: Record; email: string}>({ + res + }) + + const {query, variables, email} = body ?? {} + if (!email) { + res.writeStatus('401').end() + return + } + if (!query) { + res.writeStatus('400').end() + return + } + + const event = eventLookup[query as keyof typeof eventLookup] + if (!event) { + sendToSentry(new Error('Received unknown mattermost webhook event'), {tags: {query: query!}}) + res.writeStatus('400').end() + return + } + const convertedInput = event.convertInput?.(variables) ?? variables + const result = await publishWebhookGQL<{data: any}>(event.query, convertedInput, email) + if (result?.data) { + const convertedResult = event.convertResult?.(result.data) ?? result.data + res + .writeStatus('200') + .writeHeader('Content-Type', 'application/json') + .end(JSON.stringify(convertedResult)) + } else { + res.writeStatus('500').end() + } +}) + +export default mattermostWebhookHandler diff --git a/packages/server/package.json b/packages/server/package.json index ea334220899..26395877ecd 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -38,6 +38,7 @@ "@types/jest": "^29.5.1", "@types/json2csv": "^5.0.3", "@types/jsonwebtoken": "^8.3.0", + "@types/markdown-draft-js": "^2.2.7", "@types/mime-types": "^2.1.0", "@types/ms": "^0.7.30", "@types/node": "^20.11.17", @@ -105,6 +106,7 @@ "graphql-relay": "^0.10.0", "graphql-shield": "^7.5.0", "html-minifier-terser": "^5.0.2", + "http-message-signatures": "^1.0.4", "immutable": "3.8.2", "ioredis": "^5.2.3", "jsdom": "^20.0.0", @@ -112,6 +114,7 @@ "lodash.pick": "^4.4.0", "mailcomposer": "^4.0.1", "mailgun.js": "^9.3.0", + "markdown-draft-js": "^2.4.0", "mime-types": "^2.1.16", "ms": "^2.0.0", "nest-graphql-endpoint": "0.8.1", diff --git a/packages/server/server.ts b/packages/server/server.ts index 7a97eadb084..668fb2f015c 100644 --- a/packages/server/server.ts +++ b/packages/server/server.ts @@ -9,6 +9,7 @@ import createSSR from './createSSR' import httpGraphQLHandler from './graphql/httpGraphQLHandler' import intranetGraphQLHandler from './graphql/intranetGraphQLHandler' import './initSentry' +import mattermostWebhookHandler from './integrations/mattermost/mattermostWebhookHandler' import jiraImagesHandler from './jiraImagesHandler' import listenHandler from './listenHandler' import './monkeyPatchFetch' @@ -61,6 +62,7 @@ uws .get('/jira-attachments/:fileName', jiraImagesHandler) .post('/sse-ping', SSEPingHandler) .post('/stripe', stripeWebhookHandler) + .post('/mattermost', mattermostWebhookHandler) .post('/graphql', httpGraphQLHandler) .post('/intranet-graphql', intranetGraphQLHandler) .post('/saml/:domain', SAMLHandler) diff --git a/scripts/toolboxSrc/applyEnvVarsToClientAssets.ts b/scripts/toolboxSrc/applyEnvVarsToClientAssets.ts index 64fc00b923d..16fce913f6e 100644 --- a/scripts/toolboxSrc/applyEnvVarsToClientAssets.ts +++ b/scripts/toolboxSrc/applyEnvVarsToClientAssets.ts @@ -55,7 +55,7 @@ const rewriteIndexHTML = () => { github: process.env.GITHUB_CLIENT_ID, google: process.env.GOOGLE_OAUTH_CLIENT_ID, googleAnalytics: process.env.GA_TRACKING_ID, - mattermostDisabled: process.env.MATTERMOST_DISABLED === 'true', + mattermostDisabled: !!process.env.MATTERMOST_SECRET || process.env.MATTERMOST_DISABLED === 'true', msTeamsDisabled: process.env.MSTEAMS_DISABLED === 'true', sentry: process.env.SENTRY_DSN, slack: process.env.SLACK_CLIENT_ID, diff --git a/scripts/webpack/dev.client.config.js b/scripts/webpack/dev.client.config.js index 5ba6b1dc9da..10117087193 100644 --- a/scripts/webpack/dev.client.config.js +++ b/scripts/webpack/dev.client.config.js @@ -119,7 +119,7 @@ module.exports = { github: process.env.GITHUB_CLIENT_ID, google: process.env.GOOGLE_OAUTH_CLIENT_ID, googleAnalytics: process.env.GA_TRACKING_ID, - mattermostDisabled: process.env.MATTERMOST_DISABLED === 'true', + mattermostDisabled: !!process.env.MATTERMOST_SECRET || process.env.MATTERMOST_DISABLED === 'true', msTeamsDisabled: process.env.MSTEAMS_DISABLED === 'true', sentry: process.env.SENTRY_DSN, slack: process.env.SLACK_CLIENT_ID, diff --git a/yarn.lock b/yarn.lock index 3e85252abe0..88eec3abd86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8931,6 +8931,14 @@ dependencies: "@types/node" "*" +"@types/draft-js@*": + version "0.11.18" + resolved "https://registry.yarnpkg.com/@types/draft-js/-/draft-js-0.11.18.tgz#f2cad2178987fdd444827a2f7809a653f82a70ad" + integrity sha512-lP6yJ+EKv5tcG1dflWgDKeezdwBa8wJ7KkiNrrHqXuXhl/VGes1SKjEfKHDZqOz19KQbrAhFvNhDPWwnQXYZGQ== + dependencies: + "@types/react" "*" + immutable "~3.7.4" + "@types/draft-js@^0.10.24": version "0.10.45" resolved "https://registry.yarnpkg.com/@types/draft-js/-/draft-js-0.10.45.tgz#4ab5b0785fcacdea7d5a836d0024158fa8108e70" @@ -9188,6 +9196,13 @@ resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.3.0.tgz#a61043a62c0a72696c73a0a305c544c96501e006" integrity sha512-uKRI5QORDnrGFYgcdAVnHvEIvEZ8noTpP/Bg+HeUzZghwinDlIS87DEenV5r1YoOF9G4x600YsUXLWZ19rmTmg== +"@types/markdown-draft-js@^2.2.7": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@types/markdown-draft-js/-/markdown-draft-js-2.2.7.tgz#5ac700f307cc80e8b5e58f5f33366f317b8858a0" + integrity sha512-EXnEi36xa9m7HH4O1yH6Sp8zd29u4nDzKvtNPt0QSRDjGSC33UcyFVQ86D4GGEVnUlbB0ySm6eXZTAjekVKpNA== + dependencies: + "@types/draft-js" "*" + "@types/mime-types@^2.1.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.1.tgz#d9ba43490fa3a3df958759adf69396c3532cf2c1" @@ -10308,7 +10323,7 @@ arg@^5.0.2: resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== -argparse@^1.0.7: +argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -10485,6 +10500,13 @@ auto-bind@~4.0.0: resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== +autolinker@^3.11.0: + version "3.16.2" + resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-3.16.2.tgz#6bb4f32432fc111b65659336863e653973bfbcc9" + integrity sha512-JiYl7j2Z19F9NdTmirENSUUIIL/9MytEWtmzhfmsKPCp9E+G35Y0UNCMoM9tFigxT59qSc8Ml2dlZXOCVTYwuA== + dependencies: + tslib "^2.3.0" + autoprefixer@^10.4.13: version "10.4.13" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" @@ -14996,6 +15018,13 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" +http-message-signatures@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/http-message-signatures/-/http-message-signatures-1.0.4.tgz#3d1f614977d3a435af7c1d35a75e1e48d9094075" + integrity sha512-gavCQWnxHFg0BVlKs6CmYK7hNSH1o0x0mHTC68yBAHYOYuTVXPv52mEE7QuT5TenfiagTdOa/zPJzen4lEX7Rg== + dependencies: + structured-headers "^1.0.1" + http-parser-js@>=0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" @@ -17361,6 +17390,13 @@ map-obj@^4.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== +markdown-draft-js@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/markdown-draft-js/-/markdown-draft-js-2.4.0.tgz#164c53be05a96b3a7864cdd0fc3e51166726d01e" + integrity sha512-MalOqajYYaELKLPHLnUcaU7kwhIHveVdKd15SKBkDkWj1NBLHuM5uZjXQ5TDfM4rrk4tcAzIvwWhCJzdGNcmkg== + dependencies: + remarkable "^2.0.1" + markdown-it@^12.2.0: version "12.3.2" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" @@ -20749,6 +20785,14 @@ relay-runtime@^14.1.0: fbjs "^3.0.2" invariant "^2.2.4" +remarkable@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-2.0.1.tgz#280ae6627384dfb13d98ee3995627ca550a12f31" + integrity sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA== + dependencies: + argparse "^1.0.10" + autolinker "^3.11.0" + remedial@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0" @@ -22131,6 +22175,11 @@ strong-log-transformer@^2.1.0: minimist "^1.2.0" through "^2.3.4" +structured-headers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/structured-headers/-/structured-headers-1.0.1.tgz#1821e434e0fe45bdd78f07c779b16519ab520415" + integrity sha512-QYBxdBtA4Tl5rFPuqmbmdrS9kbtren74RTJTcs0VSQNVV5iRhJD4QlYTLD0+81SBwUQctjEQzjTRI3WG4DzICA== + stubs@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" From fb673457d6223eb00ebb66fa43368b3efb437e0f Mon Sep 17 00:00:00 2001 From: Nick O'Ferrall Date: Mon, 4 Nov 2024 16:16:46 +0000 Subject: [PATCH 18/19] fix: teamMember is nullable in generate insight (#10450) --- packages/server/graphql/public/mutations/generateInsight.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/graphql/public/mutations/generateInsight.ts b/packages/server/graphql/public/mutations/generateInsight.ts index 8fc2a78e40e..fff470fbac9 100644 --- a/packages/server/graphql/public/mutations/generateInsight.ts +++ b/packages/server/graphql/public/mutations/generateInsight.ts @@ -16,8 +16,8 @@ const generateInsight: MutationResolvers['generateInsight'] = async ( const {dataLoader, socketId: mutatorId, authToken} = context const viewerId = getUserId(authToken) const teamMemberId = toTeamMemberId(teamId, viewerId) - const teamMember = await dataLoader.get('teamMembers').loadNonNull(teamMemberId) - const isLead = teamMember.isLead + const teamMember = await dataLoader.get('teamMembers').load(teamMemberId) + const isLead = teamMember?.isLead if (!isLead && !isSuperUser(authToken)) { return standardError(new Error('Only team leads can generate insights'), {userId: viewerId}) } From 0878401922f0972d8dd1b209ef61522fb82022c4 Mon Sep 17 00:00:00 2001 From: "parabol-release-bot[bot]" <150284312+parabol-release-bot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:24:01 +0000 Subject: [PATCH 19/19] chore(release): release v8.3.1 (#10449) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- packages/chronos/package.json | 4 ++-- packages/client/package.json | 2 +- packages/embedder/package.json | 2 +- packages/gql-executor/package.json | 6 +++--- packages/integration-tests/package.json | 2 +- packages/server/package.json | 4 ++-- 9 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8d48393bbc6..b0034f9d074 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "8.3.0" + ".": "8.3.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index ed0125fea71..276f1be5440 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](http://semver.org/). This CHANGELOG follows conventions [outlined here](http://keepachangelog.com/). +## [8.3.1](https://github.com/ParabolInc/parabol/compare/v8.3.0...v8.3.1) (2024-11-04) + + +### Fixed + +* teamMember is nullable in generate insight ([#10450](https://github.com/ParabolInc/parabol/issues/10450)) ([fb67345](https://github.com/ParabolInc/parabol/commit/fb673457d6223eb00ebb66fa43368b3efb437e0f)) + + +### Changed + +* Add Mattermost webhook handler ([#10237](https://github.com/ParabolInc/parabol/issues/10237)) ([f50e32f](https://github.com/ParabolInc/parabol/commit/f50e32f5f740c42b722d2581c02c7467dfa9ff2e)) + ## [8.3.0](https://github.com/ParabolInc/parabol/compare/v8.2.0...v8.3.0) (2024-10-31) diff --git a/package.json b/package.json index e7e93708b9e..564a69a6aeb 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.3.0", + "version": "8.3.1", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/chronos/package.json b/packages/chronos/package.json index 6941b6534e0..7ac40d05ae2 100644 --- a/packages/chronos/package.json +++ b/packages/chronos/package.json @@ -1,6 +1,6 @@ { "name": "chronos", - "version": "8.3.0", + "version": "8.3.1", "description": "A cron job scheduler", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/chronos#readme", @@ -25,6 +25,6 @@ }, "dependencies": { "cron": "^2.3.1", - "parabol-server": "8.3.0" + "parabol-server": "8.3.1" } } diff --git a/packages/client/package.json b/packages/client/package.json index 1c8be883a55..4c8f394ef3d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.3.0", + "version": "8.3.1", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/embedder/package.json b/packages/embedder/package.json index d4b9c6589fe..17b3bf267d2 100644 --- a/packages/embedder/package.json +++ b/packages/embedder/package.json @@ -1,6 +1,6 @@ { "name": "parabol-embedder", - "version": "8.3.0", + "version": "8.3.1", "description": "A service that computes embedding vectors from Parabol objects", "author": "Jordan Husney ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/embedder#readme", diff --git a/packages/gql-executor/package.json b/packages/gql-executor/package.json index 33ae1a57e9c..a4db676f914 100644 --- a/packages/gql-executor/package.json +++ b/packages/gql-executor/package.json @@ -1,6 +1,6 @@ { "name": "gql-executor", - "version": "8.3.0", + "version": "8.3.1", "description": "A Stateless GraphQL Executor", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/gqlExecutor#readme", @@ -26,8 +26,8 @@ }, "dependencies": { "dd-trace": "^5.0.0", - "parabol-client": "8.3.0", - "parabol-server": "8.3.0", + "parabol-client": "8.3.1", + "parabol-server": "8.3.1", "undici": "^5.26.2" } } diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index d8606caa5b6..90a42bce389 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -2,7 +2,7 @@ "name": "integration-tests", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.3.0", + "version": "8.3.1", "description": "", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index 26395877ecd..8792841b77a 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "8.3.0", + "version": "8.3.1", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" @@ -123,7 +123,7 @@ "oauth-1.0a": "^2.2.6", "openai": "^4.53.0", "oy-vey": "^0.12.1", - "parabol-client": "8.3.0", + "parabol-client": "8.3.1", "pg": "^8.5.1", "react": "^17.0.2", "react-dom": "^17.0.2",