mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-11 18:04:27 +08:00
impr: store emailVerified status in database (@fehmer)
This commit is contained in:
parent
6dad5415c2
commit
a08f9df52d
7 changed files with 92 additions and 3 deletions
|
|
@ -253,6 +253,66 @@ describe("user controller test", () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
describe("getUser", () => {
|
||||
const getUserMock = vi.spyOn(UserDal, "getUser");
|
||||
const updateEmailMock = vi.spyOn(UserDal, "updateEmail");
|
||||
beforeEach(() => {
|
||||
getUserMock.mockReset();
|
||||
updateEmailMock.mockReset();
|
||||
});
|
||||
it("should update emailVerified if undefined", async () => {
|
||||
//GIVEN
|
||||
getUserMock.mockResolvedValue({
|
||||
uid,
|
||||
email: "old",
|
||||
} as any);
|
||||
mockAuth.modifyToken({ email_verified: false, email: "old" });
|
||||
|
||||
//WHEN
|
||||
await mockApp
|
||||
.get("/users")
|
||||
.set("Authorization", `Bearer ${uid}`)
|
||||
.expect(200);
|
||||
|
||||
//THEN
|
||||
expect(updateEmailMock).toHaveBeenCalledWith(uid, "old", false);
|
||||
});
|
||||
it("should update emailVerified if changed", async () => {
|
||||
//GIVEN
|
||||
getUserMock.mockResolvedValue({
|
||||
uid,
|
||||
emailVerified: false,
|
||||
email: "old",
|
||||
} as any);
|
||||
mockAuth.modifyToken({ email_verified: true, email: "next" });
|
||||
|
||||
//WHEN
|
||||
await mockApp
|
||||
.get("/users")
|
||||
.set("Authorization", `Bearer ${uid}`)
|
||||
.expect(200);
|
||||
|
||||
//THEN
|
||||
expect(updateEmailMock).toHaveBeenCalledWith(uid, "next", true);
|
||||
});
|
||||
it("should not update emailVerified if not changed", async () => {
|
||||
//GIVEN
|
||||
getUserMock.mockResolvedValue({
|
||||
uid,
|
||||
emailVerified: false,
|
||||
} as any);
|
||||
mockAuth.modifyToken({ email_verified: false });
|
||||
|
||||
//WHEN
|
||||
await mockApp
|
||||
.get("/users")
|
||||
.set("Authorization", `Bearer ${uid}`)
|
||||
.expect(200);
|
||||
|
||||
//THEN
|
||||
expect(updateEmailMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe("sendVerificationEmail", () => {
|
||||
const adminGetUserMock = vi.fn();
|
||||
const adminGenerateVerificationLinkMock = vi.fn();
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ describe("UserDal", () => {
|
|||
expect(insertedUser.email).toBe(newUser.email);
|
||||
expect(insertedUser.uid).toBe(newUser.uid);
|
||||
expect(insertedUser.name).toBe(newUser.name);
|
||||
expect(insertedUser.emailVerified).toBe(false);
|
||||
});
|
||||
|
||||
it("should error if the user already exists", async () => {
|
||||
|
|
@ -1167,7 +1168,10 @@ describe("UserDal", () => {
|
|||
});
|
||||
it("should update", async () => {
|
||||
//given
|
||||
const { uid } = await UserTestData.createUser({ email: "init" });
|
||||
const { uid } = await UserTestData.createUser({
|
||||
email: "init",
|
||||
emailVerified: true,
|
||||
});
|
||||
|
||||
//when
|
||||
await expect(UserDAL.updateEmail(uid, "next")).resolves.toBe(true);
|
||||
|
|
@ -1175,6 +1179,7 @@ describe("UserDal", () => {
|
|||
//then
|
||||
const read = await UserDAL.getUser(uid, "read");
|
||||
expect(read.email).toEqual("next");
|
||||
expect(read.emailVerified).toEqual(false);
|
||||
});
|
||||
});
|
||||
describe("resetPb", () => {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ const mockDecodedToken: DecodedIdToken = {
|
|||
uid: "123456789",
|
||||
email: "newuser@mail.com",
|
||||
iat: 0,
|
||||
email_verified: true,
|
||||
} as DecodedIdToken;
|
||||
|
||||
vi.spyOn(AuthUtils, "verifyIdToken").mockResolvedValue(mockDecodedToken);
|
||||
|
|
@ -62,6 +63,7 @@ describe("middlewares/auth", () => {
|
|||
type: "None",
|
||||
uid: "",
|
||||
email: "",
|
||||
emailVerified: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -122,6 +124,7 @@ describe("middlewares/auth", () => {
|
|||
expect(decodedToken?.type).toBe("Bearer");
|
||||
expect(decodedToken?.email).toBe(mockDecodedToken.email);
|
||||
expect(decodedToken?.uid).toBe(mockDecodedToken.uid);
|
||||
expect(decodedToken?.emailVerified).toBe(mockDecodedToken.email_verified);
|
||||
expect(nextFunction).toHaveBeenCalledOnce();
|
||||
|
||||
expect(prometheusIncrementAuthMock).toHaveBeenCalledWith("Bearer");
|
||||
|
|
|
|||
|
|
@ -605,6 +605,18 @@ export async function getUser(req: MonkeyRequest): Promise<GetUserResponse> {
|
|||
);
|
||||
delete relevantUserInfo.customThemes;
|
||||
|
||||
//update users emailVerified status if it changed
|
||||
const { email, emailVerified } = req.ctx.decodedToken;
|
||||
if (emailVerified !== undefined && emailVerified !== userInfo.emailVerified) {
|
||||
void addImportantLog(
|
||||
"user_verify_email",
|
||||
`emailVerified changed to ${emailVerified} for email ${email}`,
|
||||
uid
|
||||
);
|
||||
await UserDAL.updateEmail(uid, email, emailVerified);
|
||||
userInfo.emailVerified = emailVerified;
|
||||
}
|
||||
|
||||
const userData: User = {
|
||||
...relevantUserInfo,
|
||||
resultFilterPresets,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ export async function addUser(
|
|||
custom: {},
|
||||
},
|
||||
testActivity: {},
|
||||
emailVerified: false,
|
||||
};
|
||||
|
||||
const result = await getUsersCollection().updateOne(
|
||||
|
|
@ -231,9 +232,14 @@ export async function updateQuoteRatings(
|
|||
|
||||
export async function updateEmail(
|
||||
uid: string,
|
||||
email: string
|
||||
email: string,
|
||||
emailVerified: boolean = true
|
||||
): Promise<boolean> {
|
||||
await updateUser({ uid }, { $set: { email } }, { stack: "update email" });
|
||||
await updateUser(
|
||||
{ uid },
|
||||
{ $set: { email, emailVerified } },
|
||||
{ stack: "update email" }
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export type DecodedToken = {
|
|||
type: "Bearer" | "ApeKey" | "None" | "GithubWebhook";
|
||||
uid: string;
|
||||
email: string;
|
||||
emailVerified?: boolean;
|
||||
};
|
||||
|
||||
const DEFAULT_OPTIONS: RequestAuthenticationOptions = {
|
||||
|
|
@ -189,6 +190,7 @@ async function authenticateWithBearerToken(
|
|||
type: "Bearer",
|
||||
uid: decodedToken.uid,
|
||||
email: decodedToken.email ?? "",
|
||||
emailVerified: decodedToken.email_verified,
|
||||
};
|
||||
} catch (error) {
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -271,6 +271,7 @@ export const UserSchema = z.object({
|
|||
quoteMod: QuoteModSchema.optional(),
|
||||
resultFilterPresets: z.array(ResultFiltersSchema).optional(),
|
||||
testActivity: TestActivitySchema.optional(),
|
||||
emailVerified: z.boolean().optional(),
|
||||
});
|
||||
export type User = z.infer<typeof UserSchema>;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue