Skip to content

Refactoring to Hash Stored User Emails #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions packages/server/controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -82,14 +84,15 @@ 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({
data: {
userId,
firstName: "New",
lastName: "User",
email: newUser.email,
email: emailHash,
password: passwordHash,
},
});
Expand Down Expand Up @@ -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) {
Expand Down
23 changes: 14 additions & 9 deletions packages/server/controllers/users.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const prisma = require("../prisma/prisma");
const crypto = require("node:crypto");

async function getAllUsers() {
const query = await prisma.user.findMany();
Expand All @@ -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) {
Expand All @@ -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: {
Expand All @@ -82,5 +86,6 @@ module.exports = {
getGuildsForUser,
getUserIdByEmail,
getUserEmail,
hashUserEmail,
updateNewUser,
};
50 changes: 24 additions & 26 deletions packages/server/routes/api/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ router.get(
const events = await EventController.getEvents(
eventLimit,
action,
eventId
eventId,
);

if (events.length === 0) {
Expand All @@ -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
Expand Down Expand Up @@ -100,7 +100,7 @@ router.get(
message: error.message,
});
}
}
},
);

router.get(
Expand All @@ -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) {
Expand Down Expand Up @@ -157,7 +157,7 @@ router.get(
message: error.message,
});
}
}
},
);

router.post(
Expand Down Expand Up @@ -195,7 +195,7 @@ router.post(
message: error.message,
});
}
}
},
);

router.get(
Expand Down Expand Up @@ -228,7 +228,7 @@ router.get(
message: error.message,
});
}
}
},
);

router.delete(
Expand Down Expand Up @@ -263,7 +263,7 @@ router.delete(
message: error.message,
});
}
}
},
);

router.put(
Expand Down Expand Up @@ -291,7 +291,7 @@ router.put(

const updatedEvent = await EventController.updateEvent(
eventId,
validatedData
validatedData,
);

response.status(200).json({
Expand All @@ -309,7 +309,7 @@ router.put(
});
return;
}
}
},
);

router.get(
Expand All @@ -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: {
Expand All @@ -341,7 +340,7 @@ router.get(
message: error.message,
});
}
}
},
);

router.get(
Expand Down Expand Up @@ -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({
Expand All @@ -384,7 +383,7 @@ router.get(
message: error.message,
});
}
}
},
);

router.get(
Expand Down Expand Up @@ -412,7 +411,7 @@ router.get(
const archived = await EventController.getArchivedEvents(
currDate.toISO(),
pastDate.toISO(),
guildId
guildId,
);

response.status(200).json({
Expand All @@ -427,7 +426,7 @@ router.get(
message: error.message,
});
}
}
},
);

router.post(
Expand All @@ -451,7 +450,7 @@ router.post(
const eventAttendeeData = await EventController.updateAttendeeStatus(
eventId,
userId,
"CheckedIn"
"CheckedIn",
);

response.status(200).json({
Expand All @@ -466,7 +465,7 @@ router.post(
message: error.message,
});
}
}
},
);

router.put(
Expand Down Expand Up @@ -506,7 +505,7 @@ router.put(
message: error.message,
});
}
}
},
);

router.get(
Expand All @@ -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: {
Expand All @@ -540,7 +538,7 @@ router.get(
message: error.message,
});
}
}
},
);

module.exports = router;
6 changes: 3 additions & 3 deletions packages/server/validators/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
),
];

Expand All @@ -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.");
Expand Down Expand Up @@ -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!"),
Expand Down
6 changes: 3 additions & 3 deletions scripts/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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.",
);
}
}
Expand Down Expand Up @@ -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) {
Expand Down