Reminders

This commit is contained in:
Daniel Hougaard
2023-10-24 05:16:39 +04:00
parent b97dc7f599
commit 6df678067c
12 changed files with 310 additions and 26 deletions
+6
View File
@@ -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[];
}
+19
View File
@@ -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)
}
+12 -1
View File
@@ -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