OXYGENHUB
# abb98fa9964e oxygenhub / crates / hub / src / web / home.rs
2.3 KiB · Rust · last changed Milestone 0.1: browse 1 month ago source blame history raw
1
//! The front page, explore, owner pages and small endpoints.
2
3
use super::{filters, Error, Page, Shell};
4
use crate::{db, Shared};
5
use askama::Template;
6
use axum::extract::{Path, State};
7
use axum::http::header;
8
use axum::response::{IntoResponse, Response};
9
use hub_api::Visibility;
10
11
#[derive(Template)]
12
#[template(path = "home.html")]
13
pub struct HomePage {
14
    shell: Shell,
15
    description: String,
16
    repos: Vec<db::repos::RepoRow>,
17
    owner: Option<String>,
18
}
19
20
pub async fn index(State(app): State<Shared>) -> Result<Page<HomePage>, Error> {
21
    let shell = Shell::new(&app, "/");
22
    let repos = db::repos::list(&app.db).await.map_err(|e| Error::from_db(shell.clone(), e))?;
23
    let repos = repos.into_iter().filter(|r| r.visibility() == Visibility::Public).collect();
24
    Ok(Page(HomePage { description: app.config.site.description.clone(), shell, repos, owner: None }))
25
}
26
27
pub async fn explore(State(app): State<Shared>) -> Result<Page<HomePage>, Error> {
28
    let mut page = index(State(app.clone())).await?;
29
    page.0.shell = Shell::new(&app, "/explore");
30
    Ok(page)
31
}
32
33
pub async fn owner(State(app): State<Shared>, Path(owner): Path<String>) -> Result<Page<HomePage>, Error> {
34
    let shell = Shell::new(&app, &format!("/{owner}"));
35
    if !crate::repos::names::valid_owner(&owner) {
36
        return Err(Error::not_found(shell));
37
    }
38
    let repos = db::repos::list_by_owner(&app.db, &owner).await.map_err(|e| Error::from_db(shell.clone(), e))?;
39
    let repos: Vec<_> = repos.into_iter().filter(|r| r.visibility() == Visibility::Public).collect();
40
    if repos.is_empty() {
41
        return Err(Error::not_found(shell));
42
    }
43
    Ok(Page(HomePage { description: String::new(), shell, repos, owner: Some(owner) }))
44
}
45
46
pub async fn health(State(app): State<Shared>) -> Response {
47
    let body = serde_json::json!({
48
        "ok": true,
49
        "version": env!("CARGO_PKG_VERSION"),
50
        "uptime_s": app.started.elapsed().as_secs(),
51
    });
52
    axum::Json(body).into_response()
53
}
54
55
/// The hub delegate identity object (hub spec §15.5), as `oxy identity
56
/// export` writes one, so policy holders can admit it.
57
pub async fn hub_key(State(app): State<Shared>) -> Response {
58
    (
59
        [(header::CONTENT_TYPE, "application/oxy-identity"), (header::CONTENT_DISPOSITION, "attachment; filename=\"hub.identity\"")],
60
        app.hub_key.bytes.clone(),
61
    )
62
        .into_response()
63
}