diff --git a/apps/dokploy/components/dashboard/application/general/generic/save-gitea-provider.tsx b/apps/dokploy/components/dashboard/application/general/generic/save-gitea-provider.tsx
index 60565824..90de6b6b 100644
--- a/apps/dokploy/components/dashboard/application/general/generic/save-gitea-provider.tsx
+++ b/apps/dokploy/components/dashboard/application/general/generic/save-gitea-provider.tsx
@@ -1,4 +1,5 @@
import { AlertBlock } from "@/components/shared/alert-block";
+import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Command,
@@ -35,7 +36,6 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
-import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -433,7 +433,7 @@ export const SaveGiteaProvider = ({ applicationId }: Props) => {
- {field.value && field.value.map((path: string, index: number) => (
+ {field.value?.map((path: string, index: number) => (
{
);
-};
\ No newline at end of file
+};
diff --git a/apps/dokploy/components/dashboard/compose/general/generic/save-gitea-provider-compose.tsx b/apps/dokploy/components/dashboard/compose/general/generic/save-gitea-provider-compose.tsx
index 5059672e..dce6e4f7 100644
--- a/apps/dokploy/components/dashboard/compose/general/generic/save-gitea-provider-compose.tsx
+++ b/apps/dokploy/components/dashboard/compose/general/generic/save-gitea-provider-compose.tsx
@@ -39,6 +39,7 @@ import {
} from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
import { api } from "@/utils/api";
+import type { Branch, Repository } from "@/utils/gitea-utils";
import { zodResolver } from "@hookform/resolvers/zod";
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
import Link from "next/link";
@@ -47,31 +48,6 @@ import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
-interface Repository {
- name: string;
- url: string;
- id: number;
- owner: {
- username: string;
- };
-}
-
-interface Branch {
- name: string;
-}
-
-interface GiteaProviderType {
- giteaId: string;
- gitProvider: {
- name: string;
- gitProviderId: string;
- providerType: "github" | "gitlab" | "bitbucket" | "gitea";
- createdAt: string;
- organizationId: string;
- };
- name: string;
-}
-
const GiteaProviderSchema = z.object({
composePath: z.string().min(1),
repository: z
diff --git a/apps/dokploy/components/dashboard/compose/general/generic/show.tsx b/apps/dokploy/components/dashboard/compose/general/generic/show.tsx
index 340037ad..939befac 100644
--- a/apps/dokploy/components/dashboard/compose/general/generic/show.tsx
+++ b/apps/dokploy/components/dashboard/compose/general/generic/show.tsx
@@ -1,16 +1,16 @@
import {
BitbucketIcon,
+ GitIcon,
GiteaIcon,
GithubIcon,
GitlabIcon,
- GitIcon,
- } from "@/components/icons/data-tools-icons";
+} from "@/components/icons/data-tools-icons";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { api } from "@/utils/api";
import { CodeIcon, GitBranch } from "lucide-react";
import Link from "next/link";
-import { useState, useEffect } from "react";
+import { useState } from "react";
import { ComposeFileEditor } from "../compose-file-editor";
import { ShowConvertedCompose } from "../show-converted-compose";
import { SaveBitbucketProviderCompose } from "./save-bitbucket-provider-compose";
@@ -18,141 +18,174 @@ import { SaveGitProviderCompose } from "./save-git-provider-compose";
import { SaveGiteaProviderCompose } from "./save-gitea-provider-compose";
import { SaveGithubProviderCompose } from "./save-github-provider-compose";
import { SaveGitlabProviderCompose } from "./save-gitlab-provider-compose";
-
- type TabState = "github" | "git" | "raw" | "gitlab" | "bitbucket" | "gitea"; // Adding gitea to the TabState
- interface Props {
+
+type TabState = "github" | "git" | "raw" | "gitlab" | "bitbucket" | "gitea"; // Adding gitea to the TabState
+interface Props {
composeId: string;
- }
-
- export const ShowProviderFormCompose = ({ composeId }: Props) => {
+}
+
+export const ShowProviderFormCompose = ({ composeId }: Props) => {
const { data: githubProviders } = api.github.githubProviders.useQuery();
const { data: gitlabProviders } = api.gitlab.gitlabProviders.useQuery();
- const { data: bitbucketProviders } = api.bitbucket.bitbucketProviders.useQuery();
+ const { data: bitbucketProviders } =
+ api.bitbucket.bitbucketProviders.useQuery();
const { data: giteaProviders } = api.gitea.giteaProviders.useQuery(); // Fetching Gitea providers
-
+
const { data: compose } = api.compose.one.useQuery({ composeId });
const [tab, setSab] = useState(compose?.sourceType || "github");
-
+
// Ensure we fall back to empty arrays if the data is undefined
const safeGithubProviders = githubProviders || [];
const safeGitlabProviders = gitlabProviders || [];
const safeBitbucketProviders = bitbucketProviders || [];
const safeGiteaProviders = giteaProviders || [];
-
- const renderProviderContent = (providers: any[], providerType: string, ProviderComponent: React.ComponentType) => {
- if (providers.length > 0) {
- return ;
- } else {
+
+ const renderProviderContent = (
+ providers: any[],
+ providerType: string,
+ ProviderComponent: React.ComponentType,
+ ) => {
+ if (providers.length > 0) {
+ return ;
+ }
+
return (
-
- {providerType === "github" && }
- {providerType === "gitlab" && }
- {providerType === "bitbucket" && }
- {providerType === "gitea" && }
-
- To deploy using {providerType.charAt(0).toUpperCase() + providerType.slice(1)}, you need to configure your account first.
- Please, go to{" "}
-
- Settings
- {" "}
- to do so.
-
-
+
+ {providerType === "github" && (
+
+ )}
+ {providerType === "gitlab" && (
+
+ )}
+ {providerType === "bitbucket" && (
+
+ )}
+ {providerType === "gitea" && (
+
+ )}
+
+ To deploy using{" "}
+ {providerType.charAt(0).toUpperCase() + providerType.slice(1)}, you
+ need to configure your account first. Please, go to{" "}
+
+ Settings
+ {" "}
+ to do so.
+
+
);
- }
};
-
+
return (
-
-
-
-
-
Provider
-
- Select the source of your code
-
-
-
-
-
-
-
-
-
- {
- setSab(e as TabState);
- }}
- >
-
-
-
+
+
+
+
Provider
+
+ Select the source of your code
+
+
+
+
+
+
+
+
+
+ {
+ setSab(e as TabState);
+ }}
>
-
- GitHub
-
-
-
- GitLab
-
-
-
- Bitbucket
-
-
- Gitea
-
-
-
- Git
-
-
-
- Raw
-
-
-
-
-
- {renderProviderContent(safeGithubProviders, "github", SaveGithubProviderCompose)}
-
-
- {renderProviderContent(safeGiteaProviders, "gitea", SaveGiteaProviderCompose)}
-
-
- {renderProviderContent(safeGitlabProviders, "gitlab", SaveGitlabProviderCompose)}
-
-
- {renderProviderContent(safeBitbucketProviders, "bitbucket", SaveBitbucketProviderCompose)}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ GitHub
+
+
+
+ GitLab
+
+
+
+ Bitbucket
+
+
+ Gitea
+
+
+
+ Git
+
+
+
+ Raw
+
+
+
+
+
+ {renderProviderContent(
+ safeGithubProviders,
+ "github",
+ SaveGithubProviderCompose,
+ )}
+
+
+ {renderProviderContent(
+ safeGiteaProviders,
+ "gitea",
+ SaveGiteaProviderCompose,
+ )}
+
+
+ {renderProviderContent(
+ safeGitlabProviders,
+ "gitlab",
+ SaveGitlabProviderCompose,
+ )}
+
+
+ {renderProviderContent(
+ safeBitbucketProviders,
+ "bitbucket",
+ SaveBitbucketProviderCompose,
+ )}
+
+
+
+
+
+
+
+
+
+
+
);
- };
\ No newline at end of file
+};
diff --git a/apps/dokploy/components/dashboard/settings/git/gitea/add-gitea-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitea/add-gitea-provider.tsx
index 407486c0..13c65bdf 100644
--- a/apps/dokploy/components/dashboard/settings/git/gitea/add-gitea-provider.tsx
+++ b/apps/dokploy/components/dashboard/settings/git/gitea/add-gitea-provider.tsx
@@ -1,4 +1,4 @@
-import { GiteaIcon } from "@/components/icons/data-tools-icons"; // Use GiteaIcon for Gitea
+import { GiteaIcon } from "@/components/icons/data-tools-icons";
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
import { CardContent } from "@/components/ui/card";
@@ -19,9 +19,12 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
+import {
+ type GiteaProviderResponse,
+ getGiteaOAuthUrl,
+} from "@/utils/gitea-utils";
import { useUrl } from "@/utils/hooks/use-url";
import { zodResolver } from "@hookform/resolvers/zod";
-
import { ExternalLink } from "lucide-react";
import Link from "next/link";
import { useEffect, useState } from "react";
@@ -51,11 +54,14 @@ const Schema = z.object({
type Schema = z.infer;
export const AddGiteaProvider = () => {
- const utils = api.useUtils();
const [isOpen, setIsOpen] = useState(false);
- const url = useUrl();
+
+ const urlObj = useUrl();
+ const baseUrl =
+ typeof urlObj === "string" ? urlObj : (urlObj as any)?.url || "";
+
const { mutateAsync, error, isError } = api.gitea.create.useMutation();
- const webhookUrl = `${url}/api/providers/gitea/callback`;
+ const webhookUrl = `${baseUrl}/api/providers/gitea/callback`;
const form = useForm({
defaultValues: {
@@ -78,24 +84,52 @@ export const AddGiteaProvider = () => {
name: "",
giteaUrl: "https://gitea.com",
});
- }, [form, isOpen]);
+ }, [form, webhookUrl, isOpen]);
const onSubmit = async (data: Schema) => {
- await mutateAsync({
- clientId: data.clientId || "",
- clientSecret: data.clientSecret || "",
- name: data.name || "",
- redirectUri: data.redirectUri || "",
- giteaUrl: data.giteaUrl || "https://gitea.com",
- })
- .then(async () => {
- await utils.gitProvider.getAll.invalidate();
- toast.success("Gitea provider created successfully");
- setIsOpen(false);
- })
- .catch(() => {
- toast.error("Error configuring Gitea");
- });
+ try {
+ // Send the form data to create the Gitea provider
+ const result = (await mutateAsync({
+ clientId: data.clientId,
+ clientSecret: data.clientSecret,
+ name: data.name,
+ redirectUri: data.redirectUri,
+ giteaUrl: data.giteaUrl,
+ organizationName: data.organizationName,
+ })) as unknown as GiteaProviderResponse;
+
+ // Check if we have a giteaId from the response
+ if (!result || !result.giteaId) {
+ toast.error("Failed to get Gitea ID from response");
+ return;
+ }
+
+ // Generate OAuth URL using the shared utility
+ const authUrl = getGiteaOAuthUrl(
+ result.giteaId,
+ data.clientId,
+ data.giteaUrl,
+ baseUrl,
+ );
+
+ // Open the Gitea OAuth URL
+ if (authUrl !== "#") {
+ window.open(authUrl, "_blank");
+ } else {
+ toast.error("Configuration Incomplete", {
+ description: "Please fill in Client ID and Gitea URL first.",
+ });
+ }
+
+ toast.success("Gitea provider created successfully");
+ setIsOpen(false);
+ } catch (error: unknown) {
+ if (error instanceof Error) {
+ toast.error(`Error configuring Gitea: ${error.message}`);
+ } else {
+ toast.error("An unknown error occurred.");
+ }
+ }
};
return (
@@ -109,7 +143,7 @@ export const AddGiteaProvider = () => {
Gitea
-
+
Gitea Provider
diff --git a/apps/dokploy/components/dashboard/settings/git/gitea/edit-gitea-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitea/edit-gitea-provider.tsx
index b56c4845..1b05b82d 100644
--- a/apps/dokploy/components/dashboard/settings/git/gitea/edit-gitea-provider.tsx
+++ b/apps/dokploy/components/dashboard/settings/git/gitea/edit-gitea-provider.tsx
@@ -17,6 +17,7 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
+import { getGiteaOAuthUrl } from "@/utils/gitea-utils";
import { useUrl } from "@/utils/hooks/use-url";
import { zodResolver } from "@hookform/resolvers/zod";
import { PenBoxIcon } from "lucide-react";
@@ -55,7 +56,6 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
useEffect(() => {
const { connected, error } = router.query;
- // Only process if router is ready and query parameters exist
if (!router.isReady) return;
if (connected) {
@@ -64,7 +64,6 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
id: "gitea-connection-success",
});
refetch();
- // Clear the query parameters to prevent re-triggering
router.replace(
{
pathname: router.pathname,
@@ -80,7 +79,6 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
description: decodeURIComponent(error as string),
id: "gitea-connection-error",
});
- // Clear the query parameters to prevent re-triggering
router.replace(
{
pathname: router.pathname,
@@ -102,7 +100,6 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
},
});
- // Update form values when data is loaded
useEffect(() => {
if (gitea) {
form.reset({
@@ -141,7 +138,15 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
description: result,
});
} catch (error: any) {
- const authUrl = error.authorizationUrl || getGiteaOAuthUrl();
+ const formValues = form.getValues();
+ const authUrl =
+ error.authorizationUrl ||
+ getGiteaOAuthUrl(
+ giteaId,
+ formValues.clientId,
+ formValues.giteaUrl,
+ typeof url === "string" ? url : (url as any).url || "",
+ );
toast.error("Gitea Not Connected", {
description:
@@ -157,32 +162,6 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
}
};
- // Generate Gitea OAuth URL with state parameter
- const getGiteaOAuthUrl = () => {
- const clientId = form.getValues().clientId;
- const giteaUrl = form.getValues().giteaUrl;
-
- if (!clientId || !giteaUrl) {
- toast.error("Configuration Incomplete", {
- description: "Please fill in Client ID and Gitea URL first.",
- });
- return "#";
- }
-
- const redirectUri = `${url}/api/providers/gitea/callback`;
-
- // Use the scopes from the gitea data (if available), else fallback to default scopes
- const scopes =
- gitea?.scopes?.split(",").join(" ") ||
- "repo repo:status read:user read:org";
- //const scopes = gitea?.scopes || 'repo,repo:status,read:user,read:org';
-
- const state = giteaId;
-
- return `${giteaUrl}/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&scope=${encodeURIComponent(scopes)}&state=${encodeURIComponent(state)}`;
- };
-
- // Show loading state if data is being fetched
if (isLoading) {
return (