summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Murphy <tylermurphy534@gmail.com>2023-01-29 00:35:06 -0500
committerTyler Murphy <tylermurphy534@gmail.com>2023-01-29 00:35:06 -0500
commit7805c730e8ead9cd421f45d4720fd7f4062675e6 (patch)
treea46ec6de28c688f7961e6327e075925a8f50071c
parentreverse proxy ip checking (diff)
downloadxssbook-7805c730e8ead9cd421f45d4720fd7f4062675e6.tar.gz
xssbook-7805c730e8ead9cd421f45d4720fd7f4062675e6.tar.bz2
xssbook-7805c730e8ead9cd421f45d4720fd7f4062675e6.zip
no mass rerendering html plus logging fix
-rw-r--r--public/css/home.css4
-rw-r--r--public/js/header.js3
-rw-r--r--public/js/home.js88
-rw-r--r--public/js/main.js31
-rw-r--r--public/js/people.js26
-rw-r--r--public/js/profile.js40
-rw-r--r--src/api/pages.rs14
-rw-r--r--src/console.rs5
-rw-r--r--src/main.rs15
-rw-r--r--src/types/extract.rs5
10 files changed, 142 insertions, 89 deletions
diff --git a/public/css/home.css b/public/css/home.css
index 33d72c0..2686ffd 100644
--- a/public/css/home.css
+++ b/public/css/home.css
@@ -2,7 +2,7 @@ body {
background-color: #f0f2f5;
}
-#posts {
+#posts, #create {
display: flex;
flex-direction: column;
align-items: center;
@@ -172,7 +172,7 @@ body {
flex-direction: row;
}
-#comments input {
+.comments input {
all: unset;
padding: 10px;
border-radius: 10px;
diff --git a/public/js/header.js b/public/js/header.js
index 8fe03e5..5a12408 100644
--- a/public/js/header.js
+++ b/public/js/header.js
@@ -20,6 +20,5 @@ function header(home, people) {
</div>
<div class="spacer"></div>
`
-
- add(html, 'header')
+ append(html)
} \ No newline at end of file
diff --git a/public/js/home.js b/public/js/home.js
index 688cbf5..ee3d6f0 100644
--- a/public/js/home.js
+++ b/public/js/home.js
@@ -41,19 +41,19 @@ function parsePost(post) {
</span>
<div class="fullline nb"></div>
<div class="postbuttons">
- <span onclick="like(this)">
- <i class="icons like ${post.likes.includes(data.user.user_id) ? 'blue' : ''}"></i>
- <span class="bold ${post.likes.includes(data.user.user_id) ? 'blue' : ''}">Like</span>
+ <span class="likeclicky" onclick="like(this)">
+ <i class="liketoggle icons like ${post.likes.includes(data.user.user_id) ? 'blue' : ''}"></i>
+ <span class="liketoggle bold ${post.likes.includes(data.user.user_id) ? 'blue' : ''}">Like</span>
</span>
<span onclick="this.parentElement.parentElement.getElementsByClassName('newcomment')[0].focus()">
<i class="icons comm"></i>
<span class="bold">Comment</span>
</span>
</div>
- <div id="comments">
+ <div class="comments">
<div class="fullline" style="margin-top: 0"></div>
- ${post.comments.map(parseComment).join('')}
- <div class="comment">
+ ${post.comments.map(parseComment).join('')}
+ <div class="comment commentsubmit">
<a class="pfp" href="profile">
</a>
@@ -64,7 +64,6 @@ function parsePost(post) {
</div>
</div>
`
-
return html
}
@@ -78,7 +77,8 @@ function getPost(post_id) {
}
async function like(span) {
- const id = parseInt(span.parentElement.parentElement.getAttribute('postid'))
+ const container = span.parentElement.parentElement;
+ const id = parseInt(container.getAttribute('postid'))
const post = data.posts[getPost(id)]
const index = post.likes.indexOf(data.user.user_id)
const current = index !== -1
@@ -89,26 +89,40 @@ async function like(span) {
} else {
post.likes.push(data.user.user_id)
}
- render()
+ const buttons = container
+ .getElementsByClassName("postbuttons")[0]
+ .getElementsByClassName("likeclicky")[0]
+ .getElementsByClassName("liketoggle")
+ if (current) {
+ buttons[0].classList.remove("blue")
+ buttons[1].classList.remove("blue")
+ } else {
+ buttons[0].classList.add("blue")
+ buttons[1].classList.add("blue")
+ }
}
async function comment(event) {
event.preventDefault();
const text = event.target.elements.text.value.trim();
if (text.length < 1) return;
- const id = parseInt(event.target.parentElement.parentElement.parentElement.getAttribute('postid'))
- var index = getPost(id);
+ const container = event.target.parentElement.parentElement.parentElement;
+ const post_id = parseInt(container.getAttribute('postid'))
+ var index = getPost(post_id);
if (index === -1) return;
- const response = await postcomment(id, text)
+ const response = await postcomment(post_id, text)
if (response.status != 200) return;
event.target.elements.text.value = '';
- data.posts[index].comments.push([data.user.user_id, text])
- render()
+ let new_comment = [data.user.user_id, text]
+ data.posts[index].comments.push(new_comment)
+ let comments = container.getElementsByClassName("comments")[0]
+ prepend(parseComment(new_comment), comments, comments.getElementsByClassName("commentsubmit")[0])
}
async function post() {
const text = document.getElementById("text").value.trim()
const error = document.getElementsByClassName('error')[0]
+ const posts_block = document.getElementById("posts")
if (text.length < 1) return;
const response = await createpost(text);
if (response.status != 201) {
@@ -116,20 +130,32 @@ async function post() {
return;
}
error.innerHTML = '';
- data.posts.unshift({
+ let post = {
post_id: response.json.post_id,
user_id: data.user.user_id,
date: Date.now(),
content: text,
likes: [],
comments: []
- })
- render()
+ }
+ data.posts.unshift(post)
+ let html = parsePost(post)
+ prepend(html, posts_block)
+ document.getElementById('popup').classList.add('hidden')
+}
+
+async function loadMore() {
+ const posts = await load()
+ data.posts.push(... posts)
+ const posts_block = document.getElementById("posts")
+ for (p of posts) {
+ append(parsePost(p), posts_block)
+ }
}
function render() {
const html = `
- <div id="posts">
+ <div id="create">
<div class="create">
<a class="pfp" href="profile">
@@ -140,11 +166,13 @@ function render() {
</p>
</button>
</div>
+ </div>
+ <div id="posts">
${data.posts.map(p => parsePost(p)).join('')}
</div>
`
- add(html, 'posts')
+ append(html)
const popup = `
<div id="popup" class="hidden">
@@ -168,19 +196,15 @@ function render() {
</div>
`
- add(popup, 'popup')
+ append(popup)
const load = `
<div id="load">
- <a class="bold gtext" onclick="load()">Load more posts</a>
+ <a class="bold gtext" onclick="loadMore()">Load more posts</a>
</div>
`
- if (page !== -1) {
- add(load, 'load')
- } else {
- remove('load')
- }
+ append(load)
}
var page = 0
@@ -194,10 +218,11 @@ async function load() {
const posts = (await loadpostspage(page)).json
if (posts.length === 0) {
page = -1
+ remove('load')
+ return []
} else {
page++
}
- data.posts.push(... posts)
const batch = []
for (const post of posts) {
for(const comment of post.comments) {
@@ -209,17 +234,18 @@ async function load() {
if (batch.includes(post.user_id)) continue
batch.push(post.user_id)
}
- const users = (await loadusers(batch)).json
+ const users = batch.length == 0 ? [] : (await loadusers(batch)).json
for (const user of users) {
data.users[user.user_id] = user
}
- render()
+ return posts
}
-
async function init() {
header(true, false)
data.user = (await loadself()).json
data.users[data.user.user_id] = data.user
- load()
+ const posts = await load()
+ data.posts.push(... posts)
+ render()
} \ No newline at end of file
diff --git a/public/js/main.js b/public/js/main.js
index 06736ee..12f53ec 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -1,15 +1,26 @@
-var range;
-
-function add(html, id) {
- const old = document.getElementById(id)
- if (old !== null) {
- old.remove()
+function prepend(html, container, before) {
+ if (container === undefined) {
+ container = document.body
}
- if (range === undefined) {
- var range = document.createRange()
- range.setStart(document.body, 0)
+ if (before === undefined) {
+ before = container.firstChild
+ }
+ console.log(html, container, before)
+ var range = document.createRange()
+ range.setStart(container, 0);
+ container.insertBefore(
+ range.createContextualFragment(html),
+ before
+ )
+}
+
+function append(html, container) {
+ if (container === undefined) {
+ container = document.body
}
- document.body.appendChild(
+ var range = document.createRange()
+ range.setStart(container, 0);
+ container.appendChild(
range.createContextualFragment(html)
)
}
diff --git a/public/js/people.js b/public/js/people.js
index e9f5db6..5c1026b 100644
--- a/public/js/people.js
+++ b/public/js/people.js
@@ -23,19 +23,15 @@ function render() {
</div>
`
- add(html, 'users')
+ append(html)
const load = `
<div id="load">
- <a class="bold gtext" onclick="load()">Load more users</a>
+ <a class="bold gtext" onclick="loadMore()">Load more users</a>
</div>
`
- if (page !== -1) {
- add(load, 'load')
- } else {
- remove('load')
- }
+ append(load)
}
var page = 0
@@ -43,16 +39,30 @@ var data = {
users: []
}
+async function loadMore() {
+ let users = await load()
+ const users_block = document.getElementById("users")
+ for (user of users) {
+ append(parseUser(user), users_block)
+ }
+}
+
async function load() {
const users = (await loaduserspage(page)).json
if (users.length === 0) {
page = -1
+ remove('load')
} else {
page++
}
+ return users
+}
+
+async function init() {
+ let users = await load()
data.users.push(... users)
render()
}
header(false, true)
-load() \ No newline at end of file
+init() \ No newline at end of file
diff --git a/public/js/profile.js b/public/js/profile.js
index 1f72b17..787e2b2 100644
--- a/public/js/profile.js
+++ b/public/js/profile.js
@@ -1,3 +1,21 @@
+function swap(value) {
+ let postsb = document.getElementById("profilepostbutton");
+ let aboutb = document.getElementById("profileaboutbutton");
+ let posts = document.getElementById("posts");
+ let about = document.getElementById("about");
+ if (value) {
+ postsb.classList.add("selected")
+ aboutb.classList.remove("selected")
+ about.classList.add("hidden")
+ posts.classList.remove("hidden")
+ } else {
+ postsb.classList.remove("selected")
+ aboutb.classList.add("selected")
+ about.classList.remove("hidden")
+ posts.classList.add("hidden")
+ }
+}
+
function render() {
const html = `
<div id="top">
@@ -17,10 +35,10 @@ function render() {
</div>
<div class="fullline" style="width: 80em; margin-bottom: 0;"></div>
<div class="profilebuttons">
- <button class="${posts ? 'selected' : ''}" onclick="posts = true; render()">
+ <button id="profilepostbutton" class="${posts ? 'selected' : ''}" onclick="swap(true)">
Posts
</button>
- <button class="${posts ? '' : 'selected'}" onclick="posts = false; render()">
+ <button id="profileaboutbutton" class="${posts ? '' : 'selected'}" onclick="swap(false)">
About
</button>
<div style="flex: 20"></div>
@@ -29,7 +47,7 @@ function render() {
</div>
`
- add(html, 'top')
+ append(html)
const postsh = `
<div id="posts" class="${posts ? '' : 'hidden'}">
@@ -37,7 +55,7 @@ function render() {
</div>
`
- add(postsh, 'posts')
+ append(postsh)
const about = `
<div id="about" class="post ${posts ? 'hidden' : ''}">
@@ -52,7 +70,7 @@ function render() {
</div>
`
- add(about, 'about')
+ append(about)
}
async function logout_button() {
@@ -72,21 +90,22 @@ async function load() {
params[key] = value
}
- let self = (await loadself()).json;
+ data.user = (await loadself()).json;
+ data.users[data.user.user_id] = data.user
let id;
if (params.id !== undefined && !isNaN(params.id)) {
id = parseInt(params.id);
} else {
- id = self.user_id
+ id = data.user.user_id
}
- isself = id === self.user_id
+ isself = id === data.user.user_id
const posts = (await loadusersposts(id)).json
data.posts.push(... posts)
- const batch = [id]
+ const batch = []
for (const post of posts) {
for(const comment of post.comments) {
if (data.users[comment[0]] !== undefined) continue
@@ -97,11 +116,10 @@ async function load() {
if (batch.includes(post.user_id)) continue
batch.push(post.user_id)
}
- const users = (await loadusers(batch)).json
+ const users = batch.length == 0 ? [] : (await loadusers(batch)).json
for (const user of users) {
data.users[user.user_id] = user
}
- data.user = data.users[id]
render()
}
diff --git a/src/api/pages.rs b/src/api/pages.rs
index 4661b91..9149744 100644
--- a/src/api/pages.rs
+++ b/src/api/pages.rs
@@ -6,10 +6,10 @@ use axum::{
use crate::{
console,
- types::{extract::AuthorizedUser, http::ResponseCode},
+ types::{extract::{AuthorizedUser, Log}, http::ResponseCode},
};
-async fn root(user: Option<AuthorizedUser>) -> Response {
+async fn root(user: Option<AuthorizedUser>, _: Log) -> Response {
if user.is_some() {
Redirect::to("/home").into_response()
} else {
@@ -17,7 +17,7 @@ async fn root(user: Option<AuthorizedUser>) -> Response {
}
}
-async fn login(user: Option<AuthorizedUser>) -> Response {
+async fn login(user: Option<AuthorizedUser>, _: Log) -> Response {
if user.is_some() {
Redirect::to("/home").into_response()
} else {
@@ -25,7 +25,7 @@ async fn login(user: Option<AuthorizedUser>) -> Response {
}
}
-async fn home(user: Option<AuthorizedUser>) -> Response {
+async fn home(user: Option<AuthorizedUser>, _: Log) -> Response {
if user.is_none() {
Redirect::to("/login").into_response()
} else {
@@ -33,7 +33,7 @@ async fn home(user: Option<AuthorizedUser>) -> Response {
}
}
-async fn people(user: Option<AuthorizedUser>) -> Response {
+async fn people(user: Option<AuthorizedUser>, _: Log) -> Response {
if user.is_none() {
Redirect::to("/login").into_response()
} else {
@@ -41,7 +41,7 @@ async fn people(user: Option<AuthorizedUser>) -> Response {
}
}
-async fn profile(user: Option<AuthorizedUser>) -> Response {
+async fn profile(user: Option<AuthorizedUser>, _: Log) -> Response {
if user.is_none() {
Redirect::to("/login").into_response()
} else {
@@ -53,7 +53,7 @@ async fn console() -> Response {
console::generate().await
}
-async fn wordpress() -> Response {
+async fn wordpress(_: Log) -> Response {
ResponseCode::ImATeapot.text("Hello i am a teapot owo")
}
diff --git a/src/console.rs b/src/console.rs
index 14324fa..eb78c6a 100644
--- a/src/console.rs
+++ b/src/console.rs
@@ -45,10 +45,7 @@ lazy_static! {
}
pub async fn log(ip: IpAddr, method: Method, uri: Uri, path: Option<String>, body: Option<String>) {
- if uri.to_string().starts_with("/console") {
- return;
- }
-
+
let path = path.unwrap_or_default();
let body = body.unwrap_or_default();
diff --git a/src/main.rs b/src/main.rs
index cd137b9..20627d7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,11 +1,11 @@
use axum::{
body::HttpBody,
- extract::ConnectInfo,
http::{Request, StatusCode},
middleware::{self, Next},
response::Response,
Extension, RequestExt, Router,
};
+use axum_client_ip::ClientIp;
use std::{net::SocketAddr, process::exit};
use tower_cookies::CookieManagerLayer;
use tracing::{error, info, metadata::LevelFilter};
@@ -40,18 +40,11 @@ async fn log<B>(mut req: Request<B>, next: Next<B>) -> Response
where
B: Send + Sync + 'static + HttpBody,
{
- let Ok(ConnectInfo(info)) = req.extract_parts::<ConnectInfo<SocketAddr>>().await else {
+ let Ok(ClientIp(ip)) = req.extract_parts::<ClientIp>().await else {
return next.run(req).await
};
- console::log(
- info.ip(),
- req.method().clone(),
- req.uri().clone(),
- None,
- None,
- )
- .await;
+ console::log(ip, req.method().clone(), req.uri().clone(), None, None).await;
next.run(req).await
}
@@ -80,9 +73,9 @@ async fn main() {
let app = Router::new()
.fallback(not_found)
- .nest("/", pages::router())
.layer(middleware::from_fn(log))
.layer(middleware::from_fn(serve))
+ .nest("/", pages::router())
.nest(
"/api/auth",
auth::router().layer(Extension(RouterURI("/api/auth"))),
diff --git a/src/types/extract.rs b/src/types/extract.rs
index e79aa7a..4d92a3b 100644
--- a/src/types/extract.rs
+++ b/src/types/extract.rs
@@ -85,10 +85,9 @@ where
type Rejection = Response;
async fn from_request(req: Request<B>, state: &S) -> Result<Self> {
-
let body = match parse_body(req, state).await {
Ok(body) => body,
- Err(err) => return Err(err)
+ Err(err) => return Err(err),
};
let Ok(value) = serde_json::from_str::<T>(&body) else {
@@ -128,7 +127,7 @@ where
B: HttpBody + Sync + Send + 'static,
B::Data: Send,
B::Error: Into<BoxError>,
- S: Send + Sync
+ S: Send + Sync,
{
let Ok(ClientIp(ip)) = req.extract_parts::<ClientIp>().await else {
tracing::error!("Failed to read client ip");