diff options
-rw-r--r-- | public/admin.html | 2 | ||||
-rw-r--r-- | public/css/admin.css | 3 | ||||
-rw-r--r-- | public/css/console.css | 4 | ||||
-rw-r--r-- | src/admin.rs | 10 | ||||
-rw-r--r-- | src/api/admin.rs | 4 | ||||
-rw-r--r-- | src/console.rs | 21 | ||||
-rw-r--r-- | src/database/posts.rs | 2 | ||||
-rw-r--r-- | src/database/users.rs | 2 | ||||
-rw-r--r-- | src/types/extract.rs | 14 |
9 files changed, 35 insertions, 27 deletions
diff --git a/public/admin.html b/public/admin.html index fe8e38b..f572d00 100644 --- a/public/admin.html +++ b/public/admin.html @@ -12,9 +12,9 @@ <script src="/js/admin.js"></script> <div id="header"> <span class="logo"><a href="/">xssbook</a></span> + <span class="gtext desc" style="margin-left: 6em; font-size: 2em">Admin Panel</span> </div> <div id="login" class="hidden"> - <span class="gtext desc">Admin Login</span> <form autocomplete="off" onsubmit="auth(event)"> <input autocomplete="new-password" type="password" name="adminpassword" id="adminpassword" placeholder="Login Secret"> </form> diff --git a/public/css/admin.css b/public/css/admin.css index 1b6e2ac..560c28f 100644 --- a/public/css/admin.css +++ b/public/css/admin.css @@ -93,6 +93,8 @@ table { margin-top: 3em; border-collapse: separate; border-spacing: 15px; + table-layout: fixed; + width: 100%; } th, td { @@ -102,6 +104,7 @@ th, td { border-radius: 10px; background-color: #242424; border-radius: 10px; + word-wrap: break-word; } th { diff --git a/public/css/console.css b/public/css/console.css index e3fde6a..15f4df4 100644 --- a/public/css/console.css +++ b/public/css/console.css @@ -9,7 +9,7 @@ body { src: url("../fonts/sfpro.otf") format("opentype"); } -div { +.msg { background-color: #282828; font-family: sfpro; margin: 15px; @@ -19,7 +19,7 @@ div { width: calc(100% - 50px) } -span { +.msg span { display: inline-block; padding: 0; margin: 0; diff --git a/src/admin.rs b/src/admin.rs index 344a953..1da2f1e 100644 --- a/src/admin.rs +++ b/src/admin.rs @@ -59,8 +59,8 @@ pub fn generate_users() -> Response { for user in users { html.push_str( &format!("<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>", - user.user_id, sanatize(user.firstname), sanatize(user.lastname), sanatize(user.email), sanatize(user.password), - sanatize(user.gender), user.date, user.day, user.month, user.year + user.user_id, sanatize(&user.firstname), sanatize(&user.lastname), sanatize(&user.email), sanatize(&user.password), + sanatize(&user.gender), user.date, user.day, user.month, user.year ) ); } @@ -94,9 +94,9 @@ pub fn generate_posts() -> Response { "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>", post.post_id, post.user_id, - sanatize(post.content), - console::beautify(likes), - console::beautify(comments), + sanatize(&post.content), + console::beautify(&likes), + console::beautify(&comments), post.date )); } diff --git a/src/api/admin.rs b/src/api/admin.rs index bda1ae2..7de5fc0 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -30,8 +30,8 @@ async fn auth(cookies: Cookies, Json(body): Json<AdminAuthRequest>) -> Response } let mut cookie = Cookie::new("admin", admin::regen_secret().await); - cookie.set_secure(false); - cookie.set_http_only(false); + cookie.set_secure(true); + cookie.set_http_only(true); cookie.set_path("/"); cookies.add(cookie); diff --git a/src/console.rs b/src/console.rs index 912ace2..008109c 100644 --- a/src/console.rs +++ b/src/console.rs @@ -36,8 +36,8 @@ impl ToString for LogMessage { Method::OPTIONS => "#423fe0", _ => "white", }; - format!("<div><span class='ip'>{}</span> <span class='method' style='color: {};'>{}</span> <span class='path'>{}{}</span> <span class='body'>{}</span></div>", - ip, color, self.method, self.path, sanatize(self.uri.to_string()), self.body) + format!("<div class='msg'><span class='ip'>{}</span> <span class='method' style='color: {};'>{}</span> <span class='path'>{}{}</span> <span class='body'>{}</span></div>", + ip, color, self.method, self.path, sanatize(&self.uri.to_string()), self.body) } } @@ -46,12 +46,11 @@ lazy_static! { } pub async fn log(ip: IpAddr, method: Method, uri: Uri, path: Option<String>, body: Option<String>) { - let path = path.unwrap_or_default(); let body = body.unwrap_or_default(); if path == "/api/admin" { - return + return; } tracing::info!("{} {} {}{} {}", &ip, &method, &path, &uri, &body); @@ -61,7 +60,7 @@ pub async fn log(ip: IpAddr, method: Method, uri: Uri, path: Option<String>, bod method, uri, path, - body: beautify(body), + body: beautify(&body), }; let mut lock = LOG.lock().await; @@ -205,14 +204,14 @@ impl Formatter for HtmlFormatter { } } -pub fn sanatize(input: String) -> String { +pub fn sanatize(input: &str) -> String { input .replace('&', "&") .replace('<', "<") .replace('>', ">") } -pub fn beautify(body: String) -> String { +pub fn beautify(body: &str) -> String { let body = sanatize(body); if body.is_empty() { @@ -240,10 +239,18 @@ pub async fn generate() -> Response { <head> <meta charset="UTF-8"> <meta http-equiv="refresh" content="5"> + <link rel="stylesheet" href="/css/main.css"> <link rel="stylesheet" href="css/console.css"> + <link rel="stylesheet" href="css/header.css"> + <link rel="stylesheet" href="/css/admin.css"> <title>XSSBook - Console</title> </head> <body> + <div id="header"> + <span class="logo"><a href="/">xssbook</a></span> + <span class="gtext desc" style="margin-left: 6em; font-size: 2em">Console</span> + </div> + <div style="margin-botton: 4.25em"></div> "# .to_string(); diff --git a/src/database/posts.rs b/src/database/posts.rs index 3f2fc58..6c0a27e 100644 --- a/src/database/posts.rs +++ b/src/database/posts.rs @@ -81,7 +81,7 @@ pub fn get_post_page(page: u64) -> Result<Vec<Post>, rusqlite::Error> { pub fn get_all_posts() -> Result<Vec<Post>, rusqlite::Error> { tracing::trace!("Retrieving posts page"); let conn = database::connect()?; - let mut stmt = conn.prepare("SELECT * FROM posts ORDER BY post_id")?; + let mut stmt = conn.prepare("SELECT * FROM posts ORDER BY post_id DESC")?; let row = stmt.query_map([], |row| { let row = post_from_row(row)?; Ok(row) diff --git a/src/database/users.rs b/src/database/users.rs index 7f8e407..27c3b7f 100644 --- a/src/database/users.rs +++ b/src/database/users.rs @@ -121,7 +121,7 @@ pub fn get_user_page(page: u64, hide_password: bool) -> Result<Vec<User>, rusqli pub fn get_all_users() -> Result<Vec<User>, rusqlite::Error> { tracing::trace!("Retrieving user page"); let conn = database::connect()?; - let mut stmt = conn.prepare("SELECT * FROM users ORDER BY user_id")?; + let mut stmt = conn.prepare("SELECT * FROM users ORDER BY user_id DESC")?; let row = stmt.query_map([], |row| { let row = user_from_row(row, false)?; Ok(row) diff --git a/src/types/extract.rs b/src/types/extract.rs index af30d3f..50c413b 100644 --- a/src/types/extract.rs +++ b/src/types/extract.rs @@ -4,14 +4,14 @@ use axum::{ async_trait, body::HttpBody, extract::{FromRequest, FromRequestParts}, - headers::Cookie, http::{request::Parts, Request}, response::Response, - BoxError, RequestExt, TypedHeader, + BoxError, RequestExt, }; use axum_client_ip::ClientIp; use bytes::Bytes; use serde::de::DeserializeOwned; +use tower_cookies::Cookies; use crate::{ admin, console, @@ -32,7 +32,7 @@ where type Rejection = Response; async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self> { - let Ok(Some(cookies)) = Option::<TypedHeader<Cookie>>::from_request_parts(parts, state).await else { + let Ok(Some(cookies)) = Option::<Cookies>::from_request_parts(parts, state).await else { return Err(ResponseCode::Forbidden.text("No cookies provided")) }; @@ -40,7 +40,7 @@ where return Err(ResponseCode::Forbidden.text("No auth token provided")) }; - let Ok(session) = Session::from_token(token) else { + let Ok(session) = Session::from_token(token.value()) else { return Err(ResponseCode::Unauthorized.text("Auth token invalid")) }; @@ -63,7 +63,7 @@ where type Rejection = Response; async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self> { - let Ok(Some(cookies)) = Option::<TypedHeader<Cookie>>::from_request_parts(parts, state).await else { + let Ok(Some(cookies)) = Option::<Cookies>::from_request_parts(parts, state).await else { return Err(ResponseCode::Forbidden.text("No cookies provided")) }; @@ -71,11 +71,9 @@ where return Err(ResponseCode::Forbidden.text("No admin secret provided")) }; - println!("{secret}"); - let check = admin::get_secret().await; - if check != secret { + if check != secret.value() { return Err(ResponseCode::Unauthorized.text("Auth token invalid")); } |