add sbot utils, move theme utils and add flash message trait

This commit is contained in:
glyph 2022-03-20 12:26:04 +02:00
parent 31628a7155
commit 70f7ad0dc6
4 changed files with 387 additions and 0 deletions

View File

@ -0,0 +1,44 @@
use rouille::{input, Request, Response};
/// Flash message trait for `Request`.
pub trait FlashRequest {
/// Retrieve the flash message cookie values from a `Request`.
fn retrieve_flash(&self) -> (Option<&str>, Option<&str>);
}
impl FlashRequest for Request {
fn retrieve_flash(&self) -> (Option<&str>, Option<&str>) {
// check for flash cookies
let flash_name = input::cookies(&self)
.find(|&(n, _)| n == "flash_name")
// return the value of the cookie (key is already known)
.map(|key_val| key_val.1);
let flash_msg = input::cookies(&self)
.find(|&(n, _)| n == "flash_msg")
.map(|key_val| key_val.1);
(flash_name, flash_msg)
}
}
/// Flash message trait for `Response`.
pub trait FlashResponse {
/// Add flash message cookies to a `Response`.
fn add_flash(self, flash_name: String, flash_msg: String) -> Response;
/// Reset flash message cookie values for a `Response`.
fn reset_flash(self) -> Response;
}
impl FlashResponse for Response {
fn add_flash(self, flash_name: String, flash_msg: String) -> Response {
// set the flash cookie headers
self.with_additional_header("Set-Cookie", flash_name)
.with_additional_header("Set-Cookie", flash_msg)
}
fn reset_flash(self) -> Response {
// set blank cookies to clear the flash msg from the previous request
self.with_additional_header("Set-Cookie", "flash_name=")
.with_additional_header("Set-Cookie", "flash_msg=")
}
}

View File

@ -0,0 +1,3 @@
pub mod flash;
pub mod sbot;
pub mod theme;

206
peach-web/src/utils/sbot.rs Normal file
View File

