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