doido_auth/generators/
mod.rs1pub mod field;
5pub mod migration_support;
6pub mod names;
7pub mod route_injector;
8
9pub use field::Field;
10pub use names::{to_pascal, to_snake, to_table_name};
11
12pub mod controller;
13pub mod install;
14pub mod scaffold;
15
16pub use controller::AuthControllerGenerator;
17pub use install::AuthInstallGenerator;
18pub use scaffold::AuthScaffoldGenerator;
19
20use doido_core::Result;
21
22#[derive(Debug, Clone)]
24pub struct GeneratedFile {
25 pub path: String,
26 pub content: String,
27}
28
29pub trait AuthGenerator: Send + Sync {
32 fn name(&self) -> &str;
33 fn generate(&self, args: &[&str]) -> Result<Vec<GeneratedFile>>;
34}
35
36pub trait AuthGeneratorRegistry {
38 fn register_auth(&mut self, generator: Box<dyn AuthGenerator>);
39}
40
41pub fn register(reg: &mut impl AuthGeneratorRegistry) {
43 reg.register_auth(Box::new(install::AuthInstallGenerator));
44 reg.register_auth(Box::new(controller::AuthControllerGenerator));
45 reg.register_auth(Box::new(scaffold::AuthScaffoldGenerator));
46}
47
48pub(crate) fn template(rel: &str) -> &'static str {
50 match rel {
51 "migration.rs.template" => include_str!("../../templates/migration.rs.template"),
52 "user.rs.template" => include_str!("../../templates/user.rs.template"),
53 "user_entity.rs.template" => include_str!("../../templates/user_entity.rs.template"),
54 "auth/mod.rs.template" => include_str!("../../templates/auth/mod.rs.template"),
55 "auth/sessions_controller_html.rs.template" => {
56 include_str!("../../templates/auth/sessions_controller_html.rs.template")
57 }
58 "auth/sessions_controller_api.rs.template" => {
59 include_str!("../../templates/auth/sessions_controller_api.rs.template")
60 }
61 "auth/registrations_controller_html.rs.template" => {
62 include_str!("../../templates/auth/registrations_controller_html.rs.template")
63 }
64 "auth/registrations_controller_api.rs.template" => {
65 include_str!("../../templates/auth/registrations_controller_api.rs.template")
66 }
67 "auth/passwords_controller_html.rs.template" => {
68 include_str!("../../templates/auth/passwords_controller_html.rs.template")
69 }
70 "auth/passwords_controller_api.rs.template" => {
71 include_str!("../../templates/auth/passwords_controller_api.rs.template")
72 }
73 "auth/oauth_controller.rs.template" => {
74 include_str!("../../templates/auth/oauth_controller.rs.template")
75 }
76 "auth/two_factor_controller_html.rs.template" => {
77 include_str!("../../templates/auth/two_factor_controller_html.rs.template")
78 }
79 "auth/two_factor_controller_api.rs.template" => {
80 include_str!("../../templates/auth/two_factor_controller_api.rs.template")
81 }
82 "auth/views/sign_in.html.tera" => {
83 include_str!("../../templates/auth/views/sign_in.html.tera")
84 }
85 "auth/views/sign_up.html.tera" => {
86 include_str!("../../templates/auth/views/sign_up.html.tera")
87 }
88 "auth/views/password_new.html.tera" => {
89 include_str!("../../templates/auth/views/password_new.html.tera")
90 }
91 "auth/views/password_edit.html.tera" => {
92 include_str!("../../templates/auth/views/password_edit.html.tera")
93 }
94 "auth/views/two_factor.html.tera" => {
95 include_str!("../../templates/auth/views/two_factor.html.tera")
96 }
97 "auth_controller.rs.template" => {
98 include_str!("../../templates/auth_controller.rs.template")
99 }
100 "scaffold/controller_html.rs.template" => {
101 include_str!("../../templates/scaffold/controller_html.rs.template")
102 }
103 "scaffold/controller_api.rs.template" => {
104 include_str!("../../templates/scaffold/controller_api.rs.template")
105 }
106 "scaffold/model.rs.template" => include_str!("../../templates/scaffold/model.rs.template"),
107 "scaffold/entity.rs.template" => {
108 include_str!("../../templates/scaffold/entity.rs.template")
109 }
110 "scaffold/views/index.html.tera" => {
111 include_str!("../../templates/scaffold/views/index.html.tera")
112 }
113 "scaffold/views/show.html.tera" => {
114 include_str!("../../templates/scaffold/views/show.html.tera")
115 }
116 "scaffold/views/new.html.tera" => {
117 include_str!("../../templates/scaffold/views/new.html.tera")
118 }
119 "scaffold/views/edit.html.tera" => {
120 include_str!("../../templates/scaffold/views/edit.html.tera")
121 }
122 "scaffold/views/_form.html.tera" => {
123 include_str!("../../templates/scaffold/views/_form.html.tera")
124 }
125 other => panic!("unknown auth generator template: {other}"),
126 }
127}
128
129pub(crate) fn register_module(existing: &str, module: &str, marker: &str) -> String {
131 let decl = format!("pub mod {module};");
132 if existing.lines().any(|l| l.trim() == decl) {
133 return existing.to_string();
134 }
135 let mut lines: Vec<String> = existing.lines().map(String::from).collect();
136 match lines.iter().position(|l| l.contains(marker)) {
137 Some(i) => lines.insert(i, decl),
138 None => lines.push(decl),
139 }
140 let mut out = lines.join("\n");
141 out.push('\n');
142 out
143}