mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-11 14:35:17 +00:00
Simplify Gitea authorization flow with shared utilities
This commit is contained in:
@@ -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<typeof Schema>;
|
||||
|
||||
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<Schema>({
|
||||
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 = () => {
|
||||
<span>Gitea</span>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-2xl overflow-y-auto max-h-screen ">
|
||||
<DialogContent className="sm:max-w-2xl overflow-y-auto max-h-screen">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
Gitea Provider <GiteaIcon className="size-5" />
|
||||
|
||||
@@ -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 (
|
||||
<Button variant="ghost" size="icon" disabled>
|
||||
@@ -282,7 +261,13 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
const authUrl = getGiteaOAuthUrl();
|
||||
const formValues = form.getValues();
|
||||
const authUrl = getGiteaOAuthUrl(
|
||||
giteaId,
|
||||
formValues.clientId,
|
||||
formValues.giteaUrl,
|
||||
typeof url === "string" ? url : (url as any).url || "",
|
||||
);
|
||||
if (authUrl !== "#") {
|
||||
window.open(authUrl, "_blank");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user