diff --git a/src/main/java/br/com/acta/common/config/swagger/annotation/ApiAuthenticationConflictResponses.java b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiAuthenticationConflictResponses.java new file mode 100644 index 0000000..9440217 --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiAuthenticationConflictResponses.java @@ -0,0 +1,13 @@ +package br.com.acta.common.config.swagger.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@ApiAuthenticationResponses +@ApiConflictResponse +public @interface ApiAuthenticationConflictResponses { +} diff --git a/src/main/java/br/com/acta/common/config/swagger/annotation/ApiAuthenticationResponses.java b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiAuthenticationResponses.java new file mode 100644 index 0000000..a936e8b --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiAuthenticationResponses.java @@ -0,0 +1,31 @@ +package br.com.acta.common.config.swagger.annotation; + +import br.com.acta.common.config.swagger.examples.SwaggerResponseExamples; +import br.com.acta.common.handler.ErroResponse; +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 java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@ApiResponses({ + @ApiResponse( + responseCode = "401", + description = "ID Token do Firebase ausente ou inválido", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErroResponse.class), examples = @ExampleObject(value = SwaggerResponseExamples.ERRO_401)) + ), + @ApiResponse( + responseCode = "403", + description = "Usuário sem permissão para acessar o recurso", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErroResponse.class), examples = @ExampleObject(value = SwaggerResponseExamples.ERRO_403)) + ) +}) +public @interface ApiAuthenticationResponses { +} \ No newline at end of file diff --git a/src/main/java/br/com/acta/common/config/swagger/annotation/ApiBadRequestResponse.java b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiBadRequestResponse.java new file mode 100644 index 0000000..2d61a10 --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiBadRequestResponse.java @@ -0,0 +1,23 @@ +package br.com.acta.common.config.swagger.annotation; + +import br.com.acta.common.config.swagger.examples.SwaggerResponseExamples; +import br.com.acta.common.handler.ErroResponse; +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 java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@ApiResponse( + responseCode = "400", + description = "Requisição inválida", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErroResponse.class), examples = @ExampleObject(value = SwaggerResponseExamples.ERRO_400)) +) +public @interface ApiBadRequestResponse { +} \ No newline at end of file diff --git a/src/main/java/br/com/acta/common/config/swagger/annotation/ApiBusinessRuleResponse.java b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiBusinessRuleResponse.java new file mode 100644 index 0000000..deb491c --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiBusinessRuleResponse.java @@ -0,0 +1,23 @@ +package br.com.acta.common.config.swagger.annotation; + +import br.com.acta.common.config.swagger.examples.SwaggerResponseExamples; +import br.com.acta.common.handler.ErroResponse; +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 java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@ApiResponse( + responseCode = "422", + description = "Regra de negócio não atendida", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErroResponse.class), examples = @ExampleObject(value = SwaggerResponseExamples.ERRO_422)) +) +public @interface ApiBusinessRuleResponse { +} \ No newline at end of file diff --git a/src/main/java/br/com/acta/common/config/swagger/annotation/ApiConflictResponse.java b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiConflictResponse.java new file mode 100644 index 0000000..8ee5a03 --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiConflictResponse.java @@ -0,0 +1,23 @@ +package br.com.acta.common.config.swagger.annotation; + +import br.com.acta.common.config.swagger.examples.SwaggerResponseExamples; +import br.com.acta.common.handler.ErroResponse; +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 java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@ApiResponse( + responseCode = "409", + description = "Conflito com os dados existentes", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErroResponse.class), examples = @ExampleObject(value = SwaggerResponseExamples.ERRO_409)) +) +public @interface ApiConflictResponse { +} \ No newline at end of file diff --git a/src/main/java/br/com/acta/common/config/swagger/annotation/ApiNotFoundResponse.java b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiNotFoundResponse.java new file mode 100644 index 0000000..eca1a4d --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/annotation/ApiNotFoundResponse.java @@ -0,0 +1,23 @@ +package br.com.acta.common.config.swagger.annotation; + +import br.com.acta.common.config.swagger.examples.SwaggerResponseExamples; +import br.com.acta.common.handler.ErroResponse; +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 java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@ApiResponse( + responseCode = "404", + description = "Recurso não encontrado", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErroResponse.class), examples = @ExampleObject(value = SwaggerResponseExamples.ERRO_404)) +) +public @interface ApiNotFoundResponse { +} \ No newline at end of file diff --git a/src/main/java/br/com/acta/common/config/swagger/openapi/AuthOpenapi.java b/src/main/java/br/com/acta/common/config/swagger/openapi/AuthOpenapi.java new file mode 100644 index 0000000..67fc82f --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/openapi/AuthOpenapi.java @@ -0,0 +1,48 @@ +package br.com.acta.common.config.swagger.openapi; + +import br.com.acta.common.config.firebase.FirebaseAuthFilter.FirebaseIdentity; +import br.com.acta.common.config.swagger.annotation.ApiAuthenticationConflictResponses; +import br.com.acta.common.config.swagger.annotation.ApiAuthenticationResponses; +import br.com.acta.common.config.swagger.annotation.ApiBusinessRuleResponse; +import br.com.acta.common.config.swagger.annotation.ApiNotFoundResponse; +import br.com.acta.common.config.swagger.examples.SwaggerOpenapiDescriptions; +import br.com.acta.dto.auth.AtivarRequestDTO; +import br.com.acta.dto.auth.ConviteRequestDTO; +import br.com.acta.dto.auth.MeResponseDTO; +import br.com.acta.dto.core.colaborador.ColaboradorResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; + +@Tag(name = "Autenticação", description = SwaggerOpenapiDescriptions.AUTH_CONTROLLER) +public interface AuthOpenapi { + + @Operation(summary = "Consulta o usuário autenticado") + @ApiResponse(responseCode = "200", description = "Identidade Firebase válida; estadoPerfil informa PERFIL_CRIADO ou CADASTRO_NAO_INICIADO", content = @Content(schema = @Schema(implementation = MeResponseDTO.class))) + @ApiAuthenticationResponses + ResponseEntity me(@Parameter(hidden = true) FirebaseIdentity identity); + + @Operation(summary = "Ativa o usuário autenticado com código de convite") + @ApiResponse(responseCode = "200", description = "Usuário ativado", content = @Content(schema = @Schema(implementation = MeResponseDTO.class))) + @ApiAuthenticationConflictResponses + @ApiNotFoundResponse + ResponseEntity ativar(@Parameter(hidden = true) FirebaseIdentity identity, @RequestBody(description = "Código alfanumérico recebido por e-mail", required = true) @Valid AtivarRequestDTO request); + + @Operation(summary = "Cadastra um colaborador e envia convite de acesso") + @ApiResponse(responseCode = "201", description = "Convite criado e enviado", content = @Content(schema = @Schema(implementation = ColaboradorResponseDTO.class))) + @ApiAuthenticationConflictResponses + @ApiBusinessRuleResponse + ResponseEntity convidar(@RequestBody(description = "Dados do colaborador e acesso", required = true) @Valid ConviteRequestDTO request); + + @Operation(summary = "Reenvia o convite de um colaborador pendente") + @ApiResponse(responseCode = "204", description = "Convite reenviado") + @ApiAuthenticationConflictResponses + @ApiBusinessRuleResponse + ResponseEntity reenviarConvite(@Parameter(description = "ID do colaborador") Long idColaborador); +} \ No newline at end of file diff --git a/src/main/java/br/com/acta/common/config/swagger/openapi/HealthOpenapi.java b/src/main/java/br/com/acta/common/config/swagger/openapi/HealthOpenapi.java new file mode 100644 index 0000000..edd96ea --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/openapi/HealthOpenapi.java @@ -0,0 +1,22 @@ +package br.com.acta.common.config.swagger.openapi; + +import br.com.acta.common.config.swagger.examples.SwaggerOpenapiDescriptions; +import br.com.acta.dto.health.HealthResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +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 org.springframework.http.ResponseEntity; + +@Tag(name = "Saúde", description = SwaggerOpenapiDescriptions.HEALTH_CONTROLLER) +public interface HealthOpenapi { + + @Operation(summary = "Verifica a saúde da API") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "API e banco de dados disponíveis", content = @Content(schema = @Schema(implementation = HealthResponseDTO.class))), + @ApiResponse(responseCode = "503", description = "Banco de dados indisponível", content = @Content(schema = @Schema(implementation = HealthResponseDTO.class))) + }) + ResponseEntity verificar(); +} \ No newline at end of file diff --git a/src/main/java/br/com/acta/common/config/swagger/openapi/OnboardingOpenapi.java b/src/main/java/br/com/acta/common/config/swagger/openapi/OnboardingOpenapi.java new file mode 100644 index 0000000..1ef4ec6 --- /dev/null +++ b/src/main/java/br/com/acta/common/config/swagger/openapi/OnboardingOpenapi.java @@ -0,0 +1,33 @@ +package br.com.acta.common.config.swagger.openapi; + +import br.com.acta.common.config.firebase.FirebaseAuthFilter.FirebaseIdentity; +import br.com.acta.common.config.swagger.annotation.ApiAuthenticationConflictResponses; +import br.com.acta.common.config.swagger.annotation.ApiBadRequestResponse; +import br.com.acta.common.config.swagger.examples.SwaggerOpenapiDescriptions; +import br.com.acta.dto.onboarding.OnboardingInicioRequestDTO; +import br.com.acta.dto.onboarding.OnboardingRequestDTO; +import br.com.acta.dto.onboarding.OnboardingResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; + +@Tag(name = "Onboarding", description = SwaggerOpenapiDescriptions.ONBOARDING_CONTROLLER) +public interface OnboardingOpenapi { + @Operation(summary = "Verifica a empresa e inicia o onboarding do gestor") + @ApiResponse(responseCode = "200", description = "Empresa identificada, orientação para solicitar convite a um ADMIN ativo ou próxima etapa liberada", content = @Content(schema = @Schema(implementation = OnboardingResponseDTO.class))) + @ApiAuthenticationConflictResponses + @ApiBadRequestResponse + ResponseEntity iniciar(@Parameter(hidden = true) FirebaseIdentity identity, @RequestBody(description = "Dados do gestor e CNPJ da empresa", required = true, content = @Content(schema = @Schema(implementation = OnboardingInicioRequestDTO.class))) OnboardingInicioRequestDTO dto); + + @Operation(summary = "Cadastra a empresa e seu primeiro gestor") + @ApiResponse(responseCode = "201", description = "Empresa criada e primeiro gestor ativado", content = @Content(schema = @Schema(implementation = OnboardingResponseDTO.class))) + @ApiAuthenticationConflictResponses + @ApiBadRequestResponse + ResponseEntity cadastrarEmpresa(@Parameter(hidden = true) FirebaseIdentity identity, @RequestBody(description = "Dados do gestor, empresa e endereço principal", required = true, content = @Content(schema = @Schema(implementation = OnboardingRequestDTO.class))) OnboardingRequestDTO dto); + +} \ No newline at end of file