mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-07 23:15:27 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d56544c1d | ||
|
|
ca527ab6ff | ||
|
|
439fa17292 | ||
|
|
096c04486c | ||
|
|
c9e1079076 | ||
|
|
e29a86a85f | ||
|
|
1ba0eb0c2e | ||
|
|
d7dc10993e | ||
|
|
2a5d3975e8 | ||
|
|
9f3356ddb4 | ||
|
|
f5674f5bf8 |
@@ -14,13 +14,18 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
set: vi.fn(() => chain),
|
set: vi.fn(() => chain),
|
||||||
where: vi.fn(() => chain),
|
where: vi.fn(() => chain),
|
||||||
returning: vi.fn().mockResolvedValue([{}] as any),
|
returning: vi.fn().mockResolvedValue([{}] as any),
|
||||||
|
from: vi.fn(() => chain),
|
||||||
|
innerJoin: vi.fn(() => chain),
|
||||||
|
then: (resolve: (v: any) => void) => {
|
||||||
|
resolve([]);
|
||||||
|
},
|
||||||
} as any;
|
} as any;
|
||||||
return chain;
|
return chain;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db: {
|
db: {
|
||||||
select: vi.fn(),
|
select: vi.fn(() => createChainableMock()),
|
||||||
insert: vi.fn(),
|
insert: vi.fn(),
|
||||||
update: vi.fn(() => createChainableMock()),
|
update: vi.fn(() => createChainableMock()),
|
||||||
delete: vi.fn(),
|
delete: vi.fn(),
|
||||||
@@ -31,6 +36,9 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
patch: {
|
patch: {
|
||||||
findMany: vi.fn().mockResolvedValue([]),
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
},
|
},
|
||||||
|
member: {
|
||||||
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,13 +15,18 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
set: vi.fn(() => chain),
|
set: vi.fn(() => chain),
|
||||||
where: vi.fn(() => chain),
|
where: vi.fn(() => chain),
|
||||||
returning: vi.fn().mockResolvedValue([{}]),
|
returning: vi.fn().mockResolvedValue([{}]),
|
||||||
|
from: vi.fn(() => chain),
|
||||||
|
innerJoin: vi.fn(() => chain),
|
||||||
|
then: (resolve: (v: any) => void) => {
|
||||||
|
resolve([]);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return chain;
|
return chain;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db: {
|
db: {
|
||||||
select: vi.fn(),
|
select: vi.fn(() => createChainableMock()),
|
||||||
insert: vi.fn(),
|
insert: vi.fn(),
|
||||||
update: vi.fn(() => createChainableMock()),
|
update: vi.fn(() => createChainableMock()),
|
||||||
delete: vi.fn(),
|
delete: vi.fn(),
|
||||||
@@ -32,6 +37,9 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
patch: {
|
patch: {
|
||||||
findMany: vi.fn().mockResolvedValue([]),
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
},
|
},
|
||||||
|
member: {
|
||||||
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
chain.where = () => chain;
|
chain.where = () => chain;
|
||||||
chain.values = () => chain;
|
chain.values = () => chain;
|
||||||
chain.returning = () => Promise.resolve([{}]);
|
chain.returning = () => Promise.resolve([{}]);
|
||||||
chain.then = undefined;
|
chain.from = () => chain;
|
||||||
|
chain.innerJoin = () => chain;
|
||||||
|
chain.then = (resolve: (value: unknown) => void) => {
|
||||||
|
resolve([]);
|
||||||
|
};
|
||||||
|
|
||||||
const tableMock = {
|
const tableMock = {
|
||||||
findFirst: vi.fn(() => Promise.resolve(undefined)),
|
findFirst: vi.fn(() => Promise.resolve(undefined)),
|
||||||
@@ -21,7 +25,6 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
update: vi.fn(() => chain),
|
update: vi.fn(() => chain),
|
||||||
delete: vi.fn(() => chain),
|
delete: vi.fn(() => chain),
|
||||||
};
|
};
|
||||||
const createQueryMock = () => tableMock;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db: {
|
db: {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const AddGithubProvider = () => {
|
|||||||
const url = document.location.origin;
|
const url = document.location.origin;
|
||||||
const manifest = JSON.stringify(
|
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()}`,
|
name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}-${randomString()}`,
|
||||||
url: origin,
|
url: origin,
|
||||||
hook_attributes: {
|
hook_attributes: {
|
||||||
@@ -52,7 +52,7 @@ export const AddGithubProvider = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
setManifest(manifest);
|
setManifest(manifest);
|
||||||
}, [data?.id]);
|
}, [data?.id, activeOrganization?.id, session?.user?.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
@@ -131,7 +131,11 @@ export const AddGithubProvider = () => {
|
|||||||
Unsure if you already have an app?
|
Unsure if you already have an app?
|
||||||
</a>
|
</a>
|
||||||
<Button
|
<Button
|
||||||
disabled={isOrganization && organizationName.length < 1}
|
disabled={
|
||||||
|
(isOrganization && organizationName.length < 1) ||
|
||||||
|
!activeOrganization?.id ||
|
||||||
|
!session?.user?.id
|
||||||
|
}
|
||||||
type="submit"
|
type="submit"
|
||||||
className="self-end"
|
className="self-end"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BreadcrumbSidebar = ({ list }: Props) => {
|
export const BreadcrumbSidebar = ({ list }: Props) => {
|
||||||
console.log(list);
|
|
||||||
return (
|
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">
|
<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">
|
<div className="flex items-center justify-between w-full">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dokploy",
|
"name": "dokploy",
|
||||||
"version": "v0.28.1",
|
"version": "v0.28.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"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",
|
disabled: process.env.NODE_ENV === "production",
|
||||||
},
|
},
|
||||||
async trustedOrigins() {
|
async trustedOrigins() {
|
||||||
const trustedOrigins = await getTrustedOrigins();
|
|
||||||
if (IS_CLOUD) {
|
if (IS_CLOUD) {
|
||||||
return trustedOrigins;
|
return getTrustedOrigins();
|
||||||
}
|
}
|
||||||
const settings = await getWebServerSettings();
|
const [trustedOrigins, settings] = await Promise.all([
|
||||||
if (!settings) {
|
getTrustedOrigins(),
|
||||||
return [];
|
getWebServerSettings(),
|
||||||
}
|
]);
|
||||||
return [
|
if (!settings) return [];
|
||||||
...(settings?.serverIp ? [`http://${settings?.serverIp}:3000`] : []),
|
const devOrigins =
|
||||||
...(settings?.host ? [`https://${settings?.host}`] : []),
|
process.env.NODE_ENV === "development"
|
||||||
...(process.env.NODE_ENV === "development"
|
|
||||||
? [
|
? [
|
||||||
"http://localhost:3000",
|
"http://localhost:3000",
|
||||||
"https://absolutely-handy-falcon.ngrok-free.app",
|
"https://absolutely-handy-falcon.ngrok-free.app",
|
||||||
]
|
]
|
||||||
: []),
|
: [];
|
||||||
|
return [
|
||||||
|
...(settings?.serverIp ? [`http://${settings?.serverIp}:3000`] : []),
|
||||||
|
...(settings?.host ? [`https://${settings?.host}`] : []),
|
||||||
|
...devOrigins,
|
||||||
...trustedOrigins,
|
...trustedOrigins,
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -117,23 +117,33 @@ export const getDokployUrl = async () => {
|
|||||||
return `http://${settings?.serverIp}:${process.env.PORT}`;
|
return `http://${settings?.serverIp}:${process.env.PORT}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTrustedOrigins = async () => {
|
const TRUSTED_ORIGINS_CACHE_TTL_MS = 30 * 60_000;
|
||||||
const members = await db.query.member.findMany({
|
let trustedOriginsCache: { data: string[]; expiresAt: number } | null = null;
|
||||||
where: eq(member.role, "owner"),
|
|
||||||
with: {
|
|
||||||
user: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (members.length === 0) {
|
export const getTrustedOrigins = async () => {
|
||||||
return [];
|
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(
|
return runQuery();
|
||||||
(member) => member.user.trustedOrigins || [],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Array.from(new Set(trustedOrigins));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTrustedProviders = async () => {
|
export const getTrustedProviders = async () => {
|
||||||
|
|||||||
@@ -106,10 +106,6 @@ export const writeDomainsToCompose = async (
|
|||||||
compose: Compose,
|
compose: Compose,
|
||||||
domains: Domain[],
|
domains: Domain[],
|
||||||
) => {
|
) => {
|
||||||
if (!domains.length) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const composeConverted = await addDomainToCompose(compose, domains);
|
const composeConverted = await addDomainToCompose(compose, domains);
|
||||||
const path = getComposePath(compose);
|
const path = getComposePath(compose);
|
||||||
@@ -145,7 +141,7 @@ export const addDomainToCompose = async (
|
|||||||
result = await loadDockerCompose(compose);
|
result = await loadDockerCompose(compose);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result || domains.length === 0) {
|
if (!result) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user