Boarders/src/html/boards.rs
saw 38a42fdbe3 Removed browser dependant CSS, board description
I removed some browser dependant CSS that I mistakenly put in.
Everything now renders correctly on FF browsers.

I added the board description to the board view so you can see the board
topic while looking at the board.
2021-06-04 12:21:42 -04:00

274 lines
7.9 KiB
Rust

use std::{
time,
time::Duration,
path::PathBuf
};
use actix_web::{
get, post, web,
HttpResponse, Responder, HttpRequest, HttpMessage
};
use crate::{
lib::{
boards::Board,
users::{UserCookie, User}
},
api::types::*
};
#[get("/boards/")]
pub async fn list_boards(
data: web::Data<AppState>,
) -> impl Responder {
let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
let mut ab = false;
let boards = (*data.boards.lock().unwrap()).clone();
HttpResponse::Ok().body(format!(
r#"
<html><head>
<link rel="stylesheet" type="text/css" href="https://orbitalfox.us/Music/index.css">
<link rel="stylesheet" type="text/css" href="/static/index.css">
</head><body>
<div id="title" class="bar">
<div>
<h1>Board Index</h1>
</div>
<div id="login-status">
<p><a href="/account/login/">Login</a>/<a href="/account/new/">Sign Up</a></p>
</div>
</div><div id="index">
<a href="/boards/new/" style="margin-bottom: 0.5em;">New Board [+]</a>
<table style="width: 100%;" cellpadding=8px>
<tr><th>Name</th><th>Description</th><th>Last Active</th></tr>
{}
</table></body></html></div></body></html>
"#,
boards.iter().map(|b| {
ab = !ab;
format!(
"<tr class=\"{}\"><td><a href=\"/board/{}/\">{}</a></td><td>{}</td><td>{}</td></tr>",
if ab { "a" } else { "b" }, b.id, b.title, b.desc,
if let Some(a) = b.messages.borrow().last() {
format!("{:.2} minutes", now.checked_sub(Duration::from_secs(a.timestamp)).unwrap().as_secs()/60)
} else {
String::from("Never")
}
)
}).collect::<String>()
))
}
#[get("/board/{board_id}/")]
pub async fn get_board(
req: HttpRequest,
data: web::Data<AppState>,
web::Path(board_id): web::Path<u32>
) -> HttpResponse {
let mut ab = false;
let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
let boards = data.boards.lock().unwrap();
let cookie = req.cookie("auth");
let uid = if cookie.is_some() {
UserCookie::parse(cookie.unwrap().value())
} else {
UserCookie::parse("null")
};
if let Some(a) = Board::search(boards.iter(), board_id) {
HttpResponse::Ok().body(format!(
r#"
<html><head>
<link rel="stylesheet" type="text/css" href="https://orbitalfox.us/Music/index.css">
<link rel="stylesheet" type="text/css" href="/static/index.css">
</head>
<body>
<div id="title" class="bar">
<div><h1>
{} | <a href="/boards/"><- Back to index</a>
</h1></div>
<div id="description">
{}
</div>
<div id="login-status">
<p><a href="/account/login/">Login</a>/<a href="/account/new/">Sign Up</a></p>
</div>
</div>
<div id="index">
<table style="width: 100%;" cellpadding=8px>
{}
</table>
<form action="/boards/post" method="post">
<label for="content">Content:</label><br/>
<input type="hidden" id="board_id" name="board_id" value="{}">
<input type="hidden" id="user_id" name="user_id" value="{}">
<textarea name="content" id="content" rows=12 cols=50 placeholder="Enter message here..."></textarea>
<br/><input type="submit" value="Post Message" style="margin: 0.5em;">
</form>
</div></body></html>
"#,
a.title,
a.desc,
a.messages.borrow().iter().map(|x| {
ab = !ab;
format!(
"<tr class=\"message {}\"><td>{}</td><td>{}</td><td>{}</td></tr>",
if ab { "a" } else { "b" },
{
let author = x.author.clone().into_inner();
author.nick.clone().or_else(|| Some(author.username.clone())).unwrap()
},
x.text.replace('\n', "<br>"),
format!("{:.2} min.", now.checked_sub(Duration::from_secs(x.timestamp)).unwrap().as_secs()/60)//x.timestamp
)
}).collect::<String>(),
board_id,
match uid {
Ok(a) => a.id.to_string(),
Err(_e) => "null".to_string()
}
))
} else {
HttpResponse::NotFound().body("That board could not be found")
}
}
#[post("/boards/post")]
pub async fn board_post(
req: HttpRequest,
form: web::Form<MessageForm>,
data: web::Data<AppState>
) -> Result<HttpResponse, HttpResponse> {
let cookie = req.cookie("auth");
if cookie.is_none() {
return Err(HttpResponse::Unauthorized().body("Unauthorized: You are not logged in"));
}
let cookie = match UserCookie::parse(cookie.unwrap().value()) {
Ok(a) => a,
Err(e) => {
println!("{}", e);
return Err(HttpResponse::BadRequest().body("Bad Request: Could not parse cookie data"));
}
};
let mut mf = data.msg_factory.lock().unwrap();
let b = data.boards.lock().unwrap();
let board = b.iter().find(|x| (x.id == form.board_id));
let um = data.user_manager.lock().unwrap();
match board {
Some(a) => {
let msg = mf.create_message({
let user = um.get_user_by_id(form.user_id).ok_or_else(|| {
HttpResponse::NotFound().body("Not Found: User does not exist")
})?;
if user.secret == cookie.secret {
User::from(user)
} else {
return Err(HttpResponse::Unauthorized().body("Unauthorized: Bad login attempt, invalid auth token"));
}
}, form.content.clone());
println!("new message");
a.add_message(msg);
Ok(HttpResponse::SeeOther().header("location", format!("/board/{}/", a.id)).finish())
},
None => Err(HttpResponse::BadRequest().body("Bad Request: Board does not exist"))
}
}
#[get("/boards/new/")]
pub async fn new_board(
req: HttpRequest,
data: web::Data<AppState>,
) -> HttpResponse {
let cookie = req.cookie("auth");
if cookie.is_none() {
return HttpResponse::Unauthorized().body("Unauthorized: You are not logged in");
}
let cookie = match UserCookie::parse(cookie.unwrap().value()) {
Ok(a) => a,
Err(_e) => { return HttpResponse::BadRequest().body("Bad Request: Could not parse user cookie") }
};
let um = data.user_manager.lock().unwrap();
if let Some(u) = um.get_user_by_id(cookie.id) {
if cookie.secret != u.secret {
return HttpResponse::BadRequest().body("Bad Request: Could not authenticate user");
}
} else {
return HttpResponse::BadRequest().body("Bad Request: User does not exist");
}
HttpResponse::Ok().body(r#"
<html><head>
<link rel="stylesheet" type="text/css" href="https://orbitalfox.us/Music/index.css">
<link rel="stylesheet" type="text/css" href="/static/index.css">
</head><body>
<div id="title" class="bar">
<h1>New Board</h1>
</div><div id="index">
<div class="auth">
<form action="/boards/new" method="post">
<div>
<label for="name">Board Title: </label><br>
<input type="text" id="name" name="name" required>
</div>
<div>
<label for="description">Board Description: </label>
<input type="text" id="description" name="description" required>
</div>
<input type="submit" value="Create Board">
</form>
</div>
</body></html></div></body></html>
"#)
}
#[post("/boards/new")]
pub async fn new_board_result(
req: HttpRequest,
data: web::Data<AppState>,
form: web::Form<BoardForm>
) -> impl Responder {
let cookie = req.cookie("auth");
if cookie.is_none() {
return HttpResponse::Unauthorized().body("Unauthorized: You are not logged in");
}
let cookie = match UserCookie::parse(cookie.unwrap().value()) {
Ok(a) => a,
Err(_e) => { return HttpResponse::BadRequest().body("Bad Request: Could not parse user cookie") }
};
let um = data.user_manager.lock().unwrap();
if let Some(u) = um.get_user_by_id(cookie.id) {
if cookie.secret != u.secret {
return HttpResponse::BadRequest().body("Bad Request: Could not authenticate user");
}
} else {
return HttpResponse::BadRequest().body("Bad Request: User does not exist");
}
let mut bf = data.board_factory.lock().unwrap();
let mut path = PathBuf::from(
format!(
"{}/board.json", bf.next_id
)
);
path.push(&form.name);
if let Ok(_a) = Board::open(path) {
return HttpResponse::Conflict().body("Conflict: Board already exists");
}
match bf.create_board(&form.name, &form.description, cookie.id) {
Ok(a) => {
if form.name.contains(' ') {
return HttpResponse::BadRequest().body("Bad Request: Name cannot contain spaces");
}
println!("new board");
data.boards.lock().unwrap().push(a.clone());
HttpResponse::SeeOther().header("location", format!("/board/{}/", a.id)).finish()
},
Err(e) => HttpResponse::InternalServerError().body(format!("Internal Server Error: {}", e))
}
}