diff options
Diffstat (limited to 'kittybox-rs/src/frontend/onboarding.rs')
-rw-r--r-- | kittybox-rs/src/frontend/onboarding.rs | 181 |
1 files changed, 0 insertions, 181 deletions
diff --git a/kittybox-rs/src/frontend/onboarding.rs b/kittybox-rs/src/frontend/onboarding.rs deleted file mode 100644 index e44e866..0000000 --- a/kittybox-rs/src/frontend/onboarding.rs +++ /dev/null @@ -1,181 +0,0 @@ -use std::sync::Arc; - -use crate::database::{settings, Storage}; -use axum::{ - extract::{Extension, Host}, - http::StatusCode, - response::{Html, IntoResponse}, - Json, -}; -use kittybox_frontend_renderer::{ErrorPage, OnboardingPage, Template}; -use serde::Deserialize; -use tokio::{task::JoinSet, sync::Mutex}; -use tracing::{debug, error}; - -use super::FrontendError; - -pub async fn get() -> Html<String> { - Html( - Template { - title: "Kittybox - Onboarding", - blog_name: "Kittybox", - feeds: vec![], - user: None, - content: OnboardingPage {}.to_string(), - } - .to_string(), - ) -} - -#[derive(Deserialize, Debug)] -struct OnboardingFeed { - slug: String, - name: String, -} - -#[derive(Deserialize, Debug)] -pub 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() - } -} - -#[tracing::instrument(skip(db, http))] -async fn onboard<D: Storage + 'static>( - db: D, - user_uid: url::Url, - data: OnboardingData, - http: reqwest::Client, - jobset: Arc<Mutex<JoinSet<()>>>, -) -> Result<(), FrontendError> { - // Create a user to pass to the backend - // At this point the site belongs to nobody, so it is safe to do - tracing::debug!("Creating user..."); - let user = kittybox_indieauth::TokenData { - me: user_uid.clone(), - client_id: "https://kittybox.fireburn.ru/".parse().unwrap(), - scope: kittybox_indieauth::Scopes::new(vec![kittybox_indieauth::Scope::Create]), - iat: None, exp: None - }; - tracing::debug!("User data: {:?}", user); - - if data.user["type"][0] != "h-card" || data.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", - )); - } - - tracing::debug!("Setting settings..."); - let user_domain = format!( - "{}{}", - user.me.host_str().unwrap(), - user.me.port() - .map(|port| format!(":{}", port)) - .unwrap_or_default() - ); - db.set_setting::<settings::SiteName>(&user_domain, data.blog_name.to_owned()) - .await - .map_err(FrontendError::from)?; - - db.set_setting::<settings::Webring>(&user_domain, false) - .await - .map_err(FrontendError::from)?; - - let (_, hcard) = { - let mut hcard = data.user; - hcard["properties"]["uid"] = serde_json::json!([&user_uid]); - crate::micropub::normalize_mf2(hcard, &user) - }; - db.put_post(&hcard, user_domain.as_str()) - .await - .map_err(FrontendError::from)?; - - debug!("Creating feeds..."); - for feed in data.feeds { - if feed.name.is_empty() || feed.slug.is_empty() { - continue; - }; - debug!("Creating feed {} with slug {}", &feed.name, &feed.slug); - let (_, feed) = crate::micropub::normalize_mf2( - serde_json::json!({ - "type": ["h-feed"], - "properties": {"name": [feed.name], "mp-slug": [feed.slug]} - }), - &user, - ); - - db.put_post(&feed, user_uid.as_str()) - .await - .map_err(FrontendError::from)?; - } - let (uid, post) = crate::micropub::normalize_mf2(data.first_post, &user); - tracing::debug!("Posting first post {}...", uid); - crate::micropub::_post(&user, uid, post, db, http, jobset) - .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(()) -} - -pub async fn post<D: Storage + 'static>( - Extension(db): Extension<D>, - Host(host): Host, - Extension(http): Extension<reqwest::Client>, - Extension(jobset): Extension<Arc<Mutex<JoinSet<()>>>>, - Json(data): Json<OnboardingData>, -) -> axum::response::Response { - let user_uid = format!("https://{}/", host.as_str()); - - if db.post_exists(&user_uid).await.unwrap() { - IntoResponse::into_response((StatusCode::FOUND, [("Location", "/")])) - } else { - match onboard(db, user_uid.parse().unwrap(), data, http, jobset).await { - Ok(()) => IntoResponse::into_response((StatusCode::FOUND, [("Location", "/")])), - Err(err) => { - error!("Onboarding error: {}", err); - IntoResponse::into_response(( - err.code(), - Html( - Template { - title: "Kittybox - Onboarding", - blog_name: "Kittybox", - feeds: vec![], - user: None, - content: ErrorPage { - code: err.code(), - msg: Some(err.msg().to_string()), - } - .to_string(), - } - .to_string(), - ), - )) - } - } - } -} - -pub fn router<S: Storage + 'static>( - database: S, - http: reqwest::Client, - jobset: Arc<Mutex<JoinSet<()>>>, -) -> axum::routing::MethodRouter { - axum::routing::get(get) - .post(post::<S>) - .layer::<_, _, std::convert::Infallible>(axum::Extension(database)) - .layer::<_, _, std::convert::Infallible>(axum::Extension(http)) - .layer(axum::Extension(jobset)) -} |