1pub const TENANT_SLUG_MAX: usize = 40;
5pub const SERVICE_NAME_MAX: usize = 64;
6
7pub fn is_valid_tenant_slug(s: &str) -> bool {
9 (1..=TENANT_SLUG_MAX).contains(&s.len())
10 && s.bytes()
11 .all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-')
12}
13
14pub fn is_valid_service_name(s: &str) -> bool {
16 (1..=SERVICE_NAME_MAX).contains(&s.len())
17 && s.bytes()
18 .all(|b| b.is_ascii_alphanumeric() || b == b'-' || b == b'_')
19}
20
21#[cfg(test)]
22mod tests {
23 use super::*;
24
25 #[test]
26 fn tenant_slugs() {
27 for valid in ["default", "preview-pr-7", "a", "0", &"x".repeat(40)] {
28 assert!(is_valid_tenant_slug(valid), "{valid}");
29 }
30 for invalid in [
31 "",
32 "Default",
33 "preview_pr",
34 "a.b",
35 "../etc",
36 "tenant slug",
37 "ténant",
38 &"x".repeat(41),
39 ] {
40 assert!(!is_valid_tenant_slug(invalid), "{invalid}");
41 }
42 }
43
44 #[test]
45 fn service_names() {
46 for valid in ["asset-service", "Blog_Service", "a", &"s".repeat(64)] {
47 assert!(is_valid_service_name(valid), "{valid}");
48 }
49 for invalid in ["", "a.b", "../x", "a/b", "sérvice", "a b", &"s".repeat(65)] {
50 assert!(!is_valid_service_name(invalid), "{invalid}");
51 }
52 }
53}