@@ -281,6 +315,10 @@ export const SaveGiteaProviderCompose = ({ composeId }: Props) => {
key={repo.url}
value={repo.name}
onSelect={() => {
+ console.log(
+ "Repository selected:",
+ repo.name,
+ );
form.setValue("repository", {
owner: repo.owner.username,
repo: repo.name,
diff --git a/apps/dokploy/components/dashboard/compose/general/show-converted-compose.tsx b/apps/dokploy/components/dashboard/compose/general/show-converted-compose.tsx
index 53b2a9a1..70eb1442 100644
--- a/apps/dokploy/components/dashboard/compose/general/show-converted-compose.tsx
+++ b/apps/dokploy/components/dashboard/compose/general/show-converted-compose.tsx
@@ -66,7 +66,7 @@ export const ShowConvertedCompose = ({ composeId }: Props) => {
Preview your docker-compose file with added domains. Note: At least
one domain must be specified for this conversion to take effect.
-
+
{compose !== null ? (
-
-
-
+
+
+
) : (
-
- No compose file available. Make sure at least one domain is configured for this project.
-
+
+ No compose file available. Make sure at least one domain is
+ configured for this project.
+
)}
diff --git a/apps/dokploy/server/api/routers/gitea.ts b/apps/dokploy/server/api/routers/gitea.ts
index c4a89c02..fa4d84da 100644
--- a/apps/dokploy/server/api/routers/gitea.ts
+++ b/apps/dokploy/server/api/routers/gitea.ts
@@ -220,27 +220,27 @@ export const giteaRouter = createTRPCRouter({
getGiteaUrl: protectedProcedure
.input(apiFindOneGitea)
.query(async ({ input, ctx }) => {
- const { giteaId } = input;
-
- if (!giteaId) {
- throw new TRPCError({
- code: "BAD_REQUEST",
- message: "Gitea provider ID is required.",
- });
- }
-
- const giteaProvider = await findGiteaById(giteaId);
- if (
- giteaProvider.gitProvider.organizationId !==
- ctx.session.activeOrganizationId
- ) {
- throw new TRPCError({
- code: "UNAUTHORIZED",
- message: "You are not allowed to access this Gitea provider",
- });
- }
-
- // Return the base URL of the Gitea instance
- return giteaProvider.giteaUrl;
+ const { giteaId } = input;
+
+ if (!giteaId) {
+ throw new TRPCError({
+ code: "BAD_REQUEST",
+ message: "Gitea provider ID is required.",
+ });
+ }
+
+ const giteaProvider = await findGiteaById(giteaId);
+ if (
+ giteaProvider.gitProvider.organizationId !==
+ ctx.session.activeOrganizationId
+ ) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You are not allowed to access this Gitea provider",
+ });
+ }
+
+ // Return the base URL of the Gitea instance
+ return giteaProvider.giteaUrl;
}),
});
diff --git a/packages/server/src/lib/auth.ts b/packages/server/src/lib/auth.ts
index 6695756c..7ff53117 100644
--- a/packages/server/src/lib/auth.ts
+++ b/packages/server/src/lib/auth.ts
@@ -2,16 +2,16 @@ import type { IncomingMessage } from "node:http";
import * as bcrypt from "bcrypt";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
-import { organization, twoFactor, apiKey } from "better-auth/plugins";
+import { APIError } from "better-auth/api";
+import { apiKey, organization, twoFactor } from "better-auth/plugins";
import { and, desc, eq } from "drizzle-orm";
+import { IS_CLOUD } from "../constants";
import { db } from "../db";
import * as schema from "../db/schema";
-import { sendEmail } from "../verification/send-verification-email";
-import { IS_CLOUD } from "../constants";
-import { getPublicIpWithFallback } from "../wss/utils";
-import { updateUser } from "../services/user";
import { getUserByToken } from "../services/admin";
-import { APIError } from "better-auth/api";
+import { updateUser } from "../services/user";
+import { sendEmail } from "../verification/send-verification-email";
+import { getPublicIpWithFallback } from "../wss/utils";
const { handler, api } = betterAuth({
database: drizzleAdapter(db, {
diff --git a/packages/server/src/utils/providers/gitea.ts b/packages/server/src/utils/providers/gitea.ts
index eec59b1e..de28d73f 100644
--- a/packages/server/src/utils/providers/gitea.ts
+++ b/packages/server/src/utils/providers/gitea.ts
@@ -19,8 +19,7 @@ export const getErrorCloneRequirements = (entity: {
giteaBranch?: string | null;
}) => {
const reasons: string[] = [];
- const { giteaBranch, giteaOwner, giteaRepository } =
- entity;
+ const { giteaBranch, giteaOwner, giteaRepository } = entity;
if (!giteaRepository) reasons.push("1. Repository not assigned.");
if (!giteaOwner) reasons.push("2. Owner not specified.");
@@ -41,6 +40,20 @@ export const refreshGiteaToken = async (giteaProviderId: string) => {
return giteaProvider?.accessToken || null;
}
+ // Check if token is still valid (add some buffer time, e.g., 5 minutes)
+ const currentTimeSeconds = Math.floor(Date.now() / 1000);
+ const bufferTimeSeconds = 300; // 5 minutes
+
+ if (
+ giteaProvider.expiresAt &&
+ giteaProvider.expiresAt > currentTimeSeconds + bufferTimeSeconds &&
+ giteaProvider.accessToken
+ ) {
+ // Token is still valid, no need to refresh
+ return giteaProvider.accessToken;
+ }
+
+ // Token is expired or about to expire, refresh it
const tokenEndpoint = `${giteaProvider.giteaUrl}/login/oauth/access_token`;
const params = new URLSearchParams({
grant_type: "refresh_token",
@@ -409,6 +422,8 @@ export const getGiteaBranches = async (input: {
return [];
}
+ await refreshGiteaToken(input.giteaId);
+
const giteaProvider = await findGiteaById(input.giteaId);
const baseUrl = giteaProvider.giteaUrl.replace(/\/+$/, "");