use crate::secondary_validation::Validator;
pub struct GithubTokenChecksum;
impl Validator for GithubTokenChecksum {
fn is_valid_match(&self, regex_match: &str) -> bool {
let parts: Vec<&str> = regex_match.split('_').collect();
if parts.len() < 2 {
return false;
}
let last_part = parts.last().unwrap();
if !last_part.chars().all(|c| c.is_ascii_alphanumeric()) {
return false;
}
if last_part.len() <= 6 {
return false;
}
let computed_checksum = crc32fast::hash(&last_part.as_bytes()[..last_part.len() - 6]);
let checksum = base62::decode(&last_part.as_bytes()[last_part.len() - 6..]);
if checksum.is_err() {
return false;
}
computed_checksum as u64 == checksum.unwrap() as u64
}
}
#[cfg(test)]
mod test {
use crate::secondary_validation::*;
#[test]
fn test_valid_github_tokens() {
let validids = vec![
"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",
"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",
"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",
"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",
"nawak_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",
"b62_QdwULL38u41vs1OcAjhKqcaSZ9W63r0Zu4ln",
];
for id in validids {
assert!(GithubTokenChecksum.is_valid_match(id));
}
}
#[test]
fn test_invalid_github_tokens() {
let invalid_ids = vec![
"ghp_M7H4jxUDDWHP4kZ6A4dxlQYsQIWJuq11T4V3",
"ghp_M7H4jxUDDWHP4kZ6A4dxlQYsQIWJuq11T4Vñ",
"ghp_M7H4jxUDDWHP4kZ6A4dxlQYsQIWJuq11T4V/",
"ghpM7H4jxUDDWHP4kZ6A4dxlQYsQIWJuq11T4V4",
"ghp_T4V4",
];
for id in invalid_ids {
assert!(!GithubTokenChecksum.is_valid_match(id));
}
}
}