mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 13:28:27 +00:00
fix: deletion corner cases
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { TDbClient } from "@app/db";
|
import { TDbClient } from "@app/db";
|
||||||
import { TableName } from "@app/db/schemas";
|
import { TableName } from "@app/db/schemas";
|
||||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
||||||
@@ -7,9 +9,8 @@ export type TSecretReminderRecipientsDALFactory = ReturnType<typeof secretRemind
|
|||||||
export const secretReminderRecipientsDALFactory = (db: TDbClient) => {
|
export const secretReminderRecipientsDALFactory = (db: TDbClient) => {
|
||||||
const secretReminderRecipientsOrm = ormify(db, TableName.SecretReminderRecipients);
|
const secretReminderRecipientsOrm = ormify(db, TableName.SecretReminderRecipients);
|
||||||
|
|
||||||
const findUsersBySecretId = async (secretId: string) => {
|
const findUsersBySecretId = async (secretId: string, tx?: Knex) => {
|
||||||
const res = await db
|
const res = await (tx || db.replicaNode())(TableName.SecretReminderRecipients)
|
||||||
.replicaNode()(TableName.SecretReminderRecipients)
|
|
||||||
.where({ secretId })
|
.where({ secretId })
|
||||||
.leftJoin(TableName.Users, `${TableName.SecretReminderRecipients}.userId`, `${TableName.Users}.id`)
|
.leftJoin(TableName.Users, `${TableName.SecretReminderRecipients}.userId`, `${TableName.Users}.id`)
|
||||||
.leftJoin(TableName.Project, `${TableName.SecretReminderRecipients}.projectId`, `${TableName.Project}.id`)
|
.leftJoin(TableName.Project, `${TableName.SecretReminderRecipients}.projectId`, `${TableName.Project}.id`)
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ export const fnSecretBulkDelete = async ({
|
|||||||
deletedSecrets
|
deletedSecrets
|
||||||
.filter(({ reminderRepeatDays }) => Boolean(reminderRepeatDays))
|
.filter(({ reminderRepeatDays }) => Boolean(reminderRepeatDays))
|
||||||
.map(({ id, reminderRepeatDays }) =>
|
.map(({ id, reminderRepeatDays }) =>
|
||||||
secretQueueService.removeSecretReminder({ secretId: id, repeatDays: reminderRepeatDays as number })
|
secretQueueService.removeSecretReminder({ secretId: id, repeatDays: reminderRepeatDays as number }, tx)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export type TFnSecretBulkDelete = {
|
|||||||
tx?: Knex;
|
tx?: Knex;
|
||||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "deleteMany">;
|
secretDAL: Pick<TSecretV2BridgeDALFactory, "deleteMany">;
|
||||||
secretQueueService: {
|
secretQueueService: {
|
||||||
removeSecretReminder: (data: TRemoveSecretReminderDTO) => Promise<void>;
|
removeSecretReminder: (data: TRemoveSecretReminderDTO, tx?: Knex) => Promise<void>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -737,7 +737,7 @@ export const fnSecretBulkDelete = async ({
|
|||||||
deletedSecrets
|
deletedSecrets
|
||||||
.filter(({ secretReminderRepeatDays }) => Boolean(secretReminderRepeatDays))
|
.filter(({ secretReminderRepeatDays }) => Boolean(secretReminderRepeatDays))
|
||||||
.map(({ id, secretReminderRepeatDays }) =>
|
.map(({ id, secretReminderRepeatDays }) =>
|
||||||
secretQueueService.removeSecretReminder({ secretId: id, repeatDays: secretReminderRepeatDays as number })
|
secretQueueService.removeSecretReminder({ secretId: id, repeatDays: secretReminderRepeatDays as number }, tx)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
import opentelemetry from "@opentelemetry/api";
|
import opentelemetry from "@opentelemetry/api";
|
||||||
import { AxiosError } from "axios";
|
import { AxiosError } from "axios";
|
||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ProjectMembershipRole,
|
ProjectMembershipRole,
|
||||||
@@ -185,8 +186,10 @@ export const secretQueueFactory = ({
|
|||||||
unit: "1"
|
unit: "1"
|
||||||
});
|
});
|
||||||
|
|
||||||
const removeSecretReminder = async (dto: TRemoveSecretReminderDTO) => {
|
const removeSecretReminder = async ({ deleteRecipients = true, ...dto }: TRemoveSecretReminderDTO, tx?: Knex) => {
|
||||||
await secretReminderRecipientsDAL.delete({ secretId: dto.secretId });
|
if (deleteRecipients) {
|
||||||
|
await secretReminderRecipientsDAL.delete({ secretId: dto.secretId }, tx);
|
||||||
|
}
|
||||||
|
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
await queueService.stopRepeatableJob(
|
await queueService.stopRepeatableJob(
|
||||||
@@ -233,7 +236,12 @@ export const secretQueueFactory = ({
|
|||||||
.replace(":", "-");
|
.replace(":", "-");
|
||||||
};
|
};
|
||||||
|
|
||||||
const addSecretReminder = async ({ oldSecret, newSecret, projectId, recipients }: TCreateSecretReminderDTO) => {
|
const addSecretReminder = async ({
|
||||||
|
oldSecret,
|
||||||
|
newSecret,
|
||||||
|
projectId,
|
||||||
|
deleteRecipients = true
|
||||||
|
}: TCreateSecretReminderDTO) => {
|
||||||
try {
|
try {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
|
|
||||||
@@ -255,28 +263,11 @@ export const secretQueueFactory = ({
|
|||||||
if (oldSecret.secretReminderRepeatDays) {
|
if (oldSecret.secretReminderRepeatDays) {
|
||||||
await removeSecretReminder({
|
await removeSecretReminder({
|
||||||
repeatDays: oldSecret.secretReminderRepeatDays,
|
repeatDays: oldSecret.secretReminderRepeatDays,
|
||||||
secretId: oldSecret.id
|
secretId: oldSecret.id,
|
||||||
|
deleteRecipients
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingRecipients = await secretReminderRecipientsDAL.findUsersBySecretId(newSecret.id);
|
|
||||||
|
|
||||||
if (recipients?.length) {
|
|
||||||
await secretReminderRecipientsDAL.transaction(async (tx) => {
|
|
||||||
await secretReminderRecipientsDAL.delete({ secretId: newSecret.id }, tx);
|
|
||||||
await secretReminderRecipientsDAL.insertMany(
|
|
||||||
recipients.map((r) => ({
|
|
||||||
secretId: newSecret.id,
|
|
||||||
userId: r,
|
|
||||||
projectId
|
|
||||||
})),
|
|
||||||
tx
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else if (existingRecipients) {
|
|
||||||
await secretReminderRecipientsDAL.delete({ secretId: newSecret.id });
|
|
||||||
}
|
|
||||||
|
|
||||||
await queueService.queue(
|
await queueService.queue(
|
||||||
QueueName.SecretReminder,
|
QueueName.SecretReminder,
|
||||||
QueueJobs.SecretReminder,
|
QueueJobs.SecretReminder,
|
||||||
@@ -315,33 +306,52 @@ export const secretQueueFactory = ({
|
|||||||
const recipientsUpdated =
|
const recipientsUpdated =
|
||||||
secretReminderRecipients?.some(
|
secretReminderRecipients?.some(
|
||||||
(newId) => !oldSecret.secretReminderRecipients?.find((oldId) => newId === oldId)
|
(newId) => !oldSecret.secretReminderRecipients?.find((oldId) => newId === oldId)
|
||||||
) ||
|
) || secretReminderRecipients?.length !== oldSecret.secretReminderRecipients?.length;
|
||||||
(secretReminderRecipients?.length !== oldSecret.secretReminderRecipients?.length &&
|
|
||||||
secretReminderRepeatDays !== null);
|
|
||||||
|
|
||||||
if (newSecret.type !== SecretType.Personal && secretReminderRepeatDays !== undefined) {
|
await secretReminderRecipientsDAL.transaction(async (tx) => {
|
||||||
if (
|
if (newSecret.type !== SecretType.Personal && secretReminderRepeatDays !== undefined) {
|
||||||
(secretReminderRepeatDays && oldSecret.secretReminderRepeatDays !== secretReminderRepeatDays) ||
|
if (
|
||||||
(secretReminderNote && oldSecret.secretReminderNote !== secretReminderNote) ||
|
(secretReminderRepeatDays && oldSecret.secretReminderRepeatDays !== secretReminderRepeatDays) ||
|
||||||
recipientsUpdated
|
(secretReminderNote && oldSecret.secretReminderNote !== secretReminderNote)
|
||||||
) {
|
) {
|
||||||
await addSecretReminder({
|
await addSecretReminder({
|
||||||
oldSecret,
|
oldSecret,
|
||||||
newSecret,
|
newSecret,
|
||||||
projectId,
|
projectId,
|
||||||
recipients: newSecret.secretReminderRecipients
|
deleteRecipients: false
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
secretReminderRepeatDays === null &&
|
secretReminderRepeatDays === null &&
|
||||||
secretReminderNote === null &&
|
secretReminderNote === null &&
|
||||||
oldSecret.secretReminderRepeatDays
|
oldSecret.secretReminderRepeatDays
|
||||||
) {
|
) {
|
||||||
await removeSecretReminder({
|
await removeSecretReminder({
|
||||||
secretId: oldSecret.id,
|
secretId: oldSecret.id,
|
||||||
repeatDays: oldSecret.secretReminderRepeatDays
|
repeatDays: oldSecret.secretReminderRepeatDays
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (recipientsUpdated) {
|
||||||
|
// if no recipients, delete all existing recipients
|
||||||
|
if (!secretReminderRecipients?.length) {
|
||||||
|
const existingRecipients = await secretReminderRecipientsDAL.findUsersBySecretId(newSecret.id, tx);
|
||||||
|
if (existingRecipients) {
|
||||||
|
await secretReminderRecipientsDAL.delete({ secretId: newSecret.id }, tx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await secretReminderRecipientsDAL.delete({ secretId: newSecret.id }, tx);
|
||||||
|
await secretReminderRecipientsDAL.insertMany(
|
||||||
|
secretReminderRecipients.map((r) => ({
|
||||||
|
secretId: newSecret.id,
|
||||||
|
userId: r,
|
||||||
|
projectId
|
||||||
|
})),
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const createManySecretsRawFn = createManySecretsRawFnFactory({
|
const createManySecretsRawFn = createManySecretsRawFnFactory({
|
||||||
projectDAL,
|
projectDAL,
|
||||||
|
|||||||
@@ -546,10 +546,13 @@ export const secretServiceFactory = ({
|
|||||||
|
|
||||||
for await (const secret of secrets) {
|
for await (const secret of secrets) {
|
||||||
if (secret.secretReminderRepeatDays !== null && secret.secretReminderRepeatDays !== undefined) {
|
if (secret.secretReminderRepeatDays !== null && secret.secretReminderRepeatDays !== undefined) {
|
||||||
await secretQueueService.removeSecretReminder({
|
await secretQueueService.removeSecretReminder(
|
||||||
repeatDays: secret.secretReminderRepeatDays,
|
{
|
||||||
secretId: secret.id
|
repeatDays: secret.secretReminderRepeatDays,
|
||||||
});
|
secretId: secret.id
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,10 +1077,13 @@ export const secretServiceFactory = ({
|
|||||||
|
|
||||||
for await (const secret of secrets) {
|
for await (const secret of secrets) {
|
||||||
if (secret.secretReminderRepeatDays !== null && secret.secretReminderRepeatDays !== undefined) {
|
if (secret.secretReminderRepeatDays !== null && secret.secretReminderRepeatDays !== undefined) {
|
||||||
await secretQueueService.removeSecretReminder({
|
await secretQueueService.removeSecretReminder(
|
||||||
repeatDays: secret.secretReminderRepeatDays,
|
{
|
||||||
secretId: secret.id
|
repeatDays: secret.secretReminderRepeatDays,
|
||||||
});
|
secretId: secret.id
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const secretValueHidden = !hasSecretReadValueOrDescribePermission(
|
const secretValueHidden = !hasSecretReadValueOrDescribePermission(
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ export type TFnSecretBulkDelete = {
|
|||||||
tx?: Knex;
|
tx?: Knex;
|
||||||
secretDAL: Pick<TSecretDALFactory, "deleteMany">;
|
secretDAL: Pick<TSecretDALFactory, "deleteMany">;
|
||||||
secretQueueService: {
|
secretQueueService: {
|
||||||
removeSecretReminder: (data: TRemoveSecretReminderDTO) => Promise<void>;
|
removeSecretReminder: (data: TRemoveSecretReminderDTO, tx?: Knex) => Promise<void>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -410,12 +410,14 @@ export type TCreateSecretReminderDTO = {
|
|||||||
oldSecret: TPartialSecret;
|
oldSecret: TPartialSecret;
|
||||||
newSecret: TPartialSecret;
|
newSecret: TPartialSecret;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
recipients?: string[] | null;
|
|
||||||
|
deleteRecipients?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TRemoveSecretReminderDTO = {
|
export type TRemoveSecretReminderDTO = {
|
||||||
secretId: string;
|
secretId: string;
|
||||||
repeatDays: number;
|
repeatDays: number;
|
||||||
|
deleteRecipients?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TBackFillSecretReferencesDTO = TProjectPermission;
|
export type TBackFillSecretReferencesDTO = TProjectPermission;
|
||||||
|
|||||||
+9
@@ -87,6 +87,15 @@ export const CreateReminderForm = ({
|
|||||||
}
|
}
|
||||||
}, [members, isOpen, recipients]);
|
}, [members, isOpen, recipients]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (repeatDays) {
|
||||||
|
setValue("days", repeatDays);
|
||||||
|
}
|
||||||
|
if (note) {
|
||||||
|
setValue("note", note);
|
||||||
|
}
|
||||||
|
}, [repeatDays, note]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
|
|||||||
Reference in New Issue
Block a user