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.
274 lines
7.9 KiB
Rust
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))
|
|
}
|
|
}
|