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 leafletDoc = tokenData.leaflets_to_documents;
57 if (leafletDoc && leafletDoc.document) {
58 if (!identity || !identity.atp_did) {
59 throw new Error(
60 "Unauthorized: You must be logged in to delete a published leaflet",
61 );
62 }
63 const docUri = leafletDoc.documents?.uri;
64 // Extract the DID from the document URI (format: at://did:plc:xxx/...)
65 if (docUri && !docUri.includes(identity.atp_did)) {
66 throw new Error(
67 "Unauthorized: You must own the published document to delete this leaflet",
68 );
69 }
70 }
71 }
72
73 await db.transaction(async (tx) => {
74 let [token] = await tx
75 .select()
76 .from(permission_tokens)
77 .leftJoin(
78 permission_token_rights,
79 eq(permission_tokens.id, permission_token_rights.token),
80 )
81 .where(eq(permission_tokens.id, permission_token.id));
82
83 if (!token?.permission_token_rights?.write) return;
84 const entitySet = token.permission_token_rights.entity_set;
85 if (!entitySet) return;
86 await tx.delete(entities).where(eq(entities.set, entitySet));
87 await tx
88 .delete(permission_tokens)
89 .where(eq(permission_tokens.id, permission_token.id));
90 });
91 client.release();
92
93 refresh();
94 return;
95}
96
97export async function archivePost(token: string) {
98 let identity = await getIdentityData();
99 if (!identity) throw new Error("No Identity");
100
101 // Archive on homepage
102 await supabaseServerClient
103 .from("permission_token_on_homepage")
104 .update({ archived: true })
105 .eq("token", token)
106 .eq("identity", identity.id);
107
108 // Check if leaflet is in any publications where user is the creator
109 let { data: leafletInPubs } = await supabaseServerClient
110 .from("leaflets_in_publications")
111 .select("publication, publications!inner(identity_did)")
112 .eq("leaflet", token);
113
114 if (leafletInPubs) {
115 for (let pub of leafletInPubs) {
116 if (pub.publications.identity_did === identity.atp_did) {
117 await supabaseServerClient
118 .from("leaflets_in_publications")
119 .update({ archived: true })
120 .eq("leaflet", token)
121 .eq("publication", pub.publication);
122 }
123 }
124 }
125
126 refresh();
127 return;
128}
129
130export async function unarchivePost(token: string) {
131 let identity = await getIdentityData();
132 if (!identity) throw new Error("No Identity");
133
134 // Unarchive on homepage
135 await supabaseServerClient
136 .from("permission_token_on_homepage")
137 .update({ archived: false })
138 .eq("token", token)
139 .eq("identity", identity.id);
140
141 // Check if leaflet is in any publications where user is the creator
142 let { data: leafletInPubs } = await supabaseServerClient
143 .from("leaflets_in_publications")
144 .select("publication, publications!inner(identity_did)")
145 .eq("leaflet", token);
146
147 if (leafletInPubs) {
148 for (let pub of leafletInPubs) {
149 if (pub.publications.identity_did === identity.atp_did) {
150 await supabaseServerClient
151 .from("leaflets_in_publications")
152 .update({ archived: false })
153 .eq("leaflet", token)
154 .eq("publication", pub.publication);
155 }
156 }
157 }
158
159 refresh();
160 return;
161}