add news getters

EBO <eric.bouhana@softalys.com> committé le 2026-03-25 21:21

acbcd02b0c166826559298388dcc006c138505fc

1 parent(s)

2 fichiers modifiés +102 -11
M crates/rustwarden-core/src/app.rs
+50 -0
@@ -39,9 +39,16 @@ use crate::services::app_settings_service::AppSettingsService;
39 39 use crate::services::default_admin_service;
40 40
41 41 /// A fully configured Rustwarden application ready to run.
42 +///
43 +/// After `build()`, getters expose internal resources (DB, config, i18n)
44 +/// so consumer apps can run migrations, seed data, or translate messages
45 +/// before calling `run()`.
42 46 pub struct RustwardenApp {
43 47 router: Router,
44 48 address: String,
49 + db: DatabaseConnection,
50 + auth_config: Arc<AuthConfig>,
51 + i18n: Arc<I18nService>,
45 52 }
46 53
47 54 impl RustwardenApp {
@@ -50,6 +57,43 @@ impl RustwardenApp {
50 57 RustwardenBuilder::default()
51 58 }
52 59
60 + /// Access the database connection (pool) used by the framework.
61 + ///
62 + /// Allows consumer apps to run business migrations, seed data, or
63 + /// execute queries on the same connection pool as the framework.
64 + ///
65 + /// # Examples
66 + ///
67 + /// ```rust,ignore
68 + /// let app = RustwardenApp::builder().from_env().build().await?;
69 + /// my_app::migrations::run_migrations(app.database()).await?;
70 + /// app.run().await
71 + /// ```
72 + pub fn database(&self) -> &DatabaseConnection {
73 + &self.db
74 + }
75 +
76 + /// Access the authentication configuration.
77 + ///
78 + /// Exposes JWT settings, session timeouts, rate limits, and cookie
79 + /// configuration for consumer app logic that depends on auth parameters.
80 + pub fn auth_config(&self) -> &AuthConfig {
81 + &self.auth_config
82 + }
83 +
84 + /// Access the i18n translation service.
85 + ///
86 + /// Allows consumer apps to translate messages in non-handler code
87 + /// (cron tasks, seeding, CLI) or load additional translations after build.
88 + pub fn i18n_service(&self) -> &Arc<I18nService> {
89 + &self.i18n
90 + }
91 +
92 + /// Server bind address (e.g. "0.0.0.0:3000").
93 + pub fn address(&self) -> &str {
94 + &self.address
95 + }
96 +
53 97 /// Get the assembled router (for advanced usage, e.g. testing).
54 98 pub fn into_router(self) -> Router {
55 99 self.router
@@ -370,9 +414,12 @@ impl RustwardenBuilder {
370 414 let default = self.default_locale.clone();
371 415 let db_for_admin = db.clone();
372 416 let db_for_auth = db.clone();
417 + let db_for_app = db.clone(); // Retained for getter access after build
373 418
374 419 let hooks = self.hooks.clone();
375 420 let db_for_ext = db.clone();
421 + let i18n_for_app = i18n_service.clone(); // Retained for getter access after build
422 + let auth_config_for_app = auth_config.clone(); // Retained for getter access after build
376 423 let app = router.with_state(db).layer(
377 424 ServiceBuilder::new()
378 425 .layer(axum::middleware::from_fn(security_headers_middleware))
@@ -403,6 +450,9 @@ impl RustwardenBuilder {
403 450 Ok(RustwardenApp {
404 451 router: app,
405 452 address,
453 + db: db_for_app,
454 + auth_config: auth_config_for_app,
455 + i18n: i18n_for_app,
406 456 })
407 457 }
408 458
M docs/project_rustwarden_db_getter.md
+52 -11
@@ -1,15 +1,15 @@
1 1 ---
2 2 name: Rustwarden DB getter improvement
3 -description: RustwardenApp manque d'un getter database() — workaround actuel dans main.rs, amelioration upstream a envisager
3 +description: RustwardenApp manque de getters (database, auth_config, i18n_service, address) — amelioration upstream
4 4 type: project
5 5 ---
6 6
7 7 # Specification : Exposition de getters sur `RustwardenApp`
8 8
9 -**Version** : 1.0
9 +**Version** : 1.1
10 10 **Date** : 2026-03-25
11 11 **Composant** : `rustwarden-core` (crate framework)
12 -**Statut** : Proposition
12 +**Statut** : Implemente
13 13
14 14 ---
15 15
@@ -67,6 +67,7 @@ pub struct RustwardenApp {
67 67 address: String,
68 68 db: DatabaseConnection, // Nouveau
69 69 auth_config: Arc<AuthConfig>, // Nouveau
70 + i18n: Arc<I18nService>, // Nouveau
70 71 }
71 72 ```
72 73
@@ -81,6 +82,7 @@ Ok(RustwardenApp {
81 82 address,
82 83 db: db_for_app,
83 84 auth_config,
85 + i18n: i18n_service.clone(),
84 86 })
85 87 ```
86 88
@@ -101,6 +103,15 @@ impl RustwardenApp {
101 103 &self.auth_config
102 104 }
103 105
106 + /// Acces au service d'internationalisation.
107 + ///
108 + /// Permet aux consommateurs de traduire des messages dans du code
109 + /// non-handler (taches cron, seeding, CLI) ou de charger des
110 + /// traductions supplementaires apres build.
111 + pub fn i18n_service(&self) -> &Arc<I18nService> {
112 + &self.i18n
113 + }
114 +
104 115 /// Adresse de bind du serveur (ex: "0.0.0.0:3000").
105 116 pub fn address(&self) -> &str {
106 117 &self.address
@@ -131,9 +142,19 @@ app.run().await
131 142
132 143 Plus besoin de `create_connection()` ni de `.clone()` dans le main.
133 144
134 -## 4. Analyse des risques
145 +## 4. Getters evalues et rejetes
135 146
136 -### 4.1 Risques du changement
147 +| Getter | Raison du rejet |
148 +|--------|----------------|
149 +| `config()` (generique) | Il n'existe pas de struct `AppConfig` unifiee. `ServerConfig`, `EmailConfig`, `AuthConfig` sont des structs distinctes chargees a des moments differents. Des getters specifiques sont plus explicites. |
150 +| `state()` | Le "state" Axum du router est `DatabaseConnection`. Exposer `state()` serait redondant avec `database()` et fuiterait un detail d'implementation Axum. |
151 +| `hooks()` | Les hooks sont passes au builder par le consommateur lui-meme — il les possede deja. Les re-exposer n'apporte rien. |
152 +| `router()` (ref) | `into_router()` existe deja (consomme `self`). Un `&Router` immutable est inutile — on ne peut rien en faire sans le posseder. |
153 +| `session_layer()` | Detail d'implementation interne du middleware stack. Le consommateur n'a jamais besoin de manipuler le session layer directement. |
154 +
155 +## 5. Analyse des risques
156 +
157 +### 5.1 Risques du changement
137 158
138 159 | Risque | Severite | Mitigation |
139 160 |--------|----------|------------|
@@ -143,7 +164,7 @@ Plus besoin de `create_connection()` ni de `.clone()` dans le main.
143 164 | **Utilisation apres `run()`** | Nulle | `run()` consomme `self` (`self`, pas `&self`). Apres `run()`, l'app n'existe plus — aucun risque d'acces concurrent via le getter. |
144 165 | **Acces DB entre `build()` et `run()`** | Faible | Fenetre d'acces intentionnelle et utile (migrations metier, seeding). Les taches de fond (email queue, JWT cleanup) tournent deja dans cette fenetre via des `tokio::spawn` — pas de nouveau risque. |
145 166
146 -### 4.2 Risques de NE PAS faire le changement
167 +### 5.2 Risques de NE PAS faire le changement
147 168
148 169 | Risque | Severite | Impact |
149 170 |--------|----------|--------|
@@ -152,7 +173,7 @@ Plus besoin de `create_connection()` ni de `.clone()` dans le main.
152 173 | **Impossibilite de migrer apres build** | Moyenne | Le pattern actuel force a migrer AVANT `build()`. Les consommateurs qui veulent `auto_migrate(true)` pour les tables framework mais ensuite migrer leurs propres tables ne peuvent pas le faire proprement. |
153 174 | **Framework non idiomatique** | Faible | Le builder pattern en Rust expose generalement des getters sur le produit construit. L'absence degrade l'ergonomie et la credibilite du framework. |
154 175
155 -## 5. Avantages
176 +## 6. Avantages
156 177
157 178 | Avantage | Impact |
158 179 |----------|--------|
@@ -163,7 +184,7 @@ Plus besoin de `create_connection()` ni de `.clone()` dans le main.
163 184 | **Testabilite** | Les tests d'integration peuvent `app.database()` pour setup/teardown les donnees sans reconstruire une connexion |
164 185 | **Extensibilite future** | Ouvre la voie a d'autres getters (`i18n_service()`, `hooks()`) sans repenser l'architecture |
165 186
166 -## 6. Retrocompatibilite
187 +## 7. Retrocompatibilite
167 188
168 189 | Composant | Impact |
169 190 |-----------|--------|
@@ -175,20 +196,40 @@ Plus besoin de `create_connection()` ni de `.clone()` dans le main.
175 196 | Prelude | Aucun changement requis — `RustwardenApp` est deja exporte |
176 197 | CLI wizard templates | Aucun changement requis — le code genere peut adopter le nouveau pattern progressivement |
177 198
178 -## 7. Fichiers impactes
199 +## 8. Fichiers impactes
179 200
180 201 | Fichier | Modification |
181 202 |---------|-------------|
182 -| `crates/rustwarden-core/src/app.rs` | Ajout de `db` et `auth_config` dans `RustwardenApp`, getters, clone dans `build()` |
203 +| `crates/rustwarden-core/src/app.rs` | Ajout de `db`, `auth_config`, `i18n` dans `RustwardenApp`, 4 getters, clones dans `build()` |
183 204
184 205 Un seul fichier impacte. Aucune migration, aucun changement de dependance.
185 206
186 -## 8. Criteres d'acceptation
207 +## 9. Criteres d'acceptation
187 208
188 209 - [ ] `app.database()` retourne `&DatabaseConnection` fonctionnelle apres `build()`
189 210 - [ ] `app.auth_config()` retourne `&AuthConfig` fonctionnelle apres `build()`
211 +- [ ] `app.i18n_service()` retourne `&Arc<I18nService>` fonctionnelle apres `build()`
190 212 - [ ] `app.address()` retourne l'adresse de bind
191 213 - [ ] Les projets consommateurs existants compilent sans modification
192 214 - [ ] Le pattern `builder().database(db).build()` continue de fonctionner (retrocompat)
193 215 - [ ] `cargo clippy -- -D warnings` passe sans avertissement
194 216 - [ ] `cargo test` — les tests existants passent sans modification
217 +
218 +Resume des changements :
219 +
220 +Spec mise a jour (project_rustwarden_db_getter.md) — version 1.1 avec :
221 +
222 +i18n_service() ajoute aux getters proposes
223 +Section 4 "Getters evalues et rejetes" (config(), state(), hooks(), router(), session_layer())
224 +Numerotation et criteres d'acceptation mis a jour
225 +Implementation dans app.rs :
226 +
227 +RustwardenApp stocke maintenant db, auth_config, i18n en plus du router et address
228 +4 getters publics documentes : database(), auth_config(), i18n_service(), address()
229 +Les clones sont places juste avant la consommation dans les layers (cout negligeable — Arc et DatabaseConnection sont des copies de pointeurs)
230 +Les projets consommateurs peuvent maintenant ecrire :
231 +
232 +
233 +let app = RustwardenApp::builder().from_env().auto_migrate(true).build().await?;
234 +my_app::migrations::run_migrations(app.database()).await?;
235 +app.run().await
235 < \ No newline at end of file