···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()
···1+-- Create GIN index on the tags array in the JSONB data field
2+-- This allows efficient querying of documents by tag
3+CREATE INDEX IF NOT EXISTS idx_documents_tags
4+ ON "public"."documents" USING gin ((data->'tags'));
5+6+-- Function to search and aggregate tags from documents
7+-- This does the aggregation in the database rather than fetching all documents
8+CREATE OR REPLACE FUNCTION search_tags(search_query text)
9+RETURNS TABLE (name text, document_count bigint) AS $$
10+BEGIN
11+ RETURN QUERY
12+ SELECT
13+ LOWER(tag::text) as name,
14+ COUNT(DISTINCT d.uri) as document_count
15+ FROM
16+ "public"."documents" d,
17+ jsonb_array_elements_text(d.data->'tags') as tag
18+ WHERE
19+ CASE
20+ WHEN search_query = '' THEN true
21+ ELSE LOWER(tag::text) LIKE '%' || search_query || '%'
22+ END
23+ GROUP BY
24+ LOWER(tag::text)
25+ ORDER BY
26+ COUNT(DISTINCT d.uri) DESC,
27+ LOWER(tag::text) ASC
28+ LIMIT 20;
29+END;
30+$$ LANGUAGE plpgsql STABLE;
···1+set check_function_bodies = off;
2+3+CREATE OR REPLACE FUNCTION public.pull_data(token_id uuid, client_group_id text)
4+ RETURNS pull_result
5+ LANGUAGE plpgsql
6+AS $function$DECLARE
7+ result pull_result;
8+BEGIN
9+ -- Get client group data as JSON array
10+ SELECT json_agg(row_to_json(rc))
11+ FROM replicache_clients rc
12+ WHERE rc.client_group = client_group_id
13+ INTO result.client_groups;
14+15+ -- Get facts as JSON array
16+ SELECT json_agg(row_to_json(f))
17+ FROM permission_tokens pt,
18+ get_facts(pt.root_entity) f
19+ WHERE pt.id = token_id
20+ INTO result.facts;
21+22+ -- Get publication data - try leaflets_in_publications first, then leaflets_to_documents
23+ SELECT json_agg(row_to_json(lip))
24+ FROM leaflets_in_publications lip
25+ WHERE lip.leaflet = token_id
26+ INTO result.publications;
27+28+ -- If no publication data found, try leaflets_to_documents (for standalone documents)
29+ IF result.publications IS NULL THEN
30+ SELECT json_agg(row_to_json(ltd))
31+ FROM leaflets_to_documents ltd
32+ WHERE ltd.leaflet = token_id
33+ INTO result.publications;
34+ END IF;
35+36+ RETURN result;
37+END;$function$
38+;