diff --git a/packages/server/controllers/auth.js b/packages/server/controllers/auth.js index 2ad2e072..2cc2ac56 100644 --- a/packages/server/controllers/auth.js +++ b/packages/server/controllers/auth.js @@ -5,6 +5,7 @@ const token = require("../utils/token"); const bcrypt = require("bcrypt"); const client = new OAuth2Client(process.env.WEB_CLIENT_ID); const nodemailer = require("nodemailer"); +const UserController = require("./users"); const NAMESPACE = "7af17462-8078-4703-adda-be2143a4d93a"; @@ -13,6 +14,7 @@ async function create(accessToken, refreshToken, profile, callback) { let { sub, given_name, family_name, picture, email } = profile._json; picture = picture.replace("=s96-c", ""); const googleUUID = uuidv5(sub, NAMESPACE); + const emailHash = await UserController.hashUserEmail(email); const user = await prisma.user.findUniqueOrThrow({ where: { userId: googleUUID, @@ -22,7 +24,7 @@ async function create(accessToken, refreshToken, profile, callback) { const newUser = await prisma.user.create({ data: { userId: googleUUID, - email: email, + email: emailHash, avatar: picture, firstName: given_name, lastName: family_name, @@ -82,6 +84,7 @@ async function register(newUser) { const salt = await bcrypt.genSalt(saltRounds); const passwordHash = await bcrypt.hash(newUser.password, salt); const userId = uuidv4(); + const emailHash = await UserController.hashUserEmail(newUser.email); // placeholder names until new user puts in their names in onboarding screen return await prisma.user.create({ @@ -89,7 +92,7 @@ async function register(newUser) { userId, firstName: "New", lastName: "User", - email: newUser.email, + email: emailHash, password: passwordHash, }, }); @@ -191,15 +194,8 @@ async function authenticate(request, response, next) { } async function isUserEmail(email) { - const result = await prisma.user.findUnique({ - where: { - email: email, - }, - }); - - if (result === null) return false; - - return true; + const user = await UserController.getUserByEmail(email); + return !!user; } async function isGoogleAccount(userId) { diff --git a/packages/server/controllers/users.js b/packages/server/controllers/users.js index 3ba8ef2b..75bf201d 100644 --- a/packages/server/controllers/users.js +++ b/packages/server/controllers/users.js @@ -1,4 +1,5 @@ const prisma = require("../prisma/prisma"); +const crypto = require("node:crypto"); async function getAllUsers() { const query = await prisma.user.findMany(); @@ -24,21 +25,17 @@ async function getUserEmail(userId) { } async function getUserByEmail(email) { - const query = await prisma.user.findUnique({ + const emailHash = await hashUserEmail(email); + return prisma.user.findUnique({ where: { - email: email, + email: emailHash, }, }); - return query; } async function getUserIdByEmail(email) { - const query = await prisma.user.findUnique({ - where: { - email: email, - }, - }); - return query.userId; + const user = await getUserByEmail(email); + return user ? user.userId : null; } async function getGuildsForUser(userId) { @@ -62,6 +59,13 @@ async function getGuildsForUser(userId) { return guilds; } +async function hashUserEmail(email) { + const hash = crypto.createHash("sha256"); + hash.update(email); + const emailHash = hash.digest("hex"); + return emailHash; +} + async function updateNewUser(userId, userData) { const updatedUser = await prisma.user.update({ where: { @@ -82,5 +86,6 @@ module.exports = { getGuildsForUser, getUserIdByEmail, getUserEmail, + hashUserEmail, updateNewUser, }; diff --git a/packages/server/routes/api/events.js b/packages/server/routes/api/events.js index b88e2428..246fde12 100644 --- a/packages/server/routes/api/events.js +++ b/packages/server/routes/api/events.js @@ -46,7 +46,7 @@ router.get( const events = await EventController.getEvents( eventLimit, action, - eventId + eventId, ); if (events.length === 0) { @@ -59,10 +59,10 @@ router.get( const firstEventId = events[0].eventId; const lastEventId = events[events.length - 1].eventId; const prevCursor = Buffer.from( - `${currentPage - 1}___prev___${firstEventId}` + `${currentPage - 1}___prev___${firstEventId}`, ).toString("base64"); const nextCursor = Buffer.from( - `${currentPage + 1}___next___${lastEventId}` + `${currentPage + 1}___next___${lastEventId}`, ).toString("base64"); // follow-up request, not first request to api route @@ -100,7 +100,7 @@ router.get( message: error.message, }); } - } + }, ); router.get( @@ -126,7 +126,7 @@ router.get( const eventLimit = parseInt(requestedEventLimit) || DEFAULT_EVENT_LIMIT; const events = await EventController.getPublicUpcomingEvents( eventLimit, - eventId + eventId, ); if (events.length === 0) { @@ -157,7 +157,7 @@ router.get( message: error.message, }); } - } + }, ); router.post( @@ -195,7 +195,7 @@ router.post( message: error.message, }); } - } + }, ); router.get( @@ -228,7 +228,7 @@ router.get( message: error.message, }); } - } + }, ); router.delete( @@ -263,7 +263,7 @@ router.delete( message: error.message, }); } - } + }, ); router.put( @@ -291,7 +291,7 @@ router.put( const updatedEvent = await EventController.updateEvent( eventId, - validatedData + validatedData, ); response.status(200).json({ @@ -309,7 +309,7 @@ router.put( }); return; } - } + }, ); router.get( @@ -326,9 +326,8 @@ router.get( } try { const { eventId } = matchedData(request); - const eventAttendeesData = await EventController.getEventAttendees( - eventId - ); + const eventAttendeesData = + await EventController.getEventAttendees(eventId); response.status(200).json({ status: "success", data: { @@ -341,7 +340,7 @@ router.get( message: error.message, }); } - } + }, ); router.get( @@ -369,7 +368,7 @@ router.get( //Should return a list of events from the guild that are upcoming and in ascending order const upcoming = await EventController.getUpcomingEvents( currDate, - guildId + guildId, ); response.status(200).json({ @@ -384,7 +383,7 @@ router.get( message: error.message, }); } - } + }, ); router.get( @@ -412,7 +411,7 @@ router.get( const archived = await EventController.getArchivedEvents( currDate.toISO(), pastDate.toISO(), - guildId + guildId, ); response.status(200).json({ @@ -427,7 +426,7 @@ router.get( message: error.message, }); } - } + }, ); router.post( @@ -451,7 +450,7 @@ router.post( const eventAttendeeData = await EventController.updateAttendeeStatus( eventId, userId, - "CheckedIn" + "CheckedIn", ); response.status(200).json({ @@ -466,7 +465,7 @@ router.post( message: error.message, }); } - } + }, ); router.put( @@ -506,7 +505,7 @@ router.put( message: error.message, }); } - } + }, ); router.get( @@ -525,9 +524,8 @@ router.get( const data = matchedData(request); const eventId = data.eventId; try { - const generatedQRURI = await EventController.generateCheckInQRCode( - eventId - ); + const generatedQRURI = + await EventController.generateCheckInQRCode(eventId); response.status(200).json({ status: "success", data: { @@ -540,7 +538,7 @@ router.get( message: error.message, }); } - } + }, ); module.exports = router; diff --git a/packages/server/validators/events.js b/packages/server/validators/events.js index 60d4ca8c..104221e4 100644 --- a/packages/server/validators/events.js +++ b/packages/server/validators/events.js @@ -202,7 +202,7 @@ const attendeeStatusValidator = [ .withMessage("status cannot be null or empty") .matches(/^(NotInterested|Interested|Attending)$/) .withMessage( - "Invalid status value. Allowed values are: NotInterested, Interested, Attending" + "Invalid status value. Allowed values are: NotInterested, Interested, Attending", ), ]; @@ -220,7 +220,7 @@ const checkInTimeValidator = [ const event = await EventController.getEvent(eventId); const isMember = await GuildController.isGuildMember( event.guildId, - userId + userId, ); if (!isMember) { throw new Error("User is not a member of the guild."); @@ -258,7 +258,7 @@ const fetchPublicUpcomingEventsValidator = [ .isBase64() .withMessage("Cursor must be BASE64 Encoded!") .customSanitizer((value) => - value ? Buffer.from(value, "base64").toString() : " " + value ? Buffer.from(value, "base64").toString() : " ", ) .isUUID() .withMessage("Must be UUID!"), diff --git a/scripts/run.js b/scripts/run.js index 08e1db35..8adc571e 100644 --- a/scripts/run.js +++ b/scripts/run.js @@ -21,7 +21,7 @@ function setNgrokPath() { if (newPath.length > PATH_LIMIT) { throw new Error( - "Your path variable is over 1024 characters long. You will have to shorten it or add ngrok manually to your path." + "Your path variable is over 1024 characters long. You will have to shorten it or add ngrok manually to your path.", ); } else { console.log("path changed"); @@ -50,7 +50,7 @@ function newTerminal(command) { break; default: console.log( - "This dev script currently only supports Windows/unix at the moment." + "This dev script currently only supports Windows/unix at the moment.", ); } } @@ -79,7 +79,7 @@ setTimeout(() => { if (error) throw error; const overwrite = data.replace( /\b(https:\/\/)\b.*\b(.ngrok.free.app)\b/, - public_url + public_url, ); fs.writeFile(FILE_PATH, overwrite, "utf-8", function (error) {