OXYGENHUB
# a549ddd5941f oxygenhub / crates / hub / src / web / transparency.rs
2.1 KiB · Rust · last changed Drops: per-user gists, each a small hidden Oxygen repository (#279) 15 days ago source blame history raw
1
//! `/log` (oxygenhub#238): the transparency log's latest checkpoint and
2
//! its newest entries, with where to fetch the rest (C2SP tlog-tiles).
3
4
use super::{filters, Page, Shell};
5
use crate::auth::Viewer;
6
use crate::{db, Shared};
7
use askama::Template;
8
use axum::extract::State;
9
10
pub struct Row {
11
    pub idx: i64,
12
    pub kind: String,
13
    pub object: String,
14
    /// `owner/name`, when the entry is a repository's this hub still has.
15
    pub repo: Option<String>,
16
    pub received_ms: i64,
17
}
18
19
#[derive(Template)]
20
#[template(path = "log.html")]
21
pub struct LogPage {
22
    shell: Shell,
23
    origin: String,
24
    size: u64,
25
    note: Option<String>,
26
    base: String,
27
    rows: Vec<Row>,
28
}
29
30
pub async fn page(State(app): State<Shared>, viewer: Viewer) -> Page<LogPage> {
31
    let shell = Shell::new(&app, "/log", &viewer);
32
    let recent = db::tlog::recent(&app.db, None, 50).await.unwrap_or_default();
33
    let mut rows = Vec::with_capacity(recent.len());
34
    for r in recent {
35
        // Entries of private repositories show only their hashes, and so
36
        // do a secret drop's (#279), whose address is its secret.
37
        let repo = match r.repo_id {
38
            Some(id) => match db::repos::get_by_id(&app.db, id).await {
39
                Ok(Some(row))
40
                    if (!row.is_drop() || crate::drops::listed_to(viewer.account(), &row))
41
                        && crate::auth::roles::allows(
42
                            crate::auth::roles::role_for(&app.db, viewer.account(), &row).await.unwrap_or(None),
43
                            crate::auth::roles::Access::Read,
44
                        ) =>
45
                {
46
                    Some(row.slug())
47
                }
48
                _ => None,
49
            },
50
            None => None,
51
        };
52
        rows.push(Row { idx: r.idx, kind: r.kind, object: r.object, repo, received_ms: r.received_ms });
53
    }
54
    Page(LogPage {
55
        shell,
56
        origin: app.tlog.origin.clone(),
57
        size: app.tlog.size(),
58
        note: app.tlog.checkpoint(),
59
        base: app.config.base_url().trim_end_matches('/').to_string(),
60
        rows,
61
    })
62
}