From 31628a7155c4d578d83cb6730b59ca0013d204c8 Mon Sep 17 00:00:00 2001 From: glyph Date: Fri, 18 Mar 2022 11:33:27 +0200 Subject: [PATCH] remove old scuttlebutt routes file --- peach-web/src/routes/scuttlebutt.rs | 946 ---------------------------- 1 file changed, 946 deletions(-) delete mode 100644 peach-web/src/routes/scuttlebutt.rs diff --git a/peach-web/src/routes/scuttlebutt.rs b/peach-web/src/routes/scuttlebutt.rs deleted file mode 100644 index e9c1d4b..0000000 --- a/peach-web/src/routes/scuttlebutt.rs +++ /dev/null @@ -1,946 +0,0 @@ -//! Routes for Scuttlebutt related functionality. - -use log::debug; -use peach_lib::sbot::{SbotConfig, SbotStatus}; -use rocket::{ - form::{Form, FromForm}, - fs::TempFile, - get, post, - request::FlashMessage, - response::{Flash, Redirect}, - uri, -}; -use rocket_dyn_templates::{tera::Context, Template}; - -use crate::{ - context::{ - scuttlebutt, - scuttlebutt::{ - BlocksContext, FollowsContext, FriendsContext, PrivateContext, ProfileContext, - }, - }, - routes::authentication::Authenticated, - utils, -}; - -// HELPER FUNCTIONS - -/// Check to see if the go-sbot.service process is currently active. -/// Return an error in the form of a `String` if the process -/// check command fails. Otherwise, return the state of the process. -fn is_sbot_active() -> Result { - // retrieve go-sbot systemd process status - let sbot_status = match SbotStatus::read() { - Ok(status) => status, - Err(e) => return Err(format!("Failed to read sbot status: {}", e)), - }; - - if sbot_status.state == Some("active".to_string()) { - Ok(true) - } else { - Ok(false) - } -} - -/// Ensure that the given public key is a valid ed25519 key. -fn validate_public_key(public_key: &str, redirect_url: String) -> Result<(), Flash> { - // ensure the id starts with the correct sigil link - if !public_key.starts_with('@') { - return Err(Flash::error( - Redirect::to(redirect_url), - "Invalid key: expected '@' sigil as first character", - )); - } - - // find the dot index denoting the start of the algorithm definition tag - let dot_index = match public_key.rfind('.') { - Some(index) => index, - None => { - return Err(Flash::error( - Redirect::to(redirect_url), - "Invalid key: no dot index was found", - )) - } - }; - - // check hashing algorithm (must end with ".ed25519") - if !&public_key.ends_with(".ed25519") { - return Err(Flash::error( - Redirect::to(redirect_url), - "Invalid key: hashing algorithm must be ed25519", - )); - } - - // obtain the base64 portion (substring) of the public key - let base64_str = &public_key[1..dot_index]; - - // length of a base64 encoded ed25519 public key - if base64_str.len() != 44 { - return Err(Flash::error( - Redirect::to(redirect_url), - "Invalid key: base64 data length is incorrect", - )); - } - - Ok(()) -} - -// HELPERS AND ROUTES FOR INVITES - -#[get("/invites")] -pub fn invites(flash: Option, _auth: Authenticated) -> Template { - // retrieve current ui theme - let theme = utils::get_theme(); - - let mut context = Context::new(); - context.insert("theme", &theme); - context.insert("back", &Some("/scuttlebutt/peers".to_string())); - context.insert("title", &Some("Invites".to_string())); - - // check to see if there is a flash message to display - if let Some(flash) = flash { - match flash.kind() { - // we've been passed a freshly-generated invite code (redirect from post) - "code" => { - context.insert("invite_code", &Some(flash.message().to_string())); - context.insert("flash_name", &Some("success".to_string())); - context.insert("flash_msg", &Some("Generated invite code".to_string())); - } - _ => { - // add flash message contents to the context object - context.insert("flash_name", &Some(flash.kind().to_string())); - context.insert("flash_msg", &Some(flash.message().to_string())); - } - } - }; - - Template::render("scuttlebutt/invites", &context.into_json()) -} - -#[derive(Debug, FromForm)] -pub struct Invite { - pub uses: u16, -} - -#[post("/invites", data = "")] -pub async fn create_invite(invite: Form, _auth: Authenticated) -> Flash { - let uses = invite.uses; - - let url = uri!("/scuttlebutt", invites); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - debug!("Generating Scuttlebutt invite code"); - match sbot_client.invite_create(uses).await { - // construct a custom flash msg to pass along the invite code - Ok(code) => Flash::new(Redirect::to(url), "code", code), - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to create invite code: {}", e), - ), - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. New invite codes cannot be generated. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ) - } - // failed to retrieve go-sbot systemd process status - Err(e) => return Flash::error(Redirect::to(url), e) - } -} - -// HELPERS AND ROUTES FOR /private - -/// A private message composition and publication page. -#[get("/private?")] -pub async fn private( - mut public_key: Option, - flash: Option>, - _auth: Authenticated, -) -> Template { - // display a helpful message if the sbot is inactive - if let Ok(false) = is_sbot_active() { - // retrieve current ui theme - let theme = utils::get_theme(); - - let mut context = Context::new(); - context.insert("theme", &theme); - context.insert("back", &Some("/".to_string())); - context.insert("title", &Some("Private Messages".to_string())); - context.insert( - "unavailable_msg", - &Some("Private messages cannot be published.".to_string()), - ); - - // render the "sbot is inactive" template - return Template::render("scuttlebutt/inactive", &context.into_json()); - // otherwise, build the full context and render the private message template - } else { - if let Some(ref key) = public_key { - // `url_decode` replaces '+' with ' ', so we need to revert that - public_key = Some(key.replace(' ', "+")); - } - - // build the private context object - let context = PrivateContext::build(public_key).await; - - match context { - // we were able to build the context without errors - Ok(mut context) => { - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.flash_name = Some(flash.kind().to_string()); - context.flash_msg = Some(flash.message().to_string()); - }; - - Template::render("scuttlebutt/private", &context) - } - // an error occurred while building the context - Err(e) => { - // build the default context and pass along the error message - let mut context = PrivateContext::default(); - context.flash_name = Some("error".to_string()); - context.flash_msg = Some(e.to_string()); - - Template::render("scuttlebutt/private", &context) - } - } - } -} - -#[derive(Debug, FromForm)] -pub struct Private { - pub id: String, - pub text: String, - pub recipient: String, -} - -/// Publish a private message. -#[post("/private", data = "")] -pub async fn private_post(private: Form, _auth: Authenticated) -> Flash { - let url = uri!("/scuttlebutt", private(None::)); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - let id = &private.id; - let text = &private.text; - let recipient = &private.recipient; - // now we need to add the local id to the recipients vector, - // otherwise the local id will not be able to read the message. - let recipients = vec![id.to_string(), recipient.to_string()]; - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - debug!("Publishing a new Scuttlebutt private message"); - match sbot_client - .publish_private(text.to_string(), recipients) - .await - { - Ok(_) => { - Flash::success(Redirect::to(url), format!("Published private message")) - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to publish private message: {}", e), - ), - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. New private message cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ); - } - // failed to retrieve go-sbot systemd process status - Err(e) => return Flash::error(Redirect::to(url), e), - } -} - -// HELPERS AND ROUTES FOR /search - -/// Search for a peer. -#[get("/search")] -pub fn search(flash: Option, _auth: Authenticated) -> Template { - // retrieve current ui theme - let theme = utils::get_theme(); - - // retrieve go-sbot systemd process status - let sbot_status = SbotStatus::read().ok(); - - let mut context = Context::new(); - context.insert("theme", &theme); - context.insert("sbot_status", &sbot_status); - context.insert("title", &Some("Search")); - context.insert("back", &Some("/scuttlebutt/peers")); - - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.insert("flash_name", &Some(flash.kind().to_string())); - context.insert("flash_msg", &Some(flash.message().to_string())); - }; - - Template::render("scuttlebutt/search", &context.into_json()) -} - -#[derive(Debug, FromForm)] -pub struct Peer { - // public key - pub public_key: String, -} - -/// Accept the peer search form and redirect to the profile for that peer. -#[post("/search", data = "")] -pub async fn search_post(peer: Form, _auth: Authenticated) -> Flash { - let public_key = &peer.public_key; - - let search_url = "/scuttlebutt/search".to_string(); - - // validate the key before redirecting to profile url - if let Err(flash) = validate_public_key(&public_key, search_url) { - // redirect with error message - return flash; - } - - // key has not been validated and we can redirect to the profile page - let profile_url = uri!("/scuttlebutt", profile(Some(public_key))); - - Flash::new( - Redirect::to(profile_url), - // this flash msg will not be displayed in the receiving template - "ignore", - "Public key validated for profile lookup", - ) -} - -// HELPERS AND ROUTES FOR /peers - -/// A peer menu which allows navigating to lists of friends, follows, followers -/// and blocks, as well as accessing the invite creation form. -#[get("/peers")] -pub fn peers(flash: Option, _auth: Authenticated) -> Template { - // retrieve current ui theme - let theme = utils::get_theme(); - - let mut context = Context::new(); - context.insert("theme", &theme); - context.insert("title", &Some("Scuttlebutt Peers")); - context.insert("back", &Some("/")); - - // display a helpful message if the sbot is inactive - if let Ok(false) = is_sbot_active() { - context.insert( - "unavailable_msg", - &Some("Social lists and interactions are unavailable.".to_string()), - ); - - // render the "sbot is inactive" template - return Template::render("scuttlebutt/inactive", &context.into_json()); - } else { - context.insert("sbot_state", &Some("active".to_string())); - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.insert("flash_name", &Some(flash.kind().to_string())); - context.insert("flash_msg", &Some(flash.message().to_string())); - }; - } - - Template::render("scuttlebutt/peers", &context.into_json()) -} - -// HELPERS AND ROUTES FOR /post/publish - -#[derive(Debug, FromForm)] -pub struct Post { - pub text: String, -} - -/// Publish a public Scuttlebutt post. -/// Redirects to profile page of the PeachCloud local identity with a flash -/// message describing the outcome of the action (may be successful or -/// unsuccessful). -#[post("/publish", data = "")] -pub async fn publish(post: Form, _auth: Authenticated) -> Flash { - let post_text = &post.text; - let url = uri!("/scuttlebutt", profile(None::)); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - debug!("Publishing new Scuttlebutt public post"); - match sbot_client.publish_post(post_text).await { - Ok(_) => Flash::success(Redirect::to(url), format!("Published post")), - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to publish post: {}", e), - ), - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. New posts cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ); - } - Err(e) => return Flash::error(Redirect::to(url), e), - } -} - -// HELPERS AND ROUTES FOR /follow - -/// Follow a Scuttlebutt profile specified by the given public key. -/// Redirects to the appropriate profile page with a flash message describing -/// the outcome of the action (may be successful or unsuccessful). -#[post("/follow", data = "")] -pub async fn follow(peer: Form, _auth: Authenticated) -> Flash { - let public_key = &peer.public_key; - let url = uri!("/scuttlebutt", profile(Some(public_key))); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - debug!("Following Scuttlebutt peer"); - match sbot_client.follow(public_key).await { - Ok(_) => Flash::success(Redirect::to(url), format!("Followed peer")), - Err(e) => { - Flash::error(Redirect::to(url), format!("Failed to follow peer: {}", e)) - } - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. Follow messages cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ); - } - Err(e) => return Flash::error(Redirect::to(url), e), - } -} - -// HELPERS AND ROUTES FOR /unfollow - -/// Unfollow a Scuttlebutt profile specified by the given public key. -/// Redirects to the appropriate profile page with a flash message describing -/// the outcome of the action (may be successful or unsuccessful). -#[post("/unfollow", data = "")] -pub async fn unfollow(peer: Form, _auth: Authenticated) -> Flash { - let public_key = &peer.public_key; - - let url = uri!("/scuttlebutt", profile(Some(public_key))); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - debug!("Unfollowing Scuttlebutt peer"); - match sbot_client.unfollow(public_key).await { - Ok(_) => Flash::success(Redirect::to(url), format!("Unfollowed peer")), - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to unfollow peer: {}", e), - ), - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. Follow messages cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ); - } - Err(e) => return Flash::error(Redirect::to(url), e), - } -} - -// HELPERS AND ROUTES FOR /block - -/// Block a Scuttlebutt profile specified by the given public key. -/// Redirects to the appropriate profile page with a flash message describing -/// the outcome of the action (may be successful or unsuccessful). -#[post("/block", data = "")] -pub async fn block(peer: Form, _auth: Authenticated) -> Flash { - let public_key = &peer.public_key; - let url = uri!("/scuttlebutt", profile(Some(public_key))); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - debug!("Blocking Scuttlebutt peer"); - match sbot_client.block(public_key).await { - Ok(_) => Flash::success(Redirect::to(url), format!("Blocked peer")), - Err(e) => { - Flash::error(Redirect::to(url), format!("Failed to block peer: {}", e)) - } - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. Follow messages cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ); - } - Err(e) => return Flash::error(Redirect::to(url), e), - } -} - -// HELPERS AND ROUTES FOR /unblock - -/// Unblock a Scuttlebutt profile specified by the given public key. -/// Redirects to the appropriate profile page with a flash message describing -/// the outcome of the action (may be successful or unsuccessful). -#[post("/unblock", data = "")] -pub async fn unblock(peer: Form, _auth: Authenticated) -> Flash { - let public_key = &peer.public_key; - let url = uri!("/scuttlebutt", profile(Some(public_key))); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - debug!("Unblocking Scuttlebutt peer"); - match sbot_client.unblock(public_key).await { - Ok(_) => Flash::success(Redirect::to(url), format!("Unblocked peer")), - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to unblock peer: {}", e), - ), - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. Follow messages cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ); - } - Err(e) => return Flash::error(Redirect::to(url), e), - } -} - -// ROUTES FOR /profile - -/// A Scuttlebutt profile, specified by a public key. It may be our own profile -/// or the profile of a peer. If the public key query parameter is not provided, -/// the local profile is displayed (ie. the profile of the public key associated -/// with the local PeachCloud device). -#[get("/profile?")] -pub async fn profile( - mut public_key: Option, - flash: Option>, - _auth: Authenticated, -) -> Template { - // display a helpful message if the sbot is inactive - if let Ok(false) = is_sbot_active() { - // retrieve current ui theme - let theme = utils::get_theme(); - - let mut context = Context::new(); - context.insert("theme", &theme); - context.insert("back", &Some("/".to_string())); - context.insert("title", &Some("Profile".to_string())); - context.insert( - "unavailable_msg", - &Some("Profile data cannot be retrieved.".to_string()), - ); - - // render the "sbot is inactive" template - return Template::render("scuttlebutt/inactive", &context.into_json()); - } else { - if let Some(ref key) = public_key { - // `url_decode` replaces '+' with ' ', so we need to revert that - public_key = Some(key.replace(' ', "+")); - } - - // build the profile context object - let context = ProfileContext::build(public_key).await; - - match context { - // we were able to build the context without errors - Ok(mut context) => { - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.flash_name = Some(flash.kind().to_string()); - context.flash_msg = Some(flash.message().to_string()); - }; - - Template::render("scuttlebutt/profile", &context) - } - // an error occurred while building the context - Err(e) => { - // build the default context and pass along the error message - let mut context = ProfileContext::default(); - - // flash name and msg will be `Some` if the sbot is inactive (in - // that case, they are set by the context builder). - // otherwise, we need to assign the name and returned error msg - // to the flash. - if context.flash_name.is_none() || context.flash_msg.is_none() { - context.flash_name = Some("error".to_string()); - context.flash_msg = Some(e.to_string()); - } - - Template::render("scuttlebutt/profile", &context) - } - } - } -} - -// HELPERS AND ROUTES FOR /profile/update - -/// Serve a form for the purpose of updating the name, description and picture -/// for the local Scuttlebutt profile. -#[get("/profile/update")] -pub async fn update_profile(flash: Option>, _auth: Authenticated) -> Template { - // display a helpful message if the sbot is inactive - if let Ok(false) = is_sbot_active() { - // retrieve current ui theme - let theme = utils::get_theme(); - - let mut context = Context::new(); - context.insert("theme", &theme); - context.insert("back", &Some("/".to_string())); - context.insert("title", &Some("Profile".to_string())); - context.insert( - "unavailable_msg", - &Some("Profile data cannot be retrieved.".to_string()), - ); - - // render the "sbot is inactive" template - return Template::render("scuttlebutt/inactive", &context.into_json()); - } else { - // build the profile context object - let context = ProfileContext::build(None).await; - - match context { - // we were able to build the context without errors - Ok(mut context) => { - context.back = Some("/scuttlebutt/profile".to_string()); - - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.flash_name = Some(flash.kind().to_string()); - context.flash_msg = Some(flash.message().to_string()); - }; - - Template::render("scuttlebutt/update_profile", &context) - } - // an error occurred while building the context - Err(e) => { - // build the default context and pass along the error message - let mut context = ProfileContext::default(); - context.flash_name = Some("error".to_string()); - context.flash_msg = Some(e.to_string()); - - Template::render("scuttlebutt/update_profile", &context) - } - } - } -} - -#[derive(Debug, FromForm)] -pub struct Profile<'f> { - pub id: String, - pub current_name: String, - pub current_description: String, - pub new_name: String, - pub new_description: String, - pub image: TempFile<'f>, -} - -/// Update the name, description and picture for the local Scuttlebutt profile. -/// Redirects to profile page of the PeachCloud local identity with a flash -/// message describing the outcome of the action (may be successful or -/// unsuccessful). -#[post("/profile/update", data = "")] -pub async fn update_profile_post( - mut profile: Form>, - _auth: Authenticated, -) -> Flash { - let url = uri!("/scuttlebutt", update_profile); - - // we only want to try and interact with the sbot if it's active - match is_sbot_active() { - Ok(true) => { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - // initialise sbot connection with ip:port and shscap from config file - match scuttlebutt::init_sbot_with_config(&sbot_config).await { - Ok(mut sbot_client) => { - // track whether the name, description or image have been updated - let mut name_updated: bool = false; - let mut description_updated: bool = false; - let image_updated: bool; - - // only update the name if it has changed - if profile.new_name != profile.current_name { - debug!("Publishing new Scuttlebutt profile name"); - let publish_name_res = sbot_client.publish_name(&profile.new_name).await; - if publish_name_res.is_err() { - return Flash::error( - Redirect::to(url), - format!("Failed to update name: {}", publish_name_res.unwrap_err()), - ); - } else { - name_updated = true - } - } - - // only update the description if it has changed - if profile.new_description != profile.current_description { - debug!("Publishing new Scuttlebutt profile description"); - let publish_description_res = sbot_client - .publish_description(&profile.new_description) - .await; - - if publish_description_res.is_err() { - return Flash::error( - Redirect::to(url), - format!( - "Failed to update description: {}", - publish_description_res.unwrap_err() - ), - ); - } else { - description_updated = true - } - } - - // only update the image if a file was uploaded - if profile.image.name().is_some() { - match utils::write_blob_to_store(&mut profile.image).await { - Ok(blob_id) => { - // if the file was successfully added to the blobstore, - // publish an about image message with the blob id - let publish_image_res = sbot_client.publish_image(&blob_id).await; - - if publish_image_res.is_err() { - return Flash::error( - Redirect::to(url), - format!( - "Failed to update image: {}", - publish_image_res.unwrap_err() - ), - ); - } else { - image_updated = true - } - } - Err(e) => { - return Flash::error( - Redirect::to(url), - format!("Failed to add image to blobstore: {}", e), - ) - } - } - } else { - image_updated = false - } - - if name_updated || description_updated || image_updated { - return Flash::success(Redirect::to(url), "Profile updated"); - } else { - // no updates were made but no errors were encountered either - return Flash::success(Redirect::to(url), "Profile info unchanged"); - } - } - Err(e) => Flash::error( - Redirect::to(url), - format!("Failed to initialise sbot: {}", e), - ), - } - } - Ok(false) => { - return Flash::warning( - Redirect::to(url), - "The Sbot is inactive. Profile data cannot be updated. Visit the Scuttlebutt settings menu to start the Sbot and then try again", - ); - } - Err(e) => return Flash::error(Redirect::to(url), e), - } -} - -// HELPERS AND ROUTES FOR /friends - -/// A list of friends (mutual follows), with each list item displaying the -/// name, image and public key of the peer. -#[get("/friends")] -pub async fn friends(flash: Option>, _auth: Authenticated) -> Template { - // build the friends context object - let context = FriendsContext::build().await; - - match context { - // we were able to build the context without errors - Ok(mut context) => { - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.flash_name = Some(flash.kind().to_string()); - context.flash_msg = Some(flash.message().to_string()); - }; - - Template::render("scuttlebutt/peers_list", &context) - } - // an error occurred while building the context - Err(e) => { - // build the default context and pass along the error message - let mut context = FriendsContext::default(); - context.flash_name = Some("error".to_string()); - context.flash_msg = Some(e.to_string()); - - Template::render("scuttlebutt/peers_list", &context) - } - } -} - -// HELPERS AND ROUTES FOR /follows - -/// A list of follows (peers we follow who do not follow us), with each list item displaying the name, image and public -/// key of the peer. -#[get("/follows")] -pub async fn follows(flash: Option>, _auth: Authenticated) -> Template { - // build the follows context object - let context = FollowsContext::build().await; - - match context { - // we were able to build the context without errors - Ok(mut context) => { - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.flash_name = Some(flash.kind().to_string()); - context.flash_msg = Some(flash.message().to_string()); - }; - - Template::render("scuttlebutt/peers_list", &context) - } - // an error occurred while building the context - Err(e) => { - // build the default context and pass along the error message - let mut context = FollowsContext::default(); - context.flash_name = Some("error".to_string()); - context.flash_msg = Some(e.to_string()); - - Template::render("scuttlebutt/peers_list", &context) - } - } -} - -// HELPERS AND ROUTES FOR /blocks - -/// A list of blocks (peers we've blocked previously), with each list item -/// displaying the name, image and public key of the peer. -#[get("/blocks")] -pub async fn blocks(flash: Option>, _auth: Authenticated) -> Template { - // build the blocks context object - let context = BlocksContext::build().await; - - match context { - // we were able to build the context without errors - Ok(mut context) => { - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.flash_name = Some(flash.kind().to_string()); - context.flash_msg = Some(flash.message().to_string()); - }; - - Template::render("scuttlebutt/peers_list", &context) - } - // an error occurred while building the context - Err(e) => { - // build the default context and pass along the error message - let mut context = BlocksContext::default(); - context.flash_name = Some("error".to_string()); - context.flash_msg = Some(e.to_string()); - - Template::render("scuttlebutt/peers_list", &context) - } - } -}