lfsx_server/config/
forges.rs1use super::{Auth, Provider, allowed, anonymous_read, api_url_from};
2use crate::auth::Namespaces;
3use crate::namespace::is_forge_name;
4
5#[derive(Debug, Clone)]
6pub struct Forge {
7 pub name: String,
8 pub auth: Auth,
9}
10
11pub(super) fn from_env(primary: &Auth) -> Vec<Forge> {
12 let Some(names) = std::env::var("LFSX_FORGES")
13 .ok()
14 .filter(|names| !names.trim().is_empty())
15 else {
16 return Vec::new();
17 };
18
19 parse(&names, primary, |variable| std::env::var(variable).ok())
20}
21
22pub(super) fn parse(
23 names: &str,
24 primary: &Auth,
25 read: impl Fn(&str) -> Option<String>,
26) -> Vec<Forge> {
27 let Auth::Forge {
28 cache_ttl,
29 rejection_ttl,
30 lookup_budget,
31 ..
32 } = primary
33 else {
34 panic!(
35 "LFSX_FORGES is set and LFSX_AUTH=disabled: with authentication off there is nothing to \
36 ask the other forges about"
37 );
38 };
39
40 let mut forges: Vec<Forge> = Vec::new();
41 for name in names
42 .split(',')
43 .map(str::trim)
44 .filter(|name| !name.is_empty())
45 {
46 if !is_forge_name(name) {
47 panic!(
48 "LFSX_FORGES names {name}: a forge name is 1 to 32 lowercase letters, digits or \
49 dashes, and not api or dashboard"
50 );
51 }
52 if forges.iter().any(|forge| forge.name == name) {
53 panic!("LFSX_FORGES names {name} twice");
54 }
55
56 let prefix = format!("LFSX_FORGE_{}_", name.to_uppercase().replace('-', "_"));
57 let variable = |suffix: &str| format!("{prefix}{suffix}");
58 let value = |suffix: &str| read(&variable(suffix));
59
60 let provider = match value("AUTH").as_deref() {
61 Some("github") => Provider::Github,
62 Some("gitlab") => Provider::Gitlab,
63 Some("gitea") | Some("forgejo") => Provider::Gitea,
64 _ => panic!(
65 "{} must be github, gitlab, gitea or forgejo",
66 variable("AUTH")
67 ),
68 };
69
70 forges.push(Forge {
71 name: name.to_owned(),
72 auth: Auth::Forge {
73 provider,
74 api_url: api_url_from(provider, &variable("API_URL"), value("API_URL").as_deref()),
75 cache_ttl: *cache_ttl,
76 rejection_ttl: *rejection_ttl,
77 lookup_budget: *lookup_budget,
78 github_app: None,
79 anonymous_read: anonymous_read(value("ANONYMOUS_READ").as_deref()),
80 restricted: Namespaces::parse(
81 &variable("RESTRICTED"),
82 value("RESTRICTED").as_deref(),
83 ),
84 allowed: allowed(&variable("ALLOWED"), value("ALLOWED").as_deref()),
85 },
86 });
87 }
88
89 forges
90}
91
92#[cfg(test)]
93mod tests;