a tool for shared writing and social publishing
1"use server"; 2import { refresh } from "next/cache"; 3 4import { drizzle } from "drizzle-orm/node-postgres"; 5import { 6 entities, 7 permission_tokens, 8 permission_token_rights, 9} from "drizzle/schema"; 10import { eq } from "drizzle-orm"; 11import { PermissionToken } from "src/replicache"; 12import { pool } from "supabase/pool"; 13import { getIdentityData } from "./getIdentityData"; 14import { supabaseServerClient } from "supabase/serverClient"; 15 16export async function deleteLeaflet(permission_token: PermissionToken) { 17 const client = await pool.connect(); 18 const db = drizzle(client); 19 20 // Get the current user's identity 21 let identity = await getIdentityData(); 22 23 // Check publication and document ownership in one query 24 let { data: tokenData } = await supabaseServerClient 25 .from("permission_tokens") 26 .select( 27 ` 28 id, 29 leaflets_in_publications(publication, publications!inner(identity_did)), 30 leaflets_to_documents(document, documents!inner(uri)) 31 `, 32 ) 33 .eq("id", permission_token.id) 34 .single(); 35 36 if (tokenData) { 37 // Check if leaflet is in a publication 38 const leafletInPubs = tokenData.leaflets_in_publications || []; 39 if (leafletInPubs.length > 0) { 40 if (!identity) { 41 throw new Error( 42 "Unauthorized: You must be logged in to delete a leaflet in a publication", 43 ); 44 } 45 const isOwner = leafletInPubs.some( 46 (pub: any) => pub.publications.identity_did === identity.atp_did, 47 ); 48 if (!isOwner) { 49 throw new Error( 50 "Unauthorized: You must own the publication to delete this leaflet", 51 ); 52 } 53 } 54 55 // Check if there's a standalone published document 56 const leafletDocs = tokenData.leaflets_to_documents || []; 57 if (leafletDocs.length > 0) { 58 if (!identity) { 59 throw new Error( 60 "Unauthorized: You must be logged in to delete a published leaflet", 61 ); 62 } 63 for (let leafletDoc of leafletDocs) { 64 const docUri = leafletDoc.documents?.uri; 65 // Extract the DID from the document URI (format: at://did:plc:xxx/...) 66 if (docUri && identity.atp_did && !docUri.includes(identity.atp_did)) { 67 throw new Error( 68 "Unauthorized: You must own the published document to delete this leaflet", 69 ); 70 } 71 } 72 } 73 } 74 75 await db.transaction(async (tx) => { 76 let [token] = await tx 77 .select() 78 .from(permission_tokens) 79 .leftJoin( 80 permission_token_rights, 81 eq(permission_tokens.id, permission_token_rights.token), 82 ) 83 .where(eq(permission_tokens.id, permission_token.id)); 84 85 if (!token?.permission_token_rights?.write) return; 86 await tx 87 .delete(entities) 88 .where(eq(entities.set, token.permission_token_rights.entity_set)); 89 await tx 90 .delete(permission_tokens) 91 .where(eq(permission_tokens.id, permission_token.id)); 92 }); 93 client.release(); 94 95 refresh(); 96 return; 97} 98 99export async function archivePost(token: string) { 100 let identity = await getIdentityData(); 101 if (!identity) throw new Error("No Identity"); 102 103 // Archive on homepage 104 await supabaseServerClient 105 .from("permission_token_on_homepage") 106 .update({ archived: true }) 107 .eq("token", token) 108 .eq("identity", identity.id); 109 110 // Check if leaflet is in any publications where user is the creator 111 let { data: leafletInPubs } = await supabaseServerClient 112 .from("leaflets_in_publications") 113 .select("publication, publications!inner(identity_did)") 114 .eq("leaflet", token); 115 116 if (leafletInPubs) { 117 for (let pub of leafletInPubs) { 118 if (pub.publications.identity_did === identity.atp_did) { 119 await supabaseServerClient 120 .from("leaflets_in_publications") 121 .update({ archived: true }) 122 .eq("leaflet", token) 123 .eq("publication", pub.publication); 124 } 125 } 126 } 127 128 refresh(); 129 return; 130} 131 132export async function unarchivePost(token: string) { 133 let identity = await getIdentityData(); 134 if (!identity) throw new Error("No Identity"); 135 136 // Unarchive on homepage 137 await supabaseServerClient 138 .from("permission_token_on_homepage") 139 .update({ archived: false }) 140 .eq("token", token) 141 .eq("identity", identity.id); 142 143 // Check if leaflet is in any publications where user is the creator 144 let { data: leafletInPubs } = await supabaseServerClient 145 .from("leaflets_in_publications") 146 .select("publication, publications!inner(identity_did)") 147 .eq("leaflet", token); 148 149 if (leafletInPubs) { 150 for (let pub of leafletInPubs) { 151 if (pub.publications.identity_did === identity.atp_did) { 152 await supabaseServerClient 153 .from("leaflets_in_publications") 154 .update({ archived: false }) 155 .eq("leaflet", token) 156 .eq("publication", pub.publication); 157 } 158 } 159 } 160 161 refresh(); 162 return; 163}