hestia/src/routes/app/sms/+page.server.ts
Baobeld 8270c53509
41 create tenant twilio config (#62)
* add tenant config table

* add encryption/decryption + env vars

* generate secret and validate iv position is number

* expect errors

* remove TWILIO env vars

* settings page impl

* update schema definitions after Mostaphas Tenant impl

* load user env

* just return empty config

* add Settings menu item

* check if settings are present and provide warning if not

* correct form item names

* use correct locals value

* ree

* give twilio its own table

* lock prisma version

* event url is the correct param

* load twilio config from db

* commit migration

* use test script not bun command
2025-01-26 23:36:06 -05:00

96 lines
2 KiB
TypeScript

import { PhoneRegex } from '$lib/regex';
import { logger } from '$lib/server/logger';
import { prisma } from '$lib/server/prisma/index.js';
import { fail, type Actions } from '@sveltejs/kit';
import twilio from 'twilio';
import zod from 'zod';
export const load = async (event) => {
const tenantId = event.locals.tenant.id;
const configs = await prisma.tenantConfig.findUnique({
where: { tenantId: tenantId },
select: {
twilioConfig: {
select: {
accountSID: true,
authToken: true,
phoneNumber: true,
},
},
},
});
const { success, error: validationError } = zod
.object({
accountSID: zod.string(),
})
.safeParse(configs?.twilioConfig);
if (!success) {
logger.warn(validationError.message);
}
return {
isTwilioConfigured: success,
};
};
export const actions = {
push: async (event) => {
const form = await event.request.formData();
if (!form.has('phone')) {
return fail(400, { error: 'phone_missing' });
}
if (!form.get('message')) {
return fail(400, { error: 'message_missing' });
}
const {
success: phoneSuccess,
data: phone,
error: phoneError,
} = zod.string().regex(PhoneRegex).safeParse(form.get('phone'));
if (!phoneSuccess) {
logger.error(phoneError);
return fail(400, { error: 'invalid_phone' });
}
const message = form.get('message');
if (typeof message !== 'string') {
return fail(400, { error: 'invalid_message' });
}
const tenant = await prisma.tenantConfig.findUnique({
where: {
tenantId: event.locals.tenant.id,
},
select: {
twilioConfig: true,
},
});
const config = tenant?.twilioConfig;
if (!config) {
return fail(307, { error: 'no_twilio_config' });
}
const client = twilio(config.accountSID, config.authToken);
try {
const result = await client.messages.create({
to: phone,
body: message,
from: config.phoneNumber,
});
logger.debug(result);
} catch (e) {
logger.error(e);
fail(500, { success: false });
}
return {
success: true,
};
},
} satisfies Actions;