use anyhow::{Context, Result};
use std::io::Write;
use std::path::Path;
use zip::write::SimpleFileOptions;
use zip::ZipWriter;
pub const SOURCE: &str = include_str!("../../assets/gate.py");
pub const PAGE: &str = include_str!("../../assets/share.html");
pub const REQUEST_PAGE: &str = include_str!("../../assets/request.html");
pub const OG_PNG: &[u8] = include_bytes!("../../assets/og.png");
pub const OG_REQUEST_PNG: &[u8] = include_bytes!("../../assets/og-request.png");
pub const HANDLER: &str = "lambda_function.handler";
pub const RUNTIME: &str = "python3.12";
pub fn write_deployment_zip(dest: &Path) -> Result<()> {
let file =
std::fs::File::create(dest).with_context(|| format!("creating {}", dest.display()))?;
let mut zip = ZipWriter::new(file);
zip.start_file("lambda_function.py", SimpleFileOptions::default())?;
zip.write_all(SOURCE.as_bytes())?;
zip.start_file("share.html", SimpleFileOptions::default())?;
zip.write_all(PAGE.as_bytes())?;
zip.start_file("request.html", SimpleFileOptions::default())?;
zip.write_all(REQUEST_PAGE.as_bytes())?;
zip.start_file("og.png", SimpleFileOptions::default())?;
zip.write_all(OG_PNG)?;
zip.start_file("og-request.png", SimpleFileOptions::default())?;
zip.write_all(OG_REQUEST_PNG)?;
zip.finish()?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn embedded_source_is_the_handler() {
assert!(SOURCE.contains("def handler(event, _context):"));
assert!(SOURCE.contains("ConditionExpression"));
assert!(SOURCE.contains("generate_presigned_url"));
}
#[test]
fn request_page_is_self_contained_with_ogbase() {
assert!(REQUEST_PAGE.contains("__OGBASE__/og-request.png"));
assert!(REQUEST_PAGE.contains("async function encrypt")); assert!(!REQUEST_PAGE.contains("<script type=\"module\"")); assert!(!REQUEST_PAGE.contains("rel=\"stylesheet\"")); assert!(!REQUEST_PAGE.contains("Phil")); }
#[test]
fn deployment_zip_contains_the_handler_file() {
let mut b = [0u8; 6];
getrandom::getrandom(&mut b).unwrap();
let tag: String = b.iter().map(|x| format!("{x:02x}")).collect();
let dest = std::env::temp_dir().join(format!("dove-gate-{tag}.zip"));
write_deployment_zip(&dest).unwrap();
let f = std::fs::File::open(&dest).unwrap();
let mut archive = zip::ZipArchive::new(f).unwrap();
assert!(archive.by_name("lambda_function.py").is_ok());
assert!(archive.by_name("share.html").is_ok());
assert!(archive.by_name("request.html").is_ok());
std::fs::remove_file(&dest).ok();
}
}