text-display/src/http_server.rs
2023-02-16 13:30:06 +01:00

127 lines
No EOL
3.4 KiB
Rust

use std::fs;
use std::path::Path;
use rocket;
use rocket::fs::{FileServer, NamedFile, relative};
use rocket::http::{CookieJar, Cookie, Status};
use rocket::request::{FromRequest, Outcome};
use rocket::{Request, routes, uri};
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors};
use rocket::serde::json::Json;
use crate::{data, file};
use crate::data::deserialize;
use crate::file::PATH;
struct Token(String);
#[derive(Debug)]
enum ApiTokenError {
Missing,
}
#[derive(serde::Deserialize)]
#[serde(crate = "rocket::serde")]
struct Text<'r> {
text: &'r str,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Token {
type Error = ApiTokenError;
async fn from_request(request: &'r Request<'_>) -> rocket::request::Outcome<Self, Self::Error> {
let token = request.headers().get_one("token");
match token {
Some(token) => {
// check validity
Outcome::Success(Token(token.to_string()))
}
None => Outcome::Failure((Status::Unauthorized, ApiTokenError::Missing)),
}
}
}
fn make_cors() -> Cors {
rocket_cors::CorsOptions {
allowed_origins: AllowedOrigins::all(),
allowed_headers: AllowedHeaders::some(&["Authorization", "Accept"]),
allow_credentials: true,
..Default::default()
}
.to_cors()
.expect("error while building CORS")
}
#[rocket::get("/")]
fn get_text() -> String {
let content = data::deserialize(fs::read_to_string(&file::PATH).expect(""));
if content.is_err() {
return "".to_string();
}
return content.unwrap().text;
}
#[rocket::get("/edit")]
async fn edit_get() -> Option<NamedFile> {
let path = Path::new(relative!("public")).join("edit.html");
NamedFile::open(path).await.ok()
}
#[rocket::post("/login")]
fn login(token: Token, cookies: &CookieJar<'_>) -> String {
let temp = fs::read_to_string(PATH);
if temp.is_err() {
return "/".to_string();
}
let content = deserialize(temp.unwrap());
let token_int = token.0.parse::<u64>();
if token_int.is_err() {
return "/".to_string();
}
if content.is_ok() {
if content.unwrap().password == token.0.parse::<u64>().unwrap() {
cookies.add_private(Cookie::new("Token", token.0));
return uri!(edit_get).to_string();
}
}
return "/".to_string();
}
#[rocket::post("/edit", format = "json", data = "<text>")]
fn edit(text: Json<Text<'_>>, cookies: &CookieJar<'_>) -> String {
let temp = fs::read_to_string(PATH);
if temp.is_err() {
return "/".to_string();
}
let content = deserialize(temp.unwrap());
let token = cookies.get_private("Token");
if token.is_none() {
return "/".to_string();
}
let token_int = token.unwrap().value().parse::<u64>();
if token_int.is_err() {
return "/".to_string();
}
if content.is_ok() {
let mut data = content.unwrap();
if data.password == token_int.unwrap() {
data.text = text.text.to_string();
file::write_file(data);
return "/".to_string();
}
}
return "/".to_string();
}
#[rocket::main]
pub async fn main() -> Result<(), rocket::Error> {
let _rocket = rocket::build()
.mount("/", FileServer::from("public/"))
.mount("/", routes![login, edit_get])
.mount("/api", routes![get_text, edit])
.manage(make_cors())
.launch()
.await?;
Ok(())
}