docs(api): add API documentation
This commit is contained in:
parent
d417a46a06
commit
fb0ddf391f
@ -26,13 +26,6 @@
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger/OpenAPI -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
|
@ -74,6 +74,14 @@
|
||||
<version>1.39.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Swagger/OpenAPI -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.apis</groupId>
|
||||
<artifactId>google-api-services-gmail</artifactId>
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.pablotj.restemailbridge.infrastructure.config;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||
import io.swagger.v3.oas.models.media.StringSchema;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springdoc.core.customizers.OpenApiCustomizer;
|
||||
@Configuration
|
||||
public class OpenApiConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
return new OpenAPI()
|
||||
.info(new Info()
|
||||
.title("Rest Email Bridge API")
|
||||
.version("v1")
|
||||
.description("API for sending and managing emails")
|
||||
.license(new License().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0"))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public OpenApiCustomizer globalHeaderCustomizer() {
|
||||
return openApi -> openApi.getPaths().values().forEach(pathItem ->
|
||||
pathItem.readOperations().forEach(operation ->
|
||||
operation.addParametersItem(
|
||||
new Parameter()
|
||||
.in("header")
|
||||
.name("Accept-Language")
|
||||
.description("Language for messages (en, es, gl)")
|
||||
.required(false)
|
||||
.schema(new StringSchema()
|
||||
._default("en")
|
||||
.addEnumItem("en")
|
||||
.addEnumItem("es")
|
||||
.addEnumItem("gl"))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -3,6 +3,13 @@ package com.pablotj.restemailbridge.infrastructure.rest;
|
||||
import com.pablotj.restemailbridge.application.dto.EmailDTO;
|
||||
import com.pablotj.restemailbridge.application.usecase.SendEmailUseCase;
|
||||
import com.pablotj.restemailbridge.infrastructure.rest.dto.SendMailRequest;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -10,18 +17,76 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* REST controller responsible for handling email-related requests.
|
||||
* <p>
|
||||
* Exposes endpoints under {@code /v1/mail} to send emails through the system.
|
||||
* Delegates business logic to the {@link SendEmailUseCase}.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/v1/mail")
|
||||
@Tag(name = "Mail API", description = "Endpoints for sending emails")
|
||||
public class MailController {
|
||||
|
||||
private final SendEmailUseCase sendEmailUseCase;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MailController} instance.
|
||||
*
|
||||
* @param sendEmailUseCase the use case responsible for sending emails
|
||||
*/
|
||||
public MailController(SendEmailUseCase sendEmailUseCase) {
|
||||
this.sendEmailUseCase = sendEmailUseCase;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a new email using the provided request data.
|
||||
* <p>
|
||||
* The request payload is validated using {@link jakarta.validation.Valid}.
|
||||
*
|
||||
* @param request the email request containing sender, subject and body
|
||||
* @return {@link ResponseEntity} with HTTP 200 (OK) if the email is sent successfully
|
||||
*/
|
||||
@PostMapping
|
||||
@Operation(
|
||||
summary = "Send an email",
|
||||
description = "Sends an email using the provided sender, subject, and body.",
|
||||
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||
required = true,
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
examples = @ExampleObject(
|
||||
name = "Basic email",
|
||||
value = "{ \"from\": \"user@example.com\", \"subject\": \"Hello\", \"body\": \"Hi there!\" }"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "Email sent successfully"),
|
||||
@ApiResponse(responseCode = "400", description = "Invalid request payload"),
|
||||
@ApiResponse(
|
||||
responseCode = "401",
|
||||
description = "Unauthorized – missing or invalid authentication token",
|
||||
content = @Content(schema = @Schema(hidden = true))
|
||||
),
|
||||
@ApiResponse(
|
||||
responseCode = "403",
|
||||
description = "Forbidden – the authenticated user cannot send to the specified recipient",
|
||||
content = @Content(schema = @Schema(hidden = true))
|
||||
),
|
||||
@ApiResponse(
|
||||
responseCode = "422",
|
||||
description = "Unprocessable Entity – domain validation failed (e.g. invalid email address, business rule violation)",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(
|
||||
example = "{ \"error\": \"Invalid recipient domain\" }"
|
||||
)
|
||||
)
|
||||
),
|
||||
@ApiResponse(responseCode = "500", description = "Unexpected server error")
|
||||
})
|
||||
public ResponseEntity<Void> send(@Valid @RequestBody SendMailRequest request) {
|
||||
sendEmailUseCase.handle(new EmailDTO(request.from(), request.subject(), request.body()));
|
||||
return ResponseEntity.ok().build();
|
||||
|
@ -1,12 +1,26 @@
|
||||
package com.pablotj.restemailbridge.infrastructure.rest.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@Schema(description = "Request payload to send an email")
|
||||
public record SendMailRequest(
|
||||
@NotBlank @Email @Length(min = 4, max = 100) String from,
|
||||
@NotBlank @Length(min=1, max = 30) String subject,
|
||||
@NotBlank @Length(min=1, max = 4000) String body
|
||||
@NotBlank(message = "{email.from.blank}")
|
||||
@Email(message = "{email.from.invalid}")
|
||||
@Length(min = 4, max = 100, message = "email.from.length}")
|
||||
@Schema(description = "Sender email address", example = "user@example.com")
|
||||
String from,
|
||||
|
||||
@NotBlank(message = "{email.subject.blank}")
|
||||
@Length(min=1, max = 30, message = "{email.subject.length}")
|
||||
@Schema(description = "Email subject", example = "Welcome to RestEmailBridge")
|
||||
String subject,
|
||||
|
||||
@NotBlank(message = "{email.body.blank}")
|
||||
@Length(min=1, max = 4000, message = "{email.body.length}")
|
||||
@Schema(description = "Email body content", example = "Hello, thanks for signing up!")
|
||||
String body
|
||||
) {
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user