From 75a567618b3c783c5f3730fba8be2e76ae3f7809 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 08:39:44 -0800 Subject: [PATCH] chore(release): Test v7.20.0 (#9488) * chore(env vars): Stripe vars moved to the Integrations section (#9427) * chore: fix misleading `isLead` field name on `Team` (#9413) * chore: fix misleading `isLead` field name on `Team` The field indicates whether the viewer is the lead, but when used in a query for a different user, the result could be read wrong. * Fix Team.isLead dependencies * feat: remove team template limit (#9424) * update error message and increase template limit * remove max team template limits * remove canClone prop from CloneTemplate * remove unused threshold * remove unused threshold * feat: Add Google calendar meeting series for recurrence (#9380) * feat: Add recurrence to GCal events * Fun with timezones * fix: Increase the number of projects fetched per request from Atlassian (#9435) We ran into timeouts in `getAllProjects`, presumably because we're doing too many roundtrips. As a quick fix, increse the number of projects fetched per request from 50 to 500. * chore(deps): bump ip from 1.1.8 to 1.1.9 (#9442) Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9. - [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9) --- updated-dependencies: - dependency-name: ip dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(release): release v7.17.0 (#9428) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * feat(standalone-deployment): Standalone host deployment improved and documented (#9445) * Docker compose stack improved * Remove unused containers from docker-compse and add useful comment on .env.example about PGSSLMODE * Docker compose profiles added. Documentation extended on how to use the profiles to manage the stack. * README fixed as docker compose up and down commands were not working * Typo fixed and docker-compose command replaced by docker compose * feat: support env-defined saml issuer for PPMIs (#9455) * feat: support env-defined saml issuer for PPMIs Signed-off-by: Matt Krick * feat: support single SAML for entire tenant Signed-off-by: Matt Krick --------- Signed-off-by: Matt Krick * chore: Associate logs with traces (#9444) * chore: Associate logs with traces Add trace information to log output for server side log statements. This does not include logging from code exclusively used for debugging, deploying or development. * Actually add the logger * Fix DD_LOGS_INJECTION check * chore(release): release v7.18.0 (#9450) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * chore: no force-push to prod (#9401) Signed-off-by: Matt Krick * chore(release): release v7.18.1 (#9459) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * feat: embedder service (#9417) * feat: add embedder service --------- Signed-off-by: Matt Krick Co-authored-by: Matt Krick * merge production to avoid force push (#9461) Signed-off-by: Matt Krick * chore(release): release v7.19.0 (#9460) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * fix: checkout prod before merging it (#9463) Signed-off-by: Matt Krick * chore(release): release v7.19.1 (#9464) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * fix: mrege origin/production strategy (#9465) Signed-off-by: Matt Krick * chore(release): release v7.19.2 (#9466) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * fix: force push 5 (#9467) Signed-off-by: Matt Krick * chore(release): release v7.19.3 (#9468) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * fix: limit invites from spammers (#9416) * fix: limit invites from spammers * update where we check pending emails * check total plus pending invites * use invitees instead of pending * fix: Fetch Jira projects in parallel (#9456) Previously we tried to fetch more projects per page, but Jira only ever returns 50 max. Instead once we know how many projects there are after fetching the first page, we fetch all remaining pages in parallel. * fix: replace lone surrogates in draft-js content (#9415) * fix: replace lone surrogates in draft-js content Signed-off-by: Matt Krick * fix typo Signed-off-by: Matt Krick * fix: eslint errors Signed-off-by: Matt Krick --------- Signed-off-by: Matt Krick * chore(deps): bump es5-ext from 0.10.62 to 0.10.64 (#9457) Bumps [es5-ext](https://github.com/medikoo/es5-ext) from 0.10.62 to 0.10.64. - [Release notes](https://github.com/medikoo/es5-ext/releases) - [Changelog](https://github.com/medikoo/es5-ext/blob/main/CHANGELOG.md) - [Commits](https://github.com/medikoo/es5-ext/compare/v0.10.62...v0.10.64) --- updated-dependencies: - dependency-name: es5-ext dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: packages/server/package.json to reduce vulnerabilities (#9434) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-UNDICI-6252336 Co-authored-by: snyk-bot * fix: packages/server/package.json to reduce vulnerabilities (#9392) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-NODEMAILER-6219989 Co-authored-by: snyk-bot * fix: packages/server/package.json to reduce vulnerabilities (#9298) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-FOLLOWREDIRECTS-6141137 Co-authored-by: snyk-bot * chore(deps): bump follow-redirects from 1.14.8 to 1.15.4 (#9312) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.8 to 1.15.4. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.8...v1.15.4) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: Matt Krick Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matt Krick * chore: add upload to GCS step in ironbank (#9471) * add upload to GCS step in ironbank * update workflow name * chore(release): release v7.19.4 (#9470) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * fix: Fix seasonal templates for leap years (#9476) * fix: Fix seasonal templates for leap years It would produce invalid dates on February 29th. * Master was not clean * chore(release): release v7.19.5 (#9477) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * fix: After parameter for meetingCount was ignored (#9479) * chore(docker-build): simplify the docker build process and reduce docker image size (#9447) * Dockerfile basic created. Improvements added to reduce build time and size (down from 795MB to 445MB, depending on systemtap). Readme reduced, removing the old process used to build the image. * basic-env file using a RethinkDB database name that is clearly dedicated to the building proces. * Readme improved to run all three components * Unused dockerfiles removed. Docker entrypoint renamed. Docker Readme adapted * Legacy build kept in both dockerfile and env file. Readme adapted to use the new basic image. Build GH workflow adapted to use the new basic.dockerfile. * chore(release): release v7.19.6 (#9480) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * fix(docker-build): home folder is /home/node now (#9482) * chore(release): release v7.19.7 (#9483) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> * feat: OpenAIGeneration model for embedder (#9474) * fix: support single-tenant saml record (#9486) Signed-off-by: Matt Krick * chore(release): release v7.20.0 (#9485) Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Matt Krick Co-authored-by: Rafa <101704572+rafaelromcar-parabol@users.noreply.github.com> Co-authored-by: Georg Bremer Co-authored-by: Nick O'Ferrall Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: parabol-release-bot[bot] <150284312+parabol-release-bot[bot]@users.noreply.github.com> Co-authored-by: Matt Krick Co-authored-by: Jordan Husney Co-authored-by: adaniels-parabol <71724289+adaniels-parabol@users.noreply.github.com> Co-authored-by: snyk-bot Co-authored-by: Dale Bumblis <135627447+dbumblis-parabol@users.noreply.github.com> Co-authored-by: github-actions --- .release-please-manifest.json | 2 +- CHANGELOG.md | 12 +++ package.json | 2 +- packages/chronos/package.json | 4 +- packages/client/package.json | 2 +- packages/embedder/ai_models/AbstractModel.ts | 2 - packages/embedder/ai_models/ModelManager.ts | 9 +- .../embedder/ai_models/OpenAIGeneration.ts | 94 +++++++++++++++++++ .../ai_models/TextEmbeddingsInference.ts | 2 +- .../ai_models/TextGenerationInference.ts | 26 ++--- packages/embedder/embedder.ts | 3 +- .../embedder/indexing/embeddingsTablesOps.ts | 2 +- packages/gql-executor/package.json | 6 +- packages/integration-tests/package.json | 2 +- .../graphql/private/mutations/loginSAML.ts | 7 +- packages/server/package.json | 4 +- packages/server/utils/getSAMLURLFromEmail.ts | 2 +- 17 files changed, 141 insertions(+), 40 deletions(-) create mode 100644 packages/embedder/ai_models/OpenAIGeneration.ts diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 57085bcbc6b..7f814dacbc5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.19.7" + ".": "7.20.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 7191952d8a0..9d762695706 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/). +## [7.20.0](https://github.com/ParabolInc/parabol/compare/v7.19.7...v7.20.0) (2024-03-01) + + +### Added + +* OpenAIGeneration model for embedder ([#9474](https://github.com/ParabolInc/parabol/issues/9474)) ([807e347](https://github.com/ParabolInc/parabol/commit/807e34718d8a7939b7be84438900ef200a6ca896)) + + +### Fixed + +* support single-tenant saml record ([#9486](https://github.com/ParabolInc/parabol/issues/9486)) ([4e2e2ca](https://github.com/ParabolInc/parabol/commit/4e2e2ca00f237a7a8c94dc2e7f0d2f7d9ef9210d)) + ## [7.19.7](https://github.com/ParabolInc/parabol/compare/v7.19.6...v7.19.7) (2024-02-29) diff --git a/package.json b/package.json index 8749898ad6a..a2b1c1f913c 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": "7.19.7", + "version": "7.20.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/chronos/package.json b/packages/chronos/package.json index f44740aee53..b0166f09a82 100644 --- a/packages/chronos/package.json +++ b/packages/chronos/package.json @@ -1,6 +1,6 @@ { "name": "chronos", - "version": "7.19.7", + "version": "7.20.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": "7.19.7" + "parabol-server": "7.20.0" } } diff --git a/packages/client/package.json b/packages/client/package.json index a065260e9ad..085bd29d0b3 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": "7.19.7", + "version": "7.20.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/embedder/ai_models/AbstractModel.ts b/packages/embedder/ai_models/AbstractModel.ts index b0f709ce485..b57d220cd35 100644 --- a/packages/embedder/ai_models/AbstractModel.ts +++ b/packages/embedder/ai_models/AbstractModel.ts @@ -11,7 +11,6 @@ export interface GenerationModelConfig extends ModelConfig {} export abstract class AbstractModel { public readonly url?: string - public modelInstance: any constructor(config: ModelConfig) { this.url = this.normalizeUrl(config.url) @@ -57,7 +56,6 @@ export interface GenerationOptions { temperature?: number topK?: number topP?: number - truncate?: boolean } export abstract class AbstractGenerationModel extends AbstractModel { diff --git a/packages/embedder/ai_models/ModelManager.ts b/packages/embedder/ai_models/ModelManager.ts index ac8f04cc891..bf6888378c8 100644 --- a/packages/embedder/ai_models/ModelManager.ts +++ b/packages/embedder/ai_models/ModelManager.ts @@ -7,6 +7,7 @@ import { GenerationModelConfig, ModelConfig } from './AbstractModel' +import OpenAIGeneration from './OpenAIGeneration' import TextEmbeddingsInference from './TextEmbeddingsInference' import TextGenerationInference from './TextGenerationInference' @@ -16,7 +17,7 @@ interface ModelManagerConfig { } export type EmbeddingsModelType = 'text-embeddings-inference' -export type GenerationModelType = 'text-generation-inference' +export type GenerationModelType = 'openai' | 'text-generation-inference' export class ModelManager { embeddingModels: AbstractEmbeddingsModel[] @@ -80,9 +81,11 @@ export class ModelManager { const [modelType, _] = modelConfig.model.split(':') as [GenerationModelType, string] switch (modelType) { + case 'openai': { + return new OpenAIGeneration(modelConfig) + } case 'text-generation-inference': { - const generator = new TextGenerationInference(modelConfig) - return generator + return new TextGenerationInference(modelConfig) } default: throw new Error(`unsupported summarization model '${modelType}'`) diff --git a/packages/embedder/ai_models/OpenAIGeneration.ts b/packages/embedder/ai_models/OpenAIGeneration.ts new file mode 100644 index 00000000000..b5614b608c5 --- /dev/null +++ b/packages/embedder/ai_models/OpenAIGeneration.ts @@ -0,0 +1,94 @@ +import OpenAI from 'openai' +import { + AbstractGenerationModel, + GenerationModelConfig, + GenerationModelParams, + GenerationOptions +} from './AbstractModel' + +const MAX_REQUEST_TIME_S = 3 * 60 + +export type ModelId = 'gpt-3.5-turbo-0125' | 'gpt-4-turbo-preview' + +type OpenAIGenerationOptions = Omit + +const modelIdDefinitions: Record = { + 'gpt-3.5-turbo-0125': { + maxInputTokens: 4096 + }, + 'gpt-4-turbo-preview': { + maxInputTokens: 128000 + } +} + +function isValidModelId(object: any): object is ModelId { + return Object.keys(modelIdDefinitions).includes(object) +} + +export class OpenAIGeneration extends AbstractGenerationModel { + private openAIApi: OpenAI | null + private modelId: ModelId + + constructor(config: GenerationModelConfig) { + super(config) + if (!process.env.OPEN_AI_API_KEY) { + this.openAIApi = null + return + } + this.openAIApi = new OpenAI({ + apiKey: process.env.OPEN_AI_API_KEY, + organization: process.env.OPEN_AI_ORG_ID + }) + } + + async summarize(content: string, options: OpenAIGenerationOptions) { + if (!this.openAIApi) { + const eMsg = 'OpenAI is not configured' + console.log('OpenAIGenerationSummarizer.summarize(): ', eMsg) + throw new Error(eMsg) + } + const {maxNewTokens: max_tokens = 512, seed, stop, temperature = 0.8, topP: top_p} = options + const prompt = `Create a brief, one-paragraph summary of the following: ${content}` + + try { + const response = await this.openAIApi.chat.completions.create({ + frequency_penalty: 0, + max_tokens, + messages: [ + { + role: 'user', + content: prompt + } + ], + model: this.modelId, + presence_penalty: 0, + temperature, + seed, + stop, + top_p + }) + const maybeSummary = response.choices[0]?.message?.content?.trim() + if (!maybeSummary) throw new Error('OpenAI returned empty summary') + return maybeSummary + } catch (e) { + console.log('OpenAIGenerationSummarizer.summarize(): ', e) + throw e + } + } + protected constructModelParams(config: GenerationModelConfig): GenerationModelParams { + const modelConfigStringSplit = config.model.split(':') + if (modelConfigStringSplit.length != 2) { + throw new Error('OpenAIGeneration model string must be colon-delimited and len 2') + } + + const maybeModelId = modelConfigStringSplit[1] + if (!isValidModelId(maybeModelId)) + throw new Error(`OpenAIGeneration model id unknown: ${maybeModelId}`) + + this.modelId = maybeModelId + + return modelIdDefinitions[maybeModelId] + } +} + +export default OpenAIGeneration diff --git a/packages/embedder/ai_models/TextEmbeddingsInference.ts b/packages/embedder/ai_models/TextEmbeddingsInference.ts index 93bb2c88c2f..549fadcd6fd 100644 --- a/packages/embedder/ai_models/TextEmbeddingsInference.ts +++ b/packages/embedder/ai_models/TextEmbeddingsInference.ts @@ -63,7 +63,7 @@ export class TextEmbeddingsInference extends AbstractEmbeddingsModel { if (!this.url) throw new Error('TextGenerationInferenceSummarizer model requires url') const maybeModelId = modelConfigStringSplit[1] if (!isValidModelId(maybeModelId)) - throw new Error(`TextGenerationInference model subtype unknown: ${maybeModelId}`) + throw new Error(`TextGenerationInference model id unknown: ${maybeModelId}`) return modelIdDefinitions[maybeModelId] } } diff --git a/packages/embedder/ai_models/TextGenerationInference.ts b/packages/embedder/ai_models/TextGenerationInference.ts index 6f12ce09974..bcf1daa6303 100644 --- a/packages/embedder/ai_models/TextGenerationInference.ts +++ b/packages/embedder/ai_models/TextGenerationInference.ts @@ -25,16 +25,8 @@ export class TextGenerationInference extends AbstractGenerationModel { super(config) } - public async summarize(content: string, options: GenerationOptions) { - const { - maxNewTokens: max_new_tokens = 512, - seed, - stop, - temperature = 0.8, - topP, - topK, - truncate - } = options + async summarize(content: string, options: GenerationOptions) { + const {maxNewTokens: max_new_tokens = 512, seed, stop, temperature = 0.8, topP, topK} = options const parameters = { max_new_tokens, seed, @@ -42,7 +34,7 @@ export class TextGenerationInference extends AbstractGenerationModel { temperature, topP, topK, - truncate + truncate: true } const prompt = `Create a brief, one-paragraph summary of the following: ${content}` const fetchOptions = { @@ -59,27 +51,27 @@ export class TextGenerationInference extends AbstractGenerationModel { } try { - // console.log(`TextGenerationInterface.summarize(): summarizing from ${this.url}/generate`) + // console.log(`TextGenerationInference.summarize(): summarizing from ${this.url}/generate`) const res = await fetchWithRetry(`${this.url}/generate`, fetchOptions) const json = await res.json() if (!json || !json.generated_text) - throw new Error('TextGenerationInterface.summarize(): malformed response') + throw new Error('TextGenerationInference.summarize(): malformed response') return json.generated_text as string } catch (e) { - console.log('TextGenerationInterfaceSummarizer.summarize(): timeout') + console.log('TextGenerationInferenceSummarizer.summarize(): timeout') throw e } } protected constructModelParams(config: GenerationModelConfig): GenerationModelParams { const modelConfigStringSplit = config.model.split(':') if (modelConfigStringSplit.length != 2) { - throw new Error('TextGenerationInterface model string must be colon-delimited and len 2') + throw new Error('TextGenerationInference model string must be colon-delimited and len 2') } - if (!this.url) throw new Error('TextGenerationInterfaceSummarizer model requires url') + if (!this.url) throw new Error('TextGenerationInferenceSummarizer model requires url') const maybeModelId = modelConfigStringSplit[1] if (!isValidModelId(maybeModelId)) - throw new Error(`TextGenerationInterface model subtype unknown: ${maybeModelId}`) + throw new Error(`TextGenerationInference model id unknown: ${maybeModelId}`) return modelIdDefinitions[maybeModelId] } } diff --git a/packages/embedder/embedder.ts b/packages/embedder/embedder.ts index 1072a546d00..f6762013d08 100644 --- a/packages/embedder/embedder.ts +++ b/packages/embedder/embedder.ts @@ -162,9 +162,8 @@ const dequeueAndEmbedUntilEmpty = async (modelManager: ModelManager) => { try { const generator = modelManager.generationModels[0] // use 1st generator if (!generator) throw new Error(`Generator unavailable`) - const summarizeOptions = {maxInputTokens, truncate: true} console.log(`embedder: ...summarizing ${itemKey} for ${modelTable}`) - embedText = await generator.summarize(fullText, summarizeOptions) + embedText = await generator.summarize(fullText, {maxNewTokens: maxInputTokens}) } catch (e) { await updateJobState(jobQueueId, 'failed', { stateMessage: `unable to summarize long embed text: ${e}` diff --git a/packages/embedder/indexing/embeddingsTablesOps.ts b/packages/embedder/indexing/embeddingsTablesOps.ts index b68bc21ccbe..c74eb709708 100644 --- a/packages/embedder/indexing/embeddingsTablesOps.ts +++ b/packages/embedder/indexing/embeddingsTablesOps.ts @@ -52,7 +52,7 @@ export async function selectMetaToQueue( .where(({eb, not, or, and, exists, selectFrom}) => and([ or([ - not(eb('em.models', '<@', sql`ARRAY[${sql.ref('model')}]::varchar[]` as any) as any), + not(eb('em.models', '@>', sql`ARRAY[${sql.ref('model')}]::varchar[]` as any) as any), eb('em.models' as any, 'is', null) ]), not( diff --git a/packages/gql-executor/package.json b/packages/gql-executor/package.json index ea18a30925c..5fc6dbb0961 100644 --- a/packages/gql-executor/package.json +++ b/packages/gql-executor/package.json @@ -1,6 +1,6 @@ { "name": "gql-executor", - "version": "7.19.7", + "version": "7.20.0", "description": "A Stateless GraphQL Executor", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/gqlExecutor#readme", @@ -27,8 +27,8 @@ }, "dependencies": { "dd-trace": "^4.2.0", - "parabol-client": "7.19.7", - "parabol-server": "7.19.7", + "parabol-client": "7.20.0", + "parabol-server": "7.20.0", "undici": "^5.26.2" } } diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index a1780c8c5b4..9053ded2078 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": "7.19.7", + "version": "7.20.0", "description": "", "main": "index.js", "scripts": { diff --git a/packages/server/graphql/private/mutations/loginSAML.ts b/packages/server/graphql/private/mutations/loginSAML.ts index c14201f35eb..c3137a14205 100644 --- a/packages/server/graphql/private/mutations/loginSAML.ts +++ b/packages/server/graphql/private/mutations/loginSAML.ts @@ -16,6 +16,7 @@ import getSignOnURL from '../../public/mutations/helpers/SAMLHelpers/getSignOnUR import {SSORelayState} from '../../queries/SAMLIdP' import {MutationResolvers} from '../resolverTypes' import standardError from '../../../utils/standardError' +import {isSingleTenantSSO} from '../../../utils/getSAMLURLFromEmail' const serviceProvider = samlify.ServiceProvider({}) samlify.setSchemaValidator(samlXMLValidator) @@ -104,8 +105,10 @@ const loginSAML: MutationResolvers['loginSAML'] = async ( } const ssoDomain = getSSODomainFromEmail(email) if (!ssoDomain || !domains.includes(ssoDomain)) { - // don't blindly trust the IdP - return {error: {message: `${email} does not belong to ${domains.join(', ')}`}} + if (!isSingleTenantSSO) { + // don't blindly trust the IdP unless there is only 1 + return {error: {message: `${email} does not belong to ${domains.join(', ')}`}} + } } if (newMetadata) { diff --git a/packages/server/package.json b/packages/server/package.json index 4e47bbb8ad0..1d09f43fca0 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": "7.19.7", + "version": "7.20.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" @@ -124,7 +124,7 @@ "oauth-1.0a": "^2.2.6", "openai": "^4.24.1", "oy-vey": "^0.11.0", - "parabol-client": "7.19.7", + "parabol-client": "7.20.0", "pg": "^8.5.1", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/packages/server/utils/getSAMLURLFromEmail.ts b/packages/server/utils/getSAMLURLFromEmail.ts index 2c07d74a06d..896a479b483 100644 --- a/packages/server/utils/getSAMLURLFromEmail.ts +++ b/packages/server/utils/getSAMLURLFromEmail.ts @@ -4,7 +4,7 @@ import {URL} from 'url' import {DataLoaderWorker} from '../graphql/graphql' import getKysely from '../postgres/getKysely' -const isSingleTenantSSO = +export const isSingleTenantSSO = process.env.AUTH_INTERNAL_DISABLED === 'true' && process.env.AUTH_GOOGLE_DISABLED === 'true' && process.env.AUTH_MICROSOFT_DISABLED === 'true' &&