Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
1f1acac
fix(settings): confine Traefik file read/write to the Traefik config …
bunlongheng Aug 12, 2026
5e0b021
fix(deps): resolve open Dependabot alerts
narcisonunez Sep 23, 2026
a4a13b9
fix(ui): resolve tooltips overlapping open modals on remote servers page
imrja8 Oct 4, 2026
35d26a8
fix(ui): prevent tooltips from getting stuck when server modals close
imrja8 Oct 4, 2026
2bc3741
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 4, 2026
5c19d1b
fix(terminal): prevent terminal from collapsing on zoom
imrja8 Oct 4, 2026
06b3bb2
fix(libsql): validate appName like the other database kinds
cevheri Oct 4, 2026
20575da
Merge pull request #5582 from imrja8/fix/terminal-collapse-on-zoom
narcisonunez Oct 5, 2026
5aa28bc
Merge pull request #5575 from imrja8/fix/tooltip-overlapping-modals
narcisonunez Oct 5, 2026
5ccc15f
fix(ui): prevent service header overflow on mobile
GlebsonS4ntos Oct 5, 2026
5be17d3
Merge pull request #5584 from libredb/fix/libsql-app-name-validation
Siumauricio Oct 5, 2026
949ac8e
fix(ui): prevent mobile service header overflow
GlebsonS4ntos Oct 5, 2026
7289a3f
fix(deps): bump next, shell-quote and proxy-addr for critical advisories
narcisonunez Oct 7, 2026
88cb057
Merge remote-tracking branch 'origin/canary' into dependabots-alerts
narcisonunez Oct 7, 2026
9992659
fix(deps): bump nodemailer and patch transitive high advisories
narcisonunez Oct 7, 2026
749bb2c
fix(server): let members list servers in server pickers
narcisonunez Oct 7, 2026
e8f236c
feat(dns): add optional zone to OVH provider
tomron Oct 7, 2026
2674eb2
fix(dns): enforce the configured OVH zone on record operations
tomron Oct 8, 2026
b329595
feat(logs-and-metrics): ship container logs and metrics to external p…
narcisonunez Oct 8, 2026
0b537a8
feat(enterprise): dual-mode branding with separate light/dark theme l…
imrja8 Oct 11, 2026
d277913
fix(enterprise): address review feedback for dual-mode branding
imrja8 Oct 11, 2026
0898642
fix(enterprise): preserve light-mode URLs when toggling dual branding…
imrja8 Oct 11, 2026
b4681b3
fix(backups): preserve service selection when changing database type
Oct 12, 2026
412516d
fix(gitlab): share one token refresh between concurrent callers
ahmedisam99 Oct 12, 2026
20701ba
test(gitlab): cover concurrent token refreshes
ahmedisam99 Oct 12, 2026
726664a
fix(ui): wrap and clamp service card description on environment page
Totopo27 Oct 12, 2026
3cc8158
feat(ui): make projects card clickable on home dashboard
Totopo27 Oct 12, 2026
c7ee043
Merge pull request #5614 from tomron/feat/ovh-optional-zone
narcisonunez Oct 12, 2026
29107d8
Merge pull request #5649 from imrja8/feat/dual-mode-branding
narcisonunez Oct 12, 2026
ccd26e9
Merge pull request #5655 from ahmedisam99/fix/gitlab-token-refresh-race
narcisonunez Oct 12, 2026
fe3912d
Merge pull request #5657 from Totopo27/feat/gh-5546-clickable-project…
narcisonunez Oct 12, 2026
aae2dd9
Merge pull request #5656 from Totopo27/fix/gh-5600-service-card-descr…
narcisonunez Oct 12, 2026
931f5c1
Merge pull request #5654 from olivier-drieux/fix/restore-backup-servi…
narcisonunez Oct 12, 2026
94f3815
fix(templates): cap visible tags so the Create button stays visible
manozzo Oct 12, 2026
a7d8dff
Merge pull request #5624 from Dokploy/feat/logs-and-metrics
imrja8 Oct 14, 2026
9e87b9e
Merge pull request #5613 from Dokploy/fix/member-server-list
imrja8 Oct 14, 2026
502d6c8
Merge branch 'canary' into dependabots-alerts
imrja8 Oct 14, 2026
bfe24f8
Update undici version to 6.28.1
imrja8 Oct 14, 2026
d9fe046
Merge pull request #5661 from manozzo/fix/template-card-tags-overflow
imrja8 Oct 14, 2026
e000675
Merge pull request #5517 from Dokploy/dependabots-alerts
narcisonunez Oct 14, 2026
b5473e6
feat(permissions): add AI module to enterprise custom roles
imrja8 Sep 20, 2026
cd9edb2
fix(permissions): resolve AI module authorization edge cases and test…
imrja8 Sep 20, 2026
293e197
fix: resolve cross-tenant access and granular role UI issues for AI s…
imrja8 Sep 20, 2026
bdefc02
fix: redact apiKey from getAll AI endpoint to prevent credential expo…
imrja8 Sep 20, 2026
a7d8378
fix(permissions): mask apiKey on ai.one, add audit logging, remove …
imrja8 Sep 20, 2026
2bfcac5
fix(ai): mask apiKey exposure, add audit logging, resolve masked-ke…
imrja8 Sep 20, 2026
3d67665
fix(ai): require update permission for stored key resolution, dedup…
imrja8 Sep 20, 2026
0049421
fix(ai): fix PermissionCtx type on resolveInputApiKey
imrja8 Sep 20, 2026
a9871f3
refactor(ai): DRY saveAiSettings and enforce strict NOT_FOUND validation
imrja8 Sep 20, 2026
5ff8d05
perf(ai): optimize permission evaluation and remove redundant DB queries
imrja8 Sep 20, 2026
37df4e4
fix: suppress EPIPE errors in pipeBetweenServers when target exits early
imrja8 Oct 12, 2026
16c22c7
chore(deps): bump brace-expansion and source-map-js in emails lockfile
narcisonunez Oct 15, 2026
471e91c
Merge pull request #5684 from Dokploy/fix/dependabot-high-emails
narcisonunez Oct 15, 2026
c867a3c
Merge pull request #5489 from imrja8/feat/ai-custom-role-permissions
narcisonunez Oct 15, 2026
136a09d
fix(settings): check server organization in traefik file endpoints
narcisonunez Oct 15, 2026
53464e9
Merge pull request #5070 from bunlongheng/fix/traefik-file-path-trave…
narcisonunez Oct 15, 2026
8377300
fix(billing): guard loadStripe behind key check for self-hosted insta…
imrja8 Oct 16, 2026
7430afd
fix: escape HTML and truncate long messages in Telegram notifications
imrja8 Oct 16, 2026
3e75dc6
Update packages/server/src/utils/notifications/utils.ts
imrja8 Oct 16, 2026
41cecde
fix: escape metadata fields and fix entity boundary off-by-one
imrja8 Oct 16, 2026
829f8af
fix(ui): fix server badge and appName overflow on mobile
imrja8 Oct 16, 2026
e38a980
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 16, 2026
a67d9e3
Merge pull request #5693 from imrja8/fix/guard-stripe-init-self-hosted
Siumauricio Oct 16, 2026
bef77ac
Merge pull request #5694 from imrja8/fix/telegram-notification-escape…
Siumauricio Oct 16, 2026
49d250a
Merge pull request #5590 from GlebsonS4ntos/fix/prevent-service-heade…
Siumauricio Oct 16, 2026
e0c8d80
fix: decode Route53 octal escapes in record names (#5553)
Souvik-Cyclic Oct 16, 2026
b5c5faf
fix(security): pass registry login passwords through stdin
Gabrielgvl Oct 17, 2026
5849102
fix(deploy): preserve remote serverId in webhook deployment jobs
Totopo27 Oct 22, 2026
e76283b
fix: keep commands and secrets out of ExecError messages and inspect …
narcisonunez Oct 22, 2026
99e4f1c
fix(wss): bind container terminal to the service it was opened from
narcisonunez Oct 22, 2026
73c795e
fix(wss): resolve libsql services when binding the container terminal
narcisonunez Oct 22, 2026
47b0d65
refactor(wss): look up service app names from a table list
narcisonunez Oct 22, 2026
d1246ba
fix(auth): let password managers fill the 2FA code on login
imrja8 Oct 22, 2026
0a1204f
fix(auth): keep the six-box look for the 2FA code input
imrja8 Oct 22, 2026
fcfa655
fix(auth): keep 2FA code input in sync while verifying and editing
imrja8 Oct 22, 2026
95c1e81
chore: bump Node.js to 24.22.1 (security release)
imrja8 Oct 22, 2026
be47449
Merge pull request #5733 from Dokploy/fix/exec-error-secret-leak
narcisonunez Oct 22, 2026
ad22296
Merge pull request #5701 from Gabrielgvl/fix/registry-login-stdin
narcisonunez Oct 22, 2026
9f6e82a
fix(monitoring): let members with service access see container monito…
Gourav224 Oct 22, 2026
f40b3e7
refactor(wss): reuse findServiceAppName from container-ownership (#5741)
imrja8 Oct 22, 2026
c5e364d
fix(monitoring): gate host monitoring on docker access and let docker…
imrja8 Oct 22, 2026
8cac2d8
chore(monitoring): address review comments
imrja8 Oct 22, 2026
e7b640d
refactor(monitoring): run host monitoring permission checks in parallel
imrja8 Oct 22, 2026
eb98876
Merge pull request #5738 from Dokploy/chore/bump-node-24.22.1
Siumauricio Oct 22, 2026
f268508
fix: prevent Radix Select from clearing form values on reset (#5223)
Siumauricio Oct 22, 2026
3fd1fe1
fix(select): prevent clearing form values on reset by ignoring empty …
Siumauricio Oct 22, 2026
7e346bb
Merge pull request #5742 from imrja8/fix/monitoring-permissions
imrja8 Oct 22, 2026
9c06e34
Merge pull request #5732 from Totopo27/fix/gh-5659-webhook-remote-ser…
Siumauricio Oct 22, 2026
e59ba06
fix: register cloud schedules without a timezone (#5139)
Siumauricio Oct 22, 2026
b38a7fb
Merge pull request #5748 from Dokploy/fix/cloud-schedule-null-timezone
Siumauricio Oct 22, 2026
c7b0570
fix(ai): hide AI actions for users without ai.read (#5749)
imrja8 Oct 22, 2026
b3cd3c5
fix: close cross-tenant, backup destination and token leak security i…
narcisonunez Oct 22, 2026
7229968
fix: resolve YAML merge keys when rewriting compose files (#5625)
Siumauricio Oct 22, 2026
9b97af0
fix(deployment): restrict server deployment history to accessible ser…
narcisonunez Oct 22, 2026
36ffed1
test: make merge-key tests exercise injected networks and labels
Siumauricio Oct 22, 2026
9958500
chore(deps): bump dependencies flagged by Dependabot
narcisonunez Oct 22, 2026
b77e81e
Merge pull request #5745 from Dokploy/fix/select-empty-value-on-reset
Siumauricio Oct 22, 2026
4559aa6
Merge pull request #5753 from Dokploy/fix/compose-yaml-merge-keys
Siumauricio Oct 22, 2026
4a0199f
fix(emails): point ajv at fast-uri 3.1.9 in the lockfile
narcisonunez Oct 22, 2026
b6f344e
fix(auth): disable SCIM management HTTP endpoints and bump better-aut…
narcisonunez Oct 22, 2026
fec8e38
chore(deps): keep better-auth on 1.6.23
narcisonunez Oct 22, 2026
02c73be
Merge pull request #5754 from Dokploy/chore/dependabot-security-bumps
narcisonunez Oct 22, 2026
e255f69
Merge pull request #5752 from Dokploy/fix/security-issues
narcisonunez Oct 22, 2026
bce96fd
Merge pull request #5735 from imrja8/fix/2fa-password-manager-autofill
imrja8 Oct 23, 2026
9cb90d5
chore: merge upstream canary into AgentHits-Dev (2026-10-23)
agentHits Oct 23, 2026
4951eda
fix(deps): clear the advisories bun audit reports since 2026-10-22
agentHits Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Dockerfile for DevContainer
FROM node:24.4.0-bullseye-slim
FROM node:24.22.1-bookworm-slim

# Install essential packages
RUN apt-get update && apt-get install -y \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dokploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ jobs:

- uses: actions/setup-node@v7
with:
node-version: 24.21.0
node-version: 24.22.1
cache: pnpm

- name: Generate OpenAPI specification
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- uses: actions/setup-node@v7
if: ${{ !cancelled() }}
with:
node-version: 24.21.0
node-version: 24.22.1
- run: bun install --frozen-lockfile
if: ${{ !cancelled() }}
- run: bun run server:build
Expand All @@ -54,7 +54,7 @@ jobs:
bun-version: 1.4.2
- uses: actions/setup-node@v7
with:
node-version: 24.21.0
node-version: 24.22.1

- name: Install Nixpacks
if: matrix.job == 'test' && runner.environment == 'github-hosted'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sync-openapi-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
bun-version: 1.4.2
- uses: actions/setup-node@v7
with:
node-version: 24.21.0
node-version: 24.22.1

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24.4.0
24.22.1
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ feat: add new feature

Before you start, please make the clone based on the `canary` branch, since the `main` branch is the source of truth and should always reflect the latest stable release, also the PRs will be merged to the `canary` branch.

We use Node v24.4.0 and recommend this specific version. If you have nvm installed, you can run `nvm install 24.4.0 && nvm use` in the root directory.
We use Node v24.22.1 and recommend this specific version. If you have nvm installed, you can run `nvm install 24.22.1 && nvm use` in the root directory.
We use Bun v1.4.2 as the package manager and recommend this specific version. The lockfile requires Bun >=1.4.2.

```bash
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM node:24.21.0-slim AS base
FROM node:24.22.1-bookworm-slim AS base
ENV BUN_INSTALL="/root/.bun"
ENV PATH="$BUN_INSTALL/bin:$PATH"
RUN apt-get update \
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.cloud
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM node:24.21.0-slim AS base
FROM node:24.22.1-bookworm-slim AS base
ENV BUN_INSTALL="/root/.bun"
ENV PATH="$BUN_INSTALL/bin:$PATH"
RUN apt-get update \
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.monitoring
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
# Build stage
FROM golang:1.21-alpine3.19 AS builder
FROM golang:1.24-alpine3.22 AS builder

# Instalar dependencias necesarias
RUN apk add --no-cache gcc musl-dev sqlite-dev
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.schedule
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM node:24.21.0-slim AS base
FROM node:24.22.1-bookworm-slim AS base
ENV BUN_INSTALL="/root/.bun"
ENV PATH="$BUN_INSTALL/bin:$PATH"
RUN apt-get update \
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.server
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM node:24.21.0-slim AS base
FROM node:24.22.1-bookworm-slim AS base
ENV BUN_INSTALL="/root/.bun"
ENV PATH="$BUN_INSTALL/bin:$PATH"
RUN apt-get update \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ Dokploy includes multiple features to make your life easier.
- **Templates**: Deploy open-source templates (Plausible, Pocketbase, Calcom, etc.) with a single click.
- **Traefik Integration**: Automatically integrates with Traefik for routing and load balancing.
- **Real-time Monitoring**: Monitor CPU, memory, storage, and network usage for every resource.
- **Logs & Metrics**: Ship container logs and host/container metrics to Grafana (Loki, Prometheus/Mimir), Datadog, New Relic, InfluxDB, VictoriaMetrics, Better Stack, Elasticsearch/OpenSearch, Splunk, or AWS CloudWatch, tagged by project/environment/application.
- **Docker Management**: Easily deploy and manage Docker containers.
- **CLI/API**: Manage your applications and databases using the command line or through the API.
- **Notifications**: Get notified when your deployments succeed or fail (via Slack, Discord, Telegram, Email, etc.).
Expand Down
2 changes: 1 addition & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
},
"packageManager": "bun@1.4.2",
"engines": {
"node": "^24.4.0",
"node": "^24.22.1",
"bun": ">=1.4.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ vi.mock("@dokploy/server/services/deployment", () => ({

vi.mock("@dokploy/server/services/destination", () => ({
findDestinationById: mocks.findDestinationById,
findDestinationByIdForOrganization: mocks.findDestinationById,
}));

vi.mock("@dokploy/server/services/environment", () => ({
Expand Down
213 changes: 213 additions & 0 deletions apps/dokploy/__test__/backups/backup-destination-organization.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import { beforeEach, describe, expect, it, vi } from "vitest";

const mocks = vi.hoisted(() => ({
createBackup: vi.fn(),
findBackupById: vi.fn(),
updateBackupById: vi.fn(),
findPostgresById: vi.fn(),
restorePostgresBackup: vi.fn(),
restoreWebServerBackup: vi.fn(),
findDestinationRow: vi.fn(),
findRestoreBackups: vi.fn(),
}));

vi.mock("@dokploy/server/db", () => ({
db: {
query: {
backups: { findMany: mocks.findRestoreBackups },
destinations: { findFirst: mocks.findDestinationRow },
},
},
}));

vi.mock("@dokploy/server/services/permission", () => ({
checkPermission: vi.fn(async () => undefined),
checkServicePermissionAndAccess: vi.fn(async () => undefined),
}));

vi.mock("@dokploy/server", async (importOriginal) => ({
...(await importOriginal<typeof import("@dokploy/server")>()),
IS_CLOUD: false,
createBackup: mocks.createBackup,
findBackupById: mocks.findBackupById,
updateBackupById: mocks.updateBackupById,
findPostgresById: mocks.findPostgresById,
scheduleBackup: vi.fn(),
removeScheduleBackup: vi.fn(),
}));

vi.mock("@dokploy/server/lib/auth", () => ({
validateRequest: vi.fn(),
}));

vi.mock("@dokploy/server/utils/restore", () => ({
restorePostgresBackup: mocks.restorePostgresBackup,
restoreWebServerBackup: mocks.restoreWebServerBackup,
}));

vi.mock("@dokploy/server/utils/backups/compose", () => ({
runComposeBackup: vi.fn(),
}));

vi.mock("@dokploy/server/utils/backups/utils", () => ({
getS3Credentials: vi.fn(),
normalizeS3Path: vi.fn(() => ""),
}));

vi.mock("@dokploy/server/utils/process/execAsync", () => ({
execAsync: vi.fn(),
execAsyncRemote: vi.fn(),
}));

vi.mock("@/server/api/utils/audit", () => ({
audit: vi.fn(async () => undefined),
}));

vi.mock("@/server/api/utils/plan-limits", () => ({
assertDatabaseBackupLimit: vi.fn(),
}));

vi.mock("@/server/utils/backup", () => ({
removeJob: vi.fn(),
schedule: vi.fn(),
updateJob: vi.fn(),
}));

const { backupRouter } = await import("@/server/api/routers/backup");

const caller = backupRouter.createCaller({
session: { activeOrganizationId: "org-a" },
user: { id: "user-1", email: "user@example.com", role: "owner" },
} as Parameters<typeof backupRouter.createCaller>[0]);

const ownDestination = { destinationId: "dest-a", organizationId: "org-a" };
const foreignDestination = { destinationId: "dest-b", organizationId: "org-b" };

const createInput = {
schedule: "0 0 * * *",
prefix: "/",
database: "app",
databaseType: "postgres" as const,
backupType: "database" as const,
postgresId: "pg-1",
enabled: false,
};

const updateInput = {
backupId: "backup-1",
schedule: "0 0 * * *",
enabled: false,
prefix: "/",
database: "app",
keepLatestCount: 0,
serviceName: null,
metadata: {},
databaseType: "postgres" as const,
};

const restoreInput = {
databaseId: "pg-1",
databaseType: "postgres" as const,
backupType: "database" as const,
databaseName: "app",
backupFile: "app/2024.sql.gz",
};

const drain = async (stream: unknown) => {
for await (const _ of stream as AsyncIterable<string>) {
}
};

describe("backup endpoints scope destinations to the active organization", () => {
beforeEach(() => {
vi.clearAllMocks();
mocks.createBackup.mockResolvedValue({ backupId: "backup-1" });
mocks.findBackupById.mockResolvedValue({
backupId: "backup-1",
postgresId: "pg-1",
destinationId: "dest-a",
enabled: false,
databaseType: "postgres",
backupType: "database",
});
mocks.findPostgresById.mockResolvedValue({ postgresId: "pg-1" });
// The fork only restores objects under a schedule of the same database.
mocks.findRestoreBackups.mockResolvedValue([
{ appName: "app", prefix: "/", postgres: { appName: "app" } },
]);
});

it("rejects creating a backup on a destination from another organization", async () => {
mocks.findDestinationRow.mockResolvedValue(foreignDestination);

await expect(
caller.create({ ...createInput, destinationId: "dest-b" }),
).rejects.toMatchObject({
message: "You don't have access to this destination.",
});
expect(mocks.createBackup).not.toHaveBeenCalled();
});

it("creates a backup on a destination of the active organization", async () => {
mocks.findDestinationRow.mockResolvedValue(ownDestination);

await caller.create({ ...createInput, destinationId: "dest-a" });

expect(mocks.createBackup).toHaveBeenCalledTimes(1);
});

it("rejects moving a backup to a destination from another organization", async () => {
mocks.findDestinationRow.mockResolvedValue(foreignDestination);

await expect(
caller.update({ ...updateInput, destinationId: "dest-b" }),
).rejects.toMatchObject({
message: "You don't have access to this destination.",
});
expect(mocks.updateBackupById).not.toHaveBeenCalled();
});

it("rejects restoring from a destination of another organization", async () => {
mocks.findDestinationRow.mockResolvedValue(foreignDestination);

const stream = await caller.restoreBackupWithLogs({
...restoreInput,
destinationId: "dest-b",
});

await expect(drain(stream)).rejects.toMatchObject({
code: "UNAUTHORIZED",
});
expect(mocks.restorePostgresBackup).not.toHaveBeenCalled();
});

it("restores from a destination of the active organization", async () => {
mocks.findDestinationRow.mockResolvedValue(ownDestination);

const stream = await caller.restoreBackupWithLogs({
...restoreInput,
destinationId: "dest-a",
});
await drain(stream);

expect(mocks.restorePostgresBackup).toHaveBeenCalledTimes(1);
});

// Upstream leaves service-less web-server schedules unscoped; the fork
// scopes their destination like every other schedule.
it("rejects web-server schedules on a destination from another organization", async () => {
mocks.findDestinationRow.mockResolvedValue(foreignDestination);

await expect(
caller.create({
...createInput,
postgresId: undefined,
databaseType: "web-server",
destinationId: "dest-b",
}),
).rejects.toMatchObject({
message: "You don't have access to this destination.",
});
expect(mocks.createBackup).not.toHaveBeenCalled();
});
});
Loading