-
Notifications
You must be signed in to change notification settings - Fork 3
304 add api for automated scheduled encounters #314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aluapaula
wants to merge
18
commits into
v3.4.0
Choose a base branch
from
304-add-api-for-automated-scheduled-encounters
base: v3.4.0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
363ee51
WIP
aluapaula 6fe7907
Refactoring of Method saveScheduledEncounter in class EncounterContro…
aluapaula a25a72c
Refactoring of Method saveScheduledEncounter in class EncounterContro…
aluapaula 11482c9
Refactoring of Method saveScheduledEncounter in class EncounterContro…
aluapaula 039854b
Refactoring of Method saveScheduledEncounter in class EncounterContro…
aluapaula 440adb8
Add tests for Audit, EncounterScheduled, ImmediateMail and Mail servi…
aluapaula 30b2924
Fixed transactional missing a qualifier
ywarnecke 40f96ad
Merge branch 'v3.4.0' into 304-add-api-for-automated-scheduled-encoun…
aluapaula 15e35fd
Add API endpoint for external scheduled encounter:
aluapaula 4c8aba6
Add API endpoint for external scheduled encounter:
aluapaula 7ee8b01
Add API endpoint for external scheduled encounter:
aluapaula 29f6772
updated messages for configuration label to ensure correct formatting
aluapaula 32eaef4
improved: DTO-Validation for EncounterScheduledApiRequestDTO
aluapaula 2d06b07
fix: DTO-Validation for EncounterScheduledApiRequestDTO
aluapaula 76009b4
implement: EncounterScheduledApiRequestDTOValidator for Validation of…
aluapaula ca99ad6
Refactor scheduled encounter save flow and harden API validation
aluapaula d584d39
Add rate limiting filter for scheduled encounter API
aluapaula 87fce2b
Improve rate limiting filter for scheduled encounter API, add javadoc…
aluapaula File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| USE `moPat`; | ||
|
|
||
| SELECT MAX(id) | ||
| INTO @largest_id | ||
| FROM moPat.configuration; | ||
|
|
||
|
|
||
| -- Determine the highest position in configuration group 1 | ||
| SELECT COALESCE(MAX(position), 0) | ||
| INTO @max_position_group_1 | ||
| FROM `moPat`.`configuration` | ||
| WHERE `configuration_group_id` = 1; | ||
|
|
||
|
|
||
| -- Configuration group 1 is used here. | ||
| -- If your target server uses a different configuration group for these settings, | ||
| -- please adjust configuration_group_id accordingly. | ||
|
|
||
| -- Inserts: | ||
| -- 1) enableApiTokenAccess | ||
| -- 2) apiKey as child of enableApiTokenAccess | ||
| INSERT INTO moPat.configuration (`id`, `type`, `configuration_group_id`, `parent`, `position`, `attribute`, `configuration_type`, `description_message_code`, `class`, `label_message_code`, `test_method`, `update_method`, `uuid`, `value`, `pattern`) VALUES | ||
| (@largest_id + 1, 'GENERAL', 1, NULL, @max_position_group_1 +1, 'enableApiTokenAccess', 'BOOLEAN', 'configuration.description.enableApiTokenAccess', 'GLOBAL', 'configuration.label.enableApiTokenAccess', NULL, NULL, '25fd8f5e-2e90-4cd1-8a30-d84c88889c5c', false, NULL), | ||
| (@largest_id + 2, 'GENERAL', 1, @largest_id + 1, @max_position_group_1 +2, 'apiKey', 'STRING', 'configuration.description.apiKey', 'GLOBAL', 'configuration.label.apiKey', NULL, NULL, '9b48f864-8cb7-4704-82e2-12045755e2aa', '', NULL); | ||
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
104 changes: 104 additions & 0 deletions
104
src/main/java/de/imi/mopat/auth/ApiRateLimitFilter.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| package de.imi.mopat.auth; | ||
|
|
||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import de.imi.mopat.service.ApiRateLimitService; | ||
| import io.github.bucket4j.Bucket; | ||
| import io.github.bucket4j.ConsumptionProbe; | ||
| import jakarta.servlet.FilterChain; | ||
| import jakarta.servlet.ServletException; | ||
| import jakarta.servlet.http.HttpServletRequest; | ||
| import jakarta.servlet.http.HttpServletResponse; | ||
| import java.io.IOException; | ||
| import java.util.Map; | ||
| import java.util.concurrent.TimeUnit; | ||
| import org.springframework.http.MediaType; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.web.filter.OncePerRequestFilter; | ||
|
|
||
| /** | ||
| * Filter that enforces rate limiting on the API endpoint {@code POST /encounter/schedule/api}. | ||
| * Applies both a global limit and a per-IP limit using token buckets. | ||
| * Requests exceeding either limit are rejected with HTTP 429. | ||
| */ | ||
| public class ApiRateLimitFilter extends OncePerRequestFilter { | ||
|
|
||
| private static final String API_PATH = "/encounter/schedule/api"; | ||
| private static final String HTTP_METHOD = "POST"; | ||
| private final ObjectMapper objectMapper = new ObjectMapper(); | ||
| private final ApiRateLimitService apiRateLimitService; | ||
|
|
||
| public ApiRateLimitFilter(ApiRateLimitService apiRateLimitService) { | ||
| this.apiRateLimitService = apiRateLimitService; | ||
| } | ||
| /** | ||
| * Skips filtering for all requests that do not target the rate-limited endpoint. | ||
| * | ||
| * @param request the incoming HTTP request | ||
| * @return {@code true} if the request should not be filtered | ||
| */ | ||
| @Override | ||
| protected boolean shouldNotFilter(HttpServletRequest request) { | ||
| return !API_PATH.equals(request.getServletPath()) | ||
| || !HTTP_METHOD.equalsIgnoreCase(request.getMethod()); | ||
| } | ||
| /** | ||
| * Checks the global and per-IP rate limits. Forwards the request if both limits | ||
| * are satisfied, otherwise responds with HTTP 429. | ||
| * | ||
| * @param request the incoming HTTP request | ||
| * @param response the HTTP response | ||
| * @param filterChain the filter chain | ||
| */ | ||
| @Override | ||
| protected void doFilterInternal(HttpServletRequest request, | ||
| HttpServletResponse response, | ||
| FilterChain filterChain) | ||
| throws ServletException, IOException { | ||
|
|
||
| ConsumptionProbe globalProbe = | ||
| apiRateLimitService.getGlobalBucket().tryConsumeAndReturnRemaining(1); | ||
|
|
||
| if (!globalProbe.isConsumed()) { | ||
| writeTooManyRequestsResponse(response, globalProbe, "Global rate limit exceeded"); | ||
| return; | ||
| } | ||
|
|
||
| String clientIp = request.getRemoteAddr(); | ||
| Bucket ipBucket = apiRateLimitService.resolveIpBucket(clientIp); | ||
| ConsumptionProbe ipProbe = ipBucket.tryConsumeAndReturnRemaining(1); | ||
|
|
||
| if (!ipProbe.isConsumed()) { | ||
| writeTooManyRequestsResponse(response, ipProbe, "IP rate limit exceeded"); | ||
| return; | ||
| } | ||
|
|
||
| response.setHeader("X-Rate-Limit-Global-Remaining", | ||
| String.valueOf(globalProbe.getRemainingTokens())); | ||
| response.setHeader("X-Rate-Limit-IP-Remaining", | ||
| String.valueOf(ipProbe.getRemainingTokens())); | ||
|
|
||
| filterChain.doFilter(request, response); | ||
| } | ||
| /** | ||
| * Writes a {@code 429 Too Many Requests} response including a retry-after header | ||
| * and a JSON error message. | ||
| * | ||
| * @param response the HTTP response | ||
| * @param probe the consumption probe containing refill timing information | ||
| * @param message the error message to include in the response body | ||
| */ | ||
| private void writeTooManyRequestsResponse(HttpServletResponse response, | ||
| ConsumptionProbe probe, | ||
| String message) throws IOException { | ||
| response.setStatus(429); | ||
| response.setContentType(MediaType.APPLICATION_JSON_VALUE); | ||
| response.setHeader( | ||
| "X-Rate-Limit-Retry-After-Seconds", | ||
| String.valueOf(TimeUnit.NANOSECONDS.toSeconds(probe.getNanosToWaitForRefill())) | ||
| ); | ||
|
|
||
| objectMapper.writeValue(response.getWriter(), Map.of( | ||
| "error", message | ||
| )); | ||
| } | ||
| } |
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
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
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
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.