Skip to content

Commit

Permalink
start on multi-graph actinos
Browse files Browse the repository at this point in the history
  • Loading branch information
Brendonovich committed Dec 13, 2024
1 parent 855df19 commit 6d7d614
Show file tree
Hide file tree
Showing 21 changed files with 5,761 additions and 4,334 deletions.
294 changes: 147 additions & 147 deletions apps/web/src/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,215 +11,215 @@ import type { AuthProvider } from "./app/auth/providers";
import { lucia } from "./lucia";

function loginRedirect() {
const url = new URL(getRequestEvent()!.request.url);
const next = encodeURIComponent(`${url.pathname}?${url.search}`);
return redirect("/login");
const url = new URL(getRequestEvent()!.request.url);
const next = encodeURIComponent(`${url.pathname}?${url.search}`);
return redirect("/login");
}

export const getAuthState = cache(async () => {
"use server";

const requestEvent = getRequestEvent()!;
const event = requestEvent.nativeEvent;

let data: Awaited<ReturnType<typeof lucia.validateSession>>;

// header auth
const authHeader = getHeader("Authorization");
if (authHeader?.startsWith("Bearer ")) {
const [, sessionId] = authHeader.split("Bearer ");

data = await lucia.validateSession(sessionId);
}
// cookie auth
else {
if (requestEvent.request.method !== "GET") {
const originHeader = getHeader("Origin") ?? null;
// NOTE: You may need to use `X-Forwarded-Host` instead
const hostHeader = getHeader("Host") ?? null;
if (
!originHeader ||
!hostHeader ||
!verifyRequestOrigin(originHeader, [hostHeader])
) {
throw event.node.res.writeHead(403).end();
}
}

const sessionId = getCookie(event, lucia.sessionCookieName) ?? null;
if (!sessionId) return;

data = await lucia.validateSession(sessionId);

if (data.session?.fresh)
appendResponseHeader(
"Set-Cookie",
lucia.createSessionCookie(data.session.id).serialize(),
);
if (!data.session)
appendResponseHeader(
"Set-Cookie",
lucia.createBlankSessionCookie().serialize(),
);
}

if (data.user) return data;
"use server";

const requestEvent = getRequestEvent()!;
const event = requestEvent.nativeEvent;

let data: Awaited<ReturnType<typeof lucia.validateSession>>;

// header auth
const authHeader = getHeader("Authorization");
if (authHeader?.startsWith("Bearer ")) {
const [, sessionId] = authHeader.split("Bearer ");

data = await lucia.validateSession(sessionId);
}
// cookie auth
else {
if (requestEvent.request.method !== "GET") {
const originHeader = getHeader("Origin") ?? null;
// NOTE: You may need to use `X-Forwarded-Host` instead
const hostHeader = getHeader("Host") ?? null;
if (
!originHeader ||
!hostHeader ||
!verifyRequestOrigin(originHeader, [hostHeader])
) {
throw event.node.res.writeHead(403).end();
}
}

const sessionId = getCookie(event, lucia.sessionCookieName) ?? null;
if (!sessionId) return;

data = await lucia.validateSession(sessionId);

if (data.session?.fresh)
appendResponseHeader(
"Set-Cookie",
lucia.createSessionCookie(data.session.id).serialize(),
);
if (!data.session)
appendResponseHeader(
"Set-Cookie",
lucia.createBlankSessionCookie().serialize(),
);
}

if (data.user) return data;
}, "getAuthState");

export async function ensureAuthedOrThrow() {
"use server";
"use server";

const state = await getAuthState();
if (state) return state;
const state = await getAuthState();
if (state) return state;

throw { code: "forbidden" };
throw { code: "forbidden" };
}

export async function ensureAuthedOrRedirect() {
"use server";
"use server";

const state = await getAuthState();
if (state) return state;
const state = await getAuthState();
if (state) return state;

throw loginRedirect();
throw loginRedirect();
}

export const getUser = cache(async () => {
"use server";
"use server";

const state = await getAuthState();
if (!state) return null;
const state = await getAuthState();
if (!state) return null;

const { user } = state;
const { user } = state;

await new Promise((res) => setTimeout(res, 1000));
await new Promise((res) => setTimeout(res, 1000));

const res = await db.query.users.findFirst({
where: eq(users.id, user.id),
columns: {
id: true,
email: true,
},
});
const res = await db.query.users.findFirst({
where: eq(users.id, user.id),
columns: {
id: true,
email: true,
},
});

return res ?? null;
return res ?? null;
}, "user");

export const PROVIDER_DISPLAY_NAMES: Record<AuthProvider, string> = {
twitch: "Twitch",
discord: "Discord",
spotify: "Spotify",
patreon: "Patreon",
github: "GitHub",
twitch: "Twitch",
discord: "Discord",
spotify: "Spotify",
patreon: "Patreon",
github: "GitHub",
};

