mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 11:29:42 +00:00
Reminders
This commit is contained in:
@@ -802,6 +802,8 @@ export const updateSecretHelper = async ({
|
||||
secretValueIV,
|
||||
secretValueTag,
|
||||
secretPath,
|
||||
secretReminderCron,
|
||||
secretReminderNote,
|
||||
tags,
|
||||
secretCommentCiphertext,
|
||||
secretCommentIV,
|
||||
@@ -866,6 +868,10 @@ export const updateSecretHelper = async ({
|
||||
secretCommentIV,
|
||||
secretCommentTag,
|
||||
secretCommentCiphertext,
|
||||
|
||||
secretReminderCron,
|
||||
secretReminderNote,
|
||||
|
||||
skipMultilineEncoding,
|
||||
secretBlindIndex: newSecretNameBlindIndex,
|
||||
secretKeyIV,
|
||||
|
||||
@@ -59,6 +59,10 @@ export interface UpdateSecretParams {
|
||||
secretCommentCiphertext?: string;
|
||||
secretCommentIV?: string;
|
||||
secretCommentTag?: string;
|
||||
|
||||
secretReminderCron?: string | null;
|
||||
secretReminderNote?: string | null ;
|
||||
|
||||
skipMultilineEncoding?: boolean;
|
||||
tags?: string[];
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ export interface ISecret {
|
||||
secretCommentIV?: string;
|
||||
secretCommentTag?: string;
|
||||
secretCommentHash?: string;
|
||||
|
||||
// ? QUESTION: This works great for workspace-level reminders.
|
||||
// ? If we want to do it on a user-basis, we should ideally have a seperate model for reminders.
|
||||
secretReminderCron?: string | null;
|
||||
secretReminderNote?: string | null;
|
||||
|
||||
skipMultilineEncoding?: boolean;
|
||||
algorithm: "aes-256-gcm";
|
||||
keyEncoding: "utf8" | "base64";
|
||||
@@ -118,10 +124,23 @@ const secretSchema = new Schema<ISecret>(
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
|
||||
secretReminderCron: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
secretReminderNote: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
|
||||
skipMultilineEncoding: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
},
|
||||
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import Queue, { Job } from "bull";
|
||||
import { Secret, Workspace } from "../../models";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
|
||||
type TSendSecretReminders = {
|
||||
workspaceId: string
|
||||
secretId: string
|
||||
cron: string
|
||||
note: string | undefined | null
|
||||
}
|
||||
|
||||
type TDeleteSecretReminder = {
|
||||
secretId: string
|
||||
cron: string
|
||||
}
|
||||
|
||||
export const sendSecretReminders = new Queue("send-secret-reminders", process.env.REDIS_URL as string);
|
||||
|
||||
sendSecretReminders.process(async (job: Job) => {
|
||||
const { workspaceId, secretId }: TSendSecretReminders = job.data
|
||||
const secret = await Secret.findById(new Types.ObjectId(secretId));
|
||||
const workspace = await Workspace.findById(new Types.ObjectId(workspaceId));
|
||||
|
||||
|
||||
if(!workspace || !secret) {
|
||||
throw new Error("Workspace or secret not found")
|
||||
}
|
||||
|
||||
|
||||
// Send email stuff here
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
export const createSecretReminderCron = (jobDetails: TSendSecretReminders) => {
|
||||
return sendSecretReminders.add(jobDetails, {
|
||||
repeat: {
|
||||
cron: jobDetails.cron
|
||||
},
|
||||
jobId: `reminder-${jobDetails.secretId}`,
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteSecretReminderCron = (jobDetails: TDeleteSecretReminder) => {
|
||||
|
||||
return sendSecretReminders.removeRepeatable({
|
||||
cron: jobDetails.cron,
|
||||
"jobId": `reminder-${jobDetails.secretId}`,
|
||||
})
|
||||
}
|
||||
|
||||
export const updateSecretReminderCron = async (jobDetails: TSendSecretReminders) => {
|
||||
// We need to delete the potentially existing cron job first, or the new one won't be created.
|
||||
await deleteSecretReminderCron(jobDetails)
|
||||
|
||||
await createSecretReminderCron(jobDetails)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import { AuthData } from "../interfaces/middleware";
|
||||
import { ActorType } from "../ee/models";
|
||||
import { z } from "zod";
|
||||
import { SECRET_PERSONAL, SECRET_SHARED } from "../variables";
|
||||
|
||||
import { isValidCron } from "cron-validator";
|
||||
/**
|
||||
* Validate authenticated clients for secrets with id [secretId] based
|
||||
* on any known permissions.
|
||||
@@ -261,6 +261,7 @@ export const CreateSecretRawV3 = z.object({
|
||||
.string()
|
||||
.transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
|
||||
secretComment: z.string().trim().optional().default(""),
|
||||
|
||||
skipMultilineEncoding: z.boolean().optional(),
|
||||
type: z.enum([SECRET_SHARED, SECRET_PERSONAL])
|
||||
}),
|
||||
@@ -276,6 +277,7 @@ export const UpdateSecretByNameRawV3 = z.object({
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
|
||||
secretValue: z
|
||||
.string()
|
||||
.transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
|
||||
@@ -362,6 +364,15 @@ export const UpdateSecretByNameV3 = z.object({
|
||||
secretCommentCiphertext: z.string().trim().optional(),
|
||||
secretCommentIV: z.string().trim().optional(),
|
||||
secretCommentTag: z.string().trim().optional(),
|
||||
|
||||
secretReminderCron: z
|
||||
.string()
|
||||
.trim()
|
||||
.optional()
|
||||
.nullable()
|
||||
.refine((val) => val === null || (val && isValidCron(val))),
|
||||
secretReminderNote: z.string().trim().nullable().optional(),
|
||||
|
||||
tags: z.string().array().optional(),
|
||||
skipMultilineEncoding: z.boolean().optional(),
|
||||
// to update secret name
|
||||
|
||||
Reference in New Issue
Block a user