fix(security): admit team members to their own memberships endpoint - #119
Merged
Merged
Conversation
The /api/teams/** rule in SecurityConfig required MANAGER or ADMIN and runs before any controller, so TeamController#getMyMemberships never reached its method-level @PreAuthorize("isAuthenticated()"). Every DEVELOPER got 403, and the Sidebar query gating the Team nav entry left isMember permanently false. The exemption names the endpoint in full rather than the /me subtree: every sibling route binds a {teamId}, so a wildcard would hand nine manager-only handlers to MVC and leave Long conversion as the only thing stopping them. TeamMembershipsControllerTest ran with addFilters = false, disabling the filter chain the bug lived in, and so asserted 200 against code that returned 403. It now loads the real chain and pins that the neighbouring routes stay at 403. fix(http): bound the shared RestTemplate's connect and read timeouts The default factory waits forever. Its only consumers are JiraCollector and JiraProjectService, and discoverProjectsFromJira runs on the request thread, so an unreachable Jira host held a Tomcat worker until the client disconnected. The bounds are app.http.* properties, overridable like the rest of the config. Also drops an appended MappingJackson2HttpMessageConverter that never resolved: both consumers read String and parse with their own ObjectMapper, and RestTemplate registers a Jackson converter ahead of it by default. fix(scheduling): give scheduled jobs a thread pool and serialise metric writers All six @scheduled jobs shared Spring Boot's default pool of one, so a long enrichment pass delayed the nightly metric, backfill and weekly AI summary jobs. metric_snapshots carries no unique key, so MetricSnapshotWriter reads before it writes: with more than one thread the three scheduled writers can overlap and each insert. MetricWriteGate makes them mutually exclusive. The daily jobs skip on contention, since the next run covers the gap; the weekly job gates only its metric refresh and still summarises stored snapshots, because skipping there would cost a user their brief for seven days. The gate is process-local and does not cover request threads, the collect pool or the attribution listener; its Javadoc says so. All six @scheduled jobs shared Spring Boot's default pool of one, so a long enrichment pass delayed the nightly metric, backfill and weekly AI summary jobs. metric_snapshots carries no unique key, so MetricSnapshotWriter reads before it writes: with more than one thread the three scheduled writers can overlap and each insert. MetricWriteGate makes them mutually exclusive. The daily jobs skip on contention, since the next run covers the gap; the weekly job gates only its metric refresh and still summarises stored snapshots, because skipping there would cost a user their brief for seven days. The gate is process-local and does not cover request threads, the collect pool or the attribution listener; its Javadoc says so.
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.
The /api/teams/** rule in SecurityConfig required MANAGER or ADMIN and runs
before any controller, so TeamController#getMyMemberships never reached its
method-level @PreAuthorize("isAuthenticated()"). Every DEVELOPER got 403, and
the Sidebar query gating the Team nav entry left isMember permanently false.
The exemption names the endpoint in full rather than the /me subtree: every
sibling route binds a {teamId}, so a wildcard would hand nine manager-only
handlers to MVC and leave Long conversion as the only thing stopping them.
TeamMembershipsControllerTest ran with addFilters = false, disabling the filter
chain the bug lived in, and so asserted 200 against code that returned 403. It
now loads the real chain and pins that the neighbouring routes stay at 403.
fix(http): bound the shared RestTemplate's connect and read timeouts
The default factory waits forever. Its only consumers are JiraCollector and
JiraProjectService, and discoverProjectsFromJira runs on the request thread, so
an unreachable Jira host held a Tomcat worker until the client disconnected.
The bounds are app.http.* properties, overridable like the rest of the config.
Also drops an appended MappingJackson2HttpMessageConverter that never resolved:
both consumers read String and parse with their own ObjectMapper, and
RestTemplate registers a Jackson converter ahead of it by default.
fix(scheduling): give scheduled jobs a thread pool and serialise metric writers
All six @scheduled jobs shared Spring Boot's default pool of one, so a long
enrichment pass delayed the nightly metric, backfill and weekly AI summary jobs.
metric_snapshots carries no unique key, so MetricSnapshotWriter reads before it
writes: with more than one thread the three scheduled writers can overlap and
each insert. MetricWriteGate makes them mutually exclusive. The daily jobs skip
on contention, since the next run covers the gap; the weekly job gates only its
metric refresh and still summarises stored snapshots, because skipping there
would cost a user their brief for seven days.
The gate is process-local and does not cover request threads, the collect pool
or the attribution listener; its Javadoc says so.
All six @scheduled jobs shared Spring Boot's default pool of one, so a long
enrichment pass delayed the nightly metric, backfill and weekly AI summary jobs.
metric_snapshots carries no unique key, so MetricSnapshotWriter reads before it
writes: with more than one thread the three scheduled writers can overlap and
each insert. MetricWriteGate makes them mutually exclusive. The daily jobs skip
on contention, since the next run covers the gap; the weekly job gates only its
metric refresh and still summarises stored snapshots, because skipping there
would cost a user their brief for seven days.
The gate is process-local and does not cover request threads, the collect pool
or the attribution listener; its Javadoc says so.