add: littleweb full

This commit is contained in:
trisua 2025-07-08 13:35:23 -04:00
parent 3fc0872867
commit d67e7c9c33
32 changed files with 1699 additions and 71 deletions

View file

@ -365,7 +365,7 @@ pub async fn global_view_request(
Ok((
[(
"content-security-policy",
"default-src 'self' *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' *; script-src 'self' 'unsafe-inline' *; object-src 'self' *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' *.cloudflare.com; frame-ancestors *",
"default-src 'self' *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' *; script-src 'self' 'unsafe-inline' *; worker-src * blob:; object-src 'self' *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' *; frame-ancestors *",
)],
Html(data.1.render("journals/app.html", &context).unwrap()),
))

View file

@ -0,0 +1,211 @@
use super::render_error;
use crate::{assets::initial_context, get_lang, get_user_from_token, State};
use axum::{
response::{Html, IntoResponse},
extract::{Query, Path},
Extension,
};
use axum_extra::extract::CookieJar;
use tetratto_core::model::{littleweb::TLDS_VEC, Error};
use serde::Deserialize;
/// `/services`
pub async fn services_request(
jar: CookieJar,
Extension(data): Extension<State>,
) -> impl IntoResponse {
let data = data.read().await;
let user = match get_user_from_token!(jar, data.0) {
Some(ua) => ua,
None => {
return Err(Html(
render_error(Error::NotAllowed, &jar, &data, &None).await,
));
}
};
let list = match data.0.get_services_by_user(user.id).await {
Ok(x) => x,
Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)),
};
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
context.insert("list", &list);
// return
Ok(Html(
data.1.render("littleweb/services.html", &context).unwrap(),
))
}
/// `/domains`
pub async fn domains_request(
jar: CookieJar,
Extension(data): Extension<State>,
) -> impl IntoResponse {
let data = data.read().await;
let user = match get_user_from_token!(jar, data.0) {
Some(ua) => ua,
None => {
return Err(Html(
render_error(Error::NotAllowed, &jar, &data, &None).await,
));
}
};
let list = match data.0.get_domains_by_user(user.id).await {
Ok(x) => x,
Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)),
};
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
context.insert("list", &list);
context.insert("tlds", &*TLDS_VEC);
// return
Ok(Html(
data.1.render("littleweb/domains.html", &context).unwrap(),
))
}
#[derive(Deserialize)]
pub struct FileBrowserProps {
#[serde(default)]
path: String,
}
/// `/services/{id}`
pub async fn service_request(
jar: CookieJar,
Path(id): Path<usize>,
Extension(data): Extension<State>,
Query(props): Query<FileBrowserProps>,
) -> impl IntoResponse {
let data = data.read().await;
let user = match get_user_from_token!(jar, data.0) {
Some(ua) => ua,
None => {
return Err(Html(
render_error(Error::NotAllowed, &jar, &data, &None).await,
));
}
};
let service = match data.0.get_service_by_id(id).await {
Ok(x) => x,
Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)),
};
if user.id != service.owner {
return Err(Html(
render_error(Error::NotAllowed, &jar, &data, &None).await,
));
}
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
context.insert("service", &service);
match service.file(&props.path.replacen("/", "", 1)) {
Some((x, p)) => {
context.insert("id_path", &p);
context.insert("file", &x);
context.insert("files", &x.children);
}
None => {
context.insert("id_path", &Vec::<()>::new());
context.insert("files", &service.files);
}
}
let path_segments: Vec<&str> = props.path.split("/").collect();
context.insert("path_segments", &path_segments);
context.insert("path", &props.path);
// return
Ok(Html(
data.1.render("littleweb/service.html", &context).unwrap(),
))
}
/// `/domains/{id}`
pub async fn domain_request(
jar: CookieJar,
Path(id): Path<usize>,
Extension(data): Extension<State>,
) -> impl IntoResponse {
let data = data.read().await;
let user = match get_user_from_token!(jar, data.0) {
Some(ua) => ua,
None => {
return Err(Html(
render_error(Error::NotAllowed, &jar, &data, &None).await,
));
}
};
let domain = match data.0.get_domain_by_id(id).await {
Ok(x) => x,
Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)),
};
if user.id != domain.owner {
return Err(Html(
render_error(Error::NotAllowed, &jar, &data, &None).await,
));
}
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
context.insert("domain", &domain);
// return
Ok(Html(
data.1.render("littleweb/domain.html", &context).unwrap(),
))
}
/// `/net`
pub async fn browser_home_request(
jar: CookieJar,
Extension(data): Extension<State>,
) -> impl IntoResponse {
let data = data.read().await;
let user = get_user_from_token!(jar, data.0);
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &user).await;
context.insert("path", &"");
// return
Html(data.1.render("littleweb/browser.html", &context).unwrap())
}
/// `/net/{uri}`
pub async fn browser_request(
jar: CookieJar,
Path(mut uri): Path<String>,
Extension(data): Extension<State>,
) -> impl IntoResponse {
let data = data.read().await;
let user = get_user_from_token!(jar, data.0);
if !uri.contains("/") {
uri = format!("{uri}/index.html");
}
if !uri.starts_with("atto://") {
uri = format!("atto://{uri}");
}
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &user).await;
context.insert("path", &uri);
// return
Html(data.1.render("littleweb/browser.html", &context).unwrap())
}

View file

@ -4,6 +4,7 @@ pub mod communities;
pub mod developer;
pub mod forge;
pub mod journals;
pub mod littleweb;
pub mod misc;
pub mod mod_panel;
pub mod profile;
@ -139,6 +140,13 @@ pub fn routes() -> Router {
.route("/@{owner}/{journal}", get(journals::index_view_request))
.route("/@{owner}/{journal}/{note}", get(journals::view_request))
.route("/x/{note}", get(journals::global_view_request))
// littleweb
.route("/services", get(littleweb::services_request))
.route("/domains", get(littleweb::domains_request))
.route("/services/{id}", get(littleweb::service_request))
.route("/domains/{id}", get(littleweb::domain_request))
.route("/net", get(littleweb::browser_home_request))
.route("/net/{*uri}", get(littleweb::browser_request))
}
pub fn lw_routes() -> Router {