Skip to content

Commit

Permalink
verify & delete email settings
Browse files Browse the repository at this point in the history
  • Loading branch information
potts99 committed Mar 24, 2024
1 parent f6afe4b commit 5528270
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 13 deletions.
77 changes: 76 additions & 1 deletion apps/api/src/controllers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Feature Flags

import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import nodeMailer from "nodemailer";

import { checkToken } from "../lib/jwt";
import { prisma } from "../prisma";
Expand Down Expand Up @@ -152,7 +153,15 @@ export function configRoutes(fastify: FastifyInstance) {

if (token) {
// GET EMAIL SETTINGS
const config = await prisma.email.findFirst({});
const config = await prisma.email.findFirst({
select: {
active: true,
host: true,
port: true,
reply: true,
user: true,
},
});

if (config === null) {
reply.send({
Expand Down Expand Up @@ -232,6 +241,72 @@ export function configRoutes(fastify: FastifyInstance) {
);

// Test email is working
fastify.get(
"/api/v1/config/email/verify",

async (request: FastifyRequest, reply: FastifyReply) => {
const bearer = request.headers.authorization!.split(" ")[1];
const token = checkToken(bearer);

if (token) {
// GET EMAIL SETTINGS
const config = await prisma.email.findFirst({});

if (config === null) {
return reply.send({
success: true,
active: false,
});
}

const emails = await prisma.email.findMany();
const email = emails[0];

const mail = nodeMailer.createTransport({
// @ts-ignore
host: email.host,
port: email.port,
secure: email.port === "465" ? true : false,
auth: {
user: email.user,
pass: email.pass,
},
});

const ver = await mail.verify();

if (ver) {
reply.send({
success: true,
message: "Email is working!",
});
} else {
reply.send({
success: false,
message:
"Incorrect settings or credentials provided. Please check and try again.",
});
}
}
}
);

// Disable/Enable Email
fastify.delete(
"/api/v1/config/email",

async (request: FastifyRequest, reply: FastifyReply) => {
const bearer = request.headers.authorization!.split(" ")[1];
const token = checkToken(bearer);

if (token) {
await prisma.email.deleteMany({});

reply.send({
success: true,
message: "Email settings deleted!",
});
}
}
);
}
89 changes: 77 additions & 12 deletions apps/client/pages/admin/email/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ExclamationTriangleIcon } from "@heroicons/react/20/solid";
import { notifications } from "@mantine/notifications";
import { getCookie } from "cookies-next";
import { useEffect, useState } from "react";

Expand Down Expand Up @@ -34,6 +35,51 @@ export default function Notifications() {
});
}

async function deleteEmailConfig() {
setLoading(true);
await fetch(`/api/v1/config/email`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${getCookie("session")}`,
},
})
.then((res) => res.json())
.then(() => {
setHost("");
setPort("");
setUsername("");
setPassword("");
setReply("");
fetchEmailConfig();
});
}

async function testEmailConfig() {
// Send a test email to the reply address
await fetch(`/api/v1/config/email/verify`, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getCookie("session")}`,
},
})
.then((res) => res.json())
.then((res) => {
if (res.success) {
notifications.show({
title: "Email Config Test",
message: "Email Config Test was successful",
color: "teal",
});
} else {
notifications.show({
title: "Email Config Test",
message: "Email Config Test failed",
color: "red",
});
}
});
}

async function fetchEmailConfig() {
await fetch(`/api/v1/config/email`, {
method: "get",
Expand All @@ -45,7 +91,6 @@ export default function Notifications() {
.then((res) => res.json())
.then((res) => {
if (res.success && res.active) {
console.log(res);
setEnabled(res.email.active);
setHost(res.email.host);
setPort(res.email.port);
Expand Down Expand Up @@ -81,21 +126,41 @@ export default function Notifications() {
internal users for Notifications.
</p>
</div>
<div className="sm:ml-16 sm:flex-none">
<>
<button
onClick={() => updateEmailConfig()}
type="button"
className="rounded bg-white px-4 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
>
Save
</button>
</>
</div>
</div>
</div>
</div>
</div>
<div className="sm:flex-none mb-4">
<div className="flex flex-row gap-x-4 justify-between">
<div className="space-x-4">
<button
onClick={() => updateEmailConfig()}
type="button"
className="rounded bg-white px-4 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
>
Update Settings
</button>
{enabled && (
<button
onClick={testEmailConfig}
type="button"
className="rounded bg-white px-4 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
>
Test Settings
</button>
)}
</div>
{enabled && (
<button
onClick={deleteEmailConfig}
type="button"
className="rounded bg-red-500 px-4 py-2 text-sm font-semibold text-white shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-red-400"
>
Delete Settings
</button>
)}
</div>
</div>
{!loading && (
<div className="px-4 sm:px-6 md:px-0">
<div className="mb-6">
Expand Down

0 comments on commit 5528270

Please sign in to comment.