Fix secret rotation filter on dashboard query

This commit is contained in:
Carlos Monastyrski
2025-12-09 00:02:50 -03:00
parent 3a35e54cd9
commit ec5d740536
6 changed files with 20 additions and 18 deletions
@@ -963,7 +963,8 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
search, search,
tagSlugs: tags, tagSlugs: tags,
includeTagsInSearch: true, includeTagsInSearch: true,
includeMetadataInSearch: true includeMetadataInSearch: true,
excludeRotatedSecrets: includeSecretRotations
}); });
if (remainingLimit > 0 && totalSecretCount > adjustedOffset) { if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
@@ -985,7 +986,8 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
offset: adjustedOffset, offset: adjustedOffset,
tagSlugs: tags, tagSlugs: tags,
includeTagsInSearch: true, includeTagsInSearch: true,
includeMetadataInSearch: true includeMetadataInSearch: true,
excludeRotatedSecrets: includeSecretRotations
}) })
).secrets; ).secrets;
@@ -993,26 +995,11 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
rawSecrets.map((secret) => secret.id) rawSecrets.map((secret) => secret.id)
); );
const rotationSecretIds = secrets = rawSecrets.map((secret) => ({
includeSecretRotations && secretRotations?.length
? new Set(
secretRotations.flatMap((rotation) => rotation.secrets.filter(Boolean).map((secret) => secret.id))
)
: new Set<string>();
const filteredSecrets = rawSecrets.filter((secret) => !rotationSecretIds.has(secret.id));
secrets = filteredSecrets.map((secret) => ({
...secret, ...secret,
isEmpty: !secret.secretValue, isEmpty: !secret.secretValue,
reminder: reminders[secret.id] ?? null reminder: reminders[secret.id] ?? null
})); }));
if (includeSecretRotations && secretRotations?.length && totalSecretCount && rotationSecretIds.size > 0) {
const filteredCount = rawSecrets.filter((secret) => !rotationSecretIds.has(secret.id)).length;
const originalCount = rawSecrets.length;
totalSecretCount = Math.max(0, totalSecretCount - (originalCount - filteredCount));
}
} }
} }
} catch (error) { } catch (error) {
@@ -416,6 +416,7 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
tagSlugs?: string[]; tagSlugs?: string[];
includeTagsInSearch?: boolean; includeTagsInSearch?: boolean;
includeMetadataInSearch?: boolean; includeMetadataInSearch?: boolean;
excludeRotatedSecrets?: boolean;
} }
) => { ) => {
try { try {
@@ -481,6 +482,10 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
); );
} }
if (filters?.excludeRotatedSecrets) {
void query.whereNull(`${TableName.SecretRotationV2SecretMapping}.secretId`);
}
const secrets = await query; const secrets = await query;
// @ts-expect-error not inferred by knex // @ts-expect-error not inferred by knex
@@ -594,6 +599,11 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
void bd.whereIn(`${TableName.SecretTag}.slug`, slugs); void bd.whereIn(`${TableName.SecretTag}.slug`, slugs);
} }
}) })
.where((bd) => {
if (filters?.excludeRotatedSecrets) {
void bd.whereNull(`${TableName.SecretRotationV2SecretMapping}.secretId`);
}
})
.orderBy( .orderBy(
filters?.orderBy === SecretsOrderBy.Name ? "key" : "id", filters?.orderBy === SecretsOrderBy.Name ? "key" : "id",
filters?.orderDirection ?? OrderByDirection.ASC filters?.orderDirection ?? OrderByDirection.ASC
@@ -888,6 +888,7 @@ export const secretV2BridgeServiceFactory = ({
| "tagSlugs" | "tagSlugs"
| "environment" | "environment"
| "search" | "search"
| "excludeRotatedSecrets"
>) => { >) => {
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor, actor,
@@ -50,6 +50,7 @@ export type TGetSecretsDTO = {
limit?: number; limit?: number;
search?: string; search?: string;
keys?: string[]; keys?: string[];
excludeRotatedSecrets?: boolean;
} & TProjectPermission; } & TProjectPermission;
export type TGetSecretsMissingReadValuePermissionDTO = Omit< export type TGetSecretsMissingReadValuePermissionDTO = Omit<
@@ -362,6 +363,7 @@ export type TFindSecretsByFolderIdsFilter = {
includeTagsInSearch?: boolean; includeTagsInSearch?: boolean;
includeMetadataInSearch?: boolean; includeMetadataInSearch?: boolean;
keys?: string[]; keys?: string[];
excludeRotatedSecrets?: boolean;
}; };
export type TGetSecretsRawByFolderMappingsDTO = { export type TGetSecretsRawByFolderMappingsDTO = {
@@ -1154,6 +1154,7 @@ export const secretServiceFactory = ({
| "search" | "search"
| "includeTagsInSearch" | "includeTagsInSearch"
| "includeMetadataInSearch" | "includeMetadataInSearch"
| "excludeRotatedSecrets"
>) => { >) => {
const { shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); const { shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
@@ -214,6 +214,7 @@ export type TGetSecretsRawDTO = {
keys?: string[]; keys?: string[];
includeTagsInSearch?: boolean; includeTagsInSearch?: boolean;
includeMetadataInSearch?: boolean; includeMetadataInSearch?: boolean;
excludeRotatedSecrets?: boolean;
} & TProjectPermission; } & TProjectPermission;
export type TGetSecretAccessListDTO = { export type TGetSecretAccessListDTO = {