@ -0,0 +1,206 @@
use std::io::prelude::*;
use std::{collections::HashMap, error::Error};
use std::{fs, fs::File, path::Path};
use async_std::task;
use dirs;
use futures::stream::TryStreamExt;
use golgi::{blobs, messages::SsbMessageValue, Sbot};
use log::info;
use peach_lib::sbot::SbotConfig;
use temporary::Directory;
use crate::error::PeachWebError;
// SBOT HELPER FUNCTIONS
pub async fn init_sbot_with_config(
sbot_config: &Option<SbotConfig>,
) -> Result<Sbot, PeachWebError> {
// initialise sbot connection with ip:port and shscap from config file
let sbot_client = match sbot_config {
// TODO: panics if we pass `Some(conf.shscap)` as second arg
Some(conf) => {
let ip_port = conf.lis.clone();
Sbot::init(Some(ip_port), None).await?
}
None => Sbot::init(None, None).await?,
};
Ok(sbot_client)
}
// FILEPATH FUNCTIONS
// return the path of the ssb-go directory
pub fn get_go_ssb_path() -> Result<String, PeachWebError> {
let go_ssb_path = match SbotConfig::read() {
Ok(conf) => conf.repo,
// return the default path if unable to read `config.toml`
Err(_) => {
// determine the home directory
let mut home_path = dirs::home_dir().ok_or_else(|| PeachWebError::HomeDir)?;
// add the go-ssb subdirectory
home_path.push(".ssb-go");
// convert the PathBuf to a String
home_path
.into_os_string()
.into_string()
.map_err(|_| PeachWebError::OsString)?
}
};
Ok(go_ssb_path)
}
// check whether a blob is in the blobstore
pub async fn blob_is_stored_locally(blob_path: &str) -> Result<bool, PeachWebError> {
let go_ssb_path = get_go_ssb_path()?;
let complete_path = format!("{}/blobs/sha256/{}", go_ssb_path, blob_path);
let blob_exists_locally = Path::new(&complete_path).exists();
Ok(blob_exists_locally)
}
/*
// take the path to a file, add it to the blobstore and return the blob id
pub async fn write_blob_to_store(file: &mut TempFile<'_>) -> Result<String, PeachWebError> {
// create temporary directory and path
let temp_dir = Directory::new("blob")?;
// we performed a `file.name().is_some()` check before calling `write_blob_to_store`
// so it should be safe to do a simple unwrap here
let filename = file.name().expect("retrieving filename from uploaded file");
let temp_path = temp_dir.join(filename);
// write file to temporary path
file.persist_to(&temp_path).await?;
// open the file and read it into a buffer
let mut file = File::open(&temp_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
// hash the bytes representing the file
let (hex_hash, blob_id) = blobs::hash_blob(&buffer)?;
// define the blobstore path and blob filename
let (blob_dir, blob_filename) = hex_hash.split_at(2);
let go_ssb_path = get_go_ssb_path()?;
let blobstore_sub_dir = format!("{}/blobs/sha256/{}", go_ssb_path, blob_dir);
// create the blobstore sub-directory
fs::create_dir_all(&blobstore_sub_dir)?;
// copy the file to the blobstore
let blob_path = format!("{}/{}", blobstore_sub_dir, blob_filename);
fs::copy(temp_path, blob_path)?;
Ok(blob_id)
}
*/
pub fn latest_sequence_number() -> Result<u64, Box<dyn Error>> {
// retrieve latest go-sbot configuration parameters
let sbot_config = SbotConfig::read().ok();
task::block_on(async {
let mut sbot_client = init_sbot_with_config(&sbot_config).await?;
// retrieve the local id
let id = sbot_client.whoami().await?;
let history_stream = sbot_client.create_history_stream(id).await?;
let mut msgs: Vec<SsbMessageValue> = history_stream.try_collect().await?;
// reverse the list of messages so we can easily reference the latest one
msgs.reverse();
// return the sequence number of the latest msg
Ok(msgs[0].sequence)
})
}
pub fn get_blocks_list() -> Result<Vec<HashMap<String, String>>, Box<dyn Error>> {
// retrieve latest go-sbot configuration parameters
let sbot_config = SbotConfig::read().ok();
task::block_on(async {
let mut sbot_client = init_sbot_with_config(&sbot_config).await?;
let blocks = sbot_client.get_blocks().await?;
// we'll use this to store the profile info for each peer whom we block
let mut peer_list = Vec::new();
if !blocks.is_empty() {
for peer in blocks.iter() {
// trim whitespace (including newline characters) and
// remove the inverted-commas around the id
let key = peer.trim().replace('"', "");
// retrieve the profile info for the given peer
let mut peer_info = sbot_client.get_profile_info(&key).await?;
// insert the public key of the peer into the info hashmap
peer_info.insert("id".to_string(), key.to_string());
// we do not even attempt to find the blob for a blocked peer,
// since it may be vulgar to cause distress to the local peer.
peer_info.insert("blob_exists".to_string(), "false".to_string());
// push profile info to peer_list vec
peer_list.push(peer_info)
}
}
// return the list of blocked peers
Ok(peer_list)
})
}
pub fn get_follows_list() -> Result<Vec<HashMap<String, String>>, Box<dyn Error>> {
// retrieve latest go-sbot configuration parameters
let sbot_config = SbotConfig::read().ok();
task::block_on(async {
let mut sbot_client = init_sbot_with_config(&sbot_config).await?;
let follows = sbot_client.get_follows().await?;
// we'll use this to store the profile info for each peer who follows us
let mut peer_list = Vec::new();
if !follows.is_empty() {
for peer in follows.iter() {
// trim whitespace (including newline characters) and
// remove the inverted-commas around the id
let key = peer.trim().replace('"', "");
// retrieve the profile info for the given peer
let mut peer_info = sbot_client.get_profile_info(&key).await?;
// insert the public key of the peer into the info hashmap
peer_info.insert("id".to_string(), key.to_string());
// retrieve the profile image blob id for the given peer
if let Some(blob_id) = peer_info.get("image") {
// look-up the path for the image blob
if let Ok(blob_path) = blobs::get_blob_path(&blob_id) {
// insert the image blob path of the peer into the info hashmap
peer_info.insert("blob_path".to_string(), blob_path.to_string());
// check if the blob is in the blobstore
// set a flag in the info hashmap
match blob_is_stored_locally(&blob_path).await {
Ok(exists) if exists == true => {
peer_info.insert("blob_exists".to_string(), "true".to_string())
}
_ => peer_info.insert("blob_exists".to_string(), "false".to_string()),
};
}
}
// push profile info to peer_list vec
peer_list.push(peer_info)
}
}
// return the list of peers
Ok(peer_list)
})
}
pub fn get_friends_list() -> Result<Vec<String>, Box<dyn Error>> {
// retrieve latest go-sbot configuration parameters
let sbot_config = SbotConfig::read().ok();
task::block_on(async {
let mut sbot_client = init_sbot_with_config(&sbot_config).await?;
// return the sequence number of the latest msg
//Ok(msgs[0].sequence)
Ok(vec!["temp".to_string()])
})
}

View File

@ -0,0 +1,134 @@
use log::info;
use crate::THEME;
// THEME FUNCTIONS
#[derive(Debug, Copy, Clone)]
pub enum Theme {
Light,
Dark,
}
pub fn get_theme() -> String {
let current_theme = THEME.read().unwrap();
match *current_theme {
Theme::Dark => "dark".to_string(),
_ => "light".to_string(),
}
}
pub fn set_theme(theme: Theme) {
info!("set ui theme to: {:?}", theme);
let mut writable_theme = THEME.write().unwrap();
*writable_theme = theme;
}
// get_cookie
// set_cookie
/*
pub mod monitor;
use std::io::prelude::*;
use std::{fs, fs::File, path::Path};
use dirs;
use golgi::blobs;
use log::info;
use peach_lib::sbot::SbotConfig;
use rocket::{
fs::TempFile,
response::{Redirect, Responder},
serde::Serialize,
};
use rocket_dyn_templates::Template;
use temporary::Directory;
use crate::{error::PeachWebError, THEME};
// FILEPATH FUNCTIONS
// return the path of the ssb-go directory
pub fn get_go_ssb_path() -> Result<String, PeachWebError> {
let go_ssb_path = match SbotConfig::read() {
Ok(conf) => conf.repo,
// return the default path if unable to read `config.toml`
Err(_) => {
// determine the home directory
let mut home_path = dirs::home_dir().ok_or_else(|| PeachWebError::HomeDir)?;
// add the go-ssb subdirectory
home_path.push(".ssb-go");
// convert the PathBuf to a String
home_path
.into_os_string()
.into_string()
.map_err(|_| PeachWebError::OsString)?
}
};
Ok(go_ssb_path)
}
// check whether a blob is in the blobstore
pub async fn blob_is_stored_locally(blob_path: &str) -> Result<bool, PeachWebError> {
let go_ssb_path = get_go_ssb_path()?;
let complete_path = format!("{}/blobs/sha256/{}", go_ssb_path, blob_path);
let blob_exists_locally = Path::new(&complete_path).exists();
Ok(blob_exists_locally)
}
// take the path to a file, add it to the blobstore and return the blob id
pub async fn write_blob_to_store(file: &mut TempFile<'_>) -> Result<String, PeachWebError> {
// create temporary directory and path
let temp_dir = Directory::new("blob")?;
// we performed a `file.name().is_some()` check before calling `write_blob_to_store`
// so it should be safe to do a simple unwrap here
let filename = file.name().expect("retrieving filename from uploaded file");
let temp_path = temp_dir.join(filename);
// write file to temporary path
file.persist_to(&temp_path).await?;
// open the file and read it into a buffer
let mut file = File::open(&temp_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
// hash the bytes representing the file
let (hex_hash, blob_id) = blobs::hash_blob(&buffer)?;
// define the blobstore path and blob filename
let (blob_dir, blob_filename) = hex_hash.split_at(2);
let go_ssb_path = get_go_ssb_path()?;
let blobstore_sub_dir = format!("{}/blobs/sha256/{}", go_ssb_path, blob_dir);
// create the blobstore sub-directory
fs::create_dir_all(&blobstore_sub_dir)?;
// copy the file to the blobstore
let blob_path = format!("{}/{}", blobstore_sub_dir, blob_filename);
fs::copy(temp_path, blob_path)?;
Ok(blob_id)
}
// HELPER FUNCTIONS
#[derive(Debug, Serialize)]
pub struct FlashContext {
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
}
/// A helper enum which allows routes to either return a Template or a Redirect
/// from: https://github.com/SergioBenitez/Rocket/issues/253#issuecomment-532356066
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Responder)]
pub enum TemplateOrRedirect {
Template(Template),
Redirect(Redirect),
}
*/