Skip to content

Commit

Permalink
moving all auth handlers to one file
Browse files Browse the repository at this point in the history
  • Loading branch information
wmalarski committed Oct 29, 2023
1 parent 641925c commit 7a9f579
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 164 deletions.
23 changes: 2 additions & 21 deletions src/routes/api/auth/callback/+handler.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,3 @@
import { object, safeParseAsync, string } from "valibot";
import { invalidRequestError, redirectToPath } from "../../../../server/errors";
import { callback } from "../../../../server/auth";

export const GET: MarkoRun.Handler = async (context) => {
console.log({ context });
const parsed = await safeParseAsync(
object({ code: string() }),
Object.fromEntries(context.url.searchParams.entries()),
);

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

const response = await context.supabase.auth.exchangeCodeForSession(
parsed.output.code,
);

console.log({ response });

return redirectToPath({ path: "/" });
};
export const GET: MarkoRun.Handler = callback;
12 changes: 2 additions & 10 deletions src/routes/api/auth/sign-out/+handler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
import { redirectToPath } from "../../../../server/errors";
import { signOut } from "../../../../server/auth";

export const GET: MarkoRun.Handler = async (context) => {
console.log({ context });

const response = await context.supabase.auth.signOut();

console.log({ response });

return redirectToPath({ path: "/" });
};
export const GET: MarkoRun.Handler = signOut;
105 changes: 5 additions & 100 deletions src/routes/sign-in/+handler.ts
Original file line number Diff line number Diff line change
@@ -1,106 +1,11 @@
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 {
magicLinkSignIn,
oauthSignIn,
passwordSignIn,
} from "../../server/auth";
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({ path: "/api/auth/callback" });
const emailRedirectTo = `${context.url.origin}${callbackPath}`;

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

if (response.error) {
return redirectToPath({
path: "/sign-in",
query: { message: response.error.message },
});
}

console.log({ response });

return redirectToPath({
path: "/sign-in",
query: { message: "Success", variant: "success" },
});
};

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({ path: "/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 },
});

if (response.error) {
return redirectToPath({
path: "/sign-in",
query: { message: response.error.message },
});
}

return new Response(null, {
headers: { location: response.data.url },
});
};

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) {
return redirectToPath({
path: "/sign-in",
query: { message: response.error.message },
});
}

return redirectToPath({ path: "/todos" });
};

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

Expand Down
34 changes: 2 additions & 32 deletions src/routes/sign-up/+handler.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,3 @@
import { decode } from "decode-formdata";
import { email, object, safeParseAsync, string } from "valibot";
import { invalidRequestError, redirectToPath } from "../../server/errors";
import { passwordSignUp } from "../../server/auth";

export const POST: MarkoRun.Handler = async (context) => {
const parsed = await safeParseAsync(
object({ email: string([email()]), password: string() }),
decode(await context.request.formData()),
);

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

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

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

if (response.error) {
return redirectToPath({
path: "/sign-up",
query: { message: response.error.message },
});
}

return redirectToPath({
path: "/sign-up",
query: { message: "Success", variant: "success" },
});
};
export const POST: MarkoRun.Handler = passwordSignUp;
2 changes: 1 addition & 1 deletion src/routes/sign-up/components/sign-up-form.marko
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<form class="flex flex-col gap-6" method="POST">
<h2 class="text-xl">
Sign in with password
Sign up with password
</h2>

<div class="flex flex-col gap-4">
Expand Down
156 changes: 156 additions & 0 deletions src/server/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { decode } from "decode-formdata";
import { email, literal, object, safeParseAsync, string } from "valibot";
import { buildPath } from "../utils/paths";
import { invalidRequestError, redirectToPath } from "./errors";

const getCallbackUrl = (context: MarkoRun.Context) => {
const callbackPath = buildPath({ path: "/api/auth/callback" });
return `${context.url.origin}${callbackPath}`;
};

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

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

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

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

if (response.error) {
return redirectToPath({
path: "/sign-in",
query: { message: response.error.message },
});
}

console.log({ response });

return redirectToPath({
path: "/sign-in",
query: { message: "Success", variant: "success" },
});
};

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

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

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

if (response.error) {
return redirectToPath({
path: "/sign-in",
query: { message: response.error.message },
});
}

return new Response(null, {
headers: { location: response.data.url },
});
};

export 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,
});

if (response.error) {
return redirectToPath({
path: "/sign-in",
query: { message: response.error.message },
});
}

return redirectToPath({ path: "/todos" });
};

export const passwordSignUp = async (context: MarkoRun.Context) => {
const parsed = await safeParseAsync(
object({ email: string([email()]), password: string() }),
decode(await context.request.formData()),
);

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

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

if (response.error) {
return redirectToPath({
path: "/sign-up",
query: { message: response.error.message },
});
}

return redirectToPath({
path: "/sign-up",
query: { message: "Success", variant: "success" },
});
};

export const signOut = async (context: MarkoRun.Context) => {
console.log({ context });

const response = await context.supabase.auth.signOut();

console.log({ response });

return redirectToPath({ path: "/" });
};

export const callback = async (context: MarkoRun.Context) => {
const parsed = await safeParseAsync(
object({ code: string() }),
Object.fromEntries(context.url.searchParams.entries()),
);

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

const response = await context.supabase.auth.exchangeCodeForSession(
parsed.output.code,
);

if (response.error) {
return redirectToPath({ path: "/todos" });
}

return redirectToPath({ path: "/" });
};

0 comments on commit 7a9f579

Please sign in to comment.