import { api } from "https://esm.town/v/pomdtr/api";
import { zip } from "https://esm.town/v/pomdtr/sql";
import { sqlite } from "https://esm.town/v/std/sqlite";
import { deleteCookie, getCookies, setCookie } from "jsr:@std/http/cookie";
async function createSession(email: string, hostname: string) {
const sessionID = crypto.randomUUID();
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + 14);
await sqlite.batch([
`CREATE TABLE IF NOT EXISTS lastlogin_session (email TEXT, sessionID TEXT, hostname TEXT, expiresAt INTEGER)`,
{
sql: `DELETE FROM lastlogin_session WHERE email=? & hostname=?`,
args: [email, hostname],
},
{
sql: `INSERT INTO lastlogin_session VALUES (?, ?, ?, ?)`,
args: [email, sessionID, hostname, expiresAt.getTime()],
},
]);
return sessionID;
}
async function getSession(sessionID: string, hostname: string) {
try {
const res = await sqlite.execute({
sql: `SELECT * FROM lastlogin_session WHERE sessionID=? AND hostname=?`,
args: [sessionID, hostname],
});
const rows = zip(res);
if (rows.length === 0) {
return null;
}
const session = rows[0];
if (session.expiresAt < Date.now()) {
await sqlite.execute({
sql: `DELETE FROM lastlogin_session WHERE sessionID=?`,
args: [sessionID],
});
return null;
}
return session;
} catch (_) {
return null;
}
}
async function deleteSession(sessionID: string) {
await sqlite.execute({
sql: `DELETE FROM lastlogin_session WHERE sessionID=?`,
args: [sessionID],
});
}
const SESSION_COOKIE = "lastlogin_session";
const OAUTH_COOKIE = "oauth_store";
export type LastLoginOptions = {
verifyEmail: (email: string) => Promise<boolean> | boolean;
public_routes?: string[];
};
export function lastlogin(
handler: (req: Request) => Response | Promise<Response>,
options: LastLoginOptions,
) {
return async (req: Request) => {
const isPublicRoute = () => {
for (const pathname of options.public_routes ?? []) {
const pattern = new URLPattern({ pathname });
if (pattern.test(req.url)) {
return true;
}
}
return false;
};
const url = new URL(req.url);
const clientID = `${url.protocol}//${url.host}/`;
const redirectUri = `${url.protocol}//${url.host}/auth/callback`;
if (url.pathname == "/auth/callback") {
const cookies = await getCookies(req.headers);
const store = JSON.parse(decodeURIComponent(cookies[OAUTH_COOKIE]));
const state = url.searchParams.get("state");
if (!state || state != store.state) {
return new Response("state mismatch", { status: 400 });
}
const code = url.searchParams.get("code");
if (!code) {
return new Response("code not found", { status: 400 });
}
const tokenUrl = new URL("https://lastlogin.io/token");
tokenUrl.searchParams.set("client_id", clientID);
tokenUrl.searchParams.set("code", code);
tokenUrl.searchParams.set("redirect_uri", redirectUri);