diff --git a/src/app.d.ts b/src/app.d.ts index 67e90ce..a7c6b90 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,4 +1,4 @@ -import type { PrivateUserData } from "$lib/valibot.ts"; +import type { PrivateUserData } from "$lib/valibot"; import type { OAuthClient } from "@atcute/oauth-node-client"; declare global { diff --git a/src/hooks.server.ts b/src/hooks.server.ts index e97e0b5..a87602b 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,7 +1,8 @@ import { dev } from "$app/environment"; -import type { Handle } from "@sveltejs/kit"; +import { restoreSession } from "$lib/server/session"; +import { isAuthEvent } from "$lib/types"; +import { error, type Handle } from "@sveltejs/kit"; import { sequence } from "@sveltejs/kit/hooks"; -import { restoreSession } from "./lib/server/session.ts"; /** * {@link https://svelte.dev/docs/cli/devtools-json} @@ -15,6 +16,9 @@ const devHandle: Handle = ({ event, resolve }) => { }; export const defaultHandle: Handle = async ({ event, resolve }) => { + if (isAuthEvent(event) === false) { + error(500); + } // [TODO] necessary? // if ( // event.url.searchParams.has("session") || diff --git a/src/lib/server/oauth.ts b/src/lib/server/oauth.ts index 14c555e..354ce09 100644 --- a/src/lib/server/oauth.ts +++ b/src/lib/server/oauth.ts @@ -1,11 +1,11 @@ import { dev } from "$app/environment"; -import type {} from "$lexicons/index.ts"; import { OAUTH_COOKIE_PREFIX, OAUTH_MAX_AGE, SESSION_MAX_AGE, -} from "$lib/server/constants.ts"; -import { decryptText, encryptText } from "$lib/server/crypto.ts"; +} from "$lib/server/constants"; +import { decryptText, encryptText } from "$lib/server/crypto"; +import type { AuthEvent } from "$lib/types"; import { CompositeDidDocumentResolver, CompositeHandleResolver, @@ -101,12 +101,7 @@ class CookieStore implements Store { } } -export function createOAuthClient( - event: { cookies: Cookies; locals: App.Locals; platform?: App.Platform }, -): OAuthClient { - if (event.platform === undefined) { - throw new Error(); - } +export function createOAuthClient(event: AuthEvent): OAuthClient { if (event.locals.oAuthClient) { return event.locals.oAuthClient; } diff --git a/src/lib/server/session.ts b/src/lib/server/session.ts index 7778d0d..7018da0 100644 --- a/src/lib/server/session.ts +++ b/src/lib/server/session.ts @@ -4,19 +4,19 @@ import { OAUTH_MAX_AGE, SESSION_COOKIE, SESSION_MAX_AGE, -} from "$lib/server/constants.ts"; -import { decryptText, encryptText } from "$lib/server/crypto.ts"; -import { createOAuthClient } from "$lib/server/oauth.ts"; -import { parsePublicUser, type PublicUserData } from "$lib/valibot.ts"; +} from "$lib/server/constants"; +import { decryptText, encryptText } from "$lib/server/crypto"; +import { createOAuthClient } from "$lib/server/oauth"; +import type { AuthEvent } from "$lib/types"; +import { parsePublicUser, type PublicUserData } from "$lib/valibot"; import { Client } from "@atcute/client"; import { isHandle } from "@atcute/lexicons/syntax"; -import type { RequestEvent } from "@sveltejs/kit"; /** * Logout */ export const destroySession = async ( - event: RequestEvent, + event: AuthEvent, ): Promise => { event.cookies.delete(SESSION_COOKIE, { path: "/" }); if (event.locals.user) { @@ -36,7 +36,7 @@ export const destroySession = async ( * @returns {URL} OAuth redirect */ export const startSession = async ( - event: RequestEvent, + event: AuthEvent, handle: string, ): Promise => { if (isHandle(handle) === false) { @@ -65,7 +65,7 @@ export const startSession = async ( * Store the logged in user data */ export const updateSession = async ( - event: RequestEvent, + event: AuthEvent, user: PublicUserData, ) => { const { cookies, platform } = event; @@ -92,7 +92,9 @@ export const updateSession = async ( /** * Setup OAuth client from cookies */ -export const restoreSession = async (event: RequestEvent): Promise => { +export const restoreSession = async ( + event: AuthEvent, +): Promise => { const { cookies, platform } = event; if (platform?.env === undefined) { throw new Error(); diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..e9b51f0 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,9 @@ +import type { RequestEvent } from "@sveltejs/kit"; + +export type AuthEvent = RequestEvent & { + platform: App.Platform; +}; + +export const isAuthEvent = (event: RequestEvent): event is AuthEvent => { + return event.platform?.env !== undefined; +}; diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index 3268dd9..3371d52 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -1,5 +1,5 @@ -import type { PublicUserData } from "$lib/valibot.ts"; -import type { LayoutServerLoad } from "./$types.d.ts"; +import type { PublicUserData } from "$lib/valibot"; +import type { LayoutServerLoad } from "./$types"; export const load: LayoutServerLoad = (event) => { let user: PublicUserData | undefined = undefined; diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index 9cfdd5a..7092d34 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,19 +1,26 @@ -import { HANDLE_COOKIE } from "$lib/server/constants.ts"; +import { HANDLE_COOKIE } from "$lib/server/constants"; import { destroySession, startSession, updateSession, -} from "$lib/server/session.ts"; +} from "$lib/server/session"; +import { isAuthEvent } from "$lib/types"; +import { parseActorProfile } from "$lib/valibot"; import { Client } from "@atcute/client"; import { type Actions, fail, redirect } from "@sveltejs/kit"; -import { parseActorProfile } from "../lib/valibot.ts"; export const actions = { logout: async (event) => { + if (isAuthEvent(event) === false) { + throw new Error(); + } await destroySession(event); redirect(303, "/"); }, login: async (event) => { + if (isAuthEvent(event) === false) { + throw new Error(); + } const formData = await event.request.formData(); const handle = formData.get("handle"); let url: URL; @@ -27,7 +34,12 @@ export const actions = { redirect(303, url); }, displayName: async (event) => { - if (event.locals.user === undefined) return; + if (isAuthEvent(event) === false) { + throw new Error(); + } + if (event.locals.user === undefined) { + return; + } const { user } = event.locals; try { const formData = await event.request.formData(); @@ -58,8 +70,13 @@ export const actions = { } }, purge: async (event) => { + if (isAuthEvent(event) === false) { + throw new Error(); + } const { user } = event.locals; - if (user === undefined) return; + if (user === undefined) { + return; + } const rpc = new Client({ handler: user.session }); const result = await rpc.post("com.atproto.repo.deleteRecord", { input: { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index ce99b8a..d0953cf 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -5,7 +5,7 @@