add sms service

This commit is contained in:
Simon Larsen
2023-06-08 13:34:34 +01:00
parent 3f53053e1f
commit 3b0904a01d
4 changed files with 61 additions and 40 deletions

View File

@@ -1,6 +1,7 @@
enum SmsStatus {
Success = 'Success',
Error = 'Error',
LowBalance = 'Low Balance',
}
export default SmsStatus;

View File

@@ -6,47 +6,25 @@ import Express, {
const router: ExpressRouter = Express.getRouter();
import Response from 'CommonServer/Utils/Response';
import ClusterKeyAuthorization from 'CommonServer/Middleware/ClusterKeyAuthorization';
import MailService from '../Services/MailService';
import EmailMessage from 'Common/Types/Email/EmailMessage';
import EmailTemplateType from 'Common/Types/Email/EmailTemplateType';
import { JSONObject } from 'Common/Types/JSON';
import Email from 'Common/Types/Email';
import Dictionary from 'Common/Types/Dictionary';
import EmailServer from 'Common/Types/Email/EmailServer';
import JSONFunctions from 'Common/Types/JSONFunctions';
import SmsService from '../Services/SmsService';
import Phone from 'Common/Types/Phone';
import ObjectID from 'Common/Types/ObjectID';
router.post(
'/send',
ClusterKeyAuthorization.isAuthorizedServiceMiddleware,
async (req: ExpressRequest, res: ExpressResponse) => {
const body: JSONObject = req.body;
const body: JSONObject = JSONFunctions.deserialize(req.body);
const mail: EmailMessage = {
templateType: body['templateType'] as EmailTemplateType,
toEmail: new Email(body['toEmail'] as string),
subject: body['subject'] as string,
vars: body['vars'] as Dictionary<string>,
body: (body['body'] as string) || '',
};
let mailServer: EmailServer | undefined = undefined;
if (hasMailServerSettingsInBody(body)) {
mailServer = MailService.getEmailServer(req.body);
}
await MailService.send(mail, mailServer);
await SmsService.sendSms(body['to'] as Phone, body['message'] as string, {
projectId: body['projectId'] as ObjectID,
from: body['from'] as Phone,
});
return Response.sendEmptyResponse(req, res);
}
);
const hasMailServerSettingsInBody: Function = (body: JSONObject): boolean => {
return (
body &&
Object.keys(body).filter((key: string) => {
return key.startsWith('SMTP_');
}).length > 0
);
};
export default router;

View File

@@ -5,6 +5,7 @@ import Redis from 'CommonServer/Infrastructure/Redis';
// API
import MailAPI from './API/Mail';
import SmsAPI from './API/SMS';
import SMTPConfigAPI from './API/SMTPConfig';
import logger from 'CommonServer/Utils/Logger';
import { PostgresAppInstance } from 'CommonServer/Infrastructure/PostgresDatabase';
@@ -16,7 +17,7 @@ const APP_NAME: string = 'notification';
const app: ExpressApplication = Express.getExpressApp();
app.use([`/${APP_NAME}/email`, '/email'], MailAPI);
app.use([`/${APP_NAME}/sms`, '/sms'], SmsAPI);
app.use([`/${APP_NAME}/smtp-config`, '/smtp-config'], SMTPConfigAPI);
const init: Function = async (): Promise<void> => {

View File

@@ -41,18 +41,19 @@ export default class SmsService {
smsLog.projectId = options.projectId;
}
let project: Project | null = null ;
let project: Project | null = null;
try {
// make sure project has enough balance.
if (options.projectId && IsBillingEnabled) {
project = await ProjectService.findOneById({
id: options.projectId,
select: {
smsOrCallCurrentBalanceInUSDCents: true,
enableAutoRechargeSmsOrCallBalance: true
enableAutoRechargeSmsOrCallBalance: true,
enableSmsNotifications: true
},
props: {
isRoot: true
@@ -60,20 +61,60 @@ export default class SmsService {
});
if (!project) {
throw new BadDataException(`Project ${options.projectId.toString()} not found.`);
smsLog.status = SmsStatus.Error;
smsLog.statusMessage = `Project ${options.projectId.toString()} not found.`;
await SmsLogService.create({
data: smsLog,
props: {
isRoot: true
}
});
return;
}
if(!project.enableSmsNotifications){
smsLog.status = SmsStatus.Error;
smsLog.statusMessage = `SMS notifications are not enabled for this project. Please enable SMS notifications in project settings.`;
await SmsLogService.create({
data: smsLog,
props: {
isRoot: true
}
});
return;
}
if (!project.smsOrCallCurrentBalanceInUSDCents) {
throw new BadDataException(`Project ${options.projectId.toString()} does not have enough SMS balance.`);
smsLog.status = SmsStatus.LowBalance;
smsLog.statusMessage = `Project ${options.projectId.toString()} does not have enough SMS balance.`;
await SmsLogService.create({
data: smsLog,
props: {
isRoot: true
}
});
return;
}
if (project.smsOrCallCurrentBalanceInUSDCents < SMSDefaultCostInCents) {
throw new BadDataException(`Project does not have enough balance to send SMS. Current balance is ${project.smsOrCallCurrentBalanceInUSDCents} cents. Required balance is ${SMSDefaultCostInCents} cents to send this SMS.`);
smsLog.status = SmsStatus.LowBalance;
smsLog.statusMessage = `Project does not have enough balance to send SMS. Current balance is ${project.smsOrCallCurrentBalanceInUSDCents} cents. Required balance is ${SMSDefaultCostInCents} cents to send this SMS.`;
await SmsLogService.create({
data: smsLog,
props: {
isRoot: true
}
});
return;
}
}
const twillioMessage: MessageInstance = await client.messages
const twillioMessage: MessageInstance = await client.messages
.create({
body: message,
to: to.toString(),
@@ -107,7 +148,7 @@ export default class SmsService {
if (options.projectId) {
await SmsLogService.create({
data: smsLog,
data: smsLog,
props: {
isRoot: true
}