export const WINDOW_OPEN_FAILED = "window-open-failed";

export const addCredential = action(async (provider: AuthProvider) => {
const w = window.open(await loginURLForProvider(provider), "_blank");
if (!w) {
throw new Error(WINDOW_OPEN_FAILED);
}
const w = window.open(await loginURLForProvider(provider), "_blank");
if (!w) {
throw new Error(WINDOW_OPEN_FAILED);
}

const searchParams = await new Promise<string>((res) => {
window.addEventListener("message", (e) => {
if (e.source !== w) return;
const searchParams = await new Promise<string>((res) => {
window.addEventListener("message", (e) => {
if (e.source !== w) return;

if (typeof e.data !== "string" || !e.data.startsWith("?")) return;
if (typeof e.data !== "string" || !e.data.startsWith("?")) return;

res(e.data);
});
});
res(e.data);
});
});

async function inner(provider: string, searchParams: string) {
"use server";
async function inner(provider: string, searchParams: string) {
"use server";

const [{ user }, oauth] = await Promise.all([
ensureAuthedOrRedirect(),
performOAuthExchange(provider, searchParams),
]);
const [{ user }, oauth] = await Promise.all([
ensureAuthedOrRedirect(),
performOAuthExchange(provider, searchParams),
]);

if (!user) throw { code: "forbidden" };
if (!user) throw { code: "forbidden" };

await db.insert(oauthCredentials).values({
providerId: provider,
providerUserId: oauth.user.id,
userId: user.id,
token: oauth.token,
displayName: oauth.user.displayName,
issuedAt: new Date(),
});
await db.insert(oauthCredentials).values({
providerId: provider,
providerUserId: oauth.user.id,
userId: user.id,
token: oauth.token,
displayName: oauth.user.displayName,
issuedAt: new Date(),
});

return oauth;
}
return oauth;
}

return await inner(provider, searchParams);
return await inner(provider, searchParams);
});

export const removeCredential = action(
async (provider: string, providerUserId: string) => {
"use server";
const { user } = await ensureAuthedOrRedirect();

await db
.delete(oauthCredentials)
.where(
and(
eq(oauthCredentials.providerId, provider),
eq(oauthCredentials.providerUserId, providerUserId),
eq(oauthCredentials.userId, user.id),
),
);
},
async (provider: string, providerUserId: string) => {
"use server";
const { user } = await ensureAuthedOrRedirect();

await db
.delete(oauthCredentials)
.where(
and(
eq(oauthCredentials.providerId, provider),
eq(oauthCredentials.providerUserId, providerUserId),
eq(oauthCredentials.userId, user.id),
),
);
},
);

export const getCredentials = cache(async () => {
"use server";
"use server";

const { user } = await ensureAuthedOrRedirect();
const { user } = await ensureAuthedOrRedirect();

const c = await db.query.oauthCredentials.findMany({
where: eq(oauthCredentials.userId, user.id),
});
const c = await db.query.oauthCredentials.findMany({
where: eq(oauthCredentials.userId, user.id),
});

return c;
return c;
}, "credentials");
import { createStorage } from "unstorage";
import cloudflareKVHTTPDriver from "unstorage/drivers/cloudflare-kv-http";

const cloudflareKv = () => {
const apiToken = process.env.CLOUDFLARE_API_TOKEN!;

if (!apiToken) {
console.error("CLOUDFLARE_API_TOKEN not set");
return;
}

return createStorage({
driver: cloudflareKVHTTPDriver({
accountId: "3de2dd633194481d80f68f55257bdbaa",
namespaceId: "37a5c183f5b942408acae571b12206f1",
apiToken,
}),
});
const apiToken = process.env.CLOUDFLARE_API_TOKEN!;

if (!apiToken) {
console.error("CLOUDFLARE_API_TOKEN not set");
return;
}

return createStorage({
driver: cloudflareKVHTTPDriver({
accountId: "3de2dd633194481d80f68f55257bdbaa",
namespaceId: "37a5c183f5b942408acae571b12206f1",
apiToken,
}),
});
};

export const savePlaygroundProject = action(async (project: string) => {
"use server";
"use server";

const id = crypto.randomUUID();
const id = crypto.randomUUID();

await cloudflareKv()!.setItem(id, project);
await cloudflareKv()!.setItem(id, project);

return id;
return id;
});

export const fetchPlaygroundProject = cache(async (id: string) => {
"use server";
"use server";

const item = await cloudflareKv()!.getItem(id);
const item = await cloudflareKv()!.getItem(id);

if (item) return JSON.stringify(item);
if (item) return JSON.stringify(item);

return null;
return null;
}, "fetchPlaygroundProject");
Loading

0 comments on commit 6d7d614

Please sign in to comment.