remove old scuttlebutt routes file

This commit is contained in:
glyph 2022-03-18 11:33:27 +02:00
parent 3c49c067dd
commit 31628a7155
1 changed files with 0 additions and 946 deletions

View File

@ -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<bool, String> {
// 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<Redirect>> {
// 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<FlashMessage>, _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 = "<invite>")]
pub async fn create_invite(invite: Form<Invite>, _auth: Authenticated) -> Flash<Redirect> {
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?<public_key>")]
pub async fn private(
mut public_key: Option<String>,
flash: Option<FlashMessage<'_>>,
_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 = "<private>")]
pub async fn private_post(private: Form<Private>, _auth: Authenticated) -> Flash<Redirect> {
let url = uri!("/scuttlebutt", private(None::<String>));
// 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<FlashMessage>, _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 = "<peer>")]
pub async fn search_post(peer: Form<Peer>, _auth: Authenticated) -> Flash<Redirect> {
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<FlashMessage>, _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 = "<post>")]
pub async fn publish(post: Form<Post>, _auth: Authenticated) -> Flash<Redirect> {
let post_text = &post.text;
let url = uri!("/scuttlebutt", profile(None::<String>));
// 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 = "<peer>")]
pub async fn follow(peer: Form<Peer>, _auth: Authenticated) -> Flash<Redirect> {
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 = "<peer>")]
pub async fn unfollow(peer: Form<Peer>, _auth: Authenticated) -> Flash<Redirect> {
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 = "<peer>")]
pub async fn block(peer: Form<Peer>, _auth: Authenticated) -> Flash<Redirect> {
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 = "<peer>")]
pub async fn unblock(peer: Form<Peer>, _auth: Authenticated) -> Flash<Redirect> {
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?<public_key>")]
pub async fn profile(
mut public_key: Option<String>,
flash: Option<FlashMessage<'_>>,
_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<FlashMessage<'_>>, _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 = "<profile>")]
pub async fn update_profile_post(
mut profile: Form<Profile<'_>>,
_auth: Authenticated,
) -> Flash<Redirect> {
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<FlashMessage<'_>>, _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<FlashMessage<'_>>, _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<FlashMessage<'_>>, _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)
}
}
}