Skip to content

Commit

Permalink
feat: Welcome email
Browse files Browse the repository at this point in the history
  • Loading branch information
brennanwilkes committed Mar 12, 2021
1 parent 98dde7f commit 213d383
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
**/node_modules
public-frontend/
**/*.config.*
src/dev/clearCache.js
src/dev/*
src/frontend/spotifyWebSDK/
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"test:loud": "jest --colors --verbose",
"lint": "eslint \"src/**/*.[jt]s\" --fix",
"clearCache": "mongo \"$( cat .env | grep DB_CONNECTION | cut -d'=' -f2 )\" < src/dev/clearCache.js",
"clearUsers": "mongo \"$( cat .env | grep DB_CONNECTION | cut -d'=' -f2 )\" < src/dev/clearUsers.js",
"deploy": "bash ./src/dev/deploy.sh gcs-radio",
"deploy:beta": "bash ./src/dev/deploy.sh gcs-radio-beta"
},
Expand All @@ -39,6 +40,7 @@
"@babel/preset-env": "^7.12.17",
"@babel/preset-react": "^7.12.13",
"@google-cloud/text-to-speech": "^3.1.3",
"@sendgrid/mail": "^7.4.2",
"@types/fluent-ffmpeg": "^2.1.16",
"@types/multer": "^1.4.5",
"@types/spotify-web-playback-sdk": "^0.1.8",
Expand Down
3 changes: 3 additions & 0 deletions src/backend/controllers/oauthGoogleController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import UserModel, { userDocFromUser } from "../../database/models/user";
import generateToken from "../auth/generateToken";
import { UserFromGoogleCredentials, UserType } from "../../types/user";
import { GoogleCredential } from "../../types/googleCredential";
import welcomeEmail from "../email/welcomeEmail";
import { fireAndForgetMail } from "../email/email";

const generateGoogleRedirectURI = (req: Request) => `${req.protocol}://${req.get("host")}/auth/oauth/google`;

Expand Down Expand Up @@ -37,6 +39,7 @@ const redirectFromGoogle = async (req: Request, res:Response): Promise<void> =>
return generateToken(docs[0]._id);
} else {
const user = new UserFromGoogleCredentials(info as GoogleCredential);
fireAndForgetMail(welcomeEmail(user.email));
const doc = await userDocFromUser(user).save();
return await generateToken(doc._id);
}
Expand Down
3 changes: 3 additions & 0 deletions src/backend/controllers/oauthSpotifyController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import UserModel, { userDocFromUser } from "../../database/models/user";
import { UserFromSpotifyCredentials, UserType } from "../../types/user";
import SpotifyApi from "spotify-web-api-node";
import generateToken from "../auth/generateToken";
import welcomeEmail from "../email/welcomeEmail";
import { fireAndForgetMail } from "../email/email";

const generateSpotifyRedirectURI = (req: Request): string => `${req.protocol}://${req.get("host")}/auth/oauth/spotify`;
export { generateSpotifyRedirectURI };
Expand Down Expand Up @@ -44,6 +46,7 @@ const redirectFromSpotify = (req: Request, res:Response): void => {
return generateToken(docs[0]._id);
} else {
const userObj = new UserFromSpotifyCredentials(user as SpotifyApi.UserObjectPrivate);
fireAndForgetMail(welcomeEmail(userObj.email));
const doc = await userDocFromUser(userObj).save();
return await generateToken(doc._id);
}
Expand Down
4 changes: 4 additions & 0 deletions src/backend/controllers/userController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import invalidLoginErrorHandler from "../errorHandlers/invalidLoginErrorHandler"
import conflictErrorHandler from "../errorHandlers/conflictErrorHandler";
import generateToken from "../auth/generateToken";
import { getUserFromToken } from "../auth/getUser";
import welcomeEmail from "../email/welcomeEmail";
import { fireAndForgetMail } from "../email/email";

export async function login (req: Request, res: Response): Promise<void> {
const { email, password } = req.body;
Expand Down Expand Up @@ -52,6 +54,8 @@ export async function signUp (req: Request, res: Response): Promise<void> {
}).then(doc => {
return generateToken(doc._id);
}).then(token => {
fireAndForgetMail(welcomeEmail(email));

res.cookie("jwt", token);
res.status(200).json({ token });
}).catch(internalErrorHandler(req, res));
Expand Down
47 changes: 47 additions & 0 deletions src/backend/email/email.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import sgMail from "@sendgrid/mail";
import { ClientResponse } from "@sendgrid/client/src/response";
import { CONFIG, print } from "../util/util";

export interface Mail{
email: string,
subject: string,
message: string,
htmlEnable?: boolean
}
/* eslint-disable @typescript-eslint/ban-types */
export interface MailService{
send: (mail: Mail) => Promise<[ClientResponse, {}]>;
fromEmail: string;
}

const MailServiceObj = new Promise<MailService>((resolve, reject) => {
if (process.env.SENDGRID_API_KEY) {
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
resolve({
fromEmail: CONFIG.fromEmail,
send: ({ email, subject, message, htmlEnable = false }) => {
return new Promise<[ClientResponse, {}]>((resolve, reject) => {
const msg = {
to: email,
from: CONFIG.fromEmail,
subject: subject,
text: htmlEnable ? " " : message,
html: htmlEnable ? message : " "
};
sgMail.send(msg).then(resolve).catch(reject);
});
}
});
} else {
reject(new Error("SENDGRID_API_KEY not set!"));
}
});
/* eslint-enable @typescript-eslint/ban-types */

export default MailServiceObj;

export function fireAndForgetMail (mail: Mail): void {
MailServiceObj.then(({ send }) => {
send(mail).catch(print);
}).catch(print);
}
24 changes: 24 additions & 0 deletions src/backend/email/welcomeEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Mail } from "./email";

const welcomeEmail = `
Welcome to <strong>GCS Radio</strong>
<br /><br />
A project built entirely by me, <a href="https://bw.codexwilkes.com/portfolio/">Brennan</a>!
<br /><br />
To get started, go to the <a href="https://gcs-radio.494913.xyz/">dashboard</a>.
<br /><br />
GCS Radio is entirely open-source, so if you want to deploy it yourself, contribute ideas, report bugs, or just check out the code, feel free to check out the <a href="https://gitlab.com/brennanwilkes/gcs-radio">GIT repo</a>.
<br /><br />
Thanks for checking GCS Radio out!
<br /><br />
Brennan
`;

export default function (email: string): Mail {
return {
email: email,
subject: `Welcome to GCS Radio`,
message: welcomeEmail,
htmlEnable: true
};
}
3 changes: 2 additions & 1 deletion src/backend/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export const CONFIG = {
},
spotifyOauth2Credentials: {
scope: ["user-read-private", "user-read-email", "streaming"]
}
},
fromEmail: "GCS Radio <[email protected]>"
};

/**
Expand Down
2 changes: 2 additions & 0 deletions src/dev/clearUsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
use gcs-radio
db.users.drop()

0 comments on commit 213d383

Please sign in to comment.