Add REST controllers for each domain - #603
Draft
Slartibartfass2 wants to merge 39 commits into
Draft
Conversation
1 task
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 36073591 | Triggered | Generic Password | 1df56f6 | src/test/kotlin/se/uulm/snowballr/backend/rest/AuthWorkflowIntegrationTest.kt | View secret |
| 24483668 | Triggered | Generic Password | 1df56f6 | src/test/kotlin/se/uulm/snowballr/backend/rest/AuthWorkflowIntegrationTest.kt | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secrets safely. Learn here the best practices.
- Revoke and rotate these secrets.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
Code Coverage
|
Slartibartfass2
force-pushed
the
feat/600-feature-add-rest-controllers-for-each-domain
branch
from
August 16, 2026 14:19
3393e72 to
f6d4484
Compare
writeQueuedCookies ran before filterChain.doFilter, so cookies queued by handlers during the request (e.g. login, logout) were never written to the response - only pre-emptive refresh/clear cookies queued during authentication were flushed.
Drives register, verify-email, login, status, change-password, and logout through MockMvc and the actual security filter chain, rather than calling the service layer directly, so cookie handling on the wire is exercised the same way a real client would use it.
Both endpoints were caught by anyRequest().authenticated(), so /auth/status could never report UNAUTHENTICATED and /auth/logout could never clear cookies once both tokens had expired. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…requests SameSite=Strict blocks classic cross-site CSRF but still permits requests from a sibling subdomain, which is same-site. Requiring a custom header as defense-in-depth closes that gap, since forged cross-origin form/fetch requests cannot set one without triggering a CORS preflight. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cookies queued by pre-emptive token refresh (or refresh-failure clearing) were only written in the finally block after the handler ran, so a handler streaming a large enough body to auto-flush the output buffer silently dropped them, since Set-Cookie is a no-op on an already-committed response. Flush them immediately instead, and re-flush only cookies the handler itself changed afterward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Only /actuator/health is exposed today, but the wildcard sat above anyRequest().authenticated(), so exposing more endpoints later (e.g. /actuator/env, /actuator/heapdump) would have made them anonymously reachable without anyone touching the security config. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Matches the constructor-injection convention used by every other service/manager in the codebase and avoids exposing the injected service as public API on the controller bean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Matches the explicit binding annotations used by every other handler in this controller instead of relying on implicit simple-type param resolution. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…akage Switches the Docker healthcheck from grpc-health-probe to Spring Boot actuator on port 8090, replacing gRPC health with HTTP health now that Spring is the process entrypoint. This exposed a latent bug that made the REST server unreachable: shadowJar's default duplicatesStrategy (EXCLUDE) silently dropped nearly all Spring Boot autoconfiguration metadata, since several dependency jars ship META-INF/spring.factories and META-INF/spring/*.imports at the same path. Without TomcatServletWebServerAutoConfiguration surviving the merge, the app booted as a plain (non-web) ApplicationContext and never bound port 8090 at all. Fixed by setting duplicatesStrategy = INCLUDE and merging/appending the affected resource files instead of picking one arbitrarily. The healthcheck itself uses wget --spider rather than curl: curl was only ever needed for pycurl's build (libcurl/curl-dev) and isn't installed by default, while wget is already present via BusyBox in the eclipse-temurin alpine base, so no extra package is needed. It also drops a `grep "status":"UP"` step, since Spring Boot Actuator already maps health status to HTTP status codes by default (200 for UP, 503 otherwise) — wget's own exit code is sufficient. Verified with a full docker compose build/up against the real .env and database: actuator/health returns 200 and the container reaches Docker's healthy state using the wget-based check. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetAllUsers/GetUserByEmail (consolidated as a query filter), GetCurrentUser, GetUserById, UpdateUser (full-replace), SoftDeleteUser, GetUserSettings, and GetInviteCandidates (moved from Invitation per GRPC_TO_REST_MAPPING.md). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetAllProjectsForUser/GetAllArchivedProjectsForUser/GetAllDeletedProjectsForUser consolidated into GetAllProjects as userId/status query filters, plus UpdateProject (full-replace), GetProjectInformation (always whole-object), and GetDecisionStatisticsForStage, per GRPC_TO_REST_MAPPING.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetAvailableExportFormats (public, no auth per proto) and ExportProject as a binary download, per GRPC_TO_REST_MAPPING.md's case (b) exception - kept off /projects to keep ProjectsController smaller. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetProjectMembers, UpdateProjectMemberRole (role-only intent endpoint), and
RemoveProjectMember (keyed by email - covers pending invitees too), nested
under /projects/{projectId}/members per GRPC_TO_REST_MAPPING.md's
resource-nesting rule.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
InviteUserToProject and GetPendingInvitationsForProject nest under
/projects/{id}/invitations; AcceptProjectInvitation is a public
/invitations/{token}/accept, keyed only by the opaque token per the proto
(no @auth tag, matches GRPC_TO_REST_MAPPING.md's case (a) exception).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nested under /users/me/reading-list rather than a flat /reading-list, since the list is current-user-owned just like GetUserSettings. AddPaperToReadingList is PUT (client-known key, idempotent), IsPaperOnReadingList is HEAD with a 200/404 existence check instead of a boolean body. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetAllProjectPapersForProject, AddPaperToProject, GetProjectPaperByRelativeId
and GetPapersToReviewForProject nest under /projects/{id}/papers*; GetNextPaper,
GetNextPaperToReview, GetPreviousPaper and GetProjectPaperById stay on the flat
/project-papers/{id} since those gRPC methods never receive a project ID, per
GRPC_TO_REST_MAPPING.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetReviewById is a case (a) exception (review-only ID, no project-paper ID to
nest under); GetAllReviewsForProjectPaper and CreateReview nest under
/project-papers/{id}/reviews. UpdateReview/DeleteReview are unimplemented in
gRPC, so reviews are create/read-only via REST for now.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetAllCriteriaForProject nests under /projects/{id}/criteria; CreateCriterion
stays flat on /criteria since projectId is optional (global vs. project
criteria); GetCriterionById/UpdateCriterion are case (a) exceptions (no
project ID in the request). DeleteCriterion is unimplemented, so no DELETE.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetPaperById, CreatePaper, UpdatePaper (full-replace), and forward/backward reference lookups. Flat /papers throughout - Paper has no owning resource in the domain model, papers exist independently of any project. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GetAvailableFetchers is a global, non-nesting registry (/fetchers);
SearchLocalProjectPaperCandidates and SearchFetcherProjectPaperCandidates
nest under /projects/{id}/paper-candidates/{local,fetcher}.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Boolean naming (onList -> isOnReadingList) and ForbiddenVoid (ResponseEntity<Void> -> ResponseEntity<Unit>) in ReadingListController, plus a ktlint reformat of ProjectsController.updateProject. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Value-returning handlers keep expression body (fun x(): T = onRequest { ... });
Unit-returning ones now consistently use block body instead of relying on
implicit Unit inference. Fixes the two pre-existing outliers (AuthController's
login/logout/verifyEmail/changePassword, UsersController.register) that
predated this session's new controllers.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
KoinBridge now eagerly resolves 9 additional service beans for the new REST controllers; the test's minimal Koin module only covered the original 3, so the Spring context failed to start. Mock every IXService KoinBridge requires, and regenerate the committed OpenAPI spec now that it succeeds. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Slartibartfass2
force-pushed
the
feat/600-feature-add-rest-controllers-for-each-domain
branch
from
August 17, 2026 21:02
f6d4484 to
c95f59b
Compare
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.
Closes #600
What I have made
Waiting for #595
Checklist
Either tick or cross out the items that do not apply (using ~~example text~~) and give a reason why the item does not apply.
Author
AGENTS.mdif the changes affect project structure, commands, tooling, or conventionsReviewer