Merged
Conversation
Add DELETE /internal/users/{userId}/data endpoint to divination-service
for cascade deletion of user data (spreads and interpretations).
This endpoint will be called by user-service before deleting a user
to ensure data cleanup across services.
Changes:
- Add InternalController with deleteUserData endpoint
- Add deleteUserData method to DivinationService
- Add deleteByAuthorId to SpreadRepository and InterpretationRepository
- Add unit and integration tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add DivinationServiceInternalClient interface for user-service to call divination-service's internal cleanup endpoint. This client is used to delete user data before deleting the user. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add synchronous Feign call to divination-service to delete user data (spreads and interpretations) before deleting the user. User deletion fails with 503 Service Unavailable if cleanup fails. Changes: - Add openfeign and resilience4j dependencies to user-service - Enable Feign clients with @EnableFeignClients - Inject DivinationServiceInternalClient into UserService - Call cleanup endpoint in deleteUser method (fail on error) - Add ServiceUnavailableException for cleanup failures - Update tests with mocked Feign client - Add Resilience4j configuration in highload-config Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove FK constraints from divination-service tables that reference tables owned by other microservices (user-service, tarot-service): - spread.layout_type_id -> layout_type.id - spread.author_id -> user.id - spread_card.card_id -> card.id - interpretation.author_id -> user.id Internal FKs (spread_card -> spread, interpretation -> spread) are preserved for proper cascade delete within the same service. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove user, card, layout_type, and arcana_type table definitions from test initialization since cross-service FKs are dropped. Tests now only create divination-service owned tables (spread, spread_card, interpretation) with internal FKs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add UserCascadeDeleteE2ETest to verify that deleting a user correctly cascades to delete their spreads and interpretations via the internal API call to divination-service. Update CLAUDE.md: - Document database independence (no cross-service FKs) - Add internal API endpoint documentation - Document cascade delete behavior for user deletion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed DivinationServiceInternalClient to use name="divination-service" (the actual Eureka registration) with contextId to differentiate from other clients. Updated Resilience4j config accordingly. This fixes the "Load balancer does not contain an instance" error when user-service tries to call divination-service internal API. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test expected 1 interpretation to remain after user deletion, but the setup didn't create an interpretation by otherUser on their own spread. Added the missing interpretation to match test expectations. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Coverage Report
Files
|
Phase 1 of centralized Swagger UI implementation: - Added springdoc-openapi-starter-webflux-ui:2.8.4 to gateway-service - Created PROGRESS.md to track implementation progress Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2 of centralized Swagger UI implementation: - Updated highload-config with springdoc configuration for gateway - Added OpenAPI proxy routes for user-service, tarot-service, divination-service - Added public paths for Swagger UI access without authentication - Swagger UI accessible at http://localhost:8080/swagger-ui.html with service dropdown Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 3 of centralized Swagger UI implementation: - Changed user-service: webmvc-ui -> webmvc-api - Changed tarot-service: webflux-ui -> webflux-api - Changed divination-service: webflux-ui -> webflux-api Services now only expose /api-docs for gateway proxying. Swagger UI is accessible only at http://localhost:8080/swagger-ui.html Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 4 of centralized Swagger UI implementation: - Added "API Documentation (Swagger UI)" section documenting: - Centralized Swagger UI URL and features - Architecture (gateway UI + backend API-only) - Configuration file locations - Updated PROGRESS.md to mark all phases complete Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updated highload-config to remove auto-generated internal Docker IPs from OpenAPI specs. Swagger UI now uses relative URLs, routing all "Try it out" requests through the gateway. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The "Servers" dropdown in Swagger UI was showing internal Docker IPs (e.g., 10.10.3.7:8082) which are not reachable from outside Docker. Added OpenApiServerRewriteFilter that strips the "servers" array from proxied OpenAPI responses. This makes Swagger UI use relative URLs, so all "Try it out" requests correctly go through the gateway. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add @OpenAPIDefinition with gateway server URL to all services - Add @Securityscheme for JWT bearer authentication - Add @securityrequirement to enable Authorize button in Swagger UI - Remove hacky OpenApiServerRewriteFilter - Update highload-config with forward-headers-strategy Note: Server URL is hardcoded to localhost:8080 - needs config for prod Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These services have no tests, so test dependencies and JUnit configuration are unnecessary. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…andling Move circuit breaker error handling to shared fallback factories: - Add ServiceUnavailableException with service name to shared-clients - Add FeignFallbackFactories for UserService, TarotService, DivinationServiceInternal - Update @FeignClient annotations with fallbackFactory attribute - Add @componentscan to services for shared.client package - Remove redundant circuit breaker exception handlers from GlobalExceptionHandler - Simplify UserService by removing manual try-catch (fallback handles errors) All services now return consistent error format: {"error":"SERVICE_UNAVAILABLE","message":"Service '<name>' is temporarily unavailable",...} Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Upgrade testcontainers from 1.19.8 to 2.0.2 - Update module names: postgresql -> testcontainers-postgresql, junit-jupiter -> testcontainers-junit-jupiter - Migrate PostgreSQLContainer import from org.testcontainers.containers to org.testcontainers.postgresql - Update API usage: remove generic type parameter, use property access instead of getter method references (jdbcUrl, username, password) - Fix UserServiceTest to use ServiceUnavailableException from shared-clients Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ctories Remove complex FallbackFactory pattern and handle all errors in GlobalExceptionHandler instead: - Remove fallbackFactory from all @FeignClient annotations - Delete FeignFallbackFactories.kt and ServiceUnavailableException.kt - Add handlers for CallNotPermittedException (circuit open -> 503) - Add handlers for NoFallbackAvailableException (unwrap and handle cause) - FeignException.NotFound now correctly propagates as 404 - Other FeignExceptions return 503 (service unavailable) This is simpler and follows the standard pattern of centralizing error handling in GlobalExceptionHandler rather than spreading it across multiple fallback factory classes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement FallbackFactory pattern for Feign clients with clear error handling:
- Add ServiceUnavailableException with serviceName field for clear error messages
- Create generic FeignFallbackFactory using dynamic proxy to avoid boilerplate
- Re-throw 4xx client errors (404, 400) to propagate business errors
- Throw ServiceUnavailableException for 5xx, connection errors, circuit open
- Simplify GlobalExceptionHandler to only handle ServiceUnavailableException
The fallback is explicit and returns meaningful error:
{"error":"SERVICE_UNAVAILABLE","message":"Service 'tarot-service' is temporarily unavailable"}
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace manual requireAdmin() and requireMediumOrAdmin() checks with Spring Security's @PreAuthorize annotations. Gateway headers (X-User-Id, X-User-Role) are now processed by custom filters that populate the SecurityContext. Changes: - Add GatewayAuthenticationToken to shared-clients for reuse - Add GatewayAuthenticationFilter (servlet) to user-service - Add GatewayAuthenticationWebFilter (reactive) to divination-service - Add AuthorizationService to divination-service for ownership checks - Configure Spring Security filter chains for both services - Update controllers to use @PreAuthorize annotations - Add AccessDeniedException handlers to GlobalExceptionHandlers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.