feat(core): add UserLog model and REST resource for browser error logging - #23
Merged
Merged
Conversation
…ging New UserLog entity (table LIGOJ_USER_LOG, auto-created via hbm2ddl) and a /user-log REST resource: POST records a browser error for the authenticated user (login and date set server-side), GET lists them paginated with an optional date range, restricted to administrators.
This was referenced Jun 17, 2026
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.
Context
Backend part of ligoj/plugin-ui#34 (record browser-side errors and expose them in
an admin "User logs" view). This PR adds the data model and the REST resource in
plugin-core, as the issue specifies. The front-end capture and the admin UI come
in separate PRs (host + plugin-ui).
What it does
UserLogentity → tableLIGOJ_USER_LOG, created automatically by Hibernate(
jpa.hbm2ddl=update), so no SQL migration is shipped.UserLogResource(/user-log):POSTrecords one error; the server stamps the login (SecurityHelper.getLogin())and the date, so a user can only log on its own behalf. Body:
{ message, url }.GETreturns the logs paginated, newest first, with an optionalfrom/todate range (epoch ms). Restricted to administrators.
Design decisions (and why)
Event:Eventis node/subscriptionscoped; this log is user-scoped with different columns, so a clean entity is simpler.
usermapped touser_login:USERis a reserved keyword on severaldatabases (H2/HSQLDB/PostgreSQL) and breaks the generated DDL otherwise.
messagecapped at 2000 chars (truncated server-side),urlat 512 and storedpath-only (no domain) — consistent with the bug-report dialog (plugin-ui#33).
:param IS NULL OR …:the latter fails on HSQLDB (untyped NULL parameter); the bounds are portable
across all databases and semantically equivalent to "no bound".
idanddateare passed as case-sensitive columns so pagination doesnot wrap them in
lower()(invalid on numeric/temporal types).Security
GETis admin-only by two mechanisms: Ligoj's RBAC filter is default-deny (noUSERauthorization pattern covers/user-log, so onlyADMIN.*matches),AND an explicit
@PreAuthorize("hasAuthority('ADMIN')")on the method.POSTis meant to be open to any authenticated user. That requires ONE line inthe host authorization seed (
ligoj/app-api/.../system-authorization.csv):POST;^rest/user-log.*;API;USER. That change lives in the host repo and shipswith the front-end capture PR — NOT here.
and a server-side rate limit could be added later if needed.
Integration note (for the release process)
plugin-core is consumed by the host via a pinned
api.version. Going live thereforeneeds a plugin-core release and a host
api.versionbump — a release-management stepon your side. Locally this was validated by bumping
api.versionto the SNAPSHOT(not committed): table auto-created, POST → 204, GET → 200 returning the row.
What's not in this PR
POSTauthorization line.Tests
mvn -pl plugin-core -am install→ BUILD SUCCESS, 370 tests green incl. 5 newUserLogResourceTest(create, truncation, date filter, sort date desc).Feedback very welcome — happy to adjust the contract (paths, payload, naming) to
match how you'd like the model/resource shaped in plugin-core.