From b22b4409a0212bc128f11183522d19fee804a0eb Mon Sep 17 00:00:00 2001 From: Murderlon Date: Sun, 12 Jan 2025 17:37:43 +0100 Subject: [PATCH] Use OpenAuth for authentication --- bun.lockb | Bin 436824 -> 437288 bytes infra/api.ts | 3 +- infra/auth.ts | 39 ++++ infra/www.ts | 2 + packages/core/package.json | 6 +- packages/core/src/plan/seed.ts | 21 ++- packages/core/src/subscription/index.ts | 8 +- packages/core/src/user/index.ts | 72 +++++++- packages/core/sst-env.d.ts | 8 + packages/functions/api/stripe.ts | 9 +- packages/functions/auth.ts | 45 +++++ packages/functions/package.json | 5 +- packages/functions/sst-env.d.ts | 8 + packages/www/app/@types/lucide.d.ts | 5 + packages/www/app/components/navigation.tsx | 15 +- packages/www/app/env.ts | 22 --- .../app/modules/auth/auth-session.server.ts | 16 -- packages/www/app/modules/auth/auth.server.ts | 161 +++++------------ packages/www/app/root.tsx | 26 +-- packages/www/app/routes/_home+/_index.tsx | 9 +- packages/www/app/routes/admin+/_layout.tsx | 8 +- .../app/routes/auth+/$provider.callback.tsx | 15 -- packages/www/app/routes/auth+/$provider.tsx | 15 -- packages/www/app/routes/auth+/_layout.tsx | 49 ----- packages/www/app/routes/auth+/callback.ts | 20 ++ packages/www/app/routes/auth+/login.tsx | 171 ------------------ packages/www/app/routes/auth+/logout.tsx | 14 +- packages/www/app/routes/auth+/magic-link.tsx | 14 -- packages/www/app/routes/auth+/verify.tsx | 147 --------------- .../www/app/routes/dashboard+/_layout.tsx | 8 +- .../www/app/routes/dashboard+/checkout.tsx | 4 +- .../routes/dashboard+/settings.billing.tsx | 11 +- .../app/routes/dashboard+/settings.index.tsx | 19 +- .../www/app/routes/onboarding+/username.tsx | 12 +- packages/www/app/utils/misc.ts | 6 +- packages/www/app/utils/permissions.server.ts | 3 +- packages/www/package.json | 5 +- packages/www/sst-env.d.ts | 8 + readme.md | 3 +- sst-env.d.ts | 8 + 40 files changed, 348 insertions(+), 672 deletions(-) create mode 100644 infra/auth.ts create mode 100644 packages/functions/auth.ts create mode 100644 packages/www/app/@types/lucide.d.ts delete mode 100644 packages/www/app/env.ts delete mode 100644 packages/www/app/modules/auth/auth-session.server.ts delete mode 100644 packages/www/app/routes/auth+/$provider.callback.tsx delete mode 100644 packages/www/app/routes/auth+/$provider.tsx delete mode 100644 packages/www/app/routes/auth+/_layout.tsx create mode 100644 packages/www/app/routes/auth+/callback.ts delete mode 100644 packages/www/app/routes/auth+/login.tsx delete mode 100644 packages/www/app/routes/auth+/magic-link.tsx delete mode 100644 packages/www/app/routes/auth+/verify.tsx diff --git a/bun.lockb b/bun.lockb index 00760e7ed7719788aa739b3f44e9d5b2985f0915..3a2af9fc958e15046425adedcd3c0c79b67c1678 100755 GIT binary patch delta 106051 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%0DT|bl4GiY>^%RR2y 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 iTBP$zqc9V>WQlQ>RvFo%w9K28O>WXa6rcpQttf delta 106108 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 WXQe1Doer-QX>|=<1xj2k&i_AfsrBjr diff --git a/infra/api.ts b/infra/api.ts index 39537d3..79f765c 100644 --- a/infra/api.ts +++ b/infra/api.ts @@ -1,3 +1,4 @@ +import { auth } from './auth' import { domain } from './dns' import { email } from './email' import { secret } from './secret' @@ -6,7 +7,7 @@ import { webhook } from './stripe' export const api = new sst.aws.Function('Api', { url: true, handler: 'packages/functions/api/index.handler', - link: [secret.DATABASE_URL, secret.STRIPE_SECRET_KEY, webhook, email], + link: [secret.DATABASE_URL, secret.STRIPE_SECRET_KEY, webhook, email, auth], permissions: [ { actions: ['ses:SendEmail'], diff --git a/infra/auth.ts b/infra/auth.ts new file mode 100644 index 0000000..9424293 --- /dev/null +++ b/infra/auth.ts @@ -0,0 +1,39 @@ +import { domain } from './dns' +import { email } from './email' +import { secret } from './secret' + +export const authTable = new sst.aws.Dynamo('LambdaAuthTable', { + fields: { + pk: 'string', + sk: 'string', + }, + ttl: 'expiry', + primaryIndex: { + hashKey: 'pk', + rangeKey: 'sk', + }, +}) + +export const auth = new sst.aws.Auth('Auth', { + forceUpgrade: 'v2', + authorizer: { + handler: 'packages/functions/auth.handler', + link: [ + email, + authTable, + secret.GITHUB_CLIENT_ID, + secret.GITHUB_CLIENT_SECRET, + secret.DATABASE_URL, + ], + permissions: [ + { + actions: ['ses:SendEmail'], + resources: ['*'], + }, + ], + }, + domain: { + name: `auth.${domain}`, + dns: sst.cloudflare.dns(), + }, +}) diff --git a/infra/www.ts b/infra/www.ts index 4179e42..86c5d2c 100644 --- a/infra/www.ts +++ b/infra/www.ts @@ -1,3 +1,4 @@ +import { auth } from './auth' import { domain } from './dns' import { email } from './email' import { secret } from './secret' @@ -20,6 +21,7 @@ export const www = new sst.aws.React('ReactRouter', { ], link: [ email, + auth, secret.SESSION_SECRET, secret.ENCRYPTION_SECRET, secret.DATABASE_URL, diff --git a/packages/core/package.json b/packages/core/package.json index a0996c5..bfa98e5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -15,10 +15,12 @@ "dependencies": { "@aws-sdk/client-sesv2": "^3.687.0", "@neondatabase/serverless": "^0.9.5", - "stripe": "^15.5.0", - "sst": "^3.3.27", + "@openauthjs/openauth": "^0.3.2", "drizzle-orm": "^0.36.2", + "sst": "^3.3.27", + "stripe": "^15.5.0", "ulid": "^2.3.0", + "valibot": "^1.0.0-beta.11", "ws": "^8.18.0" }, "devDependencies": { diff --git a/packages/core/src/plan/seed.ts b/packages/core/src/plan/seed.ts index a9fdec0..21288cf 100644 --- a/packages/core/src/plan/seed.ts +++ b/packages/core/src/plan/seed.ts @@ -1,23 +1,28 @@ import { Stripe } from '@company/core/src/stripe' import { db, schema } from '../drizzle' +import { PRICING_PLANS } from '../constants' export default async function seed() { const prices = await Stripe.client.prices.list() const products = await Stripe.client.products.list() + const stage = JSON.parse(process.env.SST_RESOURCE_App as string).stage + const activeProducts = products.data.filter( + (p) => p.active && p.metadata.stage === stage, + ) - for (const { id, name, description } of products.data.filter((p) => p.active)) { + for (const { id, name, description } of Object.values(PRICING_PLANS)) { + const stripeProduct = activeProducts.find((p) => p.name === name)! await db.transaction(async (tx) => { - const [plan] = await tx - .insert(schema.plan) - .values({ id, name, description }) - .returning() - + await tx.insert(schema.plan).values({ id, name, description }) await tx.insert(schema.price).values( prices.data - .filter((price) => price.product === id) + .filter( + (price) => + price.product === stripeProduct.id && price.metadata.stage === stage, + ) .map((price) => ({ id: price.id, - planId: plan!.id, + planId: id, amount: price.unit_amount ?? 0, currency: price.currency, interval: price.recurring?.interval ?? 'month', diff --git a/packages/core/src/subscription/index.ts b/packages/core/src/subscription/index.ts index ccb89dd..9cc9a16 100644 --- a/packages/core/src/subscription/index.ts +++ b/packages/core/src/subscription/index.ts @@ -16,11 +16,15 @@ export namespace Subscription { }) } - export const insert = async (userID: string, sub: Stripe.Subscription) => { + export const insert = async ( + userID: string, + sub: Stripe.Subscription, + planId: string, + ) => { await db.insert(schema).values({ id: sub.id, userId: userID, - planId: String(sub.items.data[0]!.plan.product), + planId, priceId: String(sub.items.data[0]!.price.id), interval: String(sub.items.data[0]!.plan.interval), status: sub.status, diff --git a/packages/core/src/user/index.ts b/packages/core/src/user/index.ts index 1affc65..78f7e50 100644 --- a/packages/core/src/user/index.ts +++ b/packages/core/src/user/index.ts @@ -1,8 +1,48 @@ import { eq } from 'drizzle-orm' +import { createSubjects } from '@openauthjs/openauth/subject' import { db } from '../drizzle' import { user as schema, userImage as imageSchema } from './sql' +import { role, roleToUser } from '../role/sql' +import { Role } from '../role' +// TODO: switch to zod once @conform-to/zod can handle new zod version +import * as v from 'valibot' +import type { InferOutput } from 'valibot' export namespace User { + export const info = v.object({ + id: v.string(), + email: v.pipe(v.string(), v.email()), + username: v.nullable(v.string()), + customerId: v.nullable(v.string()), + roles: v.array( + v.object({ + name: v.union(Role.roles.map((role) => v.literal(role))), + id: v.string(), + }), + ), + }) + + export type info = InferOutput + + export const subjects = createSubjects({ user: info }) + + export const insert = async (email: string) => { + return db.transaction(async (tx) => { + const result = await tx.insert(schema).values({ email }).returning() + const user = result[0]! + const roles = await tx + .select({ id: role.id, name: role.name }) + .from(role) + .where(eq(role.name, 'user')) + + await tx + .insert(roleToUser) + .values(roles.map((role) => ({ roleId: role.id, userId: user.id }))) + + return { ...user, roles } + }) + } + export const update = async ( id: string, partial: Partial, @@ -27,7 +67,35 @@ export namespace User { }) } - export const image = async (id: string) => { - return db.query.userImage.findFirst({ where: eq(imageSchema.userId, id) }) + export const fromEmailWithRole = async (email: string) => { + const user = await db.query.user.findFirst({ + where: eq(schema.email, email), + columns: { createdAt: false, updatedAt: false }, + with: { + roles: { + columns: {}, + with: { + role: { + columns: { + name: true, + id: true, + }, + }, + }, + }, + }, + }) + if (!user) return + return { + ...user, + roles: user.roles.map(({ role }) => ({ id: role.id, name: role.name })), + } + } + + export const imageID = async (id: string) => { + return db.query.userImage.findFirst({ + where: eq(imageSchema.userId, id), + columns: { id: true }, + }) } } diff --git a/packages/core/sst-env.d.ts b/packages/core/sst-env.d.ts index 3483413..096a535 100644 --- a/packages/core/sst-env.d.ts +++ b/packages/core/sst-env.d.ts @@ -15,6 +15,10 @@ declare module "sst" { "type": "sst.aws.Router" "url": string } + "Auth": { + "type": "sst.aws.Auth" + "url": string + } "DATABASE_URL": { "type": "sst.sst.Secret" "value": string @@ -40,6 +44,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "LambdaAuthTable": { + "name": string + "type": "sst.aws.Dynamo" + } "ReactRouter": { "type": "sst.aws.React" "url": string diff --git a/packages/functions/api/stripe.ts b/packages/functions/api/stripe.ts index b699809..678ed28 100644 --- a/packages/functions/api/stripe.ts +++ b/packages/functions/api/stripe.ts @@ -4,7 +4,6 @@ import { Stripe } from '@company/core/src/stripe' import { Subscription } from '@company/core/src/subscription/index' import { User } from '@company/core/src/user/index' import { Hono } from 'hono' -import { Resource } from 'sst' import { z } from 'zod' export const route = new Hono().post('/', async (ctx) => { @@ -12,14 +11,10 @@ export const route = new Hono().post('/', async (ctx) => { if (!sig) throw new Error(Stripe.errors.MISSING_SIGNATURE) - console.log({ - sig, - secret: Resource.StripeWebhook.secret, - id: Resource.StripeWebhook.id, - }) - const event = await Stripe.createEvent(await ctx.req.text(), sig) + console.log(event.type) + try { switch (event.type) { /** diff --git a/packages/functions/auth.ts b/packages/functions/auth.ts new file mode 100644 index 0000000..7fcb9df --- /dev/null +++ b/packages/functions/auth.ts @@ -0,0 +1,45 @@ +import { issuer } from '@openauthjs/openauth' +import { handle } from 'hono/aws-lambda' +import { DynamoStorage } from '@openauthjs/openauth/storage/dynamo' +import { Resource } from 'sst' +import { PasswordProvider } from '@openauthjs/openauth/provider/password' +import { PasswordUI } from '@openauthjs/openauth/ui/password' +import { Email } from '@company/core/src/email/index' +import { User } from '@company/core/src/user/index' +import type { Theme } from '@openauthjs/openauth/ui/theme' + +const theme: Theme = { + title: 'My company', + radius: 'md', + primary: '#1e293b', + favicon: 'https://stack.merlijn.site/favicon.ico', +} + +const app = issuer({ + theme, + storage: DynamoStorage({ + table: Resource.LambdaAuthTable.name, + }), + subjects: User.subjects, + providers: { + password: PasswordProvider( + PasswordUI({ + sendCode: async (email, code) => { + await Email.sendAuth({ email, code }) + }, + }), + ), + }, + success: async (ctx, value) => { + if (value.provider === 'password') { + let user = await User.fromEmailWithRole(value.email) + user ??= await User.insert(value.email) + if (!user) throw new Error('Unable to create user') + + return ctx.subject('user', user) + } + throw new Error('Invalid provider') + }, +}) + +export const handler = handle(app) diff --git a/packages/functions/package.json b/packages/functions/package.json index 3771915..a07cabf 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -10,8 +10,9 @@ "typecheck": "tsc" }, "dependencies": { - "sst": "^3.3.27", - "hono": "^4.6.3" + "@openauthjs/openauth": "^0.3.2", + "hono": "^4.6.3", + "sst": "^3.3.27" }, "devDependencies": { "typescript": "^5.7.2" diff --git a/packages/functions/sst-env.d.ts b/packages/functions/sst-env.d.ts index 3483413..096a535 100644 --- a/packages/functions/sst-env.d.ts +++ b/packages/functions/sst-env.d.ts @@ -15,6 +15,10 @@ declare module "sst" { "type": "sst.aws.Router" "url": string } + "Auth": { + "type": "sst.aws.Auth" + "url": string + } "DATABASE_URL": { "type": "sst.sst.Secret" "value": string @@ -40,6 +44,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "LambdaAuthTable": { + "name": string + "type": "sst.aws.Dynamo" + } "ReactRouter": { "type": "sst.aws.React" "url": string diff --git a/packages/www/app/@types/lucide.d.ts b/packages/www/app/@types/lucide.d.ts new file mode 100644 index 0000000..18e22d9 --- /dev/null +++ b/packages/www/app/@types/lucide.d.ts @@ -0,0 +1,5 @@ +declare module 'lucide-react' { + // Only show type suggestions for Lucide icons with a prefix. + // Otherwise you editor will try to import an icon instead of some component you actually want. + export * from 'lucide-react/dist/lucide-react.prefixed' +} diff --git a/packages/www/app/components/navigation.tsx b/packages/www/app/components/navigation.tsx index f5c731e..1653907 100644 --- a/packages/www/app/components/navigation.tsx +++ b/packages/www/app/components/navigation.tsx @@ -31,10 +31,11 @@ import { cn, getUserImgSrc, userHasRole } from '#app/utils/misc' type NavigationProps = { user: Awaited> + image?: { id: string } planId?: string } -export function Navigation({ user, planId }: NavigationProps) { +export function Navigation({ user, image, planId }: NavigationProps) { const navigate = useNavigate() const submit = useSubmit() const requestInfo = useRequestInfo() @@ -64,11 +65,11 @@ export function Navigation({ user, planId }: NavigationProps) { className="gap-2 px-2 data-[state=open]:bg-primary/5" >
- {user?.image?.id ? ( + {image?.id ? ( {user.username ) : ( @@ -94,11 +95,11 @@ export function Navigation({ user, planId }: NavigationProps) {
- {user?.image?.id ? ( + {image?.id ? ( {user.username ) : ( @@ -133,11 +134,11 @@ export function Navigation({ user, planId }: NavigationProps) {
- + {user ? 'Dashboard' : 'Get Started'}
diff --git a/packages/www/app/routes/admin+/_layout.tsx b/packages/www/app/routes/admin+/_layout.tsx index 80ed1e7..caa1e0d 100644 --- a/packages/www/app/routes/admin+/_layout.tsx +++ b/packages/www/app/routes/admin+/_layout.tsx @@ -7,6 +7,7 @@ import { siteConfig } from '#app/utils/constants/brand' import { buttonVariants } from '#app/components/ui/button' import { Navigation } from '#app/components/navigation' import { Subscription } from '@company/core/src/subscription/index' +import { User } from '@company/core/src/user/index' export const ROUTE_PATH = '/admin' as const @@ -16,16 +17,17 @@ export const meta: MetaFunction = () => { export async function loader({ request }: LoaderFunctionArgs) { const user = await requireUserWithRole(request, 'admin') + const image = await User.imageID(user.id) const subscription = await Subscription.fromUserID(user.id) - return { user, subscription } + return { user, image, subscription } } export default function Admin() { - const { user, subscription } = useLoaderData() + const { user, image, subscription } = useLoaderData() return (
- +
diff --git a/packages/www/app/routes/auth+/$provider.callback.tsx b/packages/www/app/routes/auth+/$provider.callback.tsx deleted file mode 100644 index c4007ed..0000000 --- a/packages/www/app/routes/auth+/$provider.callback.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type { LoaderFunctionArgs } from 'react-router' -import { authenticator } from '#app/modules/auth/auth.server' -import { ROUTE_PATH as LOGIN_PATH } from '#app/routes/auth+/login' -import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout' - -export const ROUTE_PATH = '/auth/:provider/callback' as const - -export async function loader({ request, params }: LoaderFunctionArgs) { - if (typeof params.provider !== 'string') throw new Error('Invalid provider.') - - return authenticator.authenticate(params.provider, request, { - successRedirect: DASHBOARD_PATH, - failureRedirect: LOGIN_PATH, - }) -} diff --git a/packages/www/app/routes/auth+/$provider.tsx b/packages/www/app/routes/auth+/$provider.tsx deleted file mode 100644 index e9ebf36..0000000 --- a/packages/www/app/routes/auth+/$provider.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type { ActionFunctionArgs } from 'react-router' -import { redirect } from 'react-router' -import { authenticator } from '#app/modules/auth/auth.server' -import { ROUTE_PATH as LOGIN_PATH } from '#app/routes/auth+/login' - -export const ROUTE_PATH = '/auth/:provider' as const - -export async function loader() { - return redirect(LOGIN_PATH) -} - -export async function action({ request, params }: ActionFunctionArgs) { - if (typeof params.provider !== 'string') throw new Error('Invalid provider.') - return authenticator.authenticate(params.provider, request) -} diff --git a/packages/www/app/routes/auth+/_layout.tsx b/packages/www/app/routes/auth+/_layout.tsx deleted file mode 100644 index 8e78ba2..0000000 --- a/packages/www/app/routes/auth+/_layout.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import type { LoaderFunctionArgs } from 'react-router' -import { Link, Outlet } from 'react-router' -import { redirect } from 'react-router' -import { authenticator } from '#app/modules/auth/auth.server' -import { getDomainPathname } from '#app/utils/misc.server' -import { ROUTE_PATH as HOME_PATH } from '#app/routes/_home+/_layout' -import { ROUTE_PATH as LOGIN_PATH } from '#app/routes/auth+/login' -import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout' -import { Logo } from '#app/components/logo' - -export const ROUTE_PATH = '/auth' as const - -export async function loader({ request }: LoaderFunctionArgs) { - await authenticator.isAuthenticated(request, { - successRedirect: DASHBOARD_PATH, - }) - const pathname = getDomainPathname(request) - if (pathname === ROUTE_PATH) return redirect(LOGIN_PATH) - return {} -} - -export default function Layout() { - return ( -
-
- - - -
-
- - - -
-
-
- -
-
- ) -} diff --git a/packages/www/app/routes/auth+/callback.ts b/packages/www/app/routes/auth+/callback.ts new file mode 100644 index 0000000..f91d4fa --- /dev/null +++ b/packages/www/app/routes/auth+/callback.ts @@ -0,0 +1,20 @@ +import type { LoaderFunctionArgs } from '@remix-run/node' +import { redirect } from '@remix-run/node' +import { + authenticator, + getSession, + commitSession, +} from '#app/modules/auth/auth.server.ts' + +export async function loader({ request }: LoaderFunctionArgs) { + const sessionUser = await authenticator.authenticate('openauth', request) + const session = await getSession(request.headers.get('Cookie')) + + session.set('user', sessionUser) + + return redirect('/dashboard', { + headers: { + 'Set-Cookie': await commitSession(session), + }, + }) +} diff --git a/packages/www/app/routes/auth+/login.tsx b/packages/www/app/routes/auth+/login.tsx deleted file mode 100644 index 34053d9..0000000 --- a/packages/www/app/routes/auth+/login.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import type { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from 'react-router' -import { useRef, useEffect } from 'react' -import { Form, useLoaderData } from 'react-router' -import { data } from 'react-router' -import { useHydrated } from 'remix-utils/use-hydrated' -import { AuthenticityTokenInput } from 'remix-utils/csrf/react' -import { HoneypotInputs } from 'remix-utils/honeypot/react' -import { z } from 'zod' -import { getZodConstraint, parseWithZod } from '@conform-to/zod' -import { getFormProps, getInputProps, useForm } from '@conform-to/react' -import { LucideLoader2 } from 'lucide-react' -import { authenticator } from '#app/modules/auth/auth.server' -import { getSession, commitSession } from '#app/modules/auth/auth-session.server' -import { validateCSRF } from '#app/utils/csrf.server' -import { checkHoneypot } from '#app/utils/honeypot.server' -import { useIsPending } from '#app/utils/misc' -import { siteConfig } from '#app/utils/constants/brand' -import { Input } from '#app/components/ui/input' -import { Button } from '#app/components/ui/button' -import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout' -import { ROUTE_PATH as AUTH_VERIFY_PATH } from '#app/routes/auth+/verify' - -export const ROUTE_PATH = '/auth/login' as const - -export const LoginSchema = z.object({ - email: z.string().max(256).email('Email address is not valid.'), -}) - -export const meta: MetaFunction = () => { - return [{ title: `${siteConfig.siteTitle} - Login` }] -} - -export async function loader({ request }: LoaderFunctionArgs) { - await authenticator.isAuthenticated(request, { - successRedirect: DASHBOARD_PATH, - }) - - const cookie = await getSession(request.headers.get('Cookie')) - const authEmail = cookie.get('auth:email') - const authError = cookie.get(authenticator.sessionErrorKey) - - return data({ authEmail, authError } as const, { - headers: { - 'Set-Cookie': await commitSession(cookie), - }, - }) -} - -export async function action({ request }: ActionFunctionArgs) { - const url = new URL(request.url) - const pathname = url.pathname - - const clonedRequest = request.clone() - const formData = await clonedRequest.formData() - await validateCSRF(formData, clonedRequest.headers) - checkHoneypot(formData) - - await authenticator.authenticate('TOTP', request, { - successRedirect: AUTH_VERIFY_PATH, - failureRedirect: pathname, - }) -} - -export default function Login() { - const { authEmail, authError } = useLoaderData() - const inputRef = useRef(null) - const isHydrated = useHydrated() - const isPending = useIsPending() - - const [emailForm, { email }] = useForm({ - constraint: getZodConstraint(LoginSchema), - onValidate({ formData }) { - return parseWithZod(formData, { schema: LoginSchema }) - }, - }) - - useEffect(() => { - isHydrated && inputRef.current?.focus() - }, [isHydrated]) - - return ( -
-
-

- Continue to [your company] -

-

- Welcome back! Please log in to continue. -

-
- -
- {/* Security */} - - - -
- - -
- -
- {!authError && email.errors && ( - - {email.errors.join(' ')} - - )} - {!authEmail && authError && ( - - {authError.message} - - )} -
- - - - -
- - - Or continue with - -
- -
- -
- -

- By clicking continue, you agree to our{' '} - - Terms of Service - {' '} - and{' '} - - Privacy Policy. - -

-
- ) -} diff --git a/packages/www/app/routes/auth+/logout.tsx b/packages/www/app/routes/auth+/logout.tsx index 58449b5..8ddb4dd 100644 --- a/packages/www/app/routes/auth+/logout.tsx +++ b/packages/www/app/routes/auth+/logout.tsx @@ -1,12 +1,18 @@ -import type { LoaderFunctionArgs, ActionFunctionArgs } from 'react-router' -import { authenticator } from '#app/modules/auth/auth.server' +import { destroySession, getSession } from '#app/modules/auth/auth.server.ts' +import { + type ActionFunctionArgs, + type LoaderFunctionArgs, + redirect, +} from '@remix-run/router' export const ROUTE_PATH = '/auth/logout' as const export async function loader({ request }: LoaderFunctionArgs) { - return authenticator.logout(request, { redirectTo: '/' }) + const session = await getSession(request.headers.get('Cookie')) + return redirect('/', { headers: { 'Set-Cookie': await destroySession(session) } }) } export async function action({ request }: ActionFunctionArgs) { - return authenticator.logout(request, { redirectTo: '/' }) + const session = await getSession(request.headers.get('Cookie')) + return redirect('/', { headers: { 'Set-Cookie': await destroySession(session) } }) } diff --git a/packages/www/app/routes/auth+/magic-link.tsx b/packages/www/app/routes/auth+/magic-link.tsx deleted file mode 100644 index 00bc2cd..0000000 --- a/packages/www/app/routes/auth+/magic-link.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import type { LoaderFunctionArgs } from 'react-router' -import { authenticator } from '#app/modules/auth/auth.server' - -import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout' -import { ROUTE_PATH as LOGIN_PATH } from '#app/routes/auth+/login' - -export const ROUTE_PATH = '/auth/magic-link' as const - -export async function loader({ request }: LoaderFunctionArgs) { - return authenticator.authenticate('TOTP', request, { - successRedirect: DASHBOARD_PATH, - failureRedirect: LOGIN_PATH, - }) -} diff --git a/packages/www/app/routes/auth+/verify.tsx b/packages/www/app/routes/auth+/verify.tsx deleted file mode 100644 index 46fbc7d..0000000 --- a/packages/www/app/routes/auth+/verify.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import type { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from 'react-router' -import { useRef, useEffect } from 'react' -import { Form, useLoaderData } from 'react-router' -import { data, redirect } from 'react-router' -import { useHydrated } from 'remix-utils/use-hydrated' -import { AuthenticityTokenInput } from 'remix-utils/csrf/react' -import { HoneypotInputs } from 'remix-utils/honeypot/react' -import { z } from 'zod' -import { getZodConstraint, parseWithZod } from '@conform-to/zod' -import { getFormProps, getInputProps, useForm } from '@conform-to/react' -import { authenticator } from '#app/modules/auth/auth.server' -import { getSession, commitSession } from '#app/modules/auth/auth-session.server' -import { validateCSRF } from '#app/utils/csrf.server' -import { checkHoneypot } from '#app/utils/honeypot.server' -import { siteConfig } from '#app/utils/constants/brand' -import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout' -import { Input } from '#app/components/ui/input' -import { Button } from '#app/components/ui/button' - -export const ROUTE_PATH = '/auth/verify' as const - -export const VerifyLoginSchema = z.object({ - code: z.string().min(6, 'Code must be at least 6 characters.'), -}) - -export const meta: MetaFunction = () => { - return [{ title: `${siteConfig.siteTitle} - Verify` }] -} - -export async function loader({ request }: LoaderFunctionArgs) { - await authenticator.isAuthenticated(request, { - successRedirect: DASHBOARD_PATH, - }) - - const cookie = await getSession(request.headers.get('Cookie')) - const authEmail = cookie.get('auth:email') - const authError = cookie.get(authenticator.sessionErrorKey) - - if (!authEmail) return redirect('/auth/login') - - return data({ authEmail, authError } as const, { - headers: { - 'Set-Cookie': await commitSession(cookie), - }, - }) -} - -export async function action({ request }: ActionFunctionArgs) { - const url = new URL(request.url) - const pathname = url.pathname - - const clonedRequest = request.clone() - const formData = await clonedRequest.formData() - await validateCSRF(formData, clonedRequest.headers) - checkHoneypot(formData) - - await authenticator.authenticate('TOTP', request, { - successRedirect: pathname, - failureRedirect: pathname, - }) -} - -export default function Verify() { - const { authEmail, authError } = useLoaderData() - const inputRef = useRef(null) - const isHydrated = useHydrated() - - const [codeForm, { code }] = useForm({ - constraint: getZodConstraint(VerifyLoginSchema), - onValidate({ formData }) { - return parseWithZod(formData, { schema: VerifyLoginSchema }) - }, - }) - - useEffect(() => { - isHydrated && inputRef.current?.focus() - }, [isHydrated]) - - return ( -
-
-

Check your inbox!

-

- We've just emailed you a temporary password. -
- Please enter it below. -

-
- -
- - - -
- - -
- -
- {!authError && code.errors && ( - - {code.errors.join(' ')} - - )} - {authEmail && authError && ( - - {authError.message} - - )} -
- - - - - {/* Request New Code. */} - {/* Email is already in session, input it's not required. */} -
- - - -

- Did not receive the code? -

- - -
- ) -} diff --git a/packages/www/app/routes/dashboard+/_layout.tsx b/packages/www/app/routes/dashboard+/_layout.tsx index f35e797..45db732 100644 --- a/packages/www/app/routes/dashboard+/_layout.tsx +++ b/packages/www/app/routes/dashboard+/_layout.tsx @@ -5,6 +5,7 @@ import { requireUser } from '#app/modules/auth/auth.server' import { ROUTE_PATH as ONBOARDING_USERNAME_PATH } from '#app/routes/onboarding+/username' import { Navigation } from '#app/components/navigation' import { Subscription } from '@company/core/src/subscription/index' +import { User } from '@company/core/src/user/index' export const ROUTE_PATH = '/dashboard' as const @@ -12,16 +13,17 @@ export async function loader({ request }: LoaderFunctionArgs) { const user = await requireUser(request) if (!user.username) return redirect(ONBOARDING_USERNAME_PATH) const subscription = await Subscription.fromUserID(user.id) + const image = await User.imageID(user.id) - return { user, subscription } + return { user, subscription, image } } export default function Dashboard() { - const { user, subscription } = useLoaderData() + const { user, subscription, image } = useLoaderData() return (
- +
) diff --git a/packages/www/app/routes/dashboard+/checkout.tsx b/packages/www/app/routes/dashboard+/checkout.tsx index 926ef1e..26ab964 100644 --- a/packages/www/app/routes/dashboard+/checkout.tsx +++ b/packages/www/app/routes/dashboard+/checkout.tsx @@ -8,7 +8,7 @@ import { LucideAlertTriangle, LucideExternalLink, } from 'lucide-react' -import { requireSessionUser } from '#app/modules/auth/auth.server' +import { requireUser } from '#app/modules/auth/auth.server' import { PLANS } from '@company/core/src/constants' import { useInterval } from '#app/utils/hooks/use-interval' import { siteConfig } from '#app/utils/constants/brand' @@ -23,7 +23,7 @@ export const meta: MetaFunction = () => { } export async function loader({ request }: LoaderFunctionArgs) { - const sessionUser = await requireSessionUser(request) + const sessionUser = await requireUser(request) const subscription = await Subscription.fromUserID(sessionUser.id) if (!subscription) return redirect(DASHBOARD_PATH) diff --git a/packages/www/app/routes/dashboard+/settings.billing.tsx b/packages/www/app/routes/dashboard+/settings.billing.tsx index 3e32f7b..aead6c6 100644 --- a/packages/www/app/routes/dashboard+/settings.billing.tsx +++ b/packages/www/app/routes/dashboard+/settings.billing.tsx @@ -3,11 +3,10 @@ import type { Interval, Plan as PlanEnum } from '@company/core/src/constants' import { useState } from 'react' import { Form, useLoaderData } from 'react-router' import { redirect } from 'react-router' -import { requireSessionUser } from '#app/modules/auth/auth.server' +import { requireUser } from '#app/modules/auth/auth.server' import { PLANS, PRICING_PLANS, INTERVALS, CURRENCIES } from '@company/core/src/constants' import { getLocaleCurrency } from '#app/utils/misc.server' import { INTENTS } from '#app/utils/constants/misc' -import { ROUTE_PATH as LOGIN_PATH } from '#app/routes/auth+/login' import { Switch } from '#app/components/ui/switch' import { Button } from '#app/components/ui/button' import { Subscription } from '@company/core/src/subscription/index' @@ -22,9 +21,7 @@ export const meta: MetaFunction = () => { } export async function loader({ request }: LoaderFunctionArgs) { - const sessionUser = await requireSessionUser(request, { - redirectTo: LOGIN_PATH, - }) + const sessionUser = await requireUser(request) const subscription = await Subscription.fromUserID(sessionUser.id) const currency = getLocaleCurrency(request) @@ -33,9 +30,7 @@ export async function loader({ request }: LoaderFunctionArgs) { } export async function action({ request }: ActionFunctionArgs) { - const sessionUser = await requireSessionUser(request, { - redirectTo: LOGIN_PATH, - }) + const sessionUser = await requireUser(request) const formData = await request.formData() const intent = formData.get(INTENTS.INTENT) diff --git a/packages/www/app/routes/dashboard+/settings.index.tsx b/packages/www/app/routes/dashboard+/settings.index.tsx index cb91ed1..3713973 100644 --- a/packages/www/app/routes/dashboard+/settings.index.tsx +++ b/packages/www/app/routes/dashboard+/settings.index.tsx @@ -6,8 +6,7 @@ import { z } from 'zod' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { LucideUpload } from 'lucide-react' -import { requireUser } from '#app/modules/auth/auth.server' -import { getSession, destroySession } from '#app/modules/auth/auth-session.server' +import { destroySession, getSession, requireUser } from '#app/modules/auth/auth.server' import { createToastHeaders } from '#app/utils/toast.server' import { useDoubleCheck } from '#app/utils/hooks/use-double-check' import { getUserImgSrc } from '#app/utils/misc' @@ -38,7 +37,8 @@ export const UsernameSchema = z.object({ export async function loader({ request }: LoaderFunctionArgs) { const user = await requireUser(request) - return { user } + const image = await User.imageID(user.id) + return { user, image } } export async function action({ request }: ActionFunctionArgs) { @@ -79,11 +79,10 @@ export async function action({ request }: ActionFunctionArgs) { // TODO: cancel Stripe subscription if (intent === INTENTS.USER_DELETE_ACCOUNT) { await db.delete(schema.user).where(eq(schema.user.id, user.id)) + const session = await getSession(request.headers.get('Cookie')) return redirect(HOME_PATH, { headers: { - 'Set-Cookie': await destroySession( - await getSession(request.headers.get('Cookie')), - ), + 'Set-Cookie': await destroySession(session), }, }) } @@ -92,7 +91,7 @@ export async function action({ request }: ActionFunctionArgs) { } export default function DashboardSettings() { - const { user } = useLoaderData() + const { user, image } = useLoaderData() const lastResult = useActionData() const [imageSrc, setImageSrc] = useState(null) @@ -139,9 +138,9 @@ export default function DashboardSettings() { htmlFor={avatarFields.imageFile.id} className="group relative flex cursor-pointer overflow-hidden rounded-full transition active:scale-95" > - {imageSrc || user.image?.id ? ( + {imageSrc || image?.id ? ( {user.username @@ -177,7 +176,7 @@ export default function DashboardSettings() {

Click on the avatar to upload a custom one from your files.

- {user.image?.id && !avatarFields.imageFile.errors && ( + {image?.id && !avatarFields.imageFile.errors && (