about summary refs log tree commit diff
path: root/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mod.rs71
-rw-r--r--src/frontend/templates/onboarding.rs2
2 files changed, 68 insertions, 5 deletions
diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs
index ad50161..49faf59 100644
--- a/src/frontend/mod.rs
+++ b/src/frontend/mod.rs
@@ -126,10 +126,17 @@ struct OnboardingFeed {
 struct OnboardingData {
     user: serde_json::Value,
     first_post: serde_json::Value,
+    #[serde(default = "OnboardingData::default_blog_name")]
     blog_name: String,
     feeds: Vec<OnboardingFeed>,
 }
 
+impl OnboardingData {
+    fn default_blog_name() -> String {
+        "Kitty Box!".to_owned()
+    }
+}
+
 /*pub async fn onboarding_receiver<S: Storage>(mut req: Request<ApplicationState<S>>) -> Result {
     use serde_json::json;
 
@@ -268,23 +275,79 @@ pub fn homepage<D: Storage>(db: D, endpoints: IndiewebEndpoints) -> impl Filter<
             let feeds = db.get_channels(&owner).await.unwrap_or_default();
             match content {
                 (Some(card), Some(feed), StatusCode::OK) => {
-                    warp::reply::html(Template {
+                    Box::new(warp::reply::html(Template {
                         title: &blog_name,
                         blog_name: &blog_name,
                         endpoints,
                         feeds,
                         user: None, // TODO
                         content: MainPage { feed: &feed, card: &card }.to_string()
-                    }.to_string())
+                    }.to_string())) as Box<dyn warp::Reply>
                 },
-                _ => {
+                (None, None, StatusCode::NOT_FOUND) => {
                     // TODO Onboarding
-                    todo!("Onboarding flow")
+                    Box::new(warp::redirect::found(
+                        hyper::Uri::from_static("/onboarding")
+                    )) as Box<dyn warp::Reply>
+                }
+                _ => {
+                    todo!("Handle cases where either main h-card or main h-feed are deleted")
                 }
             }
         })
 }
 
+pub fn onboarding<D: Storage, T: hyper::client::connect::Connect + Clone + Send + Sync + 'static>(
+    db: D, endpoints: IndiewebEndpoints, http: hyper::Client<T, hyper::Body>
+) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
+    let inject_db = move || db.clone();
+    warp::get()
+        .map(move || warp::reply::html(Template {
+            title: "Kittybox - Onboarding",
+            blog_name: "Kittybox",
+            endpoints: endpoints.clone(),
+            feeds: vec![],
+            user: None,
+            content: OnboardingPage {}.to_string()
+        }.to_string()))
+        .or(warp::post()
+            .and(crate::util::require_host())
+            .and(warp::any().map(inject_db))
+            .and(warp::body::json::<OnboardingData>())
+            .and(warp::any().map(move || http.clone()))
+            .and_then(|host: warp::host::Authority, db: D, body: OnboardingData, http: _| async move {
+                let user_uid = format!("https://{}/", host.as_str());
+                if db.post_exists(&user_uid).await.map_err(FrontendError::from)? {
+                    
+                    return Ok(warp::redirect(hyper::Uri::from_static("/")));
+                }
+                let user = crate::indieauth::User::new(&user_uid, "https://kittybox.fireburn.ru/", "create");
+                if body.user["type"][0] != "h-card" || body.first_post["type"][0] != "h-entry" {
+                    return Err(FrontendError::with_code(StatusCode::BAD_REQUEST, "user and first_post should be an h-card and an h-entry").into());
+                }
+                db.set_setting("site_name", user.me.as_str(), &body.blog_name)
+                    .await
+                    .map_err(FrontendError::from)?;
+
+                let (_, hcard) = {
+                    let mut hcard = body.user;
+                    hcard["properties"]["uid"] = serde_json::json!([&user_uid]);
+                    crate::micropub::normalize_mf2(hcard, &user)
+                };
+                db.put_post(&hcard, &user_uid).await.map_err(FrontendError::from)?;
+                let (uid, post) = crate::micropub::normalize_mf2(body.first_post, &user);
+                crate::micropub::_post(user, uid, post, db, http).await.map_err(|e| {
+                    FrontendError {
+                        msg: "Error while posting the first post".to_string(),
+                        source: Some(Box::new(e)),
+                        code: StatusCode::INTERNAL_SERVER_ERROR
+                    }
+                })?;
+                Ok::<_, warp::Rejection>(warp::redirect(hyper::Uri::from_static("/")))
+            }))
+        
+}
+
 #[forbid(clippy::unwrap_used)]
 pub fn catchall<D: Storage>(db: D, endpoints: IndiewebEndpoints) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
     let inject_db = move || db.clone();
diff --git a/src/frontend/templates/onboarding.rs b/src/frontend/templates/onboarding.rs
index 0dfb462..f95e1e6 100644
--- a/src/frontend/templates/onboarding.rs
+++ b/src/frontend/templates/onboarding.rs
@@ -5,7 +5,7 @@ markup::define! {
         }
         script[type="module", src="/static/onboarding.js"] {}
         link[rel="stylesheet", href="/static/onboarding.css"];
-        form.onboarding[action="/", method="POST"] {
+        form.onboarding[action="", method="POST"] {
             noscript {
                 p {
                     "Ok, let's be honest. Most of this software doesn't require JS to be enabled "