mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
@@ -14,13 +14,18 @@ vi.mock("@dokploy/server/db", () => {
|
||||
set: vi.fn(() => chain),
|
||||
where: vi.fn(() => chain),
|
||||
returning: vi.fn().mockResolvedValue([{}] as any),
|
||||
from: vi.fn(() => chain),
|
||||
innerJoin: vi.fn(() => chain),
|
||||
then: (resolve: (v: any) => void) => {
|
||||
resolve([]);
|
||||
},
|
||||
} as any;
|
||||
return chain;
|
||||
};
|
||||
|
||||
return {
|
||||
db: {
|
||||
select: vi.fn(),
|
||||
select: vi.fn(() => createChainableMock()),
|
||||
insert: vi.fn(),
|
||||
update: vi.fn(() => createChainableMock()),
|
||||
delete: vi.fn(),
|
||||
@@ -31,6 +36,9 @@ vi.mock("@dokploy/server/db", () => {
|
||||
patch: {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
},
|
||||
member: {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,13 +15,18 @@ vi.mock("@dokploy/server/db", () => {
|
||||
set: vi.fn(() => chain),
|
||||
where: vi.fn(() => chain),
|
||||
returning: vi.fn().mockResolvedValue([{}]),
|
||||
from: vi.fn(() => chain),
|
||||
innerJoin: vi.fn(() => chain),
|
||||
then: (resolve: (v: any) => void) => {
|
||||
resolve([]);
|
||||
},
|
||||
};
|
||||
return chain;
|
||||
};
|
||||
|
||||
return {
|
||||
db: {
|
||||
select: vi.fn(),
|
||||
select: vi.fn(() => createChainableMock()),
|
||||
insert: vi.fn(),
|
||||
update: vi.fn(() => createChainableMock()),
|
||||
delete: vi.fn(),
|
||||
@@ -32,6 +37,9 @@ vi.mock("@dokploy/server/db", () => {
|
||||
patch: {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
},
|
||||
member: {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,7 +12,11 @@ vi.mock("@dokploy/server/db", () => {
|
||||
chain.where = () => chain;
|
||||
chain.values = () => chain;
|
||||
chain.returning = () => Promise.resolve([{}]);
|
||||
chain.then = undefined;
|
||||
chain.from = () => chain;
|
||||
chain.innerJoin = () => chain;
|
||||
chain.then = (resolve: (value: unknown) => void) => {
|
||||
resolve([]);
|
||||
};
|
||||
|
||||
const tableMock = {
|
||||
findFirst: vi.fn(() => Promise.resolve(undefined)),
|
||||
@@ -21,7 +25,6 @@ vi.mock("@dokploy/server/db", () => {
|
||||
update: vi.fn(() => chain),
|
||||
delete: vi.fn(() => chain),
|
||||
};
|
||||
const createQueryMock = () => tableMock;
|
||||
|
||||
return {
|
||||
db: {
|
||||
|
||||
@@ -30,7 +30,7 @@ export const AddGithubProvider = () => {
|
||||
const url = document.location.origin;
|
||||
const manifest = JSON.stringify(
|
||||
{
|
||||
redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id}&userId=${session?.user?.id}`,
|
||||
redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id ?? ""}&userId=${session?.user?.id ?? ""}`,
|
||||
name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}-${randomString()}`,
|
||||
url: origin,
|
||||
hook_attributes: {
|
||||
@@ -52,7 +52,7 @@ export const AddGithubProvider = () => {
|
||||
);
|
||||
|
||||
setManifest(manifest);
|
||||
}, [data?.id]);
|
||||
}, [data?.id, activeOrganization?.id, session?.user?.id]);
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
@@ -131,7 +131,11 @@ export const AddGithubProvider = () => {
|
||||
Unsure if you already have an app?
|
||||
</a>
|
||||
<Button
|
||||
disabled={isOrganization && organizationName.length < 1}
|
||||
disabled={
|
||||
(isOrganization && organizationName.length < 1) ||
|
||||
!activeOrganization?.id ||
|
||||
!session?.user?.id
|
||||
}
|
||||
type="submit"
|
||||
className="self-end"
|
||||
>
|
||||
|
||||
@@ -32,7 +32,6 @@ interface Props {
|
||||
}
|
||||
|
||||
export const BreadcrumbSidebar = ({ list }: Props) => {
|
||||
console.log(list);
|
||||
return (
|
||||
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
|
||||
<div className="flex items-center justify-between w-full">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dokploy",
|
||||
"version": "v0.28.1",
|
||||
"version": "v0.28.2",
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# Proprietary Features
|
||||
|
||||
This directory contains all proprietary functionality of Dokploy.
|
||||
|
||||
## Purpose
|
||||
|
||||
This folder will house all **paid features** and premium functionality that are not part of the open source code.
|
||||
|
||||
## License
|
||||
|
||||
The code in this directory is under Dokploy's proprietary license. See [LICENSE_PROPRIETARY.md](../../../LICENSE_PROPRIETARY.md) for more details.
|
||||
|
||||
## Contact
|
||||
|
||||
If you want to learn more about our paid features or have any questions, please contact us at:
|
||||
|
||||
- Email: [sales@dokploy.com](mailto:sales@dokploy.com)
|
||||
- Contact Form: [https://dokploy.com/contact](https://dokploy.com/contact)
|
||||
38
apps/dokploy/server/db/index.ts
Normal file
38
apps/dokploy/server/db/index.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { dbUrl } from "@dokploy/server/db/constants";
|
||||
import * as schema from "@dokploy/server/db/schema";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { drizzle, type PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
||||
import postgres from "postgres";
|
||||
|
||||
export { and, eq };
|
||||
|
||||
type Database = PostgresJsDatabase<typeof schema>;
|
||||
/**
|
||||
* Evita problemas de redeclaración global en monorepos.
|
||||
* No usamos `declare global`.
|
||||
*/
|
||||
const globalForDb = globalThis as unknown as {
|
||||
db?: Database;
|
||||
};
|
||||
|
||||
let dbConnection: Database;
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
// En producción no usamos global cache
|
||||
dbConnection = drizzle(postgres(dbUrl), {
|
||||
schema,
|
||||
});
|
||||
} else {
|
||||
// En desarrollo reutilizamos conexión para evitar múltiples conexiones
|
||||
if (!globalForDb.db) {
|
||||
globalForDb.db = drizzle(postgres(dbUrl), {
|
||||
schema,
|
||||
});
|
||||
}
|
||||
|
||||
dbConnection = globalForDb.db;
|
||||
}
|
||||
|
||||
export const db: Database = dbConnection;
|
||||
|
||||
export { dbUrl };
|
||||
@@ -73,23 +73,25 @@ const { handler, api } = betterAuth({
|
||||
disabled: process.env.NODE_ENV === "production",
|
||||
},
|
||||
async trustedOrigins() {
|
||||
const trustedOrigins = await getTrustedOrigins();
|
||||
if (IS_CLOUD) {
|
||||
return trustedOrigins;
|
||||
return getTrustedOrigins();
|
||||
}
|
||||
const settings = await getWebServerSettings();
|
||||
if (!settings) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
...(settings?.serverIp ? [`http://${settings?.serverIp}:3000`] : []),
|
||||
...(settings?.host ? [`https://${settings?.host}`] : []),
|
||||
...(process.env.NODE_ENV === "development"
|
||||
const [trustedOrigins, settings] = await Promise.all([
|
||||
getTrustedOrigins(),
|
||||
getWebServerSettings(),
|
||||
]);
|
||||
if (!settings) return [];
|
||||
const devOrigins =
|
||||
process.env.NODE_ENV === "development"
|
||||
? [
|
||||
"http://localhost:3000",
|
||||
"https://absolutely-handy-falcon.ngrok-free.app",
|
||||
]
|
||||
: []),
|
||||
: [];
|
||||
return [
|
||||
...(settings?.serverIp ? [`http://${settings?.serverIp}:3000`] : []),
|
||||
...(settings?.host ? [`https://${settings?.host}`] : []),
|
||||
...devOrigins,
|
||||
...trustedOrigins,
|
||||
];
|
||||
},
|
||||
|
||||
@@ -117,23 +117,33 @@ export const getDokployUrl = async () => {
|
||||
return `http://${settings?.serverIp}:${process.env.PORT}`;
|
||||
};
|
||||
|
||||
export const getTrustedOrigins = async () => {
|
||||
const members = await db.query.member.findMany({
|
||||
where: eq(member.role, "owner"),
|
||||
with: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
const TRUSTED_ORIGINS_CACHE_TTL_MS = 30 * 60_000;
|
||||
let trustedOriginsCache: { data: string[]; expiresAt: number } | null = null;
|
||||
|
||||
if (members.length === 0) {
|
||||
return [];
|
||||
export const getTrustedOrigins = async () => {
|
||||
const runQuery = async () => {
|
||||
const rows = await db
|
||||
.select({ trustedOrigins: user.trustedOrigins })
|
||||
.from(member)
|
||||
.innerJoin(user, eq(member.userId, user.id))
|
||||
.where(eq(member.role, "owner"));
|
||||
return Array.from(new Set(rows.flatMap((r) => r.trustedOrigins ?? [])));
|
||||
};
|
||||
|
||||
if (IS_CLOUD) {
|
||||
const now = Date.now();
|
||||
if (trustedOriginsCache && now < trustedOriginsCache.expiresAt) {
|
||||
return trustedOriginsCache.data;
|
||||
}
|
||||
const trustedOrigins = await runQuery();
|
||||
trustedOriginsCache = {
|
||||
data: trustedOrigins,
|
||||
expiresAt: now + TRUSTED_ORIGINS_CACHE_TTL_MS,
|
||||
};
|
||||
return trustedOrigins;
|
||||
}
|
||||
|
||||
const trustedOrigins = members.flatMap(
|
||||
(member) => member.user.trustedOrigins || [],
|
||||
);
|
||||
|
||||
return Array.from(new Set(trustedOrigins));
|
||||
return runQuery();
|
||||
};
|
||||
|
||||
export const getTrustedProviders = async () => {
|
||||
|
||||
@@ -106,10 +106,6 @@ export const writeDomainsToCompose = async (
|
||||
compose: Compose,
|
||||
domains: Domain[],
|
||||
) => {
|
||||
if (!domains.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
const composeConverted = await addDomainToCompose(compose, domains);
|
||||
const path = getComposePath(compose);
|
||||
@@ -145,7 +141,7 @@ export const addDomainToCompose = async (
|
||||
result = await loadDockerCompose(compose);
|
||||
}
|
||||
|
||||
if (!result || domains.length === 0) {
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user