* 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
96 lines
2 KiB
TypeScript
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;
|