From 9c98986fbc37ed96e828460f1e637b90388c9fbc Mon Sep 17 00:00:00 2001 From: Eva Killenberg Date: Wed, 26 Apr 2023 22:58:44 -0700 Subject: [PATCH] feat(email-notifs): send emails from admin panel for testing --- .../src/emailNotifications/createEmail.ts | 1 + functions/src/emailNotifications/index.ts | 33 +++++++++++++++++++ .../admin/pages/adminNotifications.tsx | 18 +++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/functions/src/emailNotifications/createEmail.ts b/functions/src/emailNotifications/createEmail.ts index 883d1b5cfb..e659178597 100644 --- a/functions/src/emailNotifications/createEmail.ts +++ b/functions/src/emailNotifications/createEmail.ts @@ -13,6 +13,7 @@ const getResourceLabelFromNotificationType = (type: NotificationType) => { return 'research' case 'howto_useful': case 'howto_mention': + case 'new_comment': return 'how-to' } } diff --git a/functions/src/emailNotifications/index.ts b/functions/src/emailNotifications/index.ts index 29b2848196..fe487b4a4f 100644 --- a/functions/src/emailNotifications/index.ts +++ b/functions/src/emailNotifications/index.ts @@ -1,8 +1,41 @@ import * as functions from 'firebase-functions' import { createNotificationEmails } from './createEmail' +import { db } from '../Firebase/firestoreDB' +import { DB_ENDPOINTS, IUserDB } from '../models' /** Trigger daily process to send any pending email notifications */ exports.sendDaily = functions.pubsub // Trigger daily at 5pm (https://crontab.guru/#0_17_*_*_*) .schedule('0 17 * * *') .onRun(async () => createNotificationEmails()) + +exports.sendOnce = functions.https.onCall(async (_, context) => { + if (!context.auth) { + throw new functions.https.HttpsError( + 'failed-precondition', + 'The function must be called while authenticated.', + ) + } + // Validate user exists and has admin status before triggering function. + const { uid } = context.auth + const user = await db.collection(DB_ENDPOINTS.users).doc(uid).get() + if (user.exists) { + const { userRoles } = user.data() as IUserDB + if (userRoles?.some((role) => ['admin', 'super-admin'].includes(role))) { + try { + await createNotificationEmails() + return 'OK' + } catch (error) { + console.error(error) + throw new functions.https.HttpsError( + 'internal', + 'There was an error creating emails.', + ) + } + } + } + throw new functions.https.HttpsError( + 'permission-denied', + 'Emails can be triggered by admins only.', + ) +}) diff --git a/src/modules/admin/pages/adminNotifications.tsx b/src/modules/admin/pages/adminNotifications.tsx index 31922f1625..27a2a0b2f2 100644 --- a/src/modules/admin/pages/adminNotifications.tsx +++ b/src/modules/admin/pages/adminNotifications.tsx @@ -2,12 +2,13 @@ import styled from '@emotion/styled' import { observer } from 'mobx-react' import { NotificationItem } from 'oa-components' import { useCallback, useEffect, useState } from 'react' -import { Box, Text } from 'theme-ui' +import { Box, Button, Text } from 'theme-ui' import { useDB } from 'src/App' import type { INotification, IPendingEmails } from 'src/models' import { getFormattedNotificationMessage } from 'src/pages/common/Header/getFormattedNotifications' import Table from '../components/Table/Table' import type { ICellRenderProps, ITableProps } from '../components/Table/Table' +import { functions } from 'src/utils/firebase' type IPendingEmailsDBDoc = Record @@ -33,6 +34,9 @@ const NotificationListContainer = styled(Box)` const AdminNotifictions = observer(() => { const { db } = useDB() const [emailsPending, setEmailsPending] = useState([]) + const [triggerEmailState, setTriggerEmailState] = useState( + 'Click the button to trigger emails.', + ) // Load list of pending approvals on mount only, dependencies empty to avoid reloading useEffect(() => { @@ -55,6 +59,16 @@ const AdminNotifictions = observer(() => { }) }, []) + const triggerEmails = async () => { + setTriggerEmailState('Sending...') + try { + await functions.httpsCallable('emailNotifications-sendOnce')() + setTriggerEmailState('Emails sent successfully.') + } catch (error) { + setTriggerEmailState(`Error sending emails: \n ${error}`) + } + } + /** Function applied to render each table row cell */ const RenderContent: React.FC = ( props: ICellRenderProps, @@ -82,6 +96,8 @@ const AdminNotifictions = observer(() => { <>

Admin Notifictions

Pending Emails

+ + {triggerEmailState &&

{triggerEmailState}

}