Skip to content

Commit

Permalink
API Caching, core-mailer and more!! (#559)
Browse files Browse the repository at this point in the history
* added markdown editor with save feature

* basic Emailer integration done

* feat: added user registration page (registration-admin) (#507)

* trial push

* added button

* modal added

* added modal form fields

* removed unnecessary code

* added chakra-ui

* form field display (error not fixed)

* feat: Added participand routes and hooks for registration-admin

* Did something

* proper post reuest set

* feat: added route for participant form submission in registration-admin

* registration completed

* Registration complete page added

* added cookie to check registration

* added endOfLine to prettier

* removed eol from prettier

---------

Co-authored-by: aaron-6960 <138325645+aaron-6960@users.noreply.github.com>
Co-authored-by: aaron-6960 <aaroongeorge2005@gmail.com>
Co-authored-by: Subramani E <93091455+subru-37@users.noreply.github.com>

* Build issues fixed

* Fix: Runtime error solved (#542)

* Fix:Runtime error solved

* Fix:Runtime error solved (#539)

* Revert "Fix:Runtime error solved (#539)" (#540)

This reverts commit 0e5b35b.

---------

Co-authored-by: Subramani E <93091455+subru-37@users.noreply.github.com>

* feat: added verification for html content in sendOTP and changed body to pass projecId instead of raw html (#543)

* query-cache

* integrated /core/users/mycreds in react-query

* added key for useGetQuery

* fixed cache kery error

* assigned route work

* changed some of the routes from get to useGetQuery (#545)

* Added API caching for multiple routes and verified build

* added bundle analyzer

* added bundle analyzer

* verified build and replaced routes with cached routes

* Implementing API caching (#547)

* query-cache

* integrated /core/users/mycreds in react-query

* added key for useGetQuery

* fixed cache kery error

* assigned route work

* changed some of the routes from get to useGetQuery (#545)

* Added API caching for multiple routes and verified build

* added bundle analyzer

* added bundle analyzer

* verified build and replaced routes with cached routes

---------

Co-authored-by: Aaron-53 <138325645+Aaron-53@users.noreply.github.com>

* integrated useGetQuery in some routes (#550)

* integrated useGetQuery in some routes

* fixed useGetQuery usage for some routes

* Add: viewing Email sent and not sent  (#557)

* Fix:Runtime error & Add:Single participant

* Fix:Runtime error & Add:single participant

* Add:viewing email recipients

* add:font size increased

* Added cache invalidation

* build verified

* build verified

* finishing up with API caching

* finishing up with API caching

* verified build

* removed unused libs and verified build

* added docker build for branch mvp

* Build verified

* solved a lot of unmet peer dependency issues

* Merge conflicts solved

* verified build and merge

---------

Co-authored-by: Midhun Unni <96683120+midhununni457@users.noreply.github.com>
Co-authored-by: aaron-6960 <138325645+aaron-6960@users.noreply.github.com>
Co-authored-by: aaron-6960 <aaroongeorge2005@gmail.com>
Co-authored-by: Krishnan E <111748631+krishnanx@users.noreply.github.com>
Co-authored-by: Aaron-53 <138325645+Aaron-53@users.noreply.github.com>
  • Loading branch information
6 people authored Nov 24, 2024
1 parent d3ef109 commit 6431eb6
Show file tree
Hide file tree
Showing 44 changed files with 15,699 additions and 848 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- mvp

jobs:
build-and-push-core-admin:
Expand Down
2 changes: 2 additions & 0 deletions apps/core-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"license": "ISC",
"dependencies": {
"@supabase/supabase-js": "^2.46.1",
"@typescript-eslint/parser": "6.0.0",
"axios": "^1.5.1",
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.2",
Expand All @@ -28,6 +29,7 @@
"express-oauth2-jwt-bearer": "^1.6.0",
"form-data": "^4.0.1",
"jsonwebtoken": "^9.0.0",
"marked": "^15.0.0",
"passport": "^0.7.0",
"passport-local": "^1.0.0",
"pg": "^8.11.0",
Expand Down
137 changes: 129 additions & 8 deletions apps/core-admin/src/controllers/mail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,81 @@ dotenv.config();
// import chalk from 'chalk';
import supabase from '../utils/supabase';
import FormData from 'form-data';
import { marked } from 'marked';

const MAILER_URL = process.env.MAILER_URL;
const MAILER_DATABASE_URL = process.env.MAILER_DATABASE_URL;
const AUTHORIZATION_TOKEN = process.env.AUTHORIZATION_TOKEN;
// console.log(AUTHORIZATION_TOKEN);
export const getStatusOfEmails = async (req: Request, res: Response) => {
try {
const { emailArray } = req.body;
const { orgId } = req?.params;
if (!emailArray || !orgId) {
return res.status(400).send({ message: 'Missing required fields' });
}

if (!Array.isArray(emailArray)) {
return res.status(400).send({ message: 'Element not a valid array' });
}
const data: string[] = emailArray;
// Fetch the jobId associated with the email from the Recipients table
let invalidEmails = [];
let successEmails = [];
for (const email of data) {
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (emailRegex.test(email)) {
const recipient = await prisma.Recipients.findUnique({
where: { email: email },
select: { jobId: true },
});

if (recipient) {
const jobId = recipient.jobId;

if (jobId) {
// Call external mail service to get the status of the email job
const emailStatus = await axios.get(`${MAILER_URL}/mail?jobId=${jobId}`, {
headers: {
authorization: AUTHORIZATION_TOKEN,
},
});
console.log(emailStatus);

if (
emailStatus &&
emailStatus.status === 200 &&
emailStatus.data.status.status == 'SENT'
) {
console.log({ ...emailStatus.data.status });
// return res.status(200).json({
// ...emailStatus.data.status,
// });
successEmails.push(email);
} else {
// return res.status(400).send({ message: 'JobId not found', error: emailStatus.data });
invalidEmails.push(email);
}
} else {
// return res.status(400).send({ message: 'Email Job ID not found, send email again' });
invalidEmails.push(email);
}
} else {
invalidEmails.push(email);
}
} else {
invalidEmails.push(email);
}
}
return res.status(200).json({
invalidEmails: invalidEmails,
successEmails: successEmails,
});
} catch (e: any) {
console.error(e);
return res.status(400).send({ message: e.message || 'Something went wrong' });
}
};
export const sendMailWithQR = async (req: Request, res: Response) => {
try {
const { subject, html, projectId } = req.body;
Expand All @@ -31,12 +101,14 @@ export const sendMailWithQR = async (req: Request, res: Response) => {
let numberOfRecipientsMailed = 0;
let RecipientsMailed = [];
let numberOfRecipientsAlreadyMailed = 0;
let recipientAlreadyMailed = [];
let numberOfRecipientsFailed = 0;
let RecipientsNotMailed = [];

for (const recipient of recipients) {
if (recipient.emailSent) {
numberOfRecipientsAlreadyMailed++;
recipientAlreadyMailed.push(recipient);
console.log(`Project: ${projectId} - Mail already sent to ${recipient.email}`);
} else {
console.log(`Project: ${projectId} - Sending mail to ${recipient.email}`);
Expand Down Expand Up @@ -77,24 +149,31 @@ export const sendMailWithQR = async (req: Request, res: Response) => {
});

numberOfRecipientsMailed++;
RecipientsMailed.push(recipient.email);
RecipientsMailed.push({
email: recipient.email,
jobId: response.data.jobId,
});
} else {
try {
console.log(response.data);
} catch (e) {
console.log('error', e);
}
numberOfRecipientsFailed++;
RecipientsNotMailed.push(recipient.email);
RecipientsNotMailed.push({
email: recipient.email,
jobId: null,
});
}
}
}

return res.status(200).json({
success: RecipientsMailed,
failure: RecipientsNotMailed,
nSuccess: RecipientsMailed.length,
nFailure: RecipientsNotMailed.length,
alreadyMailed: recipientAlreadyMailed,
nAlreadyMailed: recipientAlreadyMailed.length,
});
} else {
return res.status(400).send({ message: 'Invalid Project ID / project ID not found' });
Expand All @@ -110,7 +189,33 @@ export const sendMailWithQR = async (req: Request, res: Response) => {
function sleepAsync(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

export const getRecipients = async (req: Request, res: Response) => {
try {
const { projectId, orgId } = req?.params;
// console.log('Hello')
if (!projectId || !orgId) {
return res.status(400).send({ message: 'Missing required fields' });
}
const recipients = await prisma.Recipients.findMany({
where: {
projectId: projectId,
},
});
if (recipients) {
return res.status(200).json({
recipients: recipients,
});
} else {
return res.status(400).send({
message: 'Unknown prisma error',
});
}
} catch (e: any) {
console.error(e);
return res.status(400).send({ message: e.message || 'Something went wrong' });
}
// return res.send('Route works!');
};
export const getMailStatus = async (req: Request, res: Response) => {
try {
const { email } = req?.params;
Expand Down Expand Up @@ -387,14 +492,22 @@ const generateOTP = () => {

export const sendOTP = async (req: Request, res: Response) => {
try {
const { email, name, html } = req.body;
const { email, name, projectId } = req.body;
console.log(req.body);

// Check for required fields
if (!email || !name || !html) {
if (!email || !name || !projectId) {
return res.status(400).send({ message: 'Missing required fields' });
}

const markdown = await prisma.Projects.findFirst({
where: {
id: projectId,
},
select: {
html_template: true,
},
});
// Check if the OTP already exists for the email
const otpRecord = await prisma.Otp.findFirst({
where: {
Expand All @@ -417,8 +530,12 @@ export const sendOTP = async (req: Request, res: Response) => {
form.append('name', name);
form.append('to', email);
form.append('subject', 'Confirm your OTP');
let emailText: string = html;
let emailText: string = await marked(markdown.html_template);
emailText = emailText.replace('((otp))', otp.toString());
emailText = emailText.replace('{{name}}', name);
console.log(emailText);
emailText = emailText.replace(/\n/g, '');
emailText = emailText.replace(/"/g, "'");
form.append('html', emailText);
form.append('text', 'Confirm your OTP');
console.log(`${MAILER_URL}/mail`);
Expand Down Expand Up @@ -462,8 +579,12 @@ export const sendOTP = async (req: Request, res: Response) => {
form.append('name', name);
form.append('to', email);
form.append('subject', 'Confirm your OTP');
let emailText: string = html;
let emailText: string = await marked(markdown.html_template);
emailText = emailText.replace('((otp))', otp.toString());
emailText = emailText.replace('{{name}}', name);
console.log(emailText);
emailText = emailText.replace(/\n/g, '');
emailText = emailText.replace(/"/g, "'");
form.append('html', emailText);
form.append('text', 'Confirm your OTP');

Expand Down
49 changes: 26 additions & 23 deletions apps/core-admin/src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import {
addNewRecipients,
getMailProjects,
getMailStatus,
getRecipients,
getStatusOfEmails,
newMailProject,
sendMailWithQR,
sendOTP,
Expand All @@ -59,44 +61,44 @@ router.get('/', (req: any, res: any) => {
}
});

router.get('/users/mycreds', myCredential);
router.get('/users/mycreds', myCredential); //done //done

router.get('/users/me', fetchAccountDetails);
router.put('/users/me', updateAccountDetails);
router.get('/users/me', fetchAccountDetails); //aaron not used //aaron not used
router.put('/users/me', updateAccountDetails); //aaron put request //aaron put request

router.get('/organizations', getUsersOrganizations);
router.get('/organizations/:orgId', getOrganizationStats);
router.get('/organizations', getUsersOrganizations); //aaron not used //aaron not used
router.get('/organizations/:orgId', getOrganizationStats); //aaron done //aaron done
router.post('/organizations', createNewOrganization);

router.get('/organizations/:orgId/members', validateOrganizationUser, getOrganizationMembers);
router.get('/organizations/:orgId/members', validateOrganizationUser, getOrganizationMembers); // aaron done
router.post('/organizations/:orgId/members', validateOrganizationAdmin, addOrganizationMember);

router.get('/organizations/:orgId/events', getEvents);
router.get('/organizations/:orgId/events/:eventId', getEventStats);
router.post('/organizations/:orgId/events', createNewEvent);
router.get('/organizations/:orgId/events', getEvents); //aaron done //aaron done
router.get('/organizations/:orgId/events/:eventId', getEventStats); //midhun //midhun - done
router.post('/organizations/:orgId/events', createNewEvent); //midhun

router.get('/organizations/:orgId/events/:eventId/participants', getAllParticipants);
router.get('/organizations/:orgId/events/:eventId/participants', getAllParticipants); //midhun //midhun - done
router.post('/organizations/:orgId/events/:eventId/participants', addNewParticipant);
router.put('/organizations/:orgId/events/:eventId/participants/:participantId', editParticipant);

router.get(
'/organizations/:orgId/events/:eventId/participants/check-in',
getAllParticipantsCheckInDetails,
);
router.get('/organizations/:orgId/events/:eventId/participants/:participantId', getParticipantById);
); //midhun //midhun - done
router.get('/organizations/:orgId/events/:eventId/participants/:participantId', getParticipantById); //midhun //midhun - done

router.get(
'/organizations/:orgId/events/:eventId/participants/check-in/:checkInKey',
getParticipantBycheckInKey,
);
); //midhun //midhun - done

router.post('/organizations/:orgId/events/:eventId/participants/check-in', checkInParticipant);
router.post('/organizations/:orgId/events/:eventId/participants/check-out', checkOutParticipant);

router.get(
'/organizations/:orgId/events/:eventId/participants/:participantId/attributes',
getParticipantAttributes,
);
); //subru
router.post(
'/organizations/:orgId/events/:eventId/participants/:participantId/attributes',
setParticipantAttribute,
Expand All @@ -106,19 +108,19 @@ router.put(
updateParticipantAttribute,
);

router.get('/organizations/:orgId/events/:eventId/attributes', getAllAttributes);
router.get('/organizations/:orgId/events/:eventId/attributes/:attributeId', getAttributeById);
router.get('/organizations/:orgId/events/:eventId/attributes', getAllAttributes); // done
router.get('/organizations/:orgId/events/:eventId/attributes/:attributeId', getAttributeById); //done
router.get(
'/organizations/:orgId/events/:eventId/attributes/:attributeId/participants',
getAttributeParticipants,
);
router.put('/organizations/:orgId/events/:eventId/attributes/:attributeId', editAttribute);
router.post('/organizations/:orgId/events/:eventId/attributes', addNewAttribute);
); //not found
router.put('/organizations/:orgId/events/:eventId/attributes/:attributeId', editAttribute); //not found
router.post('/organizations/:orgId/events/:eventId/attributes', addNewAttribute); //done

router.get('/organizations/:orgId/events/:eventId/extras', getAllExtras);
router.get('/organizations/:orgId/events/:eventId/extras/:extraId', getExtraById);
router.post('/organizations/:orgId/events/:eventId/extras/:extraId/check-in', checkInExtra);
router.post('/organizations/:orgId/events/:eventId/extras', addNewExtra);
router.get('/organizations/:orgId/events/:eventId/extras', getAllExtras); //done
router.get('/organizations/:orgId/events/:eventId/extras/:extraId', getExtraById); //done
router.post('/organizations/:orgId/events/:eventId/extras/:extraId/check-in', checkInExtra); //done
router.post('/organizations/:orgId/events/:eventId/extras', addNewExtra); //done

//mailer routes
router.post('/organizations/:orgId/newEmailProject', newMailProject);
Expand All @@ -132,4 +134,5 @@ router.post('/organizations/:orgId/events/:eventId/mailQR', sendMailWithQR);
// OTP routes
router.post('/organizations/sendOTP', sendOTP);
router.post('/organizations/verifyOTP', verifyOTP);

export default router;
7 changes: 4 additions & 3 deletions apps/core-auth0-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^16.0.3",
"express": "^4.18.2",
"@typescript-eslint/parser": "6.0.0",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"database": "workspace:*"
"database": "workspace:*",
"dotenv": "^16.0.3",
"express": "^4.18.2"
},
"devDependencies": {
"@types/chai": "^4.3.5",
Expand Down
5 changes: 3 additions & 2 deletions apps/core-mailer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"@typescript-eslint/parser": "6.0.0",
"amqplib": "^0.10.4",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
Expand All @@ -24,6 +25,8 @@
"ioredis": "^5.4.1",
"multer": "1.4.5-lts.1",
"nodemailer": "^6.9.9",
"typedoc": "^0.26.11",
"typescript": "5.6",
"uuid": "^9.0.0"
},
"devDependencies": {
Expand All @@ -49,8 +52,6 @@
"rimraf": "^5.0.1",
"ts-loader": "^9.5.1",
"tsconfig": "workspace:*",
"typedoc": "^0.26.6",
"typescript": "^5.0.4",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4"
}
Expand Down
Loading

0 comments on commit 6431eb6

Please sign in to comment.