Skip to main content

romance_core/addon/
email.rs

1use crate::addon::Addon;
2use anyhow::Result;
3use std::path::Path;
4
5pub struct EmailAddon;
6
7impl Addon for EmailAddon {
8    fn name(&self) -> &str {
9        "email"
10    }
11
12    fn check_prerequisites(&self, project_root: &Path) -> Result<()> {
13        super::check_romance_project(project_root)
14    }
15
16    fn is_already_installed(&self, project_root: &Path) -> bool {
17        project_root.join("backend/src/email.rs").exists()
18    }
19
20    fn install(&self, project_root: &Path) -> Result<()> {
21        install_email(project_root)
22    }
23
24    fn uninstall(&self, project_root: &Path) -> Result<()> {
25        use colored::Colorize;
26
27        println!("{}", "Uninstalling email system...".bold());
28
29        // Delete files
30        if super::remove_file_if_exists(&project_root.join("backend/src/email.rs"))? {
31            println!("  {} backend/src/email.rs", "delete".red());
32        }
33        if super::remove_file_if_exists(
34            &project_root.join("backend/src/handlers/password_reset.rs"),
35        )? {
36            println!(
37                "  {} backend/src/handlers/password_reset.rs",
38                "delete".red()
39            );
40        }
41
42        // Remove mod declaration from main.rs
43        super::remove_mod_from_main(project_root, "email")?;
44
45        // Remove from handlers/mod.rs
46        super::remove_line_from_file(
47            &project_root.join("backend/src/handlers/mod.rs"),
48            "pub mod password_reset;",
49        )?;
50
51        // Remove feature flag
52        super::remove_feature_flag(project_root, "email")?;
53
54        // Regenerate AI context
55        crate::ai_context::regenerate(project_root).ok();
56
57        println!();
58        println!(
59            "{}",
60            "Email system uninstalled successfully.".green().bold()
61        );
62
63        Ok(())
64    }
65}
66
67fn install_email(project_root: &Path) -> Result<()> {
68    use crate::template::TemplateEngine;
69    use crate::utils;
70    use colored::Colorize;
71    use tera::Context;
72
73    println!("{}", "Installing email system...".bold());
74
75    let engine = TemplateEngine::new()?;
76    let ctx = Context::new();
77
78    // Generate email service module
79    let content = engine.render("addon/email/email.rs.tera", &ctx)?;
80    utils::write_file(&project_root.join("backend/src/email.rs"), &content)?;
81    println!("  {} backend/src/email.rs", "create".green());
82
83    // Generate password reset handler
84    let content = engine.render("addon/email/password_reset.rs.tera", &ctx)?;
85    utils::write_file(
86        &project_root.join("backend/src/handlers/password_reset.rs"),
87        &content,
88    )?;
89    println!(
90        "  {} backend/src/handlers/password_reset.rs",
91        "create".green()
92    );
93
94    // Add mod email to main.rs
95    super::add_mod_to_main(project_root, "email")?;
96
97    // Register password_reset handler
98    let mods_marker = "// === ROMANCE:MODS ===";
99    utils::insert_at_marker(
100        &project_root.join("backend/src/handlers/mod.rs"),
101        mods_marker,
102        "pub mod password_reset;",
103    )?;
104
105    // Add dependencies
106    crate::generator::auth::insert_cargo_dependency(
107        &project_root.join("backend/Cargo.toml"),
108        &[(
109            "lettre",
110            r#"{ version = "0.11", features = ["tokio1-native-tls"] }"#,
111        )],
112    )?;
113
114    // Add env vars
115    super::append_env_var(
116        &project_root.join("backend/.env"),
117        "SMTP_HOST=smtp.example.com",
118    )?;
119    super::append_env_var(
120        &project_root.join("backend/.env"),
121        "SMTP_PORT=587",
122    )?;
123    super::append_env_var(
124        &project_root.join("backend/.env"),
125        "SMTP_USER=your_smtp_user",
126    )?;
127    super::append_env_var(
128        &project_root.join("backend/.env"),
129        "SMTP_PASS=your_smtp_password",
130    )?;
131    super::append_env_var(
132        &project_root.join("backend/.env"),
133        "FROM_EMAIL=noreply@example.com",
134    )?;
135
136    super::append_env_var(
137        &project_root.join("backend/.env.example"),
138        "SMTP_HOST=smtp.example.com",
139    )?;
140    super::append_env_var(
141        &project_root.join("backend/.env.example"),
142        "SMTP_PORT=587",
143    )?;
144    super::append_env_var(
145        &project_root.join("backend/.env.example"),
146        "SMTP_USER=",
147    )?;
148    super::append_env_var(
149        &project_root.join("backend/.env.example"),
150        "SMTP_PASS=",
151    )?;
152    super::append_env_var(
153        &project_root.join("backend/.env.example"),
154        "FROM_EMAIL=noreply@example.com",
155    )?;
156
157    // Update romance.toml
158    super::update_feature_flag(project_root, "email", true)?;
159
160    println!();
161    println!(
162        "{}",
163        "Email system installed successfully!".green().bold()
164    );
165    println!("  Configure SMTP settings in backend/.env");
166    println!("  Use EmailService::new() to create an instance.");
167    println!("  Password reset handler available at /api/auth/password-reset");
168
169    Ok(())
170}