Skip to content

Commit

Permalink
moves all sign in to single handler
Browse files Browse the repository at this point in the history
  • Loading branch information
wmalarski committed Oct 29, 2023
1 parent 247752e commit cdfc3d8
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 102 deletions.
12 changes: 11 additions & 1 deletion .marko-run/routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ declare module "../src/routes/api/auth/sign-out/+handler" {
}
}

declare module "../src/routes/sign-in/+handler" {
namespace MarkoRun {
export { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform };
export type Route = Run.Routes["/sign-in"];
export type Context = Run.MultiRouteContext<Route>;
export type Handler = Run.HandlerLike<Route>;
export const route: Run.HandlerTypeFn<Route>;
}
}

declare module "../src/routes/sign-in/api/magic-link/+handler" {
namespace MarkoRun {
export { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform };
Expand Down Expand Up @@ -163,7 +173,7 @@ type Routes = {
"/_index": { verb: "get"; meta: typeof import("../src/routes/_index/+meta.json"); };
"/api/auth/callback": { verb: "get"; };
"/api/auth/sign-out": { verb: "get"; };
"/sign-in": { verb: "get"; meta: typeof import("../src/routes/sign-in/+meta.json"); };
"/sign-in": { verb: "get" | "post"; meta: typeof import("../src/routes/sign-in/+meta.json"); };
"/sign-in/api/magic-link": { verb: "post"; };
"/sign-in/api/oauth": { verb: "post"; };
"/sign-in/api/password": { verb: "post"; };
Expand Down
117 changes: 117 additions & 0 deletions src/routes/sign-in/+handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { decode } from "decode-formdata";
import { email, literal, object, safeParseAsync, string } from "valibot";
import { invalidRequestError, redirectToPath } from "../../server/errors";
import { buildPath } from "../../utils/paths";
import { buildSearchParams } from "../../utils/searchParams";

type SignInArgs = {
context: MarkoRun.Context;
decoded: ReturnType<typeof decode>;
};

const magicLinkSignIn = async ({ context, decoded }: SignInArgs) => {
const parsed = await safeParseAsync(
object({ email: string([email()]) }),
decoded,
);

if (!parsed.success) {
return invalidRequestError(parsed.issues);
}

const callbackPath = buildPath("/api/auth/callback", {});
const emailRedirectTo = `${context.url.origin}${callbackPath}`;

const response = await context.supabase.auth.signInWithOtp({
email: parsed.output.email,
options: { emailRedirectTo },
});

console.log({ response });

return new Response(JSON.stringify(response), { status: 200 });
};

export const oauthSignIn = async ({ context, decoded }: SignInArgs) => {
const parsed = await safeParseAsync(
object({ provider: literal("google") }),
decoded,
);

if (!parsed.success) {
return invalidRequestError(parsed.issues);
}

const callbackPath = buildPath("/api/auth/callback", {});
const redirectTo = `${context.url.origin}${callbackPath}`;

console.log({ context, form: parsed, callbackPath });

const response = await context.supabase.auth.signInWithOAuth({
provider: parsed.output.provider,
options: { redirectTo },
});

console.log({ response });

return new Response(JSON.stringify(response), { status: 200 });
};

const passwordSignIn = async ({ context, decoded }: SignInArgs) => {
const parsed = await safeParseAsync(
object({ email: string([email()]), password: string() }),
decoded,
);

if (!parsed.success) {
return invalidRequestError(parsed.issues);
}

const response = await context.supabase.auth.signInWithPassword({
email: parsed.output.email,
password: parsed.output.password,
});

console.log({ response });

if (response.error) {
const params = buildSearchParams({ message: response.error.message });

const url = new URL(`${context.url.pathname}?${params}`, context.url);

console.log({ url });

return new Response(null, {
status: 302,
headers: { location: String(url) },
});
}

return redirectToPath("/todos", {});
};

const handlers = {
password: passwordSignIn,
oauth: oauthSignIn,
"magic-link": magicLinkSignIn,
};

export const POST: MarkoRun.Handler = async (context) => {
const decoded = decode(await context.request.formData());

switch (decoded.action) {
case "password":
return passwordSignIn({ context, decoded });
case "oauth":
return oauthSignIn({ context, decoded });
case "magic-link":
return magicLinkSignIn({ context, decoded });
}

const params = buildSearchParams({ message: "Invalid request" });
const url = new URL(`${context.url.pathname}?${params}`, context.url);
return new Response(null, {
status: 302,
headers: { location: String(url) },
});
};
27 changes: 0 additions & 27 deletions src/routes/sign-in/api/magic-link/+handler.ts

This file was deleted.

29 changes: 0 additions & 29 deletions src/routes/sign-in/api/oauth/+handler.ts

This file was deleted.

37 changes: 0 additions & 37 deletions src/routes/sign-in/api/password/+handler.ts

This file was deleted.

8 changes: 3 additions & 5 deletions src/routes/sign-in/components/magic-link-form.marko
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<form
class="flex flex-col gap-6"
action="/sign-in/api/magic-link"
method="POST"
>
<form class="flex flex-col gap-6" method="POST">
<input type="hidden" name="action" value="magic-link">

<h2 class="text-xl">
Send magic link
</h2>
Expand Down
4 changes: 3 additions & 1 deletion src/routes/sign-in/components/oauth-form.marko
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<form class="flex flex-col gap-6" action="/sign-in/api/oauth" method="POST">
<form class="flex flex-col gap-6" method="POST">
<input type="hidden" name="provider" value="google">
<input type="hidden" name="action" value="oauth">

<h2 class="text-xl">
Login with google
</h2>
Expand Down
4 changes: 3 additions & 1 deletion src/routes/sign-in/components/password-form.marko
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<form class="flex flex-col gap-6" action="/sign-in/api/password" method="POST">
<form class="flex flex-col gap-6" method="POST">
<input type="hidden" name="action" value="password">

<h2 class="text-xl">
Sign in with password
</h2>
Expand Down
5 changes: 4 additions & 1 deletion src/server/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export const redirectToPath = <Path extends RoutePath>(
params: RouteParams<Path>,
) => {
const url = buildPath(path, params);
return Response.redirect(url, 301);
return new Response(null, {
status: 302,
headers: { location: String(url) },
});
};

export const invalidRequestError = (issues: Issues) => {
Expand Down

0 comments on commit cdfc3d8

Please sign in to comment.