diff --git a/pom.xml b/pom.xml index 9fd3161..d87c284 100644 --- a/pom.xml +++ b/pom.xml @@ -136,6 +136,11 @@ org.flywaydb flyway-database-postgresql + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 3.0.3 + diff --git a/src/main/java/com/example/boka/booking/infrastructure/BookingController.java b/src/main/java/com/example/boka/booking/infrastructure/BookingController.java index e01b22d..291f9ca 100644 --- a/src/main/java/com/example/boka/booking/infrastructure/BookingController.java +++ b/src/main/java/com/example/boka/booking/infrastructure/BookingController.java @@ -12,9 +12,12 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; +import io.swagger.v3.oas.annotations.tags.Tag; + import java.util.HashMap; import java.util.Map; +@Tag(name = "Bookings", description = "Create and manage gym class bookings") @RestController @RequestMapping("/api/bookings") @RequiredArgsConstructor diff --git a/src/main/java/com/example/boka/config/OpenApiConfig.java b/src/main/java/com/example/boka/config/OpenApiConfig.java new file mode 100644 index 0000000..e1f7a94 --- /dev/null +++ b/src/main/java/com/example/boka/config/OpenApiConfig.java @@ -0,0 +1,15 @@ +package com.example.boka.config; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.info.Info; +import org.springframework.context.annotation.Configuration; + +@Configuration +@OpenAPIDefinition( + info = @Info( + title = "Boka API", + description = "Gym class booking platform — REST API", + version = "1.0.0" + ) +) +public class OpenApiConfig {} diff --git a/src/main/java/com/example/boka/gym/infrastructure/GymController.java b/src/main/java/com/example/boka/gym/infrastructure/GymController.java index 31e6c4d..54cd83c 100644 --- a/src/main/java/com/example/boka/gym/infrastructure/GymController.java +++ b/src/main/java/com/example/boka/gym/infrastructure/GymController.java @@ -7,10 +7,12 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Tag(name = "Gyms", description = "List and locate gyms") @RestController @RequestMapping("/api/gyms") @RequiredArgsConstructor diff --git a/src/main/java/com/example/boka/gymclass/infrastructure/AdminGymClassController.java b/src/main/java/com/example/boka/gymclass/infrastructure/AdminGymClassController.java index 760d5d2..5542abc 100644 --- a/src/main/java/com/example/boka/gymclass/infrastructure/AdminGymClassController.java +++ b/src/main/java/com/example/boka/gymclass/infrastructure/AdminGymClassController.java @@ -6,6 +6,7 @@ import com.example.boka.gymclass.application.ClassTypeResponse; import com.example.boka.gymclass.application.CreateGymClassRequest; import com.example.boka.gymclass.application.UpdateGymClassRequest; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -17,6 +18,7 @@ import java.util.List; import java.util.Map; +@Tag(name = "Admin", description = "Admin-only: manage gym classes, instructors, and class types") @RestController @RequestMapping("/api/admin") @RequiredArgsConstructor diff --git a/src/main/java/com/example/boka/gymclass/infrastructure/ClassSearchController.java b/src/main/java/com/example/boka/gymclass/infrastructure/ClassSearchController.java index 5294b82..c4f64ad 100644 --- a/src/main/java/com/example/boka/gymclass/infrastructure/ClassSearchController.java +++ b/src/main/java/com/example/boka/gymclass/infrastructure/ClassSearchController.java @@ -10,10 +10,12 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; +@Tag(name = "Classes", description = "Search and browse gym classes") @RestController @RequestMapping("/api/classes") @RequiredArgsConstructor diff --git a/src/main/java/com/example/boka/security/AuthController.java b/src/main/java/com/example/boka/security/AuthController.java index a90a472..5b4482a 100644 --- a/src/main/java/com/example/boka/security/AuthController.java +++ b/src/main/java/com/example/boka/security/AuthController.java @@ -11,12 +11,14 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; import java.util.Optional; +@Tag(name = "Auth", description = "Login, logout, registration, and current user") @RestController @RequestMapping("/api/auth") @RequiredArgsConstructor diff --git a/src/main/java/com/example/boka/security/SecurityConfig.java b/src/main/java/com/example/boka/security/SecurityConfig.java index 2b74a61..fe1d3fe 100644 --- a/src/main/java/com/example/boka/security/SecurityConfig.java +++ b/src/main/java/com/example/boka/security/SecurityConfig.java @@ -58,7 +58,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .cors(Customizer.withDefaults()) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth - .requestMatchers("/", "/index.html", "/search", "/gyms", "/bookings", "/settings", "/admin", "/static/**", "/assets/**", "/api/classes/**", "/api/gyms/**", "/api/auth/me", "/api/auth/register").permitAll() + .requestMatchers("/", "/index.html", "/search", "/gyms", "/bookings", "/settings", "/admin", "/static/**", "/assets/**", "/api/classes/**", "/api/gyms/**", "/api/auth/me", "/api/auth/register", "/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**").permitAll() .requestMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() ) diff --git a/src/main/java/com/example/boka/user/infrastructure/UserController.java b/src/main/java/com/example/boka/user/infrastructure/UserController.java index 455f6f7..756b70e 100644 --- a/src/main/java/com/example/boka/user/infrastructure/UserController.java +++ b/src/main/java/com/example/boka/user/infrastructure/UserController.java @@ -11,11 +11,13 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.validation.BindingResult; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; +@Tag(name = "Users", description = "User profile and account management") @RestController @RequestMapping("/api/users") @RequiredArgsConstructor diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index da532c5..8a190c4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -34,3 +34,8 @@ spring.security.oauth2.client.registration.google.scope=profile,email # Security (temporary - for local testing) spring.security.user.name=admin spring.security.user.password=admin + +# OpenAPI / Swagger UI +springdoc.api-docs.path=/v3/api-docs +springdoc.swagger-ui.path=/swagger-ui.html +springdoc.swagger-ui.try-it-out-enabled=true