a tool for shared writing and social publishing
at update/reader 119 lines 3.5 kB view raw
1"use server"; 2import { drizzle } from "drizzle-orm/node-postgres"; 3import postgres from "postgres"; 4import { 5 email_auth_tokens, 6 identities, 7 permission_token_on_homepage, 8 poll_votes_on_entity, 9} from "drizzle/schema"; 10import { and, eq, isNull } from "drizzle-orm"; 11import { cookies } from "next/headers"; 12import { redirect } from "next/navigation"; 13import { pool } from "supabase/pool"; 14import { supabaseServerClient } from "supabase/serverClient"; 15 16export async function loginWithEmailToken( 17 localLeaflets: { token: { id: string }; added_at: string }[], 18) { 19 const client = await pool.connect(); 20 const db = drizzle(client); 21 let token_id = (await cookies()).get("auth_token")?.value; 22 let voter_token = (await cookies()).get("poll_voter_token")?.value; 23 if (!token_id) return null; 24 let result = await db.transaction(async (tx) => { 25 let [token] = await tx 26 .select() 27 .from(email_auth_tokens) 28 .where( 29 and( 30 eq(email_auth_tokens.id, token_id), 31 eq(email_auth_tokens.confirmed, true), 32 ), 33 ); 34 if (!token || !token.email) return null; 35 if (token.identity) { 36 let id = token.identity; 37 if (localLeaflets.length > 0) 38 await tx 39 .insert(permission_token_on_homepage) 40 .values( 41 localLeaflets.map((l) => ({ 42 identity: id, 43 token: l.token.id, 44 })), 45 ) 46 .onConflictDoNothing(); 47 return token; 48 } 49 let [existingIdentity] = await tx 50 .select() 51 .from(identities) 52 .where(eq(identities.email, token.email)); 53 54 let identity = existingIdentity; 55 if (!existingIdentity) { 56 let identityCookie = (await cookies()).get("identity"); 57 if (identityCookie) { 58 let [existingIdentityFromCookie] = await tx 59 .select() 60 .from(identities) 61 .where( 62 and( 63 eq(identities.id, identityCookie.value), 64 isNull(identities.email), 65 ), 66 ); 67 if (existingIdentityFromCookie) { 68 await tx 69 .update(identities) 70 .set({ email: token.email }) 71 .where(eq(identities.id, existingIdentityFromCookie.id)); 72 identity = existingIdentityFromCookie; 73 } 74 } else { 75 const { data: newIdentity } = await supabaseServerClient 76 .from("identities") 77 .insert({ email: token.email }) 78 .select() 79 .single(); 80 identity = newIdentity!; 81 } 82 } 83 84 await tx 85 .update(email_auth_tokens) 86 .set({ identity: identity.id }) 87 .where(eq(email_auth_tokens.id, token_id)); 88 89 if (localLeaflets.length > 0) 90 await tx 91 .insert(permission_token_on_homepage) 92 .values( 93 localLeaflets.map((l) => ({ 94 identity: identity.id, 95 token: l.token.id, 96 })), 97 ) 98 .onConflictDoNothing(); 99 100 return token; 101 }); 102 if (result?.identity) { 103 if (result.identity !== voter_token) { 104 if (voter_token) 105 await db 106 .update(poll_votes_on_entity) 107 .set({ voter_token: result.identity }) 108 .where(eq(poll_votes_on_entity.voter_token, voter_token)); 109 110 (await cookies()).set("poll_voter_token", result.identity, { 111 maxAge: 60 * 60 * 24 * 365, 112 secure: process.env.NODE_ENV === "production", 113 httpOnly: true, 114 sameSite: "lax", 115 }); 116 } 117 } 118 client.release(); 119}