@@ -33,7 +33,7 @@ use schemars::JsonSchema;
3333use serde:: { Deserialize , Serialize } ;
3434
3535use super :: errors:: CreateConfigError ;
36- use crate :: shared:: { DomainName , Email } ;
36+ use crate :: shared:: Email ;
3737
3838/// Common HTTPS configuration (top-level)
3939///
@@ -126,62 +126,6 @@ impl HttpsSection {
126126 }
127127}
128128
129- /// Service-specific TLS configuration
130- ///
131- /// Embedded in each service that supports HTTPS. The presence of this
132- /// configuration indicates that TLS should be enabled for the service.
133- ///
134- /// # Domain Requirements
135- ///
136- /// The domain must:
137- /// - Point to the deployment server's IP via DNS
138- /// - Be owned/controlled by the deployer
139- /// - Be configured before deployment (for HTTP-01 challenge)
140- ///
141- /// # Examples
142- ///
143- /// ```json
144- /// {
145- /// "tls": {
146- /// "domain": "api.example.com"
147- /// }
148- /// }
149- /// ```
150- #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize , JsonSchema ) ]
151- pub struct TlsSection {
152- /// Domain name for this service
153- ///
154- /// This domain will be used for:
155- /// - HTTPS certificate acquisition (Let's Encrypt HTTP-01 challenge)
156- /// - Caddy reverse proxy routing
157- /// - SNI-based TLS termination
158- pub domain : String ,
159- }
160-
161- impl TlsSection {
162- /// Creates a new TLS configuration section
163- #[ must_use]
164- pub fn new ( domain : String ) -> Self {
165- Self { domain }
166- }
167-
168- /// Validates the TLS configuration
169- ///
170- /// Uses the domain-level `DomainName` type for DNS-compliant validation.
171- ///
172- /// # Errors
173- ///
174- /// Returns `CreateConfigError::InvalidDomain` if the domain format is invalid.
175- pub fn validate ( & self ) -> Result < ( ) , CreateConfigError > {
176- // Validate domain using the domain type for DNS-compliant validation
177- DomainName :: new ( & self . domain ) . map_err ( |e| CreateConfigError :: InvalidDomain {
178- domain : self . domain . clone ( ) ,
179- reason : e. to_string ( ) ,
180- } ) ?;
181- Ok ( ( ) )
182- }
183- }
184-
185129#[ cfg( test) ]
186130mod tests {
187131 use super :: * ;
@@ -248,86 +192,6 @@ mod tests {
248192 }
249193 }
250194
251- mod tls_section_tests {
252- use super :: * ;
253-
254- #[ test]
255- fn it_should_create_tls_section ( ) {
256- let section = TlsSection :: new ( "api.example.com" . to_string ( ) ) ;
257- assert_eq ! ( section. domain, "api.example.com" ) ;
258- }
259-
260- #[ test]
261- fn it_should_validate_valid_domain ( ) {
262- let section = TlsSection :: new ( "api.example.com" . to_string ( ) ) ;
263- assert ! ( section. validate( ) . is_ok( ) ) ;
264- }
265-
266- #[ test]
267- fn it_should_validate_subdomain ( ) {
268- let section = TlsSection :: new ( "sub.api.example.com" . to_string ( ) ) ;
269- assert ! ( section. validate( ) . is_ok( ) ) ;
270- }
271-
272- #[ test]
273- fn it_should_reject_empty_domain ( ) {
274- let section = TlsSection :: new ( String :: new ( ) ) ;
275- assert ! ( section. validate( ) . is_err( ) ) ;
276- }
277-
278- #[ test]
279- fn it_should_reject_domain_without_tld ( ) {
280- let section = TlsSection :: new ( "localhost" . to_string ( ) ) ;
281- assert ! ( section. validate( ) . is_err( ) ) ;
282- }
283-
284- #[ test]
285- fn it_should_reject_domain_starting_with_dot ( ) {
286- let section = TlsSection :: new ( ".example.com" . to_string ( ) ) ;
287- assert ! ( section. validate( ) . is_err( ) ) ;
288- }
289-
290- #[ test]
291- fn it_should_reject_domain_ending_with_dot ( ) {
292- let section = TlsSection :: new ( "example.com." . to_string ( ) ) ;
293- assert ! ( section. validate( ) . is_err( ) ) ;
294- }
295-
296- #[ test]
297- fn it_should_reject_domain_with_consecutive_dots ( ) {
298- let section = TlsSection :: new ( "example..com" . to_string ( ) ) ;
299- assert ! ( section. validate( ) . is_err( ) ) ;
300- }
301-
302- #[ test]
303- fn it_should_reject_domain_with_whitespace ( ) {
304- let section = TlsSection :: new ( "my domain.com" . to_string ( ) ) ;
305- assert ! ( section. validate( ) . is_err( ) ) ;
306- }
307-
308- #[ test]
309- fn it_should_accept_domain_with_hyphen ( ) {
310- // Hyphens are allowed in domain names
311- let section = TlsSection :: new ( "my-service.example.com" . to_string ( ) ) ;
312- assert ! ( section. validate( ) . is_ok( ) ) ;
313- }
314-
315- #[ test]
316- fn it_should_accept_domain_with_underscore ( ) {
317- // Underscores are allowed with minimal validation
318- // (they're valid in some DNS contexts like SRV records)
319- let section = TlsSection :: new ( "my_service.example.com" . to_string ( ) ) ;
320- assert ! ( section. validate( ) . is_ok( ) ) ;
321- }
322-
323- #[ test]
324- fn it_should_deserialize_from_json ( ) {
325- let json = r#"{"domain": "api.torrust.com"}"# ;
326- let section: TlsSection = serde_json:: from_str ( json) . unwrap ( ) ;
327- assert_eq ! ( section. domain, "api.torrust.com" ) ;
328- }
329- }
330-
331195 /// Tests for email validation in HTTPS context
332196 ///
333197 /// Note: Comprehensive email format validation tests are in `src/shared/email.rs`.
@@ -351,28 +215,4 @@ mod tests {
351215 ) ) ;
352216 }
353217 }
354-
355- /// Tests for domain validation in TLS context
356- ///
357- /// Note: Comprehensive domain format validation tests are in `src/shared/domain_name.rs`.
358- /// These tests verify the integration of the `DomainName` type with `TlsSection`.
359- mod domain_validation_integration_tests {
360- use super :: * ;
361-
362- #[ test]
363- fn it_should_accept_dns_compliant_domain ( ) {
364- let section = TlsSection :: new ( "example.com" . to_string ( ) ) ;
365- assert ! ( section. validate( ) . is_ok( ) ) ;
366- }
367-
368- #[ test]
369- fn it_should_reject_dns_non_compliant_domain ( ) {
370- let section = TlsSection :: new ( "localhost" . to_string ( ) ) ;
371- let result = section. validate ( ) ;
372- assert ! ( matches!(
373- result,
374- Err ( CreateConfigError :: InvalidDomain { .. } )
375- ) ) ;
376- }
377- }
378218}
0 commit comments