diff --git a/app/components/Notice.tsx b/app/components/Notice.tsx index abaf94bfea..6a2d804f3f 100644 --- a/app/components/Notice.tsx +++ b/app/components/Notice.tsx @@ -39,7 +39,7 @@ const Container = styled(Text)` border-radius: 4px; position: relative; font-size: 14px; - margin: 1em 0 0; + margin: 1em 0; svg { flex-shrink: 0; diff --git a/plugins/gitlab/client/Settings.tsx b/plugins/gitlab/client/Settings.tsx index cfac9e3f60..84c12929a0 100644 --- a/plugins/gitlab/client/Settings.tsx +++ b/plugins/gitlab/client/Settings.tsx @@ -47,6 +47,10 @@ function GitLab() { You need to accept the permissions in GitLab to connect{" "} {{ appName }} to your workspace. Try again? + ) : error === "duplicate_account" ? ( + + The GitLab account is already connected to this workspace. + ) : ( Something went wrong while authenticating your request. Please try diff --git a/plugins/gitlab/server/api/gitlab.ts b/plugins/gitlab/server/api/gitlab.ts index 5351cce00a..9270db0c90 100644 --- a/plugins/gitlab/server/api/gitlab.ts +++ b/plugins/gitlab/server/api/gitlab.ts @@ -184,6 +184,24 @@ router.get( customUrl, }); + // Check if another integration already exists with the same installation + const duplicateIntegration = await Integration.findOne({ + where: { + service: IntegrationService.GitLab, + teamId: user.teamId, + settings: { gitlab: { installation: { id: userInfo.id } } }, + ...(existingIntegration + ? { id: { [Op.ne]: existingIntegration.id } } + : {}), + }, + transaction, + }); + + if (duplicateIntegration) { + ctx.redirect(GitLabUtils.errorUrl("duplicate_account")); + return; + } + let authentication: IntegrationAuthentication; if (pendingAuth) { diff --git a/plugins/gitlab/shared/GitLabUtils.ts b/plugins/gitlab/shared/GitLabUtils.ts index c5ff72631c..d2388219a2 100644 --- a/plugins/gitlab/shared/GitLabUtils.ts +++ b/plugins/gitlab/shared/GitLabUtils.ts @@ -1,4 +1,3 @@ -import { Gitlab } from "@gitbeaker/rest"; import env from "@shared/env"; import { integrationSettingsPath } from "@shared/utils/routeHelpers"; import { UnfurlResourceType } from "@shared/types"; @@ -97,20 +96,6 @@ export class GitLabUtils { return `${this.url}?install_request=true`; } - /** - * Creates a Gitbeaker client instance. - * - * @param accessToken - The access token for authentication. - * @param customUrl - Optional custom GitLab URL from integration settings. - * @returns A configured Gitbeaker client. - */ - public static createClient(accessToken: string, customUrl?: string) { - return new Gitlab({ - host: this.getGitlabUrl(customUrl), - oauthToken: accessToken, - }); - } - /** * Parses a GitLab URL and extracts resource identifiers. * @@ -192,57 +177,6 @@ export class GitLabUtils { }; } - /** - * Fetches an issue from a GitLab project. - * - * @param accessToken - The access token for authentication. - * @param projectPath - The project path (owner/repo). - * @param issueIid - The issue IID (internal ID within the project). - * @param customUrl - Optional custom GitLab URL from integration settings. - * @returns The issue data. - */ - public static async getIssue( - accessToken: string, - projectPath: string, - issueIid: number, - customUrl?: string - ) { - const client = this.createClient(accessToken, customUrl); - - const issues = await client.Issues.all({ - projectId: projectPath, - iids: [issueIid], - withLabelsDetails: true, - }); - - if (!issues || issues.length === 0) { - throw new Error(`Issue ${issueIid} not found in project ${projectPath}`); - } - - return issues[0]; - } - - /** - * Fetches a merge request from a GitLab project. - * - * @param accessToken - The access token for authentication. - * @param projectPath - The project path (owner/repo). - * @param mrIid - The merge request IID (internal ID within the project). - * @param customUrl - Optional custom GitLab URL from integration settings. - * @returns The merge request data. - */ - public static async getMergeRequest( - accessToken: string, - projectPath: string, - mrIid: number, - customUrl?: string - ) { - const client = this.createClient(accessToken, customUrl); - // MergeRequests.show properly accepts projectId and mergerequestIId - const mr = await client.MergeRequests.show(projectPath, mrIid); - return mr; - } - /** * Returns the color associated with a given status. * diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index abc661e934..3619eaaed5 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -1449,6 +1449,7 @@ "Self-managed": "Self-managed", "Connect to a custom GitLab installation": "Connect to a custom GitLab installation", "You need to accept the permissions in GitLab to connect {{appName}} to your workspace. Try again?": "You need to accept the permissions in GitLab to connect {{appName}} to your workspace. Try again?", + "The GitLab account is already connected to this workspace.": "The GitLab account is already connected to this workspace.", "Something went wrong while authenticating your request. Please try again.": "Something went wrong while authenticating your request. Please try again.", "The owner of GitLab account has been requested to install the application. Once approved, the connection will be completed.": "The owner of GitLab account has been requested to install the application. Once approved, the connection will be completed.", "Enable previews of GitLab issues and merge requests in documents by connecting a GitLab organization or specific repositories to {appName}.": "Enable previews of GitLab issues and merge requests in documents by connecting a GitLab organization or specific repositories to {appName}.",