Add SSB routes for newly added templates #27
@ -30,15 +30,15 @@ pub mod routes;
|
|||||||
mod tests;
|
mod tests;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
use log::{info, error};
|
use log::{error, info};
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use rocket::{catchers, routes, Rocket, Build, fs::FileServer};
|
use rocket::{catchers, fs::FileServer, routes, Build, Rocket};
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
|
|
||||||
use crate::routes::authentication::*;
|
use crate::routes::authentication::*;
|
||||||
use crate::routes::device::*;
|
|
||||||
use crate::routes::catchers::*;
|
use crate::routes::catchers::*;
|
||||||
|
use crate::routes::device::*;
|
||||||
use crate::routes::index::*;
|
use crate::routes::index::*;
|
||||||
use crate::routes::ping::*;
|
use crate::routes::ping::*;
|
||||||
use crate::routes::scuttlebutt::*;
|
use crate::routes::scuttlebutt::*;
|
||||||
@ -47,12 +47,27 @@ use crate::routes::settings::admin::*;
|
|||||||
use crate::routes::settings::dns::*;
|
use crate::routes::settings::dns::*;
|
||||||
use crate::routes::settings::network::*;
|
use crate::routes::settings::network::*;
|
||||||
|
|
||||||
|
|
||||||
pub type BoxError = Box<dyn std::error::Error>;
|
pub type BoxError = Box<dyn std::error::Error>;
|
||||||
|
|
||||||
/// Create rocket instance & mount all routes.
|
/// Create rocket instance & mount all routes.
|
||||||
fn init_rocket() -> Rocket<Build> {
|
fn init_rocket() -> Rocket<Build> {
|
||||||
rocket::build()
|
rocket::build()
|
||||||
|
.mount(
|
||||||
|
"/scuttlebutt",
|
||||||
|
routes![
|
||||||
|
peers, // WEB ROUTE
|
||||||
|
friends, // WEB ROUTE
|
||||||
|
follows, // WEB ROUTE
|
||||||
|
followers, // WEB ROUTE
|
||||||
|
blocks, // WEB ROUTE
|
||||||
|
profile, // WEB ROUTE
|
||||||
|
private, // WEB ROUTE
|
||||||
|
follow, // WEB ROUTE
|
||||||
|
unfollow, // WEB ROUTE
|
||||||
|
block, // WEB ROUTE
|
||||||
|
publish, // WEB ROUTE
|
||||||
|
],
|
||||||
|
)
|
||||||
.mount(
|
.mount(
|
||||||
"/",
|
"/",
|
||||||
routes![
|
routes![
|
||||||
@ -68,13 +83,10 @@ fn init_rocket() -> Rocket<Build> {
|
|||||||
login, // WEB ROUTE
|
login, // WEB ROUTE
|
||||||
login_post, // WEB ROUTE
|
login_post, // WEB ROUTE
|
||||||
logout, // WEB ROUTE
|
logout, // WEB ROUTE
|
||||||
messages, // WEB ROUTE
|
|
||||||
network_home, // WEB ROUTE
|
network_home, // WEB ROUTE
|
||||||
network_add_ssid, // WEB ROUTE
|
network_add_ssid, // WEB ROUTE
|
||||||
network_add_wifi, // WEB ROUTE
|
network_add_wifi, // WEB ROUTE
|
||||||
network_detail, // WEB ROUTE
|
network_detail, // WEB ROUTE
|
||||||
peers, // WEB ROUTE
|
|
||||||
profile, // WEB ROUTE
|
|
||||||
reboot_cmd, // WEB ROUTE
|
reboot_cmd, // WEB ROUTE
|
||||||
shutdown_cmd, // WEB ROUTE
|
shutdown_cmd, // WEB ROUTE
|
||||||
shutdown_menu, // WEB ROUTE
|
shutdown_menu, // WEB ROUTE
|
||||||
@ -130,7 +142,6 @@ fn init_rocket() -> Rocket<Build> {
|
|||||||
/// Launch the peach-web rocket server.
|
/// Launch the peach-web rocket server.
|
||||||
#[rocket::main]
|
#[rocket::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
|
||||||
// initialize logger
|
// initialize logger
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
@ -140,7 +151,7 @@ async fn main() {
|
|||||||
|
|
||||||
// launch rocket
|
// launch rocket
|
||||||
info!("Launching Rocket");
|
info!("Launching Rocket");
|
||||||
if let Err(e) = rocket.launch().await {
|
if let Err(e) = rocket.launch().await {
|
||||||
error!("Error in Rocket application: {}", e);
|
error!("Error in Rocket application: {}", e);
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,30 @@
|
|||||||
//! Routes for ScuttleButt related functionality.
|
//! Routes for Scuttlebutt related functionality.
|
||||||
|
|
||||||
use rocket::{get, request::FlashMessage};
|
use rocket::{
|
||||||
|
form::{Form, FromForm},
|
||||||
|
get, post,
|
||||||
|
request::FlashMessage,
|
||||||
|
response::{Flash, Redirect},
|
||||||
|
serde::{Deserialize, Serialize},
|
||||||
|
uri,
|
||||||
|
};
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
use crate::routes::authentication::Authenticated;
|
use crate::routes::authentication::Authenticated;
|
||||||
|
|
||||||
// HELPERS AND ROUTES FOR /messages
|
// HELPERS AND ROUTES FOR /private
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct MessageContext {
|
pub struct PrivateContext {
|
||||||
pub back: Option<String>,
|
pub back: Option<String>,
|
||||||
pub flash_name: Option<String>,
|
pub flash_name: Option<String>,
|
||||||
pub flash_msg: Option<String>,
|
pub flash_msg: Option<String>,
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageContext {
|
impl PrivateContext {
|
||||||
pub fn build() -> MessageContext {
|
pub fn build() -> PrivateContext {
|
||||||
MessageContext {
|
PrivateContext {
|
||||||
back: None,
|
back: None,
|
||||||
flash_name: None,
|
flash_name: None,
|
||||||
flash_msg: None,
|
flash_msg: None,
|
||||||
@ -27,9 +33,10 @@ impl MessageContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/messages")]
|
/// A private message composition and publication page.
|
||||||
pub fn messages(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
#[get("/private")]
|
||||||
let mut context = MessageContext::build();
|
pub fn private(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||||
|
let mut context = PrivateContext::build();
|
||||||
context.back = Some("/".to_string());
|
context.back = Some("/".to_string());
|
||||||
context.title = Some("Private Messages".to_string());
|
context.title = Some("Private Messages".to_string());
|
||||||
// check to see if there is a flash message to display
|
// check to see if there is a flash message to display
|
||||||
@ -62,6 +69,7 @@ impl PeerContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A peer menu which allows navigating to lists of friends, follows, followers and blocks.
|
||||||
#[get("/peers")]
|
#[get("/peers")]
|
||||||
pub fn peers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
pub fn peers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||||
let mut context = PeerContext::build();
|
let mut context = PeerContext::build();
|
||||||
@ -76,6 +84,94 @@ pub fn peers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
|||||||
Template::render("peers", &context)
|
Template::render("peers", &context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HELPERS AND ROUTES FOR /post/publish
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, 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 fn publish(
|
||||||
|
post: Form<Post>,
|
||||||
|
flash: Option<FlashMessage>,
|
||||||
|
_auth: Authenticated,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
let post_text = &post.text;
|
||||||
|
// perform the sbotcli publish action using post_text
|
||||||
|
// if successful, redirect to home profile page and flash "success"
|
||||||
|
// if error, redirect to home profile page and flash "error"
|
||||||
|
// redirect to the profile template without public key ("home" / local profile)
|
||||||
|
let pub_key: std::option::Option<&str> = None;
|
||||||
|
let profile_url = uri!(profile(pub_key));
|
||||||
|
// consider adding the message reference to the flash message (or render it in the template for
|
||||||
|
// `profile`
|
||||||
|
Flash::success(Redirect::to(profile_url), "Published public post")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HELPERS AND ROUTES FOR /follow
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, FromForm)]
|
||||||
|
pub struct PublicKey {
|
||||||
|
pub key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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_key>")]
|
||||||
|
pub fn follow(
|
||||||
|
pub_key: Form<PublicKey>,
|
||||||
|
flash: Option<FlashMessage>,
|
||||||
|
_auth: Authenticated,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
let public_key = &pub_key.key;
|
||||||
|
// perform the sbotcli follow action using &pub_key.0
|
||||||
|
// if successful, redirect to profile page with provided public key and flash "success"
|
||||||
|
// if error, redirect to profile page with provided public key and flash "error"
|
||||||
|
// redirect to the profile template with provided public key
|
||||||
|
let profile_url = uri!(profile(Some(public_key)));
|
||||||
|
let success_msg = format!("Followed {}", public_key);
|
||||||
|
Flash::success(Redirect::to(profile_url), success_msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_key>")]
|
||||||
|
pub fn unfollow(
|
||||||
|
pub_key: Form<PublicKey>,
|
||||||
|
flash: Option<FlashMessage>,
|
||||||
|
_auth: Authenticated,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
let public_key = &pub_key.key;
|
||||||
|
// perform the sbotcli unfollow action using &pub_key.0
|
||||||
|
// if successful, redirect to profile page with provided public key and flash "success"
|
||||||
|
// if error, redirect to profile page with provided public key and flash "error"
|
||||||
|
// redirect to the profile template with provided public key
|
||||||
|
let profile_url = uri!(profile(Some(public_key)));
|
||||||
|
let success_msg = format!("Unfollowed {}", public_key);
|
||||||
|
Flash::success(Redirect::to(profile_url), success_msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_key>")]
|
||||||
|
pub fn block(
|
||||||
|
pub_key: Form<PublicKey>,
|
||||||
|
flash: Option<FlashMessage>,
|
||||||
|
_auth: Authenticated,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
let public_key = &pub_key.key;
|
||||||
|
// perform the sbotcli block action using &pub_key.0
|
||||||
|
// if successful, redirect to profile page with provided public key and flash "success"
|
||||||
|
// if error, redirect to profile page with provided public key and flash "error"
|
||||||
|
// redirect to the profile template with provided public key
|
||||||
|
let profile_url = uri!(profile(Some(public_key)));
|
||||||
|
let success_msg = format!("Blocked {}", public_key);
|
||||||
|
Flash::success(Redirect::to(profile_url), success_msg)
|
||||||
|
}
|
||||||
|
|
||||||
// HELPERS AND ROUTES FOR /profile
|
// HELPERS AND ROUTES FOR /profile
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -97,8 +193,13 @@ impl ProfileContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/profile")]
|
/// A Scuttlebutt profile, specified by a public key. It may be our own profile or the profile of a peer. If not public key query parameter is provided, the local profile is displayed (ie. the profile of the public key associated with the local PeachCloud device).
|
||||||
pub fn profile(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
#[get("/profile?<pub_key>")]
|
||||||
|
pub fn profile(
|
||||||
|
pub_key: Option<&str>,
|
||||||
|
flash: Option<FlashMessage>,
|
||||||
|
_auth: Authenticated,
|
||||||
|
) -> Template {
|
||||||
let mut context = ProfileContext::build();
|
let mut context = ProfileContext::build();
|
||||||
context.back = Some("/".to_string());
|
context.back = Some("/".to_string());
|
||||||
context.title = Some("Profile".to_string());
|
context.title = Some("Profile".to_string());
|
||||||
@ -110,3 +211,155 @@ pub fn profile(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
|||||||
};
|
};
|
||||||
Template::render("profile", &context)
|
Template::render("profile", &context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HELPERS AND ROUTES FOR /friends
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct FriendsContext {
|
||||||
|
pub back: Option<String>,
|
||||||
|
pub flash_name: Option<String>,
|
||||||
|
pub flash_msg: Option<String>,
|
||||||
|
pub title: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FriendsContext {
|
||||||
|
pub fn build() -> FriendsContext {
|
||||||
|
FriendsContext {
|
||||||
|
back: None,
|
||||||
|
flash_name: None,
|
||||||
|
flash_msg: None,
|
||||||
|
title: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A list of friends (mutual follows), with each list item displaying the name, image and public
|
||||||
|
/// key of the peer.
|
||||||
|
#[get("/friends")]
|
||||||
|
pub fn friends(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||||
|
let mut context = FriendsContext::build();
|
||||||
|
context.back = Some("/scuttlebutt/peers".to_string());
|
||||||
|
context.title = Some("Friends".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("peers_list", &context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HELPERS AND ROUTES FOR /follows
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct FollowsContext {
|
||||||
|
pub back: Option<String>,
|
||||||
|
pub flash_name: Option<String>,
|
||||||
|
pub flash_msg: Option<String>,
|
||||||
|
pub title: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FollowsContext {
|
||||||
|
pub fn build() -> FollowsContext {
|
||||||
|
FollowsContext {
|
||||||
|
back: None,
|
||||||
|
flash_name: None,
|
||||||
|
flash_msg: None,
|
||||||
|
title: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 fn follows(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||||
|
let mut context = FollowsContext::build();
|
||||||
|
context.back = Some("/scuttlebutt/peers".to_string());
|
||||||
|
context.title = Some("Follows".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("peers_list", &context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HELPERS AND ROUTES FOR /followers
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct FollowersContext {
|
||||||
|
pub back: Option<String>,
|
||||||
|
pub flash_name: Option<String>,
|
||||||
|
pub flash_msg: Option<String>,
|
||||||
|
pub title: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FollowersContext {
|
||||||
|
pub fn build() -> FollowersContext {
|
||||||
|
FollowersContext {
|
||||||
|
back: None,
|
||||||
|
flash_name: None,
|
||||||
|
flash_msg: None,
|
||||||
|
title: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A list of followers (peers who follow us but who we do not follow), with each list item displaying the name, image and public
|
||||||
|
/// key of the peer.
|
||||||
|
#[get("/followers")]
|
||||||
|
pub fn followers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||||
|
let mut context = FollowersContext::build();
|
||||||
|
context.back = Some("/scuttlebutt/peers".to_string());
|
||||||
|
context.title = Some("Followers".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("peers_list", &context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HELPERS AND ROUTES FOR /blocks
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct BlocksContext {
|
||||||
|
pub back: Option<String>,
|
||||||
|
pub flash_name: Option<String>,
|
||||||
|
pub flash_msg: Option<String>,
|
||||||
|
pub title: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlocksContext {
|
||||||
|
pub fn build() -> BlocksContext {
|
||||||
|
BlocksContext {
|
||||||
|
back: None,
|
||||||
|
flash_name: None,
|
||||||
|
flash_msg: None,
|
||||||
|
title: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 fn blocks(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||||
|
let mut context = BlocksContext::build();
|
||||||
|
context.back = Some("/scuttlebutt/peers".to_string());
|
||||||
|
context.title = Some("Blocks".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("peers_list", &context)
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use rocket::serde::json::{Value, json};
|
|
||||||
use rocket::http::{ContentType, Status};
|
use rocket::http::{ContentType, Status};
|
||||||
use rocket::local::blocking::Client;
|
use rocket::local::blocking::Client;
|
||||||
|
use rocket::serde::json::{json, Value};
|
||||||
|
|
||||||
use crate::utils::build_json_response;
|
use crate::utils::build_json_response;
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ fn index_html() {
|
|||||||
let body = response.into_string().unwrap();
|
let body = response.into_string().unwrap();
|
||||||
assert!(body.contains("/peers"));
|
assert!(body.contains("/peers"));
|
||||||
assert!(body.contains("/profile"));
|
assert!(body.contains("/profile"));
|
||||||
assert!(body.contains("/messages"));
|
assert!(body.contains("/private"));
|
||||||
assert!(body.contains("/device"));
|
assert!(body.contains("/device"));
|
||||||
assert!(body.contains("/help"));
|
assert!(body.contains("/help"));
|
||||||
assert!(body.contains("/network"));
|
assert!(body.contains("/network"));
|
||||||
@ -154,9 +154,9 @@ fn login_html() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn messages_html() {
|
fn private_html() {
|
||||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
let response = client.get("/messages").dispatch();
|
let response = client.get("/scuttlebutt/private").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||||
let body = response.into_string().unwrap();
|
let body = response.into_string().unwrap();
|
||||||
@ -166,17 +166,102 @@ fn messages_html() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn peers_html() {
|
fn peers_html() {
|
||||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
let response = client.get("/peers").dispatch();
|
let response = client.get("/scuttlebutt/peers").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||||
let body = response.into_string().unwrap();
|
let body = response.into_string().unwrap();
|
||||||
assert!(body.contains("Scuttlebutt Peers"));
|
assert!(body.contains("Scuttlebutt Peers"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn friends_html() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client.get("/scuttlebutt/friends").dispatch();
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||||
|
let body = response.into_string().unwrap();
|
||||||
|
assert!(body.contains("Friends"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn follows_html() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client.get("/scuttlebutt/follows").dispatch();
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||||
|
let body = response.into_string().unwrap();
|
||||||
|
assert!(body.contains("Follows"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn followers_html() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client.get("/scuttlebutt/followers").dispatch();
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||||
|
let body = response.into_string().unwrap();
|
||||||
|
assert!(body.contains("Followers"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_html() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client.get("/scuttlebutt/blocks").dispatch();
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||||
|
let body = response.into_string().unwrap();
|
||||||
|
assert!(body.contains("Blocks"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn follow() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client
|
||||||
|
.post("/scuttlebutt/follow")
|
||||||
|
.header(ContentType::Form)
|
||||||
|
.body("key=@HEqy940T6uB+T+d9Jaa58aNfRzLx9eRWqkZljBmnkmk=.ed25519")
|
||||||
|
.dispatch();
|
||||||
|
// ensure we redirect (303)
|
||||||
|
assert_eq!(response.status(), Status::SeeOther);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unfollow() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client
|
||||||
|
.post("/scuttlebutt/unfollow")
|
||||||
|
.header(ContentType::Form)
|
||||||
|
.body("key=@HEqy940T6uB+T+d9Jaa58aNfRzLx9eRWqkZljBmnkmk=.ed25519")
|
||||||
|
.dispatch();
|
||||||
|
assert_eq!(response.status(), Status::SeeOther);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client
|
||||||
|
.post("/scuttlebutt/block")
|
||||||
|
.header(ContentType::Form)
|
||||||
|
.body("key=HEqy940T6uB+T+d9Jaa58aNfRzLx9eRWqkZljBmnkmk=.ed25519")
|
||||||
|
.dispatch();
|
||||||
|
assert_eq!(response.status(), Status::SeeOther);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn publish_post() {
|
||||||
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
|
let response = client
|
||||||
|
.post("/scuttlebutt/publish")
|
||||||
|
.header(ContentType::Form)
|
||||||
|
.body("text='golden ripples in the meshwork'")
|
||||||
|
.dispatch();
|
||||||
|
assert_eq!(response.status(), Status::SeeOther);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn profile_html() {
|
fn profile_html() {
|
||||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||||
let response = client.get("/profile").dispatch();
|
let response = client.get("/scuttlebutt/profile").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||||
let body = response.into_string().unwrap();
|
let body = response.into_string().unwrap();
|
||||||
@ -432,7 +517,6 @@ fn test_build_json_response() {
|
|||||||
assert_eq!(j["msg"], json!(null));
|
assert_eq!(j["msg"], json!(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FILE TESTS
|
// FILE TESTS
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -4,21 +4,21 @@
|
|||||||
<div class="grid">
|
<div class="grid">
|
||||||
<!-- top-left -->
|
<!-- top-left -->
|
||||||
<!-- PEERS LINK AND ICON -->
|
<!-- PEERS LINK AND ICON -->
|
||||||
<a class="top-left" href="/peers" title="Scuttlebutt Peers">
|
<a class="top-left" href="/scuttlebutt/peers" title="Scuttlebutt Peers">
|
||||||
<div class="circle circle-small">
|
<div class="circle circle-small">
|
||||||
<img class="icon-medium" src="icons/users.svg">
|
<img class="icon-medium" src="icons/users.svg">
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<!-- top-middle -->
|
<!-- top-middle -->
|
||||||
<!-- CURRENT USER LINK AND ICON -->
|
<!-- CURRENT USER LINK AND ICON -->
|
||||||
<a class="top-middle" href="/profile" title="Profile">
|
<a class="top-middle" href="/scuttlebutt/profile" title="Profile">
|
||||||
<div class="circle circle-small">
|
<div class="circle circle-small">
|
||||||
<img class="icon-medium" src="icons/user.svg">
|
<img class="icon-medium" src="icons/user.svg">
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<!-- top-right -->
|
<!-- top-right -->
|
||||||
<!-- MESSAGES LINK AND ICON -->
|
<!-- MESSAGES LINK AND ICON -->
|
||||||
<a class="top-right" href="/messages" title="Private Messages">
|
<a class="top-right" href="/scuttlebutt/private" title="Private Messages">
|
||||||
<div class="circle circle-small">
|
<div class="circle circle-small">
|
||||||
<img class="icon-medium" src="icons/envelope.svg">
|
<img class="icon-medium" src="icons/envelope.svg">
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
<input id="publishPost" class="button button-primary center" title="Publish" type="submit" value="Publish">
|
<input id="publishPost" class="button button-primary center" title="Publish" type="submit" value="Publish">
|
||||||
</form>
|
</form>
|
||||||
<!-- BUTTONS -->
|
<!-- BUTTONS -->
|
||||||
|
<!-- TODO: each of these buttons needs to be a form with a public key -->
|
||||||
<div id="buttons">
|
<div id="buttons">
|
||||||
<a id="followPeer" class="button button-primary center" href="/scuttlebutt/follow" title="Follow Peer">Follow</a>
|
<a id="followPeer" class="button button-primary center" href="/scuttlebutt/follow" title="Follow Peer">Follow</a>
|
||||||
<a id="blockPeer" class="button button-warning center" href="/scuttlebutt/block" title="Block Peer">Block</a>
|
<a id="blockPeer" class="button button-warning center" href="/scuttlebutt/block" title="Block Peer">Block</a>
|
||||||
|
Reference in New Issue
Block a user