mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge pull request #1981 from ayham291/canary
feat: Git Provider Permissions
This commit is contained in:
@@ -16,9 +16,11 @@ import { api } from "@/utils/api";
|
|||||||
import { GitBranch, Loader2, UploadCloud } from "lucide-react";
|
import { GitBranch, Loader2, UploadCloud } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { SaveBitbucketProvider } from "./save-bitbucket-provider";
|
import { SaveBitbucketProvider } from "./save-bitbucket-provider";
|
||||||
import { SaveDragNDrop } from "./save-drag-n-drop";
|
import { SaveDragNDrop } from "./save-drag-n-drop";
|
||||||
import { SaveGitlabProvider } from "./save-gitlab-provider";
|
import { SaveGitlabProvider } from "./save-gitlab-provider";
|
||||||
|
import { UnauthorizedGitProvider } from "./unauthorized-git-provider";
|
||||||
|
|
||||||
type TabState =
|
type TabState =
|
||||||
| "github"
|
| "github"
|
||||||
@@ -43,12 +45,31 @@ export const ShowProviderForm = ({ applicationId }: Props) => {
|
|||||||
const { data: giteaProviders, isLoading: isLoadingGitea } =
|
const { data: giteaProviders, isLoading: isLoadingGitea } =
|
||||||
api.gitea.giteaProviders.useQuery();
|
api.gitea.giteaProviders.useQuery();
|
||||||
|
|
||||||
const { data: application } = api.application.one.useQuery({ applicationId });
|
const { data: application, refetch } = api.application.one.useQuery({
|
||||||
|
applicationId,
|
||||||
|
});
|
||||||
|
const { mutateAsync: disconnectGitProvider } =
|
||||||
|
api.application.disconnectGitProvider.useMutation();
|
||||||
|
|
||||||
const [tab, setSab] = useState<TabState>(application?.sourceType || "github");
|
const [tab, setSab] = useState<TabState>(application?.sourceType || "github");
|
||||||
|
|
||||||
const isLoading =
|
const isLoading =
|
||||||
isLoadingGithub || isLoadingGitlab || isLoadingBitbucket || isLoadingGitea;
|
isLoadingGithub || isLoadingGitlab || isLoadingBitbucket || isLoadingGitea;
|
||||||
|
|
||||||
|
const handleDisconnect = async () => {
|
||||||
|
try {
|
||||||
|
await disconnectGitProvider({ applicationId });
|
||||||
|
toast.success("Repository disconnected successfully");
|
||||||
|
await refetch();
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(
|
||||||
|
`Failed to disconnect repository: ${
|
||||||
|
error instanceof Error ? error.message : "Unknown error"
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<Card className="group relative w-full bg-transparent">
|
<Card className="group relative w-full bg-transparent">
|
||||||
@@ -77,6 +98,38 @@ export const ShowProviderForm = ({ applicationId }: Props) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if user doesn't have access to the current git provider
|
||||||
|
if (
|
||||||
|
application &&
|
||||||
|
!application.hasGitProviderAccess &&
|
||||||
|
application.sourceType !== "docker" &&
|
||||||
|
application.sourceType !== "drop"
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<Card className="group relative w-full bg-transparent">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-start justify-between">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<span className="flex flex-col space-y-0.5">Provider</span>
|
||||||
|
<p className="flex items-center text-sm font-normal text-muted-foreground">
|
||||||
|
Repository connection through unauthorized provider
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="hidden space-y-1 text-sm font-normal md:block">
|
||||||
|
<GitBranch className="size-6 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<UnauthorizedGitProvider
|
||||||
|
service={application}
|
||||||
|
onDisconnect={handleDisconnect}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="group relative w-full bg-transparent">
|
<Card className="group relative w-full bg-transparent">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
import {
|
||||||
|
BitbucketIcon,
|
||||||
|
GitIcon,
|
||||||
|
GiteaIcon,
|
||||||
|
GithubIcon,
|
||||||
|
GitlabIcon,
|
||||||
|
} from "@/components/icons/data-tools-icons";
|
||||||
|
import { DialogAction } from "@/components/shared/dialog-action";
|
||||||
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import type { RouterOutputs } from "@/utils/api";
|
||||||
|
import { AlertCircle, GitBranch, Unlink } from "lucide-react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
service:
|
||||||
|
| RouterOutputs["application"]["one"]
|
||||||
|
| RouterOutputs["compose"]["one"];
|
||||||
|
onDisconnect: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UnauthorizedGitProvider = ({ service, onDisconnect }: Props) => {
|
||||||
|
const getProviderIcon = (sourceType: string) => {
|
||||||
|
switch (sourceType) {
|
||||||
|
case "github":
|
||||||
|
return <GithubIcon className="size-5 text-muted-foreground" />;
|
||||||
|
case "gitlab":
|
||||||
|
return <GitlabIcon className="size-5 text-muted-foreground" />;
|
||||||
|
case "bitbucket":
|
||||||
|
return <BitbucketIcon className="size-5 text-muted-foreground" />;
|
||||||
|
case "gitea":
|
||||||
|
return <GiteaIcon className="size-5 text-muted-foreground" />;
|
||||||
|
case "git":
|
||||||
|
return <GitIcon className="size-5 text-muted-foreground" />;
|
||||||
|
default:
|
||||||
|
return <GitBranch className="size-5 text-muted-foreground" />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRepositoryInfo = () => {
|
||||||
|
switch (service.sourceType) {
|
||||||
|
case "github":
|
||||||
|
return {
|
||||||
|
repo: service.repository,
|
||||||
|
branch: service.branch,
|
||||||
|
owner: service.owner,
|
||||||
|
};
|
||||||
|
case "gitlab":
|
||||||
|
return {
|
||||||
|
repo: service.gitlabRepository,
|
||||||
|
branch: service.gitlabBranch,
|
||||||
|
owner: service.gitlabOwner,
|
||||||
|
};
|
||||||
|
case "bitbucket":
|
||||||
|
return {
|
||||||
|
repo: service.bitbucketRepository,
|
||||||
|
branch: service.bitbucketBranch,
|
||||||
|
owner: service.bitbucketOwner,
|
||||||
|
};
|
||||||
|
case "gitea":
|
||||||
|
return {
|
||||||
|
repo: service.giteaRepository,
|
||||||
|
branch: service.giteaBranch,
|
||||||
|
owner: service.giteaOwner,
|
||||||
|
};
|
||||||
|
case "git":
|
||||||
|
return {
|
||||||
|
repo: service.customGitUrl,
|
||||||
|
branch: service.customGitBranch,
|
||||||
|
owner: null,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return { repo: null, branch: null, owner: null };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { repo, branch, owner } = getRepositoryInfo();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<Alert>
|
||||||
|
<AlertCircle className="h-4 w-4" />
|
||||||
|
<AlertDescription>
|
||||||
|
This application is connected to a {service.sourceType} repository
|
||||||
|
through a git provider that you don't have access to. You can see
|
||||||
|
basic repository information below, but cannot modify the
|
||||||
|
configuration.
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
|
||||||
|
<Card className="border-dashed border-2 border-muted-foreground/20 bg-transparent">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2">
|
||||||
|
{getProviderIcon(service.sourceType)}
|
||||||
|
<span className="capitalize text-sm font-medium">
|
||||||
|
{service.sourceType} Repository
|
||||||
|
</span>
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-3">
|
||||||
|
{owner && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium text-muted-foreground">
|
||||||
|
Owner:
|
||||||
|
</span>
|
||||||
|
<p className="text-sm">{owner}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{repo && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium text-muted-foreground">
|
||||||
|
Repository:
|
||||||
|
</span>
|
||||||
|
<p className="text-sm">{repo}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{branch && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium text-muted-foreground">
|
||||||
|
Branch:
|
||||||
|
</span>
|
||||||
|
<p className="text-sm">{branch}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="pt-4 border-t">
|
||||||
|
<DialogAction
|
||||||
|
title="Disconnect Repository"
|
||||||
|
description="Are you sure you want to disconnect this repository?"
|
||||||
|
type="default"
|
||||||
|
onClick={async () => {
|
||||||
|
onDisconnect();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button variant="secondary" className="w-full">
|
||||||
|
<Unlink className="size-4 mr-2" />
|
||||||
|
Disconnect Repository
|
||||||
|
</Button>
|
||||||
|
</DialogAction>
|
||||||
|
<p className="text-xs text-muted-foreground mt-2">
|
||||||
|
Disconnecting will allow you to configure a new repository with
|
||||||
|
your own git providers.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -18,6 +18,8 @@ import { SaveGitProviderCompose } from "./save-git-provider-compose";
|
|||||||
import { SaveGiteaProviderCompose } from "./save-gitea-provider-compose";
|
import { SaveGiteaProviderCompose } from "./save-gitea-provider-compose";
|
||||||
import { SaveGithubProviderCompose } from "./save-github-provider-compose";
|
import { SaveGithubProviderCompose } from "./save-github-provider-compose";
|
||||||
import { SaveGitlabProviderCompose } from "./save-gitlab-provider-compose";
|
import { SaveGitlabProviderCompose } from "./save-gitlab-provider-compose";
|
||||||
|
import { UnauthorizedGitProvider } from "@/components/dashboard/application/general/generic/unauthorized-git-provider";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
type TabState = "github" | "git" | "raw" | "gitlab" | "bitbucket" | "gitea";
|
type TabState = "github" | "git" | "raw" | "gitlab" | "bitbucket" | "gitea";
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -34,12 +36,29 @@ export const ShowProviderFormCompose = ({ composeId }: Props) => {
|
|||||||
const { data: giteaProviders, isLoading: isLoadingGitea } =
|
const { data: giteaProviders, isLoading: isLoadingGitea } =
|
||||||
api.gitea.giteaProviders.useQuery();
|
api.gitea.giteaProviders.useQuery();
|
||||||
|
|
||||||
const { data: compose } = api.compose.one.useQuery({ composeId });
|
const { mutateAsync: disconnectGitProvider } =
|
||||||
|
api.compose.disconnectGitProvider.useMutation();
|
||||||
|
|
||||||
|
const { data: compose, refetch } = api.compose.one.useQuery({ composeId });
|
||||||
const [tab, setSab] = useState<TabState>(compose?.sourceType || "github");
|
const [tab, setSab] = useState<TabState>(compose?.sourceType || "github");
|
||||||
|
|
||||||
const isLoading =
|
const isLoading =
|
||||||
isLoadingGithub || isLoadingGitlab || isLoadingBitbucket || isLoadingGitea;
|
isLoadingGithub || isLoadingGitlab || isLoadingBitbucket || isLoadingGitea;
|
||||||
|
|
||||||
|
const handleDisconnect = async () => {
|
||||||
|
try {
|
||||||
|
await disconnectGitProvider({ composeId });
|
||||||
|
toast.success("Repository disconnected successfully");
|
||||||
|
await refetch();
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(
|
||||||
|
`Failed to disconnect repository: ${
|
||||||
|
error instanceof Error ? error.message : "Unknown error"
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<Card className="group relative w-full bg-transparent">
|
<Card className="group relative w-full bg-transparent">
|
||||||
@@ -68,6 +87,37 @@ export const ShowProviderFormCompose = ({ composeId }: Props) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if user doesn't have access to the current git provider
|
||||||
|
if (
|
||||||
|
compose &&
|
||||||
|
!compose.hasGitProviderAccess &&
|
||||||
|
compose.sourceType !== "raw"
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<Card className="group relative w-full bg-transparent">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-start justify-between">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<span className="flex flex-col space-y-0.5">Provider</span>
|
||||||
|
<p className="flex items-center text-sm font-normal text-muted-foreground">
|
||||||
|
Repository connection through unauthorized provider
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="hidden space-y-1 text-sm font-normal md:block">
|
||||||
|
<GitBranch className="size-6 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<UnauthorizedGitProvider
|
||||||
|
service={compose}
|
||||||
|
onDisconnect={handleDisconnect}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="group relative w-full bg-transparent">
|
<Card className="group relative w-full bg-transparent">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
export const extractExpirationDate = (certData: string): Date | null => {
|
export const extractExpirationDate = (certData: string): Date | null => {
|
||||||
try {
|
try {
|
||||||
// Decode PEM base64 to DER binary
|
// Decode PEM base64 to DER binary
|
||||||
@@ -12,11 +14,13 @@ export const extractExpirationDate = (certData: string): Date | null => {
|
|||||||
|
|
||||||
// Helper: read ASN.1 length field
|
// Helper: read ASN.1 length field
|
||||||
function readLength(pos: number): { length: number; offset: number } {
|
function readLength(pos: number): { length: number; offset: number } {
|
||||||
|
// biome-ignore lint/style/noParameterAssign: <explanation>
|
||||||
let len = der[pos++];
|
let len = der[pos++];
|
||||||
if (len & 0x80) {
|
if (len & 0x80) {
|
||||||
const bytes = len & 0x7f;
|
const bytes = len & 0x7f;
|
||||||
len = 0;
|
len = 0;
|
||||||
for (let i = 0; i < bytes; i++) {
|
for (let i = 0; i < bytes; i++) {
|
||||||
|
// biome-ignore lint/style/noParameterAssign: <explanation>
|
||||||
len = (len << 8) + der[pos++];
|
len = (len << 8) + der[pos++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,19 +72,19 @@ export const extractExpirationDate = (certData: string): Date | null => {
|
|||||||
function parseTime(str: string): Date {
|
function parseTime(str: string): Date {
|
||||||
if (str.length === 13) {
|
if (str.length === 13) {
|
||||||
// UTCTime YYMMDDhhmmssZ
|
// UTCTime YYMMDDhhmmssZ
|
||||||
const year = parseInt(str.slice(0, 2), 10);
|
const year = Number.parseInt(str.slice(0, 2), 10);
|
||||||
const fullYear = year < 50 ? 2000 + year : 1900 + year;
|
const fullYear = year < 50 ? 2000 + year : 1900 + year;
|
||||||
return new Date(
|
return new Date(
|
||||||
`${fullYear}-${str.slice(2, 4)}-${str.slice(4, 6)}T${str.slice(6, 8)}:${str.slice(8, 10)}:${str.slice(10, 12)}Z`,
|
`${fullYear}-${str.slice(2, 4)}-${str.slice(4, 6)}T${str.slice(6, 8)}:${str.slice(8, 10)}:${str.slice(10, 12)}Z`,
|
||||||
);
|
);
|
||||||
} else if (str.length === 15) {
|
}
|
||||||
|
if (str.length === 15) {
|
||||||
// GeneralizedTime YYYYMMDDhhmmssZ
|
// GeneralizedTime YYYYMMDDhhmmssZ
|
||||||
return new Date(
|
return new Date(
|
||||||
`${str.slice(0, 4)}-${str.slice(4, 6)}-${str.slice(6, 8)}T${str.slice(8, 10)}:${str.slice(10, 12)}:${str.slice(12, 14)}Z`,
|
`${str.slice(0, 4)}-${str.slice(4, 6)}-${str.slice(6, 8)}T${str.slice(8, 10)}:${str.slice(10, 12)}:${str.slice(12, 14)}Z`,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
throw new Error("Invalid ASN.1 time format");
|
|
||||||
}
|
}
|
||||||
|
throw new Error("Invalid ASN.1 time format");
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseTime(notAfterStr);
|
return parseTime(notAfterStr);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { useEffect, useState } from "react";
|
|||||||
export const AddGithubProvider = () => {
|
export const AddGithubProvider = () => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||||
|
const { data: session } = authClient.useSession();
|
||||||
const { data } = api.user.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
const [manifest, setManifest] = useState("");
|
const [manifest, setManifest] = useState("");
|
||||||
const [isOrganization, setIsOrganization] = useState(false);
|
const [isOrganization, setIsOrganization] = useState(false);
|
||||||
@@ -27,7 +28,7 @@ export const AddGithubProvider = () => {
|
|||||||
const url = document.location.origin;
|
const url = document.location.origin;
|
||||||
const manifest = JSON.stringify(
|
const manifest = JSON.stringify(
|
||||||
{
|
{
|
||||||
redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id}`,
|
redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id}&userId=${session?.user?.id}`,
|
||||||
name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}`,
|
name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}`,
|
||||||
url: origin,
|
url: origin,
|
||||||
hook_attributes: {
|
hook_attributes: {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { ImpersonationBar } from "../dashboard/impersonation/impersonation-bar";
|
import { ImpersonationBar } from "../dashboard/impersonation/impersonation-bar";
|
||||||
import Page from "./side";
|
|
||||||
import { ChatwootWidget } from "../shared/ChatwootWidget";
|
import { ChatwootWidget } from "../shared/ChatwootWidget";
|
||||||
|
import Page from "./side";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|||||||
15
apps/dokploy/drizzle/0094_numerous_carmella_unuscione.sql
Normal file
15
apps/dokploy/drizzle/0094_numerous_carmella_unuscione.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
ALTER TABLE "git_provider" ADD COLUMN "userId" text;--> statement-breakpoint
|
||||||
|
|
||||||
|
-- Update existing git providers to be owned by the organization owner
|
||||||
|
-- We need to get the account.user_id for the organization owner
|
||||||
|
UPDATE "git_provider"
|
||||||
|
SET "userId" = (
|
||||||
|
SELECT a.user_id
|
||||||
|
FROM "organization" o
|
||||||
|
JOIN "account" a ON o."owner_id" = a.user_id
|
||||||
|
WHERE o.id = "git_provider"."organizationId"
|
||||||
|
);--> statement-breakpoint
|
||||||
|
|
||||||
|
-- Now make the column NOT NULL since all rows should have values
|
||||||
|
ALTER TABLE "git_provider" ALTER COLUMN "userId" SET NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
5737
apps/dokploy/drizzle/meta/0094_snapshot.json
Normal file
5737
apps/dokploy/drizzle/meta/0094_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -659,6 +659,13 @@
|
|||||||
"when": 1750397258622,
|
"when": 1750397258622,
|
||||||
"tag": "0093_nice_gorilla_man",
|
"tag": "0093_nice_gorilla_man",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 94,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1750559214977,
|
||||||
|
"tag": "0094_numerous_carmella_unuscione",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -10,13 +10,14 @@ type Query = {
|
|||||||
state: string;
|
state: string;
|
||||||
installation_id: string;
|
installation_id: string;
|
||||||
setup_action: string;
|
setup_action: string;
|
||||||
|
userId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function handler(
|
export default async function handler(
|
||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
) {
|
) {
|
||||||
const { code, state, installation_id }: Query = req.query as Query;
|
const { code, state, installation_id, userId }: Query = req.query as Query;
|
||||||
|
|
||||||
if (!code) {
|
if (!code) {
|
||||||
return res.status(400).json({ error: "Missing code parameter" });
|
return res.status(400).json({ error: "Missing code parameter" });
|
||||||
@@ -44,6 +45,7 @@ export default async function handler(
|
|||||||
githubPrivateKey: data.pem,
|
githubPrivateKey: data.pem,
|
||||||
},
|
},
|
||||||
value as string,
|
value as string,
|
||||||
|
userId,
|
||||||
);
|
);
|
||||||
} else if (action === "gh_setup") {
|
} else if (action === "gh_setup") {
|
||||||
await db
|
await db
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
createApplication,
|
createApplication,
|
||||||
deleteAllMiddlewares,
|
deleteAllMiddlewares,
|
||||||
findApplicationById,
|
findApplicationById,
|
||||||
|
findGitProviderById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
getApplicationStats,
|
getApplicationStats,
|
||||||
mechanizeDockerContainer,
|
mechanizeDockerContainer,
|
||||||
@@ -126,7 +127,45 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
message: "You are not authorized to access this application",
|
message: "You are not authorized to access this application",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return application;
|
|
||||||
|
let hasGitProviderAccess = true;
|
||||||
|
let unauthorizedProvider: string | null = null;
|
||||||
|
|
||||||
|
const getGitProviderId = () => {
|
||||||
|
switch (application.sourceType) {
|
||||||
|
case "github":
|
||||||
|
return application.github?.gitProviderId;
|
||||||
|
case "gitlab":
|
||||||
|
return application.gitlab?.gitProviderId;
|
||||||
|
case "bitbucket":
|
||||||
|
return application.bitbucket?.gitProviderId;
|
||||||
|
case "gitea":
|
||||||
|
return application.gitea?.gitProviderId;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const gitProviderId = getGitProviderId();
|
||||||
|
|
||||||
|
if (gitProviderId) {
|
||||||
|
try {
|
||||||
|
const gitProvider = await findGitProviderById(gitProviderId);
|
||||||
|
if (gitProvider.userId !== ctx.session.userId) {
|
||||||
|
hasGitProviderAccess = false;
|
||||||
|
unauthorizedProvider = application.sourceType;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
hasGitProviderAccess = false;
|
||||||
|
unauthorizedProvider = application.sourceType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...application,
|
||||||
|
hasGitProviderAccess,
|
||||||
|
unauthorizedProvider,
|
||||||
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
reload: protectedProcedure
|
reload: protectedProcedure
|
||||||
@@ -488,6 +527,67 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
enableSubmodules: input.enableSubmodules,
|
enableSubmodules: input.enableSubmodules,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
|
disconnectGitProvider: protectedProcedure
|
||||||
|
.input(apiFindOneApplication)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const application = await findApplicationById(input.applicationId);
|
||||||
|
if (
|
||||||
|
application.project.organizationId !== ctx.session.activeOrganizationId
|
||||||
|
) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not authorized to disconnect this git provider",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset all git provider related fields
|
||||||
|
await updateApplication(input.applicationId, {
|
||||||
|
// GitHub fields
|
||||||
|
repository: null,
|
||||||
|
branch: null,
|
||||||
|
owner: null,
|
||||||
|
buildPath: "/",
|
||||||
|
githubId: null,
|
||||||
|
triggerType: "push",
|
||||||
|
|
||||||
|
// GitLab fields
|
||||||
|
gitlabRepository: null,
|
||||||
|
gitlabOwner: null,
|
||||||
|
gitlabBranch: null,
|
||||||
|
gitlabBuildPath: null,
|
||||||
|
gitlabId: null,
|
||||||
|
gitlabProjectId: null,
|
||||||
|
gitlabPathNamespace: null,
|
||||||
|
|
||||||
|
// Bitbucket fields
|
||||||
|
bitbucketRepository: null,
|
||||||
|
bitbucketOwner: null,
|
||||||
|
bitbucketBranch: null,
|
||||||
|
bitbucketBuildPath: null,
|
||||||
|
bitbucketId: null,
|
||||||
|
|
||||||
|
// Gitea fields
|
||||||
|
giteaRepository: null,
|
||||||
|
giteaOwner: null,
|
||||||
|
giteaBranch: null,
|
||||||
|
giteaBuildPath: null,
|
||||||
|
giteaId: null,
|
||||||
|
|
||||||
|
// Custom Git fields
|
||||||
|
customGitBranch: null,
|
||||||
|
customGitBuildPath: null,
|
||||||
|
customGitUrl: null,
|
||||||
|
customGitSSHKeyId: null,
|
||||||
|
|
||||||
|
// Common fields
|
||||||
|
sourceType: "github", // Reset to default
|
||||||
|
applicationStatus: "idle",
|
||||||
|
watchPaths: null,
|
||||||
|
enableSubmodules: false,
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
markRunning: protectedProcedure
|
markRunning: protectedProcedure
|
||||||
|
|||||||
@@ -22,7 +22,11 @@ export const bitbucketRouter = createTRPCRouter({
|
|||||||
.input(apiCreateBitbucket)
|
.input(apiCreateBitbucket)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
try {
|
try {
|
||||||
return await createBitbucket(input, ctx.session.activeOrganizationId);
|
return await createBitbucket(
|
||||||
|
input,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
ctx.session.userId,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
@@ -37,7 +41,8 @@ export const bitbucketRouter = createTRPCRouter({
|
|||||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||||
if (
|
if (
|
||||||
bitbucketProvider.gitProvider.organizationId !==
|
bitbucketProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
bitbucketProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -56,11 +61,13 @@ export const bitbucketRouter = createTRPCRouter({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
result = result.filter(
|
result = result.filter((provider) => {
|
||||||
(provider) =>
|
return (
|
||||||
provider.gitProvider.organizationId ===
|
provider.gitProvider.organizationId ===
|
||||||
ctx.session.activeOrganizationId,
|
ctx.session.activeOrganizationId &&
|
||||||
);
|
provider.gitProvider.userId === ctx.session.userId
|
||||||
|
);
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -70,7 +77,8 @@ export const bitbucketRouter = createTRPCRouter({
|
|||||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||||
if (
|
if (
|
||||||
bitbucketProvider.gitProvider.organizationId !==
|
bitbucketProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
bitbucketProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -87,7 +95,8 @@ export const bitbucketRouter = createTRPCRouter({
|
|||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
bitbucketProvider.gitProvider.organizationId !==
|
bitbucketProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
bitbucketProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -103,7 +112,8 @@ export const bitbucketRouter = createTRPCRouter({
|
|||||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||||
if (
|
if (
|
||||||
bitbucketProvider.gitProvider.organizationId !==
|
bitbucketProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
bitbucketProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -126,7 +136,8 @@ export const bitbucketRouter = createTRPCRouter({
|
|||||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||||
if (
|
if (
|
||||||
bitbucketProvider.gitProvider.organizationId !==
|
bitbucketProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
bitbucketProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
deleteMount,
|
deleteMount,
|
||||||
findComposeById,
|
findComposeById,
|
||||||
findDomainsByComposeId,
|
findDomainsByComposeId,
|
||||||
|
findGitProviderById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
findServerById,
|
findServerById,
|
||||||
findUserById,
|
findUserById,
|
||||||
@@ -119,7 +120,45 @@ export const composeRouter = createTRPCRouter({
|
|||||||
message: "You are not authorized to access this compose",
|
message: "You are not authorized to access this compose",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return compose;
|
|
||||||
|
let hasGitProviderAccess = true;
|
||||||
|
let unauthorizedProvider: string | null = null;
|
||||||
|
|
||||||
|
const getGitProviderId = () => {
|
||||||
|
switch (compose.sourceType) {
|
||||||
|
case "github":
|
||||||
|
return compose.github?.gitProviderId;
|
||||||
|
case "gitlab":
|
||||||
|
return compose.gitlab?.gitProviderId;
|
||||||
|
case "bitbucket":
|
||||||
|
return compose.bitbucket?.gitProviderId;
|
||||||
|
case "gitea":
|
||||||
|
return compose.gitea?.gitProviderId;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const gitProviderId = getGitProviderId();
|
||||||
|
|
||||||
|
if (gitProviderId) {
|
||||||
|
try {
|
||||||
|
const gitProvider = await findGitProviderById(gitProviderId);
|
||||||
|
if (gitProvider.userId !== ctx.session.userId) {
|
||||||
|
hasGitProviderAccess = false;
|
||||||
|
unauthorizedProvider = compose.sourceType;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
hasGitProviderAccess = false;
|
||||||
|
unauthorizedProvider = compose.sourceType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...compose,
|
||||||
|
hasGitProviderAccess,
|
||||||
|
unauthorizedProvider,
|
||||||
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
update: protectedProcedure
|
update: protectedProcedure
|
||||||
@@ -526,6 +565,61 @@ export const composeRouter = createTRPCRouter({
|
|||||||
const uniqueTags = _.uniq(allTags);
|
const uniqueTags = _.uniq(allTags);
|
||||||
return uniqueTags;
|
return uniqueTags;
|
||||||
}),
|
}),
|
||||||
|
disconnectGitProvider: protectedProcedure
|
||||||
|
.input(apiFindCompose)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const compose = await findComposeById(input.composeId);
|
||||||
|
if (compose.project.organizationId !== ctx.session.activeOrganizationId) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not authorized to disconnect this git provider",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset all git provider related fields
|
||||||
|
await updateCompose(input.composeId, {
|
||||||
|
// GitHub fields
|
||||||
|
repository: null,
|
||||||
|
branch: null,
|
||||||
|
owner: null,
|
||||||
|
composePath: undefined,
|
||||||
|
githubId: null,
|
||||||
|
triggerType: "push",
|
||||||
|
|
||||||
|
// GitLab fields
|
||||||
|
gitlabRepository: null,
|
||||||
|
gitlabOwner: null,
|
||||||
|
gitlabBranch: null,
|
||||||
|
gitlabId: null,
|
||||||
|
gitlabProjectId: null,
|
||||||
|
gitlabPathNamespace: null,
|
||||||
|
|
||||||
|
// Bitbucket fields
|
||||||
|
bitbucketRepository: null,
|
||||||
|
bitbucketOwner: null,
|
||||||
|
bitbucketBranch: null,
|
||||||
|
bitbucketId: null,
|
||||||
|
|
||||||
|
// Gitea fields
|
||||||
|
giteaRepository: null,
|
||||||
|
giteaOwner: null,
|
||||||
|
giteaBranch: null,
|
||||||
|
giteaId: null,
|
||||||
|
|
||||||
|
// Custom Git fields
|
||||||
|
customGitBranch: null,
|
||||||
|
customGitUrl: null,
|
||||||
|
customGitSSHKeyId: null,
|
||||||
|
|
||||||
|
// Common fields
|
||||||
|
sourceType: "github", // Reset to default
|
||||||
|
composeStatus: "idle",
|
||||||
|
watchPaths: null,
|
||||||
|
enableSubmodules: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
|
|
||||||
move: protectedProcedure
|
move: protectedProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { db } from "@/server/db";
|
|||||||
import { apiRemoveGitProvider, gitProvider } from "@/server/db/schema";
|
import { apiRemoveGitProvider, gitProvider } from "@/server/db/schema";
|
||||||
import { findGitProviderById, removeGitProvider } from "@dokploy/server";
|
import { findGitProviderById, removeGitProvider } from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { desc, eq } from "drizzle-orm";
|
import { and, desc, eq } from "drizzle-orm";
|
||||||
|
|
||||||
export const gitProviderRouter = createTRPCRouter({
|
export const gitProviderRouter = createTRPCRouter({
|
||||||
getAll: protectedProcedure.query(async ({ ctx }) => {
|
getAll: protectedProcedure.query(async ({ ctx }) => {
|
||||||
@@ -15,7 +15,10 @@ export const gitProviderRouter = createTRPCRouter({
|
|||||||
gitea: true,
|
gitea: true,
|
||||||
},
|
},
|
||||||
orderBy: desc(gitProvider.createdAt),
|
orderBy: desc(gitProvider.createdAt),
|
||||||
where: eq(gitProvider.organizationId, ctx.session.activeOrganizationId),
|
where: and(
|
||||||
|
eq(gitProvider.userId, ctx.session.userId),
|
||||||
|
eq(gitProvider.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
remove: protectedProcedure
|
remove: protectedProcedure
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
.input(apiCreateGitea)
|
.input(apiCreateGitea)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
try {
|
try {
|
||||||
return await createGitea(input, ctx.session.activeOrganizationId);
|
return await createGitea(
|
||||||
|
input,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
ctx.session.userId,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
@@ -42,7 +46,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
const giteaProvider = await findGiteaById(input.giteaId);
|
const giteaProvider = await findGiteaById(input.giteaId);
|
||||||
if (
|
if (
|
||||||
giteaProvider.gitProvider.organizationId !==
|
giteaProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
giteaProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -62,7 +67,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
result = result.filter(
|
result = result.filter(
|
||||||
(provider) =>
|
(provider) =>
|
||||||
provider.gitProvider.organizationId ===
|
provider.gitProvider.organizationId ===
|
||||||
ctx.session.activeOrganizationId,
|
ctx.session.activeOrganizationId &&
|
||||||
|
provider.gitProvider.userId === ctx.session.userId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filtered = result
|
const filtered = result
|
||||||
@@ -94,7 +100,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
const giteaProvider = await findGiteaById(giteaId);
|
const giteaProvider = await findGiteaById(giteaId);
|
||||||
if (
|
if (
|
||||||
giteaProvider.gitProvider.organizationId !==
|
giteaProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
giteaProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -130,7 +137,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
const giteaProvider = await findGiteaById(giteaId);
|
const giteaProvider = await findGiteaById(giteaId);
|
||||||
if (
|
if (
|
||||||
giteaProvider.gitProvider.organizationId !==
|
giteaProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
giteaProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -162,7 +170,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
const giteaProvider = await findGiteaById(giteaId);
|
const giteaProvider = await findGiteaById(giteaId);
|
||||||
if (
|
if (
|
||||||
giteaProvider.gitProvider.organizationId !==
|
giteaProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
giteaProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -190,7 +199,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
const giteaProvider = await findGiteaById(input.giteaId);
|
const giteaProvider = await findGiteaById(input.giteaId);
|
||||||
if (
|
if (
|
||||||
giteaProvider.gitProvider.organizationId !==
|
giteaProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
giteaProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -231,7 +241,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
const giteaProvider = await findGiteaById(giteaId);
|
const giteaProvider = await findGiteaById(giteaId);
|
||||||
if (
|
if (
|
||||||
giteaProvider.gitProvider.organizationId !==
|
giteaProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
giteaProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ export const githubRouter = createTRPCRouter({
|
|||||||
const githubProvider = await findGithubById(input.githubId);
|
const githubProvider = await findGithubById(input.githubId);
|
||||||
if (
|
if (
|
||||||
githubProvider.gitProvider.organizationId !==
|
githubProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
githubProvider.gitProvider.userId === ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -36,7 +37,8 @@ export const githubRouter = createTRPCRouter({
|
|||||||
const githubProvider = await findGithubById(input.githubId);
|
const githubProvider = await findGithubById(input.githubId);
|
||||||
if (
|
if (
|
||||||
githubProvider.gitProvider.organizationId !==
|
githubProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
githubProvider.gitProvider.userId === ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -51,7 +53,8 @@ export const githubRouter = createTRPCRouter({
|
|||||||
const githubProvider = await findGithubById(input.githubId || "");
|
const githubProvider = await findGithubById(input.githubId || "");
|
||||||
if (
|
if (
|
||||||
githubProvider.gitProvider.organizationId !==
|
githubProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
githubProvider.gitProvider.userId === ctx.session.userId
|
||||||
) {
|
) {
|
||||||
//TODO: Remove this line when the cloud version is ready
|
//TODO: Remove this line when the cloud version is ready
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@@ -71,7 +74,8 @@ export const githubRouter = createTRPCRouter({
|
|||||||
result = result.filter(
|
result = result.filter(
|
||||||
(provider) =>
|
(provider) =>
|
||||||
provider.gitProvider.organizationId ===
|
provider.gitProvider.organizationId ===
|
||||||
ctx.session.activeOrganizationId,
|
ctx.session.activeOrganizationId &&
|
||||||
|
provider.gitProvider.userId === ctx.session.userId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filtered = result
|
const filtered = result
|
||||||
@@ -95,7 +99,8 @@ export const githubRouter = createTRPCRouter({
|
|||||||
const githubProvider = await findGithubById(input.githubId);
|
const githubProvider = await findGithubById(input.githubId);
|
||||||
if (
|
if (
|
||||||
githubProvider.gitProvider.organizationId !==
|
githubProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
githubProvider.gitProvider.userId === ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -117,7 +122,8 @@ export const githubRouter = createTRPCRouter({
|
|||||||
const githubProvider = await findGithubById(input.githubId);
|
const githubProvider = await findGithubById(input.githubId);
|
||||||
if (
|
if (
|
||||||
githubProvider.gitProvider.organizationId !==
|
githubProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
githubProvider.gitProvider.userId === ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ export const gitlabRouter = createTRPCRouter({
|
|||||||
.input(apiCreateGitlab)
|
.input(apiCreateGitlab)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
try {
|
try {
|
||||||
return await createGitlab(input, ctx.session.activeOrganizationId);
|
return await createGitlab(
|
||||||
|
input,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
ctx.session.userId,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
@@ -40,7 +44,8 @@ export const gitlabRouter = createTRPCRouter({
|
|||||||
const gitlabProvider = await findGitlabById(input.gitlabId);
|
const gitlabProvider = await findGitlabById(input.gitlabId);
|
||||||
if (
|
if (
|
||||||
gitlabProvider.gitProvider.organizationId !==
|
gitlabProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
gitlabProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -56,11 +61,13 @@ export const gitlabRouter = createTRPCRouter({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
result = result.filter(
|
result = result.filter((provider) => {
|
||||||
(provider) =>
|
return (
|
||||||
provider.gitProvider.organizationId ===
|
provider.gitProvider.organizationId ===
|
||||||
ctx.session.activeOrganizationId,
|
ctx.session.activeOrganizationId &&
|
||||||
);
|
provider.gitProvider.userId === ctx.session.userId
|
||||||
|
);
|
||||||
|
});
|
||||||
const filtered = result
|
const filtered = result
|
||||||
.filter((provider) => haveGitlabRequirements(provider))
|
.filter((provider) => haveGitlabRequirements(provider))
|
||||||
.map((provider) => {
|
.map((provider) => {
|
||||||
@@ -80,7 +87,8 @@ export const gitlabRouter = createTRPCRouter({
|
|||||||
const gitlabProvider = await findGitlabById(input.gitlabId);
|
const gitlabProvider = await findGitlabById(input.gitlabId);
|
||||||
if (
|
if (
|
||||||
gitlabProvider.gitProvider.organizationId !==
|
gitlabProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
gitlabProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -96,7 +104,8 @@ export const gitlabRouter = createTRPCRouter({
|
|||||||
const gitlabProvider = await findGitlabById(input.gitlabId || "");
|
const gitlabProvider = await findGitlabById(input.gitlabId || "");
|
||||||
if (
|
if (
|
||||||
gitlabProvider.gitProvider.organizationId !==
|
gitlabProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
gitlabProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -112,7 +121,8 @@ export const gitlabRouter = createTRPCRouter({
|
|||||||
const gitlabProvider = await findGitlabById(input.gitlabId || "");
|
const gitlabProvider = await findGitlabById(input.gitlabId || "");
|
||||||
if (
|
if (
|
||||||
gitlabProvider.gitProvider.organizationId !==
|
gitlabProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
gitlabProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
@@ -135,7 +145,8 @@ export const gitlabRouter = createTRPCRouter({
|
|||||||
const gitlabProvider = await findGitlabById(input.gitlabId);
|
const gitlabProvider = await findGitlabById(input.gitlabId);
|
||||||
if (
|
if (
|
||||||
gitlabProvider.gitProvider.organizationId !==
|
gitlabProvider.gitProvider.organizationId !==
|
||||||
ctx.session.activeOrganizationId
|
ctx.session.activeOrganizationId &&
|
||||||
|
gitlabProvider.gitProvider.userId !== ctx.session.userId
|
||||||
) {
|
) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { bitbucket } from "./bitbucket";
|
|||||||
import { gitea } from "./gitea";
|
import { gitea } from "./gitea";
|
||||||
import { github } from "./github";
|
import { github } from "./github";
|
||||||
import { gitlab } from "./gitlab";
|
import { gitlab } from "./gitlab";
|
||||||
|
import { users_temp } from "./user";
|
||||||
|
|
||||||
export const gitProviderType = pgEnum("gitProviderType", [
|
export const gitProviderType = pgEnum("gitProviderType", [
|
||||||
"github",
|
"github",
|
||||||
@@ -29,6 +30,9 @@ export const gitProvider = pgTable("git_provider", {
|
|||||||
organizationId: text("organizationId")
|
organizationId: text("organizationId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => organization.id, { onDelete: "cascade" }),
|
.references(() => organization.id, { onDelete: "cascade" }),
|
||||||
|
userId: text("userId")
|
||||||
|
.notNull()
|
||||||
|
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
|
export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
|
||||||
@@ -52,6 +56,10 @@ export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
|
|||||||
fields: [gitProvider.organizationId],
|
fields: [gitProvider.organizationId],
|
||||||
references: [organization.id],
|
references: [organization.id],
|
||||||
}),
|
}),
|
||||||
|
user: one(users_temp, {
|
||||||
|
fields: [gitProvider.userId],
|
||||||
|
references: [users_temp.id],
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const createSchema = createInsertSchema(gitProvider);
|
const createSchema = createInsertSchema(gitProvider);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export type Bitbucket = typeof bitbucket.$inferSelect;
|
|||||||
export const createBitbucket = async (
|
export const createBitbucket = async (
|
||||||
input: typeof apiCreateBitbucket._type,
|
input: typeof apiCreateBitbucket._type,
|
||||||
organizationId: string,
|
organizationId: string,
|
||||||
|
userId: string,
|
||||||
) => {
|
) => {
|
||||||
return await db.transaction(async (tx) => {
|
return await db.transaction(async (tx) => {
|
||||||
const newGitProvider = await tx
|
const newGitProvider = await tx
|
||||||
@@ -21,6 +22,7 @@ export const createBitbucket = async (
|
|||||||
providerType: "bitbucket",
|
providerType: "bitbucket",
|
||||||
organizationId: organizationId,
|
organizationId: organizationId,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
userId: userId,
|
||||||
})
|
})
|
||||||
.returning()
|
.returning()
|
||||||
.then((response) => response[0]);
|
.then((response) => response[0]);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type Gitea = typeof gitea.$inferSelect;
|
|||||||
export const createGitea = async (
|
export const createGitea = async (
|
||||||
input: typeof apiCreateGitea._type,
|
input: typeof apiCreateGitea._type,
|
||||||
organizationId: string,
|
organizationId: string,
|
||||||
|
userId: string,
|
||||||
) => {
|
) => {
|
||||||
return await db.transaction(async (tx) => {
|
return await db.transaction(async (tx) => {
|
||||||
const newGitProvider = await tx
|
const newGitProvider = await tx
|
||||||
@@ -20,6 +21,7 @@ export const createGitea = async (
|
|||||||
providerType: "gitea",
|
providerType: "gitea",
|
||||||
organizationId: organizationId,
|
organizationId: organizationId,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
userId: userId,
|
||||||
})
|
})
|
||||||
.returning()
|
.returning()
|
||||||
.then((response) => response[0]);
|
.then((response) => response[0]);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export type Github = typeof github.$inferSelect;
|
|||||||
export const createGithub = async (
|
export const createGithub = async (
|
||||||
input: typeof apiCreateGithub._type,
|
input: typeof apiCreateGithub._type,
|
||||||
organizationId: string,
|
organizationId: string,
|
||||||
|
userId: string,
|
||||||
) => {
|
) => {
|
||||||
return await db.transaction(async (tx) => {
|
return await db.transaction(async (tx) => {
|
||||||
const newGitProvider = await tx
|
const newGitProvider = await tx
|
||||||
@@ -21,6 +22,7 @@ export const createGithub = async (
|
|||||||
providerType: "github",
|
providerType: "github",
|
||||||
organizationId: organizationId,
|
organizationId: organizationId,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
userId: userId,
|
||||||
})
|
})
|
||||||
.returning()
|
.returning()
|
||||||
.then((response) => response[0]);
|
.then((response) => response[0]);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type Gitlab = typeof gitlab.$inferSelect;
|
|||||||
export const createGitlab = async (
|
export const createGitlab = async (
|
||||||
input: typeof apiCreateGitlab._type,
|
input: typeof apiCreateGitlab._type,
|
||||||
organizationId: string,
|
organizationId: string,
|
||||||
|
userId: string,
|
||||||
) => {
|
) => {
|
||||||
return await db.transaction(async (tx) => {
|
return await db.transaction(async (tx) => {
|
||||||
const newGitProvider = await tx
|
const newGitProvider = await tx
|
||||||
@@ -20,6 +21,7 @@ export const createGitlab = async (
|
|||||||
providerType: "gitlab",
|
providerType: "gitlab",
|
||||||
organizationId: organizationId,
|
organizationId: organizationId,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
userId: userId,
|
||||||
})
|
})
|
||||||
.returning()
|
.returning()
|
||||||
.then((response) => response[0]);
|
.then((response) => response[0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user