Add account connections, guild wallets and admin fixes [skip ci]

This commit is contained in:
SCOPEDD committed 2026-09-30 12:25:29 -04:00
1 parent 7076e847ea
commit 004862ea88
38 files changed
+1696 -458

No files matched your search

+58 -1
View File
@@ -20,7 +20,7 @@ pub async fn kv_set<T: Serialize>(state: &AppState, key: &str, value: &T) -> App
Ok(())
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Settings {
pub auth: AuthConfig,
@@ -30,6 +30,63 @@ pub struct Settings {
/// Public address of the panel (e.g. https://panel.example.com). Used in
/// skin URLs and the auth server metadata. Falls back to the request.
pub public_url: Option<String>,
/// Exact names by default; `*term*` also blocks the term inside names.
pub username_blocklist: Vec<String>,
}
impl Default for Settings {
fn default() -> Self {
Self {
auth: AuthConfig::default(),
curseforge_api_key: None,
launcher_download_url: None,
public_url: None,
username_blocklist: default_username_blocklist(),
}
}
}
fn default_username_blocklist() -> Vec<String> {
["*nazi*", "*hitler*", "*nigger*", "*faggot*", "*pedophile*", "fuck", "shit", "bitch", "cunt", "rape"]
.into_iter()
.map(str::to_string)
.collect()
}
pub fn username_blocked(name: &str, entries: &[String]) -> bool {
let normalized = name.to_ascii_lowercase().replace('_', "");
entries.iter().any(|entry| {
let rule = entry.trim().to_ascii_lowercase();
if rule.is_empty() {
return false;
}
if let Some(inner) = rule.strip_prefix('*').and_then(|r| r.strip_suffix('*')) {
inner.len() >= 3 && normalized.contains(inner)
} else {
normalized == rule.replace('_', "")
}
})
}
pub async fn check_username(state: &AppState, name: &str) -> AppResult<()> {
if username_blocked(name, &settings(state).await?.username_blocklist) {
return Err(AppError::bad_request("that username is unavailable; choose another"));
}
Ok(())
}
#[cfg(test)]
mod username_tests {
use super::*;
#[test]
fn blacklist_matches_exact_and_marked_substrings_without_overblocking() {
let rules = vec!["*nazi*".into(), "shit".into()];
assert!(username_blocked("naziFan", &rules));
assert!(username_blocked("ShIt", &rules));
assert!(!username_blocked("grapes", &rules));
assert!(!username_blocked("Shitake", &rules));
}
}
pub async fn settings(state: &AppState) -> AppResult<Settings> {