Skip to content

feat(core): add UserLog model and REST resource for browser error logging - #23

Merged
fdaugan merged 1 commit into
ligoj:masterfrom
Terracosmos:norman/user-log-backend
Jun 17, 2026
Merged

feat(core): add UserLog model and REST resource for browser error logging#23
fdaugan merged 1 commit into
ligoj:masterfrom
Terracosmos:norman/user-log-backend

Conversation

@Terracosmos

Copy link
Copy Markdown
Contributor

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

  • UserLog entity → table LIGOJ_USER_LOG, created automatically by Hibernate
    (jpa.hbm2ddl=update), so no SQL migration is shipped.
  • UserLogResource (/user-log):
    • POST records 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 }.
    • GET returns the logs paginated, newest first, with an optional from/to
      date range (epoch ms). Restricted to administrators.

Design decisions (and why)

  • New dedicated entity rather than reusing Event: Event is node/subscription
    scoped; this log is user-scoped with different columns, so a clean entity is simpler.
  • Column user mapped to user_login: USER is a reserved keyword on several
    databases (H2/HSQLDB/PostgreSQL) and breaks the generated DDL otherwise.
  • message capped at 2000 chars (truncated server-side), url at 512 and stored
    path-only (no domain) — consistent with the bug-report dialog (plugin-ui#33).
  • Date filter uses explicit bounds (EPOCH .. 9999) instead of :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".
  • Sorting: id and date are passed as case-sensitive columns so pagination does
    not wrap them in lower() (invalid on numeric/temporal types).

Security

  • GET is admin-only by two mechanisms: Ligoj's RBAC filter is default-deny (no
    USER authorization pattern covers /user-log, so only ADMIN .* matches),
    AND an explicit @PreAuthorize("hasAuthority('ADMIN')") on the method.
  • POST is meant to be open to any authenticated user. That requires ONE line in
    the host authorization seed (ligoj/app-api/.../system-authorization.csv):
    POST;^rest/user-log.*;API;USER. That change lives in the host repo and ships
    with the front-end capture PR — NOT here.
  • Note: an open POST is a potential spam vector; the front-end will throttle/dedupe,
    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 therefore
needs a plugin-core release and a host api.version bump — a release-management step
on your side. Locally this was validated by bumping api.version to the SNAPSHOT
(not committed): table auto-created, POST → 204, GET → 200 returning the row.

What's not in this PR

  • Front-end error capture (host) + the POST authorization line.
  • The admin "User logs" UI (plugin-ui).

Tests

mvn -pl plugin-core -am install → BUILD SUCCESS, 370 tests green incl. 5 new
UserLogResourceTest (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.

…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.
@fdaugan
fdaugan merged commit 5e04dc4 into ligoj:master Jun 17, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants