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}