From d379b5d9b93c84bd8f168fd83631b0d6abb37c3c Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Tue, 5 Dec 2023 15:31:53 +0100 Subject: [PATCH 1/8] add token and new notifications Signed-off-by: Marlon Pina Tojal --- .../notification/NotificationConstants.java | 2 ++ .../notification/NotificationGroup.java | 4 +++- .../publisher/AbstractWebhookPublisher.java | 6 ++++++ .../notification/publisher/Publisher.java | 1 + .../resources/v1/UserResource.java | 19 +++++++++++++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/dependencytrack/notification/NotificationConstants.java b/src/main/java/org/dependencytrack/notification/NotificationConstants.java index 9bb4e8f64f..52a1c51e82 100644 --- a/src/main/java/org/dependencytrack/notification/NotificationConstants.java +++ b/src/main/java/org/dependencytrack/notification/NotificationConstants.java @@ -61,6 +61,8 @@ public static class Title { public static final String VEX_CONSUMED = "Vulnerability Exploitability Exchange (VEX) Consumed"; public static final String VEX_PROCESSED = "Vulnerability Exploitability Exchange (VEX) Processed"; public static final String PROJECT_CREATED = "Project Added"; + public static final String USER_CREATED = "User Created"; + public static final String USER_DELETED = "User Deleted"; } } diff --git a/src/main/java/org/dependencytrack/notification/NotificationGroup.java b/src/main/java/org/dependencytrack/notification/NotificationGroup.java index 1780e0a92d..07508b7a33 100644 --- a/src/main/java/org/dependencytrack/notification/NotificationGroup.java +++ b/src/main/java/org/dependencytrack/notification/NotificationGroup.java @@ -43,5 +43,7 @@ public enum NotificationGroup { VEX_CONSUMED, VEX_PROCESSED, POLICY_VIOLATION, - PROJECT_CREATED + PROJECT_CREATED, + USER_CREATED, + USER_DELETED } diff --git a/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java b/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java index 2ae0205b4e..5686f16eb6 100644 --- a/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java +++ b/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java @@ -76,6 +76,8 @@ public void publish(final PublishContext ctx, final PebbleTemplate template, fin } else { request.addHeader("Authorization", "Bearer " + credentials.password); } + } else if (getToken(config) != null) { + request.addHeader("X-Api-Key", getToken(config)); } try { @@ -107,6 +109,10 @@ protected AuthCredentials getAuthCredentials() { return null; } + protected String getToken(final JsonObject config) { + return config.getString(CONFIG_TOKEN, null); + } + protected record AuthCredentials(String user, String password) { } diff --git a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java index 34c06bc080..8fd960e6da 100644 --- a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java +++ b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java @@ -52,6 +52,7 @@ public interface Publisher { String CONFIG_TEMPLATE_MIME_TYPE_KEY = "mimeType"; String CONFIG_DESTINATION = "destination"; + String CONFIG_TOKEN = "token"; void inform(final PublishContext ctx, final Notification notification, final JsonObject config); diff --git a/src/main/java/org/dependencytrack/resources/v1/UserResource.java b/src/main/java/org/dependencytrack/resources/v1/UserResource.java index e32e5a6f0b..f0009909fa 100644 --- a/src/main/java/org/dependencytrack/resources/v1/UserResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/UserResource.java @@ -26,6 +26,8 @@ import alpine.model.Permission; import alpine.model.Team; import alpine.model.UserPrincipal; +import alpine.notification.Notification; +import alpine.notification.NotificationLevel; import alpine.security.crypto.KeyManager; import alpine.server.auth.AlpineAuthenticationException; import alpine.server.auth.AuthenticationNotRequired; @@ -45,6 +47,9 @@ import org.apache.commons.lang3.StringUtils; import org.dependencytrack.auth.Permissions; import org.dependencytrack.model.IdentifiableObject; +import org.dependencytrack.notification.NotificationConstants; +import org.dependencytrack.notification.NotificationGroup; +import org.dependencytrack.notification.NotificationScope; import org.dependencytrack.persistence.QueryManager; import org.owasp.security.logging.SecurityMarkers; @@ -555,6 +560,13 @@ public Response createOidcUser(final OidcUser jsonUser) { if (user == null) { user = qm.createOidcUser(jsonUser.getUsername()); super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "OpenID Connect user created: " + jsonUser.getUsername()); + Notification.dispatch(new Notification() + .scope(NotificationScope.SYSTEM) + .group(NotificationGroup.USER_CREATED) + .title(NotificationConstants.Title.USER_CREATED) + .level(NotificationLevel.INFORMATIONAL) + .content("A user was created") + .subject(user)); return Response.status(Response.Status.CREATED).entity(user).build(); } else { return Response.status(Response.Status.CONFLICT).entity("A user with the same username already exists. Cannot create new user.").build(); @@ -581,6 +593,13 @@ public Response deleteOidcUser(final OidcUser jsonUser) { if (user != null) { qm.delete(user); super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "OpenID Connect user deleted: " + jsonUser.getUsername()); + Notification.dispatch(new Notification() + .scope(NotificationScope.SYSTEM) + .group(NotificationGroup.USER_DELETED) + .title(NotificationConstants.Title.USER_DELETED) + .level(NotificationLevel.INFORMATIONAL) + .content("A user was deleted") + .subject(user)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); From 69aab57a459bd39d0fe4c18f66c0d25a13cf1fb3 Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Tue, 5 Dec 2023 15:38:47 +0100 Subject: [PATCH 2/8] add missing user events Signed-off-by: Marlon Pina Tojal --- .../resources/v1/UserResource.java | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/dependencytrack/resources/v1/UserResource.java b/src/main/java/org/dependencytrack/resources/v1/UserResource.java index f0009909fa..431d7ae117 100644 --- a/src/main/java/org/dependencytrack/resources/v1/UserResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/UserResource.java @@ -388,6 +388,13 @@ public Response createLdapUser(LdapUser jsonUser) { if (user == null) { user = qm.createLdapUser(jsonUser.getUsername()); super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "LDAP user created: " + jsonUser.getUsername()); + Notification.dispatch(new Notification() + .scope(NotificationScope.SYSTEM) + .group(NotificationGroup.USER_CREATED) + .title(NotificationConstants.Title.USER_CREATED) + .level(NotificationLevel.INFORMATIONAL) + .content("LDAP user created") + .subject(user)); return Response.status(Response.Status.CREATED).entity(user).build(); } else { return Response.status(Response.Status.CONFLICT).entity("A user with the same username already exists. Cannot create new user.").build(); @@ -414,6 +421,13 @@ public Response deleteLdapUser(LdapUser jsonUser) { if (user != null) { qm.delete(user); super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "LDAP user deleted: " + jsonUser.getUsername()); + Notification.dispatch(new Notification() + .scope(NotificationScope.SYSTEM) + .group(NotificationGroup.USER_DELETED) + .title(NotificationConstants.Title.USER_DELETED) + .level(NotificationLevel.INFORMATIONAL) + .content("LDAP user deleted") + .subject(user)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); @@ -461,6 +475,13 @@ public Response createManagedUser(ManagedUser jsonUser) { String.valueOf(PasswordService.createHash(jsonUser.getNewPassword().toCharArray())), jsonUser.isForcePasswordChange(), jsonUser.isNonExpiryPassword(), jsonUser.isSuspended()); super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "Managed user created: " + jsonUser.getUsername()); + Notification.dispatch(new Notification() + .scope(NotificationScope.SYSTEM) + .group(NotificationGroup.USER_CREATED) + .title(NotificationConstants.Title.USER_CREATED) + .level(NotificationLevel.INFORMATIONAL) + .content("Managed user created") + .subject(user)); return Response.status(Response.Status.CREATED).entity(user).build(); } else { return Response.status(Response.Status.CONFLICT).entity("A user with the same username already exists. Cannot create new user.").build(); @@ -529,6 +550,13 @@ public Response deleteManagedUser(ManagedUser jsonUser) { if (user != null) { qm.delete(user); super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "Managed user deleted: " + jsonUser.getUsername()); + Notification.dispatch(new Notification() + .scope(NotificationScope.SYSTEM) + .group(NotificationGroup.USER_DELETED) + .title(NotificationConstants.Title.USER_DELETED) + .level(NotificationLevel.INFORMATIONAL) + .content("Managed user deleted") + .subject(user)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); @@ -565,7 +593,7 @@ public Response createOidcUser(final OidcUser jsonUser) { .group(NotificationGroup.USER_CREATED) .title(NotificationConstants.Title.USER_CREATED) .level(NotificationLevel.INFORMATIONAL) - .content("A user was created") + .content("OpenID Connect user created") .subject(user)); return Response.status(Response.Status.CREATED).entity(user).build(); } else { @@ -598,7 +626,7 @@ public Response deleteOidcUser(final OidcUser jsonUser) { .group(NotificationGroup.USER_DELETED) .title(NotificationConstants.Title.USER_DELETED) .level(NotificationLevel.INFORMATIONAL) - .content("A user was deleted") + .content("OpenID Connect user deleted") .subject(user)); return Response.status(Response.Status.NO_CONTENT).build(); } else { From 18ff7e20e865618626d6b8926396fc2e1dec7e5d Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Mon, 11 Dec 2023 11:06:50 +0100 Subject: [PATCH 3/8] add template for user notifications Signed-off-by: Marlon Pina Tojal --- .../notification/publisher/Publisher.java | 6 ++++++ .../org/dependencytrack/util/NotificationUtil.java | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java index 8fd960e6da..233507fbee 100644 --- a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java +++ b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java @@ -20,6 +20,7 @@ import alpine.common.util.UrlUtil; import alpine.model.ConfigProperty; +import alpine.model.UserPrincipal; import alpine.notification.Notification; import io.pebbletemplates.pebble.PebbleEngine; import io.pebbletemplates.pebble.template.PebbleTemplate; @@ -125,6 +126,11 @@ default String prepareTemplate(final Notification notification, final PebbleTemp context.put("subject", subject); context.put("subjectJson", NotificationUtil.toJson(subject)); } + } else if (NotificationScope.SYSTEM.name().equals(notification.getScope())) { + if (notification.getSubject() instanceof final UserPrincipal subject) { + context.put("subject", subject); + context.put("subjectJson", NotificationUtil.toJson(subject)); + } } enrichTemplateContext(context); diff --git a/src/main/java/org/dependencytrack/util/NotificationUtil.java b/src/main/java/org/dependencytrack/util/NotificationUtil.java index b244173dfc..227f33db21 100644 --- a/src/main/java/org/dependencytrack/util/NotificationUtil.java +++ b/src/main/java/org/dependencytrack/util/NotificationUtil.java @@ -19,6 +19,7 @@ package org.dependencytrack.util; import alpine.model.ConfigProperty; +import alpine.model.UserPrincipal; import alpine.notification.Notification; import alpine.notification.NotificationLevel; import org.apache.commons.io.FileUtils; @@ -272,6 +273,16 @@ public static JsonObject toJson(final Project project) { return projectBuilder.build(); } + public static JsonObject toJson(final UserPrincipal user) { + final JsonObjectBuilder userBuilder = Json.createObjectBuilder(); + userBuilder.add("id", user.getId()); + userBuilder.add("username", user.getUsername()); + userBuilder.add("name", user.getName()); + userBuilder.add("email", user.getEmail()); + + return userBuilder.build(); + } + public static JsonObject toJson(final Component component) { final JsonObjectBuilder componentBuilder = Json.createObjectBuilder(); componentBuilder.add("uuid", component.getUuid().toString()); From a68bfedc4281380ab494e6a7c87c6edb37fb2af2 Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Mon, 11 Dec 2023 12:20:03 +0100 Subject: [PATCH 4/8] fix user delete notification Signed-off-by: Marlon Pina Tojal --- .../resources/v1/UserResource.java | 6 +++--- .../dependencytrack/util/NotificationUtil.java | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/dependencytrack/resources/v1/UserResource.java b/src/main/java/org/dependencytrack/resources/v1/UserResource.java index 431d7ae117..95db02d1e1 100644 --- a/src/main/java/org/dependencytrack/resources/v1/UserResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/UserResource.java @@ -427,7 +427,7 @@ public Response deleteLdapUser(LdapUser jsonUser) { .title(NotificationConstants.Title.USER_DELETED) .level(NotificationLevel.INFORMATIONAL) .content("LDAP user deleted") - .subject(user)); + .subject(jsonUser)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); @@ -556,7 +556,7 @@ public Response deleteManagedUser(ManagedUser jsonUser) { .title(NotificationConstants.Title.USER_DELETED) .level(NotificationLevel.INFORMATIONAL) .content("Managed user deleted") - .subject(user)); + .subject(jsonUser)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); @@ -627,7 +627,7 @@ public Response deleteOidcUser(final OidcUser jsonUser) { .title(NotificationConstants.Title.USER_DELETED) .level(NotificationLevel.INFORMATIONAL) .content("OpenID Connect user deleted") - .subject(user)); + .subject(jsonUser)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); diff --git a/src/main/java/org/dependencytrack/util/NotificationUtil.java b/src/main/java/org/dependencytrack/util/NotificationUtil.java index 227f33db21..5b03216111 100644 --- a/src/main/java/org/dependencytrack/util/NotificationUtil.java +++ b/src/main/java/org/dependencytrack/util/NotificationUtil.java @@ -275,10 +275,19 @@ public static JsonObject toJson(final Project project) { public static JsonObject toJson(final UserPrincipal user) { final JsonObjectBuilder userBuilder = Json.createObjectBuilder(); - userBuilder.add("id", user.getId()); + userBuilder.add("username", user.getUsername()); - userBuilder.add("name", user.getName()); - userBuilder.add("email", user.getEmail()); + + if (user.getId() != 0) { + userBuilder.add("id", user.getId()); + } + if (user.getName() != null) { + userBuilder.add("name", user.getName()); + } + + if (user.getEmail() != null) { + userBuilder.add("email", user.getEmail()); + } return userBuilder.build(); } From 9be9d485081f48996427f9bd7dfa725c7ce76f9d Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Mon, 18 Dec 2023 10:31:56 +0100 Subject: [PATCH 5/8] add documentation Signed-off-by: Marlon Pina Tojal --- docs/_docs/integrations/notifications.md | 44 +++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/_docs/integrations/notifications.md b/docs/_docs/integrations/notifications.md index c590391c40..5595de405a 100644 --- a/docs/_docs/integrations/notifications.md +++ b/docs/_docs/integrations/notifications.md @@ -44,6 +44,8 @@ multiple levels, while others can only ever have a single level. | SYSTEM | INDEXING_SERVICE | (Any) | Notifications generated as a result of performing maintenance on Dependency-Tracks internal index used for global searching | | SYSTEM | FILE_SYSTEM | (Any) | Notifications generated as a result of a file system operation. These are typically only generated on error conditions | | SYSTEM | REPOSITORY | (Any) | Notifications generated as a result of interacting with one of the supported repositories such as Maven Central, RubyGems, or NPM | +| SYSTEM | USER_CREATED | INFORMATIONAL | Notifications generated as a result of a user creation | +| SYSTEM | USER_DELETED | INFORMATIONAL | Notifications generated as a result of a user deletion | | PORTFOLIO | NEW_VULNERABILITY | INFORMATIONAL | Notifications generated whenever a new vulnerability is identified | | PORTFOLIO | NEW_VULNERABLE_DEPENDENCY | INFORMATIONAL | Notifications generated as a result of a vulnerable component becoming a dependency of a project | | PORTFOLIO | GLOBAL_AUDIT_CHANGE | INFORMATIONAL | Notifications generated whenever an analysis or suppression state has changed on a finding from a component (global) | @@ -365,6 +367,46 @@ This type of notification will always contain: } ``` +#### USER_CREATED + +```json +{ + "notification": { + "level": "INFORMATIONAL", + "scope": "SYSTEM", + "group": "USER_CREATED", + "timestamp": "2022-05-12T23:07:59.611303", + "title": "User Created", + "content": "LDAP user created", + "subject": { + "id": "user", + "username": "user", + "name": "User 1", + "email": "user@example.com", + } + } +} +``` + +#### USER_DELETED + +```json +{ + "notification": { + "level": "INFORMATIONAL", + "scope": "SYSTEM", + "group": "USER_CREATED", + "timestamp": "2022-05-12T23:07:59.611303", + "title": "User Deleted", + "content": "LDAP user deleted", + "subject": { + "username": "user", + } + } +} +``` + + ### Override of default templates Default publishers are installed in the database at startup using templates retrieved in Dependency-Track classpath. Those publishers are **read-only** by default. Dependency-Track can be configured from the administrative page to allow an override of the default templates. This requires SYSTEM_CONFIGURATION permission. @@ -376,7 +418,7 @@ Switch on enable default template override flag and provide a filesystem base di ![notification publisher general configuration](/images/screenshots/notifications-publisher-override-template.png) -> The default template override flag is switched off by default and can set at initial startup with environment variable `DEFAULT_TEMPLATES_OVERRIDE_ENABLED`. +> The default template override flag is switched off by default and can set at initial startup with environment variable `DEFAULT_TEMPLATES_OVERRIDE_ENABLED`. > The default templates base directory is set to ${user.home} by default and can be set at initial startup with environment variable `DEFAULT_TEMPLATES_OVERRIDE_BASE_DIRECTORY`. To override all default templates, you must have the following [Pebble Templates](https://pebbletemplates.io/) template files inside the configured base directory. From 0131c7e5eeee93253fcb355f75cb0d3cbafc5a83 Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Thu, 11 Jan 2024 08:42:59 +0100 Subject: [PATCH 6/8] add support for token header in configuration Signed-off-by: Marlon Pina Tojal --- .../notification/publisher/AbstractWebhookPublisher.java | 6 +++++- .../dependencytrack/notification/publisher/Publisher.java | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java b/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java index 5686f16eb6..8238123fb1 100644 --- a/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java +++ b/src/main/java/org/dependencytrack/notification/publisher/AbstractWebhookPublisher.java @@ -77,7 +77,7 @@ public void publish(final PublishContext ctx, final PebbleTemplate template, fin request.addHeader("Authorization", "Bearer " + credentials.password); } } else if (getToken(config) != null) { - request.addHeader("X-Api-Key", getToken(config)); + request.addHeader(getTokenHeader(config), getToken(config)); } try { @@ -113,6 +113,10 @@ protected String getToken(final JsonObject config) { return config.getString(CONFIG_TOKEN, null); } + protected String getTokenHeader(final JsonObject config) { + return config.getString(CONFIG_TOKEN_HEADER, "X-Api-Key"); + } + protected record AuthCredentials(String user, String password) { } diff --git a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java index 233507fbee..71a1278449 100644 --- a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java +++ b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java @@ -54,6 +54,7 @@ public interface Publisher { String CONFIG_DESTINATION = "destination"; String CONFIG_TOKEN = "token"; + String CONFIG_TOKEN_HEADER = "token_header"; void inform(final PublishContext ctx, final Notification notification, final JsonObject config); From ba0eacf148cff46e9eed0d56548e1cf58ca992bc Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Thu, 11 Jan 2024 08:51:31 +0100 Subject: [PATCH 7/8] add api token header Signed-off-by: Marlon Pina Tojal --- .../org/dependencytrack/notification/publisher/Publisher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java index 71a1278449..cc6bf42468 100644 --- a/src/main/java/org/dependencytrack/notification/publisher/Publisher.java +++ b/src/main/java/org/dependencytrack/notification/publisher/Publisher.java @@ -54,7 +54,7 @@ public interface Publisher { String CONFIG_DESTINATION = "destination"; String CONFIG_TOKEN = "token"; - String CONFIG_TOKEN_HEADER = "token_header"; + String CONFIG_TOKEN_HEADER = "tokenHeader"; void inform(final PublishContext ctx, final Notification notification, final JsonObject config); From 07d64b86bfc20eb1a952db76ca9fb5759cfbefff Mon Sep 17 00:00:00 2001 From: Marlon Pina Tojal Date: Mon, 19 Feb 2024 13:26:31 +0100 Subject: [PATCH 8/8] detached user Signed-off-by: Marlon Pina Tojal --- .../resources/v1/UserResource.java | 15 +++++++++------ .../dependencytrack/util/NotificationUtil.java | 3 --- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/dependencytrack/resources/v1/UserResource.java b/src/main/java/org/dependencytrack/resources/v1/UserResource.java index 95db02d1e1..a427e9bdb6 100644 --- a/src/main/java/org/dependencytrack/resources/v1/UserResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/UserResource.java @@ -419,15 +419,16 @@ public Response deleteLdapUser(LdapUser jsonUser) { try (QueryManager qm = new QueryManager()) { final LdapUser user = qm.getLdapUser(jsonUser.getUsername()); if (user != null) { + final LdapUser detachedUser = qm.getPersistenceManager().detachCopy(user); qm.delete(user); - super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "LDAP user deleted: " + jsonUser.getUsername()); + super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "LDAP user deleted: " + detachedUser); Notification.dispatch(new Notification() .scope(NotificationScope.SYSTEM) .group(NotificationGroup.USER_DELETED) .title(NotificationConstants.Title.USER_DELETED) .level(NotificationLevel.INFORMATIONAL) .content("LDAP user deleted") - .subject(jsonUser)); + .subject(detachedUser)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); @@ -548,15 +549,16 @@ public Response deleteManagedUser(ManagedUser jsonUser) { try (QueryManager qm = new QueryManager()) { final ManagedUser user = qm.getManagedUser(jsonUser.getUsername()); if (user != null) { + final ManagedUser detachedUser = qm.getPersistenceManager().detachCopy(user); qm.delete(user); - super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "Managed user deleted: " + jsonUser.getUsername()); + super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "Managed user deleted: " +detachedUser); Notification.dispatch(new Notification() .scope(NotificationScope.SYSTEM) .group(NotificationGroup.USER_DELETED) .title(NotificationConstants.Title.USER_DELETED) .level(NotificationLevel.INFORMATIONAL) .content("Managed user deleted") - .subject(jsonUser)); + .subject(detachedUser)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); @@ -619,15 +621,16 @@ public Response deleteOidcUser(final OidcUser jsonUser) { try (QueryManager qm = new QueryManager()) { final OidcUser user = qm.getOidcUser(jsonUser.getUsername()); if (user != null) { + final OidcUser detachedUser = qm.getPersistenceManager().detachCopy(user); qm.delete(user); - super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "OpenID Connect user deleted: " + jsonUser.getUsername()); + super.logSecurityEvent(LOGGER, SecurityMarkers.SECURITY_AUDIT, "OpenID Connect user deleted: " + detachedUser); Notification.dispatch(new Notification() .scope(NotificationScope.SYSTEM) .group(NotificationGroup.USER_DELETED) .title(NotificationConstants.Title.USER_DELETED) .level(NotificationLevel.INFORMATIONAL) .content("OpenID Connect user deleted") - .subject(jsonUser)); + .subject(detachedUser)); return Response.status(Response.Status.NO_CONTENT).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("The user could not be found.").build(); diff --git a/src/main/java/org/dependencytrack/util/NotificationUtil.java b/src/main/java/org/dependencytrack/util/NotificationUtil.java index 5b03216111..3b8a7e7997 100644 --- a/src/main/java/org/dependencytrack/util/NotificationUtil.java +++ b/src/main/java/org/dependencytrack/util/NotificationUtil.java @@ -278,9 +278,6 @@ public static JsonObject toJson(final UserPrincipal user) { userBuilder.add("username", user.getUsername()); - if (user.getId() != 0) { - userBuilder.add("id", user.getId()); - } if (user.getName() != null) { userBuilder.add("name", user.getName()); }