diff --git a/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts b/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts index ecfbc380d..4849a0ba7 100644 --- a/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts +++ b/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts @@ -42,6 +42,7 @@ const ENTERPRISE_RESOURCES = [ "auditLog", "vaultProvider", "dnsProvider", + "ai", ]; describe("enterpriseOnlyResources set", () => { diff --git a/apps/dokploy/__test__/utils/remote-stream.test.ts b/apps/dokploy/__test__/utils/remote-stream.test.ts index 6f7a3b358..e428de9f3 100644 --- a/apps/dokploy/__test__/utils/remote-stream.test.ts +++ b/apps/dokploy/__test__/utils/remote-stream.test.ts @@ -16,7 +16,7 @@ describe("pipeBetweenServers", () => { target: { serverId: null, command: "sleep 0.3; cat > /dev/null" }, }); expect(bytes).toBe(11); - }); + }, 30_000); it("pipes data larger than the pipe buffer unchanged", async () => { const dir = await fs.mkdtemp(path.join(os.tmpdir(), "pipe-")); @@ -47,7 +47,7 @@ describe("pipeBetweenServers", () => { target: { serverId: null, command: "echo boom >&2; exit 3" }, }), ).rejects.toThrow("target exited with code 3: boom"); - }); + }, 30_000); it("reports a source failure", async () => { await expect( @@ -56,5 +56,5 @@ describe("pipeBetweenServers", () => { target: { serverId: null, command: "cat > /dev/null" }, }), ).rejects.toThrow("source exited with code 2"); - }); + }, 30_000); }); diff --git a/apps/dokploy/components/dashboard/settings/ai-form.tsx b/apps/dokploy/components/dashboard/settings/ai-form.tsx index 797aad23c..abe1a1c3e 100644 --- a/apps/dokploy/components/dashboard/settings/ai-form.tsx +++ b/apps/dokploy/components/dashboard/settings/ai-form.tsx @@ -18,7 +18,9 @@ import { HandleAiProviders } from "./handle-ai-providers"; export const AiForm = () => { const { data: aiConfigs, refetch, isPending } = api.ai.getAll.useQuery(); const { mutateAsync, isPending: isRemoving } = api.ai.delete.useMutation(); + const { data: permissions } = api.user.getPermissions.useQuery(); const { data: currentUser } = api.user.get.useQuery(); + const isOrgAdmin = currentUser?.role === "owner" || currentUser?.role === "admin"; @@ -36,7 +38,9 @@ export const AiForm = () => {
{isOrgAdmin && } - {aiConfigs && aiConfigs?.length > 0 && } + {permissions?.ai.create && aiConfigs && aiConfigs?.length > 0 && ( + + )}
@@ -53,7 +57,7 @@ export const AiForm = () => { You don't have any AI configurations - + {permissions?.ai.create && } ) : (
@@ -70,33 +74,37 @@ export const AiForm = () => { {config.model}
- - { - await mutateAsync({ - aiId: config.aiId, - }) - .then(() => { - toast.success("AI deleted successfully"); - refetch(); + {permissions?.ai.update && ( + + )} + {permissions?.ai.delete && ( + { + await mutateAsync({ + aiId: config.aiId, }) - .catch(() => { - toast.error("Error deleting AI"); - }); - }} - > - - + + + )}
diff --git a/apps/dokploy/components/dashboard/settings/handle-ai.tsx b/apps/dokploy/components/dashboard/settings/handle-ai.tsx index b7cf186e7..0cd73d82a 100644 --- a/apps/dokploy/components/dashboard/settings/handle-ai.tsx +++ b/apps/dokploy/components/dashboard/settings/handle-ai.tsx @@ -148,6 +148,7 @@ export const HandleAi = ({ aiId }: Props) => { { apiUrl: apiUrl ?? "", apiKey: apiKey ?? "", + ...(aiId ? { aiId } : {}), }, { enabled: !!apiUrl && (isLocalOllama || !!apiKey), @@ -482,6 +483,7 @@ export const HandleAi = ({ aiId }: Props) => { apiUrl={apiUrl} apiKey={apiKey} model={form.watch("model")} + aiId={aiId} />