diff --git a/e2e_test.ts b/e2e_test.ts
index 10aabc57a..868758ba9 100644
--- a/e2e_test.ts
+++ b/e2e_test.ts
@@ -125,6 +125,7 @@ Deno.test("[e2e] GET /", async () => {
Deno.test("[e2e] GET /callback", async (test) => {
setupEnv();
+ const id = crypto.randomUUID();
const login = crypto.randomUUID();
const sessionId = crypto.randomUUID();
@@ -137,17 +138,19 @@ Deno.test("[e2e] GET /callback", async (test) => {
},
sessionId,
};
- const id = crypto.randomUUID();
const handleCallbackStub = stub(
_internals,
"handleCallback",
returnsNext([Promise.resolve(handleCallbackResp)]),
);
const githubRespBody = {
+ id,
login,
email: crypto.randomUUID(),
};
- const stripeRespBody: Partial> = { id };
+ const stripeRespBody: Partial> = {
+ id: crypto.randomUUID(),
+ };
const fetchStub = stub(
window,
"fetch",
@@ -161,7 +164,7 @@ Deno.test("[e2e] GET /callback", async (test) => {
handleCallbackStub.restore();
fetchStub.restore();
- const user = await getUser(githubRespBody.login);
+ const user = await getUser(githubRespBody.id);
assert(user !== null);
assertEquals(user.sessionId, handleCallbackResp.sessionId);
});
@@ -175,17 +178,19 @@ Deno.test("[e2e] GET /callback", async (test) => {
},
sessionId: crypto.randomUUID(),
};
- const id = crypto.randomUUID();
const handleCallbackStub = stub(
_internals,
"handleCallback",
returnsNext([Promise.resolve(handleCallbackResp)]),
);
const githubRespBody = {
+ id,
login,
email: crypto.randomUUID(),
};
- const stripeRespBody: Partial> = { id };
+ const stripeRespBody: Partial> = {
+ id: crypto.randomUUID(),
+ };
const fetchStub = stub(
window,
"fetch",
@@ -199,7 +204,7 @@ Deno.test("[e2e] GET /callback", async (test) => {
handleCallbackStub.restore();
fetchStub.restore();
- const user = await getUser(githubRespBody.login);
+ const user = await getUser(githubRespBody.id);
assert(user !== null);
assertNotEquals(user.sessionId, sessionId);
});
@@ -418,7 +423,7 @@ Deno.test("[e2e] POST /submit", async (test) => {
body,
}),
);
- const items = await collectValues(listItemsByUser(user.login));
+ const items = await collectValues(listItemsByUser(user.id));
assertRedirect(resp, "/");
// Deep partial match since the item ID is a ULID generated at runtime
@@ -493,7 +498,7 @@ Deno.test("[e2e] GET /api/users/[login]/items", async (test) => {
const user = randomUser();
const item: Item = {
...randomItem(),
- userLogin: user.login,
+ userId: user.id,
};
const req = new Request(`http://localhost/api/users/${user.login}/items`);
@@ -547,7 +552,7 @@ Deno.test("[e2e] POST /api/vote", async (test) => {
});
await test.step("creates a vote", async () => {
- const item = { ...randomItem(), userLogin: user.login };
+ const item = { ...randomItem(), userId: user.id };
await createItem(item);
const resp = await handler(
new Request(url, {
@@ -700,7 +705,7 @@ Deno.test("[e2e] POST /api/stripe-webhooks", async (test) => {
constructEventAsyncStub.restore();
assertEquals(resp.status, STATUS_CODE.Created);
- assertEquals(await getUser(user.login), { ...user, isSubscribed: true });
+ assertEquals(await getUser(user.id), { ...user, isSubscribed: true });
});
await test.step("serves not found response if the user is not found for subscription deletion", async () => {
@@ -750,7 +755,7 @@ Deno.test("[e2e] POST /api/stripe-webhooks", async (test) => {
constructEventAsyncStub.restore();
- assertEquals(await getUser(user.login), { ...user, isSubscribed: false });
+ assertEquals(await getUser(user.id), { ...user, isSubscribed: false });
assertEquals(resp.status, STATUS_CODE.Accepted);
});
@@ -970,11 +975,11 @@ Deno.test("[e2e] GET /api/me/votes", async () => {
await createItem(item1);
await createItem(item2);
await createVote({
- userLogin: user.login,
+ userId: user.id,
itemId: item1.id,
});
await createVote({
- userLogin: user.login,
+ userId: user.id,
itemId: item2.id,
});
const resp = await handler(
diff --git a/islands/ItemsList.tsx b/islands/ItemsList.tsx
index c3a97b48e..54c6905a5 100644
--- a/islands/ItemsList.tsx
+++ b/islands/ItemsList.tsx
@@ -105,12 +105,12 @@ function ItemSummary(props: ItemSummaryProps) {
-
- {props.item.userLogin}
+
+ {props.item.userId}
{" "}
{timeAgo(new Date(decodeTime(props.item.id)))}
diff --git a/plugins/kv_oauth.ts b/plugins/kv_oauth.ts
index 8a741f292..883203318 100644
--- a/plugins/kv_oauth.ts
+++ b/plugins/kv_oauth.ts
@@ -42,10 +42,11 @@ export default {
);
const githubUser = await getGitHubUser(tokens.accessToken);
- const user = await getUser(githubUser.login);
+ const user = await getUser(githubUser.id);
if (user === null) {
const user: User = {
+ id: githubUser.id,
login: githubUser.login,
sessionId,
isSubscribed: false,
diff --git a/routes/api/me/votes.ts b/routes/api/me/votes.ts
index e2566eda5..cba29ae53 100644
--- a/routes/api/me/votes.ts
+++ b/routes/api/me/votes.ts
@@ -5,7 +5,7 @@ import { SignedInState } from "@/plugins/session.ts";
export const handler: Handlers = {
async GET(_req, ctx) {
- const iter = listItemsVotedByUser(ctx.state.sessionUser.login);
+ const iter = listItemsVotedByUser(ctx.state.sessionUser.id);
const items = await collectValues(iter);
return Response.json(items);
},
diff --git a/routes/api/users/[login]/index.ts b/routes/api/users/[login]/index.ts
index 10fcb51be..382015feb 100644
--- a/routes/api/users/[login]/index.ts
+++ b/routes/api/users/[login]/index.ts
@@ -1,10 +1,10 @@
// Copyright 2023-2024 the Deno authors. All rights reserved. MIT license.
import type { Handlers } from "$fresh/server.ts";
-import { getUser } from "@/utils/db.ts";
+import { getUserByLogin } from "@/utils/db.ts";
export const handler: Handlers = {
async GET(_req, ctx) {
- const user = await getUser(ctx.params.login);
+ const user = await getUserByLogin(ctx.params.login);
if (user === null) throw new Deno.errors.NotFound("User not found");
return Response.json(user);
},
diff --git a/routes/api/users/[login]/items.ts b/routes/api/users/[login]/items.ts
index 99cd23aa6..7ae90d9d9 100644
--- a/routes/api/users/[login]/items.ts
+++ b/routes/api/users/[login]/items.ts
@@ -1,15 +1,15 @@
// Copyright 2023-2024 the Deno authors. All rights reserved. MIT license.
import type { Handlers } from "$fresh/server.ts";
-import { collectValues, getUser, listItemsByUser } from "@/utils/db.ts";
+import { collectValues, getUserByLogin, listItemsByUser } from "@/utils/db.ts";
import { getCursor } from "@/utils/http.ts";
export const handler: Handlers = {
async GET(req, ctx) {
- const user = await getUser(ctx.params.login);
+ const user = await getUserByLogin(ctx.params.login);
if (user === null) throw new Deno.errors.NotFound("User not found");
const url = new URL(req.url);
- const iter = listItemsByUser(ctx.params.login, {
+ const iter = listItemsByUser(user.id, {
cursor: getCursor(url),
limit: 10,
});
diff --git a/routes/api/vote.ts b/routes/api/vote.ts
index 3398d6ef3..32f012c58 100644
--- a/routes/api/vote.ts
+++ b/routes/api/vote.ts
@@ -14,7 +14,7 @@ export const handler: Handlers = {
await createVote({
itemId,
- userLogin: ctx.state.sessionUser.login,
+ userId: ctx.state.sessionUser.id,
});
return new Response(null, { status: STATUS_CODE.Created });
diff --git a/routes/submit.tsx b/routes/submit.tsx
index c7511dc7f..39abcd6e1 100644
--- a/routes/submit.tsx
+++ b/routes/submit.tsx
@@ -33,7 +33,7 @@ export const handler: Handlers = {
await createItem({
id: ulid(),
- userLogin: ctx.state.sessionUser.login,
+ userId: ctx.state.sessionUser.id,
title,
url,
score: 0,
diff --git a/utils/db.ts b/utils/db.ts
index 0de59738c..d859c5cde 100644
--- a/utils/db.ts
+++ b/utils/db.ts
@@ -21,7 +21,7 @@ export const kv = await Deno.openKv(path);
*
* const items = await collectValues- (listItems());
* items[0].id; // Returns "01H9YD2RVCYTBVJEYEJEV5D1S1";
- * items[0].userLogin; // Returns "snoop"
+ * items[0].userId; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
* items[0].title; // Returns "example-title"
* items[0].url; // Returns "http://example.com"
* items[0].score; // Returns 420
@@ -35,7 +35,7 @@ export async function collectValues(iter: Deno.KvListIterator) {
export interface Item {
// Uses ULID
id: string;
- userLogin: string;
+ userId: string;
title: string;
url: string;
score: number;
@@ -45,7 +45,7 @@ export interface Item {
export function randomItem(): Item {
return {
id: ulid(),
- userLogin: crypto.randomUUID(),
+ userId: crypto.randomUUID(),
title: crypto.randomUUID(),
url: `http://${crypto.randomUUID()}.com`,
score: 0,
@@ -63,7 +63,7 @@ export function randomItem(): Item {
*
* await createItem({
* id: ulid(),
- * userLogin: "john_doe",
+ * userId: "13d643e1-ad65-42bf-be9f-31c95e1b94d8",
* title: "example-title",
* url: "https://example.com",
* score: 0,
@@ -72,7 +72,7 @@ export function randomItem(): Item {
*/
export async function createItem(item: Item) {
const itemsKey = ["items", item.id];
- const itemsByUserKey = ["items_by_user", item.userLogin, item.id];
+ const itemsByUserKey = ["items_by_user", item.userId, item.id];
const res = await kv.atomic()
.check({ key: itemsKey, versionstamp: null })
@@ -93,7 +93,7 @@ export async function createItem(item: Item) {
*
* const item = await getItem("01H9YD2RVCYTBVJEYEJEV5D1S1");
* item?.id; // Returns "01H9YD2RVCYTBVJEYEJEV5D1S1";
- * item?.userLogin; // Returns "snoop"
+ * item?.userId; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
* item?.title; // Returns "example-title"
* item?.url; // Returns "http://example.com"
* item?.score; // Returns 420
@@ -114,8 +114,8 @@ export async function getItem(id: string) {
*
* for await (const entry of listItems()) {
* entry.value.id; // Returns "01H9YD2RVCYTBVJEYEJEV5D1S1"
- * entry.value.userLogin; // Returns "pedro"
- * entry.key; // Returns ["items_voted_by_user", "01H9YD2RVCYTBVJEYEJEV5D1S1", "pedro"]
+ * entry.value.userId; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
+ * entry.key; // Returns ["items_voted_by_user", "01H9YD2RVCYTBVJEYEJEV5D1S1", "13d643e1-ad65-42bf-be9f-31c95e1b94d8"]
* entry.versionstamp; // Returns "00000000000000010000"
* }
* ```
@@ -132,25 +132,25 @@ export function listItems(options?: Deno.KvListOptions) {
* ```ts
* import { listItemsByUser } from "@/utils/db.ts";
*
- * for await (const entry of listItemsByUser("pedro")) {
+ * for await (const entry of listItemsByUser("13d643e1-ad65-42bf-be9f-31c95e1b94d8")) {
* entry.value.id; // Returns "01H9YD2RVCYTBVJEYEJEV5D1S1"
- * entry.value.userLogin; // Returns "pedro"
- * entry.key; // Returns ["items_voted_by_user", "01H9YD2RVCYTBVJEYEJEV5D1S1", "pedro"]
+ * entry.value.userId; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
+ * entry.key; // Returns ["items_voted_by_user", "01H9YD2RVCYTBVJEYEJEV5D1S1", "13d643e1-ad65-42bf-be9f-31c95e1b94d8"]
* entry.versionstamp; // Returns "00000000000000010000"
* }
* ```
*/
export function listItemsByUser(
- userLogin: string,
+ userId: string,
options?: Deno.KvListOptions,
) {
- return kv.list
- ({ prefix: ["items_by_user", userLogin] }, options);
+ return kv.list
- ({ prefix: ["items_by_user", userId] }, options);
}
// Vote
export interface Vote {
itemId: string;
- userLogin: string;
+ userId: string;
}
/**
@@ -163,13 +163,13 @@ export interface Vote {
*
* await createVote({
* itemId: "01H9YD2RVCYTBVJEYEJEV5D1S1",
- * userLogin: "pedro",
+ * userId: "pedro",
* });
* ```
*/
export async function createVote(vote: Vote) {
const itemKey = ["items", vote.itemId];
- const userKey = ["users", vote.userLogin];
+ const userKey = ["users", vote.userId];
const [itemRes, userRes] = await kv.getMany<[Item, User]>([itemKey, userKey]);
const item = itemRes.value;
const user = userRes.value;
@@ -178,15 +178,15 @@ export async function createVote(vote: Vote) {
const itemVotedByUserKey = [
"items_voted_by_user",
- vote.userLogin,
+ vote.userId,
vote.itemId,
];
const userVotedForItemKey = [
"users_voted_for_item",
vote.itemId,
- vote.userLogin,
+ vote.userId,
];
- const itemByUserKey = ["items_by_user", item.userLogin, item.id];
+ const itemByUserKey = ["items_by_user", item.userId, item.id];
item.score++;
@@ -214,18 +214,19 @@ export async function createVote(vote: Vote) {
*
* for await (const entry of listItemsVotedByUser("john")) {
* entry.value.id; // Returns "01H9YD2RVCYTBVJEYEJEV5D1S1"
- * entry.value.userLogin; // Returns "pedro"
- * entry.key; // Returns ["items_voted_by_user", "01H9YD2RVCYTBVJEYEJEV5D1S1", "pedro"]
+ * entry.value.userId; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
+ * entry.key; // Returns ["items_voted_by_user", "01H9YD2RVCYTBVJEYEJEV5D1S1", "13d643e1-ad65-42bf-be9f-31c95e1b94d8"]
* entry.versionstamp; // Returns "00000000000000010000"
* }
* ```
*/
-export function listItemsVotedByUser(userLogin: string) {
- return kv.list
- ({ prefix: ["items_voted_by_user", userLogin] });
+export function listItemsVotedByUser(userId: string) {
+ return kv.list
- ({ prefix: ["items_voted_by_user", userId] });
}
// User
export interface User {
+ id: string;
// AKA username
login: string;
sessionId: string;
@@ -240,6 +241,7 @@ export interface User {
/** For testing */
export function randomUser(): User {
return {
+ id: crypto.randomUUID(),
login: crypto.randomUUID(),
sessionId: crypto.randomUUID(),
isSubscribed: false,
@@ -256,6 +258,7 @@ export function randomUser(): User {
* import { createUser } from "@/utils/db.ts";
*
* await createUser({
+ * id: "13d643e1-ad65-42bf-be9f-31c95e1b94d8",
* login: "john",
* sessionId: crypto.randomUUID(),
* isSubscribed: false,
@@ -263,13 +266,16 @@ export function randomUser(): User {
* ```
*/
export async function createUser(user: User) {
- const usersKey = ["users", user.login];
+ const usersKey = ["users", user.id];
+ const usersByLoginKey = ["users_by_login", user.login];
const usersBySessionKey = ["users_by_session", user.sessionId];
const atomicOp = kv.atomic()
.check({ key: usersKey, versionstamp: null })
+ .check({ key: usersByLoginKey, versionstamp: null })
.check({ key: usersBySessionKey, versionstamp: null })
.set(usersKey, user)
+ .set(usersByLoginKey, user)
.set(usersBySessionKey, user);
if (user.stripeCustomerId !== undefined) {
@@ -294,6 +300,7 @@ export async function createUser(user: User) {
* import { updateUser } from "@/utils/db.ts";
*
* await updateUser({
+ * id: "13d643e1-ad65-42bf-be9f-31c95e1b94d8",
* login: "john",
* sessionId: crypto.randomUUID(),
* isSubscribed: false,
@@ -301,11 +308,13 @@ export async function createUser(user: User) {
* ```
*/
export async function updateUser(user: User) {
- const usersKey = ["users", user.login];
+ const usersKey = ["users", user.id];
+ const usersByLoginKey = ["users_by_login", user.login];
const usersBySessionKey = ["users_by_session", user.sessionId];
const atomicOp = kv.atomic()
.set(usersKey, user)
+ .set(usersByLoginKey, user)
.set(usersBySessionKey, user);
if (user.stripeCustomerId !== undefined) {
@@ -329,6 +338,7 @@ export async function updateUser(user: User) {
* import { updateUserSession } from "@/utils/db.ts";
*
* await updateUserSession({
+ * id: "13d643e1-ad65-42bf-be9f-31c95e1b94d8",
* login: "john",
* sessionId: "xxx",
* isSubscribed: false,
@@ -336,13 +346,15 @@ export async function updateUser(user: User) {
* ```
*/
export async function updateUserSession(user: User, sessionId: string) {
- const userKey = ["users", user.login];
+ const userKey = ["users", user.id];
+ const usersByLoginKey = ["users_by_login", user.login];
const oldUserBySessionKey = ["users_by_session", user.sessionId];
const newUserBySessionKey = ["users_by_session", sessionId];
const newUser: User = { ...user, sessionId };
const atomicOp = kv.atomic()
.set(userKey, newUser)
+ .set(usersByLoginKey, newUser)
.delete(oldUserBySessionKey)
.check({ key: newUserBySessionKey, versionstamp: null })
.set(newUserBySessionKey, newUser);
@@ -361,20 +373,40 @@ export async function updateUserSession(user: User, sessionId: string) {
}
/**
- * Gets the user with the given login from the database.
+ * Gets the user with the given ID from the database.
*
* @example
* ```ts
* import { getUser } from "@/utils/db.ts";
*
- * const user = await getUser("jack");
+ * const user = await getUser("13d643e1-ad65-42bf-be9f-31c95e1b94d8");
+ * user?.id; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
+ * user?.login; // Returns "jack"
+ * user?.sessionId; // Returns "xxx"
+ * user?.isSubscribed; // Returns false
+ * ```
+ */
+export async function getUser(id: string) {
+ const res = await kv.get(["users", id]);
+ return res.value;
+}
+
+/**
+ * Gets the user with the given username from the database.
+ *
+ * @example
+ * ```ts
+ * import { getUserByLogin } from "@/utils/db.ts";
+ *
+ * const user = await getUserByLogin("jack");
+ * user?.id; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
* user?.login; // Returns "jack"
* user?.sessionId; // Returns "xxx"
* user?.isSubscribed; // Returns false
* ```
*/
-export async function getUser(login: string) {
- const res = await kv.get(["users", login]);
+export async function getUserByLogin(login: string) {
+ const res = await kv.get(["users_by_login", login]);
return res.value;
}
@@ -390,6 +422,7 @@ export async function getUser(login: string) {
* import { getUserBySession } from "@/utils/db.ts";
*
* const user = await getUserBySession("xxx");
+ * user?.id; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
* user?.login; // Returns "jack"
* user?.sessionId; // Returns "xxx"
* user?.isSubscribed; // Returns false
@@ -413,6 +446,7 @@ export async function getUserBySession(sessionId: string) {
* import { getUserByStripeCustomer } from "@/utils/db.ts";
*
* const user = await getUserByStripeCustomer("123");
+ * user?.id; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
* user?.login; // Returns "jack"
* user?.sessionId; // Returns "xxx"
* user?.isSubscribed; // Returns false
@@ -436,6 +470,7 @@ export async function getUserByStripeCustomer(stripeCustomerId: string) {
* import { listUsers } from "@/utils/db.ts";
*
* for await (const entry of listUsers()) {
+ * entry.value.id; // Returns "13d643e1-ad65-42bf-be9f-31c95e1b94d8"
* entry.value.login; // Returns "jack"
* entry.value.sessionId; // Returns "xxx"
* entry.value.isSubscribed; // Returns false
diff --git a/utils/db_test.ts b/utils/db_test.ts
index eb4a7c3ca..c563b5af4 100644
--- a/utils/db_test.ts
+++ b/utils/db_test.ts
@@ -21,24 +21,25 @@ import {
updateUserSession,
type User,
} from "./db.ts";
+import { getUserByLogin } from "@/utils/db.ts";
Deno.test("[db] items", async () => {
const user = randomUser();
const item1: Item = {
...randomItem(),
id: ulid(),
- userLogin: user.login,
+ userId: user.id,
};
const item2: Item = {
...randomItem(),
id: ulid(Date.now() + 1_000),
- userLogin: user.login,
+ userId: user.id,
};
assertEquals(await getItem(item1.id), null);
assertEquals(await getItem(item2.id), null);
assertEquals(await collectValues(listItems()), []);
- assertEquals(await collectValues(listItemsByUser(user.login)), []);
+ assertEquals(await collectValues(listItemsByUser(user.id)), []);
await createItem(item1);
await createItem(item2);
@@ -47,7 +48,7 @@ Deno.test("[db] items", async () => {
assertEquals(await getItem(item1.id), item1);
assertEquals(await getItem(item2.id), item2);
assertEquals(await collectValues(listItems()), [item1, item2]);
- assertEquals(await collectValues(listItemsByUser(user.login)), [
+ assertEquals(await collectValues(listItemsByUser(user.id)), [
item1,
item2,
]);
@@ -56,19 +57,22 @@ Deno.test("[db] items", async () => {
Deno.test("[db] user", async () => {
const user = randomUser();
+ assertEquals(await getUser(user.id), null);
assertEquals(await getUser(user.login), null);
assertEquals(await getUserBySession(user.sessionId), null);
assertEquals(await getUserByStripeCustomer(user.stripeCustomerId!), null);
await createUser(user);
await assertRejects(async () => await createUser(user));
- assertEquals(await getUser(user.login), user);
+ assertEquals(await getUser(user.id), user);
+ assertEquals(await getUserByLogin(user.login), user);
assertEquals(await getUserBySession(user.sessionId), user);
assertEquals(await getUserByStripeCustomer(user.stripeCustomerId!), user);
const subscribedUser: User = { ...user, isSubscribed: true };
await updateUser(subscribedUser);
- assertEquals(await getUser(subscribedUser.login), subscribedUser);
+ assertEquals(await getUser(subscribedUser.id), subscribedUser);
+ assertEquals(await getUserByLogin(subscribedUser.login), subscribedUser);
assertEquals(
await getUserBySession(subscribedUser.sessionId),
subscribedUser,
@@ -98,11 +102,11 @@ Deno.test("[db] votes", async () => {
const user = randomUser();
const vote = {
itemId: item.id,
- userLogin: user.login,
+ userId: user.id,
createdAt: new Date(),
};
- assertEquals(await collectValues(listItemsVotedByUser(user.login)), []);
+ assertEquals(await collectValues(listItemsVotedByUser(user.id)), []);
await assertRejects(
async () => await createVote(vote),
@@ -119,7 +123,7 @@ Deno.test("[db] votes", async () => {
await createVote(vote);
item.score++;
- assertEquals(await collectValues(listItemsVotedByUser(user.login)), [item]);
+ assertEquals(await collectValues(listItemsVotedByUser(user.id)), [item]);
await assertRejects(async () => await createVote(vote));
});
@@ -128,13 +132,13 @@ Deno.test("[db] getAreVotedByUser()", async () => {
const user = randomUser();
const vote = {
itemId: item.id,
- userLogin: user.login,
+ userId: user.id,
createdAt: new Date(),
};
assertEquals(await getItem(item.id), null);
- assertEquals(await getUser(user.login), null);
- assertEquals(await getAreVotedByUser([item], user.login), [false]);
+ assertEquals(await getUser(user.id), null);
+ assertEquals(await getAreVotedByUser([item], user.id), [false]);
await createItem(item);
await createUser(user);
@@ -142,6 +146,6 @@ Deno.test("[db] getAreVotedByUser()", async () => {
item.score++;
assertEquals(await getItem(item.id), item);
- assertEquals(await getUser(user.login), user);
- assertEquals(await getAreVotedByUser([item], user.login), [true]);
+ assertEquals(await getUser(user.id), user);
+ assertEquals(await getAreVotedByUser([item], user.id), [true]);
});
diff --git a/utils/github.ts b/utils/github.ts
index 6b7f1ff15..0a2031c96 100644
--- a/utils/github.ts
+++ b/utils/github.ts
@@ -12,6 +12,7 @@ export function isGitHubSetup() {
}
interface GitHubUser {
+ id: string;
login: string;
email: string;
}
diff --git a/utils/github_test.ts b/utils/github_test.ts
index bdaab9316..939be7190 100644
--- a/utils/github_test.ts
+++ b/utils/github_test.ts
@@ -27,7 +27,11 @@ Deno.test("[plugins] getGitHubUser()", async (test) => {
});
await test.step("resolves to a GitHub user object", async () => {
- const body = { login: crypto.randomUUID(), email: crypto.randomUUID() };
+ const body = {
+ id: crypto.randomUUID(),
+ login: crypto.randomUUID(),
+ email: crypto.randomUUID(),
+ };
const fetchStub = stub(
window,
"fetch",