solid_pod_rs_forge/
preview.rs1use crate::ownership::ForgeAgent;
29use crate::request::{ForgeRequest, ForgeResponse};
30use crate::web_edit::{cors_err, resolve_branch, validate};
31use crate::ForgeService;
32
33pub const EPHEMERAL_PREVIEW_KIND: u64 = 21617;
36
37impl ForgeService {
38 pub(crate) async fn h_api_preview(
41 &self,
42 req: &ForgeRequest,
43 agent: &ForgeAgent,
44 owner: &str,
45 name: &str,
46 ) -> ForgeResponse {
47 if !req.method.eq_ignore_ascii_case("POST") {
48 return crate::api::api_err(405, "method not allowed");
49 }
50 let ed = match validate(self.cfg.open_edit, req, agent, owner, "preview") {
51 Ok(e) => e,
52 Err(resp) => return resp,
53 };
54 let dir = match self.resolve_repo(owner, name).await {
55 Ok(d) => d,
56 Err(_) => return cors_err(404, "not found"),
57 };
58 let branch = match resolve_branch(&dir, ed.branch.as_ref()).await {
59 Ok(b) => b,
60 Err(resp) => return resp,
61 };
62 self.publish_preview(owner, name, &branch, &ed).await
63 }
64
65 #[cfg(feature = "announce")]
66 async fn publish_preview(
67 &self,
68 owner: &str,
69 name: &str,
70 branch: &str,
71 ed: &crate::web_edit::EditRequest,
72 ) -> ForgeResponse {
73 use crate::publish::{publish_event, RELAY_TIMEOUT};
74 use crate::web_edit::cors_json;
75 let a = &self.announcer;
76 if a.relays.is_empty() {
77 return cors_json(
78 200,
79 &serde_json::json!({
80 "ok": true,
81 "published": false,
82 "reason": "no relays configured (set config.announceRelays)",
83 }),
84 );
85 }
86 let tags = vec![
87 vec!["d".to_string(), format!("{owner}/{name}")],
88 vec!["f".to_string(), ed.path.clone()],
89 vec!["branch".to_string(), branch.to_string()],
90 ];
91 let ev = match a
92 .signer
93 .sign(EPHEMERAL_PREVIEW_KIND, tags, &ed.content, crate::now_secs())
94 {
95 Ok(e) => e,
96 Err(e) => {
97 tracing::warn!("forge: preview {owner}/{name} signing failed: {e}");
98 return cors_err(500, "preview failed");
99 }
100 };
101 let relays = publish_event(&ev, &a.relays, RELAY_TIMEOUT, a.ssrf.as_ref()).await;
102 cors_json(
103 200,
104 &serde_json::json!({
105 "ok": true,
106 "published": true,
107 "kind": ev.kind,
108 "id": ev.id,
109 "path": ed.path,
110 "relays": serde_json::to_value(&relays).unwrap_or(serde_json::Value::Null),
111 }),
112 )
113 }
114
115 #[cfg(not(feature = "announce"))]
116 async fn publish_preview(
117 &self,
118 _owner: &str,
119 _name: &str,
120 _branch: &str,
121 _ed: &crate::web_edit::EditRequest,
122 ) -> ForgeResponse {
123 cors_err(501, "NIP-34 emission is not compiled into this build")
124 }
125}