mirror of
https://github.com/fosrl/pangolin.git
synced 2026-09-04 18:29:21 +02:00
batch identity key emails
This commit is contained in:
@@ -7,6 +7,18 @@ import VirtualApiKeyGenerated from "@server/emails/templates/VirtualApiKeyGenera
|
|||||||
import { formatVirtualApiKeyCredential } from "@server/lib/virtualApiKey";
|
import { formatVirtualApiKeyCredential } from "@server/lib/virtualApiKey";
|
||||||
|
|
||||||
const EMAIL_GATEWAY_URL_LIMIT = 5;
|
const EMAIL_GATEWAY_URL_LIMIT = 5;
|
||||||
|
const VIRTUAL_API_KEY_EMAIL_BATCH_SIZE = 50;
|
||||||
|
|
||||||
|
export async function mapInBatches<T>(
|
||||||
|
items: T[],
|
||||||
|
fn: (item: T) => Promise<void>,
|
||||||
|
batchSize = VIRTUAL_API_KEY_EMAIL_BATCH_SIZE
|
||||||
|
): Promise<void> {
|
||||||
|
for (let i = 0; i < items.length; i += batchSize) {
|
||||||
|
const batch = items.slice(i, i + batchSize);
|
||||||
|
await Promise.all(batch.map(fn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function listVirtualApiKeyGatewayUrls(params: {
|
async function listVirtualApiKeyGatewayUrls(params: {
|
||||||
orgId: string;
|
orgId: string;
|
||||||
@@ -161,7 +173,7 @@ export async function sendVirtualApiKeyEmails(params: {
|
|||||||
? `Your identity key for ${params.orgName}`
|
? `Your identity key for ${params.orgName}`
|
||||||
: `Virtual API key for ${params.orgName}`;
|
: `Virtual API key for ${params.orgName}`;
|
||||||
|
|
||||||
for (const to of params.recipients) {
|
await mapInBatches(params.recipients, async (to) => {
|
||||||
await sendEmail(
|
await sendEmail(
|
||||||
params.isIdentityKey
|
params.isIdentityKey
|
||||||
? IdentityApiKeyGenerated({
|
? IdentityApiKeyGenerated({
|
||||||
@@ -184,5 +196,5 @@ export async function sendVirtualApiKeyEmails(params: {
|
|||||||
subject
|
subject
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import config from "@server/lib/config";
|
|||||||
import { getOrCreateUserVirtualApiKey } from "@server/lib/virtualApiKey";
|
import { getOrCreateUserVirtualApiKey } from "@server/lib/virtualApiKey";
|
||||||
import {
|
import {
|
||||||
sendVirtualApiKeyEmails,
|
sendVirtualApiKeyEmails,
|
||||||
listOrgInferenceGatewayUrls
|
listOrgInferenceGatewayUrls,
|
||||||
|
mapInBatches
|
||||||
} from "@server/lib/sendVirtualApiKeyEmail";
|
} from "@server/lib/sendVirtualApiKeyEmail";
|
||||||
import type { EmailIdentityKeysResponse } from "@server/routers/virtualApiKey/types";
|
import type { EmailIdentityKeysResponse } from "@server/routers/virtualApiKey/types";
|
||||||
import rateLimit, { ipKeyGenerator } from "express-rate-limit";
|
import rateLimit, { ipKeyGenerator } from "express-rate-limit";
|
||||||
@@ -218,15 +219,13 @@ export async function emailIdentityKeys(
|
|||||||
|
|
||||||
const orgName = org?.name || orgId;
|
const orgName = org?.name || orgId;
|
||||||
const gatewayUrls = await listOrgInferenceGatewayUrls(orgId);
|
const gatewayUrls = await listOrgInferenceGatewayUrls(orgId);
|
||||||
|
const recipients = members.flatMap(({ user }) =>
|
||||||
|
user.email ? [{ user, email: user.email }] : []
|
||||||
|
);
|
||||||
let sent = 0;
|
let sent = 0;
|
||||||
let skipped = 0;
|
const skipped = members.length - recipients.length;
|
||||||
|
|
||||||
for (const { user } of members) {
|
|
||||||
if (!user.email) {
|
|
||||||
skipped += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
await mapInBatches(recipients, async ({ user, email }) => {
|
||||||
const { key, secret } = await getOrCreateUserVirtualApiKey({
|
const { key, secret } = await getOrCreateUserVirtualApiKey({
|
||||||
orgId,
|
orgId,
|
||||||
user,
|
user,
|
||||||
@@ -234,7 +233,7 @@ export async function emailIdentityKeys(
|
|||||||
});
|
});
|
||||||
|
|
||||||
await sendVirtualApiKeyEmails({
|
await sendVirtualApiKeyEmails({
|
||||||
recipients: [user.email],
|
recipients: [email],
|
||||||
orgName,
|
orgName,
|
||||||
orgId,
|
orgId,
|
||||||
keyName: key.name,
|
keyName: key.name,
|
||||||
@@ -242,11 +241,11 @@ export async function emailIdentityKeys(
|
|||||||
secret,
|
secret,
|
||||||
allResources: true,
|
allResources: true,
|
||||||
isIdentityKey: true,
|
isIdentityKey: true,
|
||||||
accountLabel: user.email || user.name || user.username,
|
accountLabel: email,
|
||||||
gatewayUrls
|
gatewayUrls
|
||||||
});
|
});
|
||||||
sent += 1;
|
sent += 1;
|
||||||
}
|
});
|
||||||
|
|
||||||
return response<EmailIdentityKeysResponse>(res, {
|
return response<EmailIdentityKeysResponse>(res, {
|
||||||
data: { sent, skipped },
|
data: { sent, skipped },
|
||||||
|
|||||||
Reference in New Issue
Block a user