Skip to content
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

refactor: user logic in KV #292

Merged
merged 3 commits into from
Jun 23, 2023
Merged
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
4 changes: 2 additions & 2 deletions routes/account/_middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2023 the Deno authors. All rights reserved. MIT license.
import { State } from "@/routes/_middleware.ts";
import { MiddlewareHandlerContext } from "$fresh/server.ts";
import { getUserBySessionId, User } from "@/utils/db.ts";
import { getUserBySession, User } from "@/utils/db.ts";
import { redirectToLogin } from "@/utils/redirect.ts";

export interface AccountState extends State {
Expand All @@ -15,7 +15,7 @@ export async function handler(
) {
const redirectResponse = redirectToLogin(req.url);
if (!ctx.state.sessionId) return redirectResponse;
const user = await getUserBySessionId(ctx.state.sessionId);
const user = await getUserBySession(ctx.state.sessionId);
if (!user) return redirectResponse;
ctx.state.user = user;
return await ctx.next();
Expand Down
13 changes: 5 additions & 8 deletions routes/api/stripe-webhooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
import type { Handlers } from "$fresh/server.ts";
import { stripe } from "@/utils/payments.ts";
import { Stripe } from "stripe";
import {
getUserByStripeCustomerId,
updateUserIsSubscribed,
} from "@/utils/db.ts";
import { getUserByStripeCustomer, updateUser } from "@/utils/db.ts";

const cryptoProvider = Stripe.createSubtleCryptoProvider();

Expand Down Expand Up @@ -39,15 +36,15 @@ export const handler: Handlers = {

switch (event.type) {
case "customer.subscription.created": {
const user = await getUserByStripeCustomerId(customer);
const user = await getUserByStripeCustomer(customer);
if (!user) return new Response(null, { status: 400 });
await updateUserIsSubscribed(user, true);
await updateUser({ ...user, isSubscribed: true });
return new Response(null, { status: 201 });
}
case "customer.subscription.deleted": {
const user = await getUserByStripeCustomerId(customer);
const user = await getUserByStripeCustomer(customer);
if (!user) return new Response(null, { status: 400 });
await updateUserIsSubscribed(user, false);
await updateUser({ ...user, isSubscribed: false });
return new Response(null, { status: 202 });
}
default: {
Expand Down
4 changes: 2 additions & 2 deletions routes/api/vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { HandlerContext, Handlers, PageProps } from "$fresh/server.ts";
import type { State } from "@/routes/_middleware.ts";
import { createVote, deleteVote, getItem } from "@/utils/db.ts";
import { getUserBySessionId } from "@/utils/db.ts";
import { getUserBySession } from "@/utils/db.ts";

async function sharedHandler(
req: Request,
Expand All @@ -20,7 +20,7 @@ async function sharedHandler(

const [item, user] = await Promise.all([
getItem(itemId),
getUserBySessionId(ctx.state.sessionId),
getUserBySession(ctx.state.sessionId),
]);

if (item === null || user === null) {
Expand Down
22 changes: 14 additions & 8 deletions routes/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
import type { Handlers } from "$fresh/server.ts";
import {
createUser,
getUserById,
setUserSessionId,
deleteUserBySession,
getUser,
incrementAnalyticsMetricPerDay,
newUserProps,
updateUser,
type User,
} from "@/utils/db.ts";
import { stripe } from "@/utils/payments.ts";
Expand All @@ -22,7 +25,7 @@ interface GitHubUser {
email: string;
}

async function getUser(accessToken: string): Promise<GitHubUser> {
async function getGitHubUser(accessToken: string): Promise<GitHubUser> {
const response = await fetch("https://api.github.com/user", {
headers: { authorization: `Bearer ${accessToken}` },
});
Expand All @@ -44,23 +47,26 @@ export const handler: Handlers<any, State> = {

deleteRedirectUrlCookie(response.headers);

const githubUser = await getUser(accessToken);
const githubUser = await getGitHubUser(accessToken);

const user = await getUserById(githubUser.id.toString());
const user = await getUser(githubUser.id.toString());
if (!user) {
const customer = await stripe.customers.create({
email: githubUser.email,
});
const userInit: Omit<User, "isSubscribed"> | null = {
const user: User = {
id: githubUser.id.toString(),
login: githubUser.login,
avatarUrl: githubUser.avatar_url,
stripeCustomerId: customer.id,
sessionId,
...newUserProps(),
};
await createUser(userInit);
await createUser(user);
await incrementAnalyticsMetricPerDay("users_count", new Date());
} else {
await setUserSessionId(user, sessionId);
await deleteUserBySession(sessionId);
await updateUser({ ...user, sessionId });
}
return response;
},
Expand Down
8 changes: 4 additions & 4 deletions routes/item/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import {
getCommentsByItem,
getItem,
getManyUsers,
getUserById,
getUserBySessionId,
getUser,
getUserBySession,
type Item,
newCommentProps,
type User,
Expand Down Expand Up @@ -56,7 +56,7 @@ export const handler: Handlers<ItemPageData, State> = {
const commentsUsers = await getManyUsers(
comments.map((comment) => comment.userId),
);
const user = await getUserById(item.userId);
const user = await getUser(item.userId);

const [isVoted] = await getAreVotedBySessionId(
[item],
Expand Down Expand Up @@ -87,7 +87,7 @@ export const handler: Handlers<ItemPageData, State> = {
return new Response(null, { status: 400 });
}

const user = await getUserBySessionId(ctx.state.sessionId);
const user = await getUserBySession(ctx.state.sessionId);

const comment: Comment = {
userId: user!.id,
Expand Down
4 changes: 2 additions & 2 deletions routes/pricing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { BUTTON_STYLES } from "@/utils/constants.ts";
import { formatAmountForDisplay, stripe } from "@/utils/payments.ts";
import Stripe from "stripe";
import { ComponentChild } from "preact";
import { getUserBySessionId, type User } from "@/utils/db.ts";
import { getUserBySession, type User } from "@/utils/db.ts";

interface PricingPageData extends State {
products: Stripe.Product[];
Expand All @@ -27,7 +27,7 @@ export const handler: Handlers<PricingPageData, State> = {
const products = data.sort(comparePrices);

const user = ctx.state.sessionId
? await getUserBySessionId(ctx.state.sessionId)
? await getUserBySession(ctx.state.sessionId)
: null;

return ctx.render({ ...ctx.state, products, user });
Expand Down
4 changes: 2 additions & 2 deletions routes/submit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { BUTTON_STYLES, INPUT_STYLES } from "@/utils/constants.ts";
import type { State } from "@/routes/_middleware.ts";
import {
createItem,
getUserBySessionId,
getUserBySession,
incrementAnalyticsMetricPerDay,
type Item,
newItemProps,
Expand Down Expand Up @@ -40,7 +40,7 @@ export const handler: Handlers<State, State> = {
return new Response(null, { status: 400 });
}

const user = await getUserBySessionId(ctx.state.sessionId);
const user = await getUserBySession(ctx.state.sessionId);

if (!user) return new Response(null, { status: 400 });

Expand Down
12 changes: 8 additions & 4 deletions tools/seed_submissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
incrementAnalyticsMetricPerDay,
type Item,
newItemProps,
newUserProps,
User,
} from "@/utils/db.ts";

// Reference: https://github.com/HackerNews/API
Expand Down Expand Up @@ -94,15 +96,17 @@ async function main(limit = 20) {

// Create dummy users to ensure each post has a corresponding user
for (const batch of batchify(items)) {
await Promise.allSettled(batch.map(({ userId: id }) =>
createUser({
await Promise.allSettled(batch.map(({ userId: id }) => {
const user: User = {
id, // id must match userId for post
login: id,
avatarUrl: "https://www.gravatar.com/avatar/?d=mp&s=64",
stripeCustomerId: crypto.randomUUID(), // unique per userId
sessionId: crypto.randomUUID(), // unique per userId
}) // ignore errors if dummy user already exists
));
...newUserProps(),
};
return createUser(user); // ignore errors if dummy user already exists
}));
}
}

Expand Down
Loading