diff --git a/backend/src/db/migrations/20250701202824_add-reminder-table.ts b/backend/src/db/migrations/20250701202824_add-reminder-table.ts index cfcd048bf..f1f5bc84d 100644 --- a/backend/src/db/migrations/20250701202824_add-reminder-table.ts +++ b/backend/src/db/migrations/20250701202824_add-reminder-table.ts @@ -13,7 +13,6 @@ export async function up(knex: Knex): Promise { t.integer("repeatDays").checkPositive().nullable(); t.timestamp("nextReminderDate").notNullable(); t.timestamps(true, true, true); - t.index("secretId"); t.unique("secretId"); }); } diff --git a/backend/src/server/routes/v1/reminder-routers/secret-reminder-router.ts b/backend/src/server/routes/v1/reminder-routers/secret-reminder-router.ts index 658f75752..4aa68197f 100644 --- a/backend/src/server/routes/v1/reminder-routers/secret-reminder-router.ts +++ b/backend/src/server/routes/v1/reminder-routers/secret-reminder-router.ts @@ -17,9 +17,6 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) = params: z.object({ secretId: z.string().uuid() }), - querystring: z.object({ - projectId: z.string().uuid() - }), body: z .object({ message: z.string().trim().max(1024).optional(), @@ -43,7 +40,6 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) = actor: req.permission.type, actorOrgId: req.permission.orgId, actorAuthMethod: req.permission.authMethod, - projectId: req.query.projectId, reminder: { secretId: req.params.secretId, message: req.body.message, @@ -56,7 +52,6 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) = await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, orgId: req.permission.orgId, - projectId: req.query.projectId, event: { type: EventType.CREATE_SECRET_REMINDER, metadata: { @@ -83,9 +78,6 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) = params: z.object({ secretId: z.string().uuid() }), - querystring: z.object({ - projectId: z.string().uuid() - }), response: { 200: z.object({ reminder: RemindersSchema.extend({ @@ -103,14 +95,12 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) = actor: req.permission.type, actorOrgId: req.permission.orgId, actorAuthMethod: req.permission.authMethod, - secretId: req.params.secretId, - projectId: req.query.projectId + secretId: req.params.secretId }); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, orgId: req.permission.orgId, - projectId: req.query.projectId, event: { type: EventType.GET_SECRET_REMINDER, metadata: { @@ -132,9 +122,6 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) = params: z.object({ secretId: z.string().uuid() }), - querystring: z.object({ - projectId: z.string().uuid() - }), response: { 200: z.object({ message: z.string() @@ -148,14 +135,12 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) = actor: req.permission.type, actorOrgId: req.permission.orgId, actorAuthMethod: req.permission.authMethod, - secretId: req.params.secretId, - projectId: req.query.projectId + secretId: req.params.secretId }); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, orgId: req.permission.orgId, - projectId: req.query.projectId, event: { type: EventType.DELETE_SECRET_REMINDER, metadata: { diff --git a/backend/src/services/reminder/reminder-service.ts b/backend/src/services/reminder/reminder-service.ts index 6842897e4..85cc1cc2b 100644 --- a/backend/src/services/reminder/reminder-service.ts +++ b/backend/src/services/reminder/reminder-service.ts @@ -2,6 +2,7 @@ import { ForbiddenError } from "@casl/ability"; import { Knex } from "knex"; +import { TableName } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { ProjectPermissionSecretActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError } from "@app/lib/errors"; @@ -21,7 +22,7 @@ type TReminderServiceFactoryDep = { smtpService: TSmtpService; projectMembershipDAL: Pick; permissionService: Pick; - secretV2BridgeDAL: Pick; + secretV2BridgeDAL: Pick; }; export const reminderServiceFactory = ({ @@ -136,13 +137,16 @@ export const reminderServiceFactory = ({ actorId, actorOrgId, actorAuthMethod, - projectId, reminder }: TCreateReminderDTO) => { + const secret = await secretV2BridgeDAL.findOneWithTags({ [`${TableName.SecretV2}.id` as "id"]: reminder.secretId }); + if (!secret) { + throw new BadRequestError({ message: `Secret ${reminder.secretId} not found` }); + } const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectId, + projectId: secret.projectId, actorAuthMethod, actorOrgId }); @@ -150,30 +154,32 @@ export const reminderServiceFactory = ({ const response = await createReminderInternal({ ...reminder, - projectId + projectId: secret.projectId }); return response; }; const getReminder: TReminderServiceFactory["getReminder"] = async ({ secretId, - projectId, actor, actorId, actorOrgId, actorAuthMethod }: { secretId: string; - projectId: string; actor: ActorType; actorId: string; actorOrgId: string; actorAuthMethod: ActorAuthMethod; }) => { + const secret = await secretV2BridgeDAL.findOneWithTags({ [`${TableName.SecretV2}.id` as "id"]: secretId }); + if (!secret) { + throw new BadRequestError({ message: `Secret ${secretId} not found` }); + } const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectId, + projectId: secret.projectId, actorAuthMethod, actorOrgId }); @@ -228,40 +234,29 @@ export const reminderServiceFactory = ({ actorId, actorOrgId, actorAuthMethod, - secretId, - projectId + secretId }: { actor: ActorType; actorId: string; actorOrgId: string; actorAuthMethod: ActorAuthMethod; secretId: string; - projectId: string; }) => { + const secret = await secretV2BridgeDAL.findOneWithTags({ [`${TableName.SecretV2}.id` as "id"]: secretId }); + if (!secret) { + throw new BadRequestError({ message: `Secret ${secretId} not found` }); + } const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectId, + projectId: secret.projectId, actorAuthMethod, actorOrgId }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionSecretActions.Edit, ProjectPermissionSub.Secrets); await reminderDAL.delete({ secretId }); - await secretV2BridgeDAL.invalidateSecretCacheByProjectId(projectId); - }; - - const removeReminderRecipients: TReminderServiceFactory["removeReminderRecipients"] = async ( - secretId: string, - projectId: string, - tx?: Knex - ) => { - const reminder = await reminderDAL.findOne({ secretId }, tx); - if (!reminder) { - return; - } - await reminderRecipientDAL.delete({ reminderId: reminder.id }, tx); - await secretV2BridgeDAL.invalidateSecretCacheByProjectId(projectId); + await secretV2BridgeDAL.invalidateSecretCacheByProjectId(secret.projectId); }; const deleteReminderBySecretId: TReminderServiceFactory["deleteReminderBySecretId"] = async ( @@ -354,7 +349,6 @@ export const reminderServiceFactory = ({ getReminder, sendDailyReminders, deleteReminder, - removeReminderRecipients, deleteReminderBySecretId, batchCreateReminders, createReminderInternal diff --git a/backend/src/services/reminder/reminder-types.ts b/backend/src/services/reminder/reminder-types.ts index cc9c092d3..1f6a53ac7 100644 --- a/backend/src/services/reminder/reminder-types.ts +++ b/backend/src/services/reminder/reminder-types.ts @@ -17,7 +17,6 @@ export type TCreateReminderDTO = { actorId: string; actorOrgId: string; actorAuthMethod: ActorAuthMethod; - projectId: string; reminder: { secretId?: string; message?: string | null; @@ -37,28 +36,19 @@ export type TBatchCreateReminderDTO = { }[]; export interface TReminderServiceFactory { - createReminder: ({ - actor, - actorId, - actorOrgId, - actorAuthMethod, - projectId, - reminder - }: TCreateReminderDTO) => Promise<{ + createReminder: ({ actor, actorId, actorOrgId, actorAuthMethod, reminder }: TCreateReminderDTO) => Promise<{ id: string; created: boolean; }>; getReminder: ({ secretId, - projectId, actor, actorId, actorOrgId, actorAuthMethod }: { secretId: string; - projectId: string; actor: ActorType; actorId: string; actorOrgId: string; @@ -72,19 +62,15 @@ export interface TReminderServiceFactory { actorId, actorOrgId, actorAuthMethod, - secretId, - projectId + secretId }: { actor: ActorType; actorId: string; actorOrgId: string; actorAuthMethod: ActorAuthMethod; secretId: string; - projectId: string; }) => Promise; - removeReminderRecipients: (secretId: string, projectId: string, tx?: Knex) => Promise; - deleteReminderBySecretId: (secretId: string, projectId: string, tx?: Knex) => Promise; batchCreateReminders: ( diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts index 6712305bf..c4a74cf5e 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts @@ -344,7 +344,6 @@ export const secretV2BridgeServiceFactory = ({ actorId, actorOrgId, actorAuthMethod, - projectId, reminder: { secretId: secret.id, message: inputSecret.secretReminderNote, @@ -558,7 +557,6 @@ export const secretV2BridgeServiceFactory = ({ actorId, actorOrgId, actorAuthMethod, - projectId, reminder: { secretId: secret.id, message: inputSecret.secretReminderNote, diff --git a/backend/src/services/secret/secret-queue.ts b/backend/src/services/secret/secret-queue.ts index 4540eef82..89820641d 100644 --- a/backend/src/services/secret/secret-queue.ts +++ b/backend/src/services/secret/secret-queue.ts @@ -111,10 +111,7 @@ type TSecretQueueFactoryDep = { resourceMetadataDAL: Pick; folderCommitService: Pick; secretSyncQueue: Pick; - reminderService: Pick< - TReminderServiceFactory, - "createReminderInternal" | "deleteReminderBySecretId" | "removeReminderRecipients" - >; + reminderService: Pick; }; export type TGetSecrets = { diff --git a/backend/src/services/secret/secret-service.ts b/backend/src/services/secret/secret-service.ts index 565788d74..6139d468b 100644 --- a/backend/src/services/secret/secret-service.ts +++ b/backend/src/services/secret/secret-service.ts @@ -1859,7 +1859,6 @@ export const secretServiceFactory = ({ actorId, actorOrgId, actorAuthMethod, - projectId, reminder: { secretId: secret.id, message: secretReminderNote, @@ -2269,7 +2268,6 @@ export const secretServiceFactory = ({ actorId, actorOrgId, actorAuthMethod, - projectId, reminder: { secretId: secrets.find( (el) => diff --git a/frontend/src/hooks/api/reminders/queries.tsx b/frontend/src/hooks/api/reminders/queries.tsx index 613afef56..68c00913d 100644 --- a/frontend/src/hooks/api/reminders/queries.tsx +++ b/frontend/src/hooks/api/reminders/queries.tsx @@ -5,17 +5,16 @@ import { apiRequest } from "@app/config/request"; import { CreateReminderDTO, DeleteReminderDTO, Reminder } from "./types"; export const reminderKeys = { - getReminder: (secretId: string, projectId: string) => - ["get-reminder", secretId, projectId] as const + getReminder: (secretId: string) => ["get-reminder", secretId] as const }; -export const useCreateReminder = (secretId: string, projectId: string) => { +export const useCreateReminder = (secretId: string) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ message, repeatDays, nextReminderDate, recipients }) => { const { data } = await apiRequest.post<{ reminder: Reminder }>( - `/api/v1/reminders/secrets/${secretId}?projectId=${projectId}`, + `/api/v1/reminders/secrets/${secretId}`, { message, repeatDays, @@ -26,36 +25,36 @@ export const useCreateReminder = (secretId: string, projectId: string) => { return data.reminder; }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId, projectId) }); + queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId) }); } }); }; -export const useDeleteReminder = (secretId: string, projectId: string) => { +export const useDeleteReminder = (secretId: string) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async () => { const { data } = await apiRequest.delete<{ reminder: Reminder }>( - `/api/v1/reminders/secrets/${secretId}?projectId=${projectId}` + `/api/v1/reminders/secrets/${secretId}` ); return data.reminder; }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId, projectId) }); + queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId) }); } }); }; -export const useGetReminder = (secretId: string, projectId: string) => { +export const useGetReminder = (secretId: string) => { return useQuery({ - queryKey: reminderKeys.getReminder(secretId, projectId), + queryKey: reminderKeys.getReminder(secretId), queryFn: async () => { const { data } = await apiRequest.get<{ reminder: Reminder }>( - `/api/v1/reminders/secrets/${secretId}?projectId=${projectId}` + `/api/v1/reminders/secrets/${secretId}` ); return data.reminder; }, - enabled: Boolean(secretId && projectId) + enabled: Boolean(secretId) }); }; diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx index 0bb8faffc..3b9db7bed 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx @@ -143,8 +143,8 @@ export const CreateReminderForm = ({ const { memberOptions } = useWorkspaceMembers(); // API mutations - const { mutateAsync: createReminder } = useCreateReminder(secretId, workspaceId); - const { mutateAsync: deleteReminder } = useDeleteReminder(secretId, workspaceId); + const { mutateAsync: createReminder } = useCreateReminder(secretId); + const { mutateAsync: deleteReminder } = useDeleteReminder(secretId); // Form setup const form = useForm({ @@ -183,7 +183,7 @@ export const CreateReminderForm = ({ queryKey: secretKeys.getProjectSecret({ workspaceId, environment, secretPath }) }); queryClient.invalidateQueries({ - queryKey: reminderKeys.getReminder(secretId, workspaceId) + queryKey: reminderKeys.getReminder(secretId) }); }; diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx index 1e6be0529..61dbdb4be 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx @@ -115,7 +115,7 @@ export const SecretDetailSidebar = ({ const { permission } = useProjectPermission(); const { currentWorkspace } = useWorkspace(); - const { data: reminderData } = useGetReminder(secret?.id, currentWorkspace.id); + const { data: reminderData } = useGetReminder(secret?.id); const tagFields = useFieldArray({ control,