diff --git a/apps/dokploy/components/shared/env-autocomplete.ts b/apps/dokploy/components/shared/env-autocomplete.ts index 3bad00b4b..0b6039976 100644 --- a/apps/dokploy/components/shared/env-autocomplete.ts +++ b/apps/dokploy/components/shared/env-autocomplete.ts @@ -85,9 +85,13 @@ export const useEnvCompletionSource = ({ const vaultSecret = /^vault\.([a-zA-Z0-9_-]+)\.([^}\n]*)$/.exec(inner); if (vaultSecret) { const provider = providers?.find((p) => p.name === vaultSecret[1]); - if (!provider) return null; + if (!provider || !projectId) return null; const names = await utils.vaultProvider.listSecretNames - .fetch({ vaultProviderId: provider.vaultProviderId }) + .fetch({ + vaultProviderId: provider.vaultProviderId, + projectId, + environmentId, + }) .catch(() => [] as string[]); return { from: innerFrom + `vault.${vaultSecret[1]}.`.length, @@ -176,6 +180,14 @@ export const useEnvCompletionSource = ({ return null; }, - [providers, projectEnv, environmentEnv, includeShared, utils], + [ + providers, + projectEnv, + environmentEnv, + includeShared, + projectId, + environmentId, + utils, + ], ); }; diff --git a/apps/dokploy/server/api/routers/vault-provider.ts b/apps/dokploy/server/api/routers/vault-provider.ts index d59ffca69..4ca3b5789 100644 --- a/apps/dokploy/server/api/routers/vault-provider.ts +++ b/apps/dokploy/server/api/routers/vault-provider.ts @@ -2,6 +2,7 @@ import { createVaultProvider, findVaultProviderInOrganization, findVaultProvidersByOrganizationId, + isVaultProviderAssigned, listVaultProviderSecretNames, maskVaultProviderConfig, mergeVaultProviderConfig, @@ -9,6 +10,7 @@ import { testVaultProviderConnection, updateVaultProvider, } from "@dokploy/server"; +import { findMemberByUserId } from "@dokploy/server/services/permission"; import { TRPCError } from "@trpc/server"; import { audit } from "@/server/api/utils/audit"; import { @@ -129,6 +131,34 @@ export const vaultProviderRouter = createTRPCRouter({ input.vaultProviderId, ctx.session.activeOrganizationId, ); + + if (ctx.user.role !== "owner" && ctx.user.role !== "admin") { + const { accessedProjects } = await findMemberByUserId( + ctx.user.id, + ctx.session.activeOrganizationId, + ); + if (!accessedProjects.includes(input.projectId)) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this project", + }); + } + } + + if ( + !isVaultProviderAssigned( + provider.assignments, + input.projectId, + input.environmentId, + ) + ) { + throw new TRPCError({ + code: "FORBIDDEN", + message: + "This vault provider is not enabled for the given project/environment", + }); + } + return await listVaultProviderSecretNames(provider.config); }), }); diff --git a/packages/server/src/db/schema/vault-provider.ts b/packages/server/src/db/schema/vault-provider.ts index 2b78c9008..6056e54cf 100644 --- a/packages/server/src/db/schema/vault-provider.ts +++ b/packages/server/src/db/schema/vault-provider.ts @@ -140,4 +140,6 @@ export const apiTestVaultProvider = z.object({ export const apiListVaultSecretNames = z.object({ vaultProviderId: z.string().min(1), + projectId: z.string().min(1), + environmentId: z.string().optional(), }); diff --git a/packages/server/src/utils/vault/index.ts b/packages/server/src/utils/vault/index.ts index 5d69cdf45..b5908cb85 100644 Binary files a/packages/server/src/utils/vault/index.ts and b/packages/server/src/utils/vault/index.ts differ