Skip to content

Commit

Permalink
wip!
Browse files Browse the repository at this point in the history
  • Loading branch information
matze committed Feb 7, 2025
1 parent 5844a10 commit 52f3f38
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 24 deletions.
18 changes: 18 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ impl FromRef<AppState> for Key {
}
}

impl FromRef<AppState> for Arc<Highlighter> {
fn from_ref(state: &AppState) -> Self {
state.highlighter.clone()
}
}

impl FromRef<AppState> for Arc<Page> {
fn from_ref(state: &AppState) -> Self {
state.page.clone()
}
}

impl FromRef<AppState> for Database {
fn from_ref(state: &AppState) -> Self {
state.db.clone()
}
}

async fn security_headers_layer(req: Request, next: Next) -> impl IntoResponse {
const SECURITY_HEADERS: [(HeaderName, HeaderValue); 7] = [

Expand Down
68 changes: 44 additions & 24 deletions src/routes/paste.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::cache::Key as CacheKey;
use crate::crypto::Password;
use crate::db::read::Entry;
use crate::highlight::Highlighter;
use crate::pages::{self, make_error, Burn};
use crate::routes::{form, json};
use crate::{AppState, Error};
use crate::{AppState, Database, Error, Page};
use axum::body::Body;
use axum::extract::{Form, Json, Path, Query, State};
use axum::http::header::{self, HeaderMap};
Expand All @@ -14,6 +15,7 @@ use axum_extra::extract::cookie::SignedCookieJar;
use axum_extra::headers;
use axum_extra::headers::{HeaderMapExt, HeaderValue};
use serde::Deserialize;
use std::sync::Arc;

#[derive(Deserialize, Debug)]
pub enum Format {
Expand All @@ -36,7 +38,7 @@ pub struct PasswordForm {
}

fn qr_code_from(
state: &AppState,
page: Arc<Page>,
id: String,
ext: Option<String>,
) -> Result<qrcodegen::QrCode, Error> {
Expand All @@ -47,31 +49,34 @@ fn qr_code_from(
};

Ok(qrcodegen::QrCode::encode_text(
state.page.base_url.join(&name)?.as_str(),
page.base_url.join(&name)?.as_str(),
qrcodegen::QrCodeEcc::High,
)?)
}

async fn get_qr(
state: AppState,
page: Arc<Page>,
key: CacheKey,
title: String,
) -> Result<pages::Qr, pages::ErrorResponse> {
let page = state.page.clone();
let err_page = page.clone();

async {
let id = key.id();
let ext = key.ext.is_empty().then_some(key.ext.clone());
let page = state.page.clone();

let qr_code = tokio::task::spawn_blocking(move || qr_code_from(&state, id, ext))
.await
.map_err(Error::from)??;
let qr_code = {
let page = page.clone();

tokio::task::spawn_blocking(move || qr_code_from(page, id, ext))
.await
.map_err(Error::from)??
};

Ok(pages::Qr::new(qr_code, key, title, page))
}
.await
.map_err(|err| make_error(err, page))
.map_err(|err| make_error(err, err_page))
}

fn get_download(text: String, id: &str, extension: &str) -> impl IntoResponse {
Expand All @@ -91,6 +96,8 @@ fn get_download(text: String, id: &str, extension: &str) -> impl IntoResponse {

async fn get_html(
state: AppState,
page: Arc<Page>,
highlighter: Arc<Highlighter>,
key: CacheKey,
entry: Entry,
jar: SignedCookieJar,
Expand Down Expand Up @@ -126,7 +133,7 @@ async fn get_html(
let can_be_cached = !entry.must_be_deleted;
let ext = key.ext.clone();
let title = entry.title.clone().unwrap_or_default();
let html = state.highlighter.highlight(entry, ext).await?;
let html = highlighter.highlight(entry, ext).await?;

if can_be_cached && !is_protected {
tracing::trace!(?key, "cache item");
Expand All @@ -140,15 +147,16 @@ async fn get_html(
}

pub async fn get(
State(state): State<AppState>,
State(page): State<Arc<Page>>,
State(db): State<Database>,
State(highlighter): State<Arc<Highlighter>>,
Path(id): Path<String>,
headers: HeaderMap,
jar: SignedCookieJar,
Query(query): Query<QueryData>,
State(state): State<AppState>,
form: Option<Form<PasswordForm>>,
) -> Result<Response, pages::ErrorResponse> {
let page = state.page.clone();

async {
let password = form
.map(|form| form.password.clone())
Expand All @@ -159,22 +167,27 @@ pub async fn get(
})
.map(|password| Password::from(password.as_bytes().to_vec()));
let key: CacheKey = id.parse()?;
let page = state.page.clone();

match state.db.get(key.id, password.clone()).await {
Err(Error::NoPassword) => Ok(pages::Encrypted::new(key, &query, page).into_response()),
match db.get(key.id, password.clone()).await {
Err(Error::NoPassword) => {
Ok(pages::Encrypted::new(key, &query, page.clone()).into_response())
}
Err(err) => Err(err),
Ok(entry) => {
if entry.must_be_deleted {
state.db.delete(key.id).await?;
db.delete(key.id).await?;
}

match query.fmt {
Some(Format::Raw) => return Ok(entry.text.into_response()),
Some(Format::Qr) => {
return Ok(get_qr(state, key, entry.title.clone().unwrap_or_default())
.await
.into_response())
return Ok(get_qr(
page.clone(),
key,
entry.title.clone().unwrap_or_default(),
)
.await
.into_response())
}
Some(Format::Dl) => {
return Ok(get_download(entry.text, &key.id(), &key.ext).into_response());
Expand All @@ -185,9 +198,16 @@ pub async fn get(
if let Some(value) = headers.get(header::ACCEPT) {
if let Ok(value) = value.to_str() {
if value.contains("text/html") {
return Ok(get_html(state, key, entry, jar, password.is_some())
.await
.into_response());
return Ok(get_html(
state,
highlighter,
key,
entry,
jar,
password.is_some(),
)
.await
.into_response());
}
}
}
Expand Down

0 comments on commit 52f3f38

Please sign in to comment.