OXYGENHUB
# 8bf3010760d7 oxygenhub / crates / hub / src / levels.rs
2.0 KiB · Rust · last changed Variables for pipelines at the site, organisation and repository 1 month ago source blame history raw
1
//! The three levels settings live at, site, organisation and repository,
2
//! and how a repository sees the levels above it. Shared by AI assistants
3
//! (§13.4) and Flow variables (§13.2).
4
5
use crate::db::Pool;
6
7
/// Which level a setting belongs to.
8
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9
pub enum Scope {
10
    Site,
11
    Org(i64),
12
    Repo(i64),
13
}
14
15
impl Scope {
16
    pub fn kind(self) -> &'static str {
17
        match self {
18
            Scope::Site => "site",
19
            Scope::Org(_) => "org",
20
            Scope::Repo(_) => "repo",
21
        }
22
    }
23
24
    pub fn id(self) -> i64 {
25
        match self {
26
            Scope::Site => 0,
27
            Scope::Org(id) | Scope::Repo(id) => id,
28
        }
29
    }
30
}
31
32
/// A level as a settings page addresses it.
33
pub struct At {
34
    pub scope: Scope,
35
    /// The owner name, so a repository finds its organisation.
36
    pub owner: String,
37
    /// What the audit log names.
38
    pub label: String,
39
}
40
41
impl At {
42
    pub fn site() -> At {
43
        At { scope: Scope::Site, owner: String::new(), label: "site".into() }
44
    }
45
46
    pub fn org(org: &crate::db::accounts::Organisation) -> At {
47
        At { scope: Scope::Org(org.id), owner: org.name.clone(), label: org.name.clone() }
48
    }
49
50
    pub fn repo(row: &crate::db::repos::RepoRow) -> At {
51
        At { scope: Scope::Repo(row.id), owner: row.owner.clone(), label: format!("{}/{}", row.owner, row.name) }
52
    }
53
}
54
55
/// The levels above a scope, outermost first: the site, then the
56
/// organisation when the owner is one.
57
pub async fn above(pool: &Pool, scope: Scope, owner: &str) -> sqlx::Result<Vec<(Scope, String)>> {
58
    let mut out = vec![];
59
    match scope {
60
        Scope::Site => {}
61
        Scope::Org(_) => out.push((Scope::Site, "the site".to_string())),
62
        Scope::Repo(_) => {
63
            out.push((Scope::Site, "the site".to_string()));
64
            if let Some(org) = crate::db::accounts::org_by_name(pool, owner).await? {
65
                out.push((Scope::Org(org.id), format!("the {} organisation", org.name)));
66
            }
67
        }
68
    }
69
    Ok(out)
70
}