diff --git a/alpine/alpine-server/src/main/java/alpine/server/auth/PermissionRequired.java b/alpine/alpine-server/src/main/java/alpine/server/auth/PermissionRequired.java
index 97fea0bfe7..acd26b2799 100644
--- a/alpine/alpine-server/src/main/java/alpine/server/auth/PermissionRequired.java
+++ b/alpine/alpine-server/src/main/java/alpine/server/auth/PermissionRequired.java
@@ -36,10 +36,16 @@
@Documented
public @interface PermissionRequired {
+ public enum Operator {
+ AND, OR
+ }
+
/**
* An array of permissions.
* @return an array of permissions
*/
String[] value();
+ Operator operator() default Operator.OR;
+
}
diff --git a/alpine/alpine-server/src/main/java/alpine/server/filters/AuthorizationFilter.java b/alpine/alpine-server/src/main/java/alpine/server/filters/AuthorizationFilter.java
index d838bcff40..989b8dcc07 100644
--- a/alpine/alpine-server/src/main/java/alpine/server/filters/AuthorizationFilter.java
+++ b/alpine/alpine-server/src/main/java/alpine/server/filters/AuthorizationFilter.java
@@ -35,7 +35,6 @@
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
import java.security.Principal;
-import java.util.Collections;
import java.util.Set;
/**
@@ -83,24 +82,30 @@ public void filter(ContainerRequestContext requestContext) {
final PermissionRequired annotation = resourceInfo.getResourceMethod().getDeclaredAnnotation(PermissionRequired.class);
final Set permissions = Set.of(annotation.value());
- final boolean hasNoRequiredPermission = Collections.disjoint(permissions, effectivePermissions);
- if (hasNoRequiredPermission) {
- final String requestUri = requestContext.getUriInfo().getRequestUri().toString();
- final String requestPrincipal;
+ final boolean hasRequiredPermission = switch (annotation.operator()) {
+ case AND -> permissions.stream().allMatch(effectivePermissions::contains);
+ case OR -> permissions.stream().anyMatch(effectivePermissions::contains);
+ default -> false;
+ };
- switch (principal) {
- case ApiKey apiKey -> requestPrincipal = "API Key " + apiKey.getMaskedKey();
- case User user -> requestPrincipal = user.getUsername();
- default -> throw new IllegalStateException("Unexpected principal type: " + principal.getClass().getName());
- }
+ if (hasRequiredPermission) {
+ requestContext.setProperty(EFFECTIVE_PERMISSIONS_PROPERTY, effectivePermissions);
+ return;
+ }
- LOGGER.info(SecurityMarkers.SECURITY_FAILURE, "Unauthorized access attempt made by %s to %s"
- .formatted(requestPrincipal, requestUri));
+ final String requestUri = requestContext.getUriInfo().getRequestUri().toString();
+ final String requestPrincipal;
- throw new ForbiddenException(Response.status(Response.Status.FORBIDDEN).build());
- } else {
- requestContext.setProperty(EFFECTIVE_PERMISSIONS_PROPERTY, effectivePermissions);
+ switch (principal) {
+ case ApiKey apiKey -> requestPrincipal = "API Key " + apiKey.getMaskedKey();
+ case User user -> requestPrincipal = user.getUsername();
+ default -> throw new IllegalStateException("Unexpected principal type: " + principal.getClass().getName());
}
+
+ LOGGER.info(SecurityMarkers.SECURITY_FAILURE, "Unauthorized access attempt made by %s to %s"
+ .formatted(requestPrincipal, requestUri));
+
+ throw new ForbiddenException(Response.status(Response.Status.FORBIDDEN).build());
}
}
diff --git a/apiserver/src/main/java/org/dependencytrack/auth/Permissions.java b/apiserver/src/main/java/org/dependencytrack/auth/Permissions.java
index 679df1c90e..ee3709ce04 100644
--- a/apiserver/src/main/java/org/dependencytrack/auth/Permissions.java
+++ b/apiserver/src/main/java/org/dependencytrack/auth/Permissions.java
@@ -26,96 +26,78 @@
*/
public enum Permissions {
- BOM_UPLOAD("Allows the ability to upload CycloneDX Software Bill of Materials (SBOM)"),
- VIEW_PORTFOLIO("Provides the ability to view the portfolio of projects, components, and licenses"),
- PORTFOLIO_ACCESS_CONTROL_BYPASS("Provides the ability to bypass portfolio access control, granting access to all projects"),
- PORTFOLIO_MANAGEMENT("Allows the creation, modification, and deletion of data in the portfolio"),
- PORTFOLIO_MANAGEMENT_CREATE("Allows the creation of data in the portfolio"),
- PORTFOLIO_MANAGEMENT_READ("Allows the reading of data in the portfolio"),
- PORTFOLIO_MANAGEMENT_UPDATE("Allows the updating of data in the portfolio"),
- PORTFOLIO_MANAGEMENT_DELETE("Allows the deletion of data in the portfolio"),
- VIEW_VULNERABILITY("Provides the ability to view the vulnerabilities projects are affected by"),
- VULNERABILITY_ANALYSIS("Provides all abilities to make analysis decisions on vulnerabilities"),
- VULNERABILITY_ANALYSIS_CREATE("Provides the ability to upload supported VEX documents to a project"),
- VULNERABILITY_ANALYSIS_READ("Provides the ability read the VEX document for a project"),
- VULNERABILITY_ANALYSIS_UPDATE("Provides the ability to make analysis decisions on vulnerabilities and upload supported VEX documents for a project"),
- VIEW_POLICY_VIOLATION("Provides the ability to view policy violations"),
- VULNERABILITY_MANAGEMENT("Allows all management permissions of internally-defined vulnerabilities"),
- VULNERABILITY_MANAGEMENT_CREATE("Allows creation of internally-defined vulnerabilities"),
- VULNERABILITY_MANAGEMENT_READ("Allows reading internally-defined vulnerabilities"),
- VULNERABILITY_MANAGEMENT_UPDATE("Allows updating internally-defined vulnerabilities and vulnerability tags"),
- VULNERABILITY_MANAGEMENT_DELETE("Allows management of internally-defined vulnerabilities"),
- POLICY_VIOLATION_ANALYSIS("Provides the ability to make analysis decisions on policy violations"),
- ACCESS_MANAGEMENT("Allows the management of users, teams, and API keys"),
- ACCESS_MANAGEMENT_CREATE("Allows create permissions of users, teams, and API keys"),
- ACCESS_MANAGEMENT_READ("Allows read permissions of users, teams, and API keys"),
- ACCESS_MANAGEMENT_UPDATE("Allows update permissions of users, teams, and API keys"),
- ACCESS_MANAGEMENT_DELETE("Allows delete permissions of users, teams, and API keys"),
- SYSTEM_CONFIGURATION("Allows all access to configuration of the system including notifications, repositories, and email settings"),
- SYSTEM_CONFIGURATION_CREATE("Allows creating configuration of the system including notifications, repositories, and email settings"),
- SYSTEM_CONFIGURATION_READ("Allows reading the configuration of the system including notifications, repositories, and email settings"),
- SYSTEM_CONFIGURATION_UPDATE("Allows updating the configuration of the system including notifications, repositories, and email settings"),
- SYSTEM_CONFIGURATION_DELETE("Allows deleting the configuration of the system including notifications, repositories, and email settings"),
- PROJECT_CREATION_UPLOAD("Provides the ability to optionally create project (if non-existent) on BOM or scan upload"),
- POLICY_MANAGEMENT("Allows the creation, modification, and deletion of policy"),
- POLICY_MANAGEMENT_CREATE("Allows the creation of a policy"),
- POLICY_MANAGEMENT_READ("Allows reading of policies"),
- POLICY_MANAGEMENT_UPDATE("Allows the modification of a policy"),
- POLICY_MANAGEMENT_DELETE("Allows the deletion of a policy"),
- TAG_MANAGEMENT("Allows the modification and deletion of tags"),
- TAG_MANAGEMENT_DELETE("Allows the deletion of a tag"),
- VIEW_BADGES("Provides the ability to view badges");
+ // @formatter:off
+ ACCESS_MANAGEMENT("Allows the management of users, teams, and API keys", Scope.SYSTEM),
+ BADGES_READ("Provides the ability to view badges", Scope.PROJECT),
+ BOM_CREATE("Allows the ability to upload CycloneDX Software Bill of Materials (SBOM)", Scope.PROJECT),
+ BOM_READ("Allows the ability to view CycloneDX Software Bill of Materials (SBOM)", Scope.PROJECT),
+ FINDING_CREATE("Provides the ability to upload supported VEX documents to a project", Scope.PROJECT),
+ FINDING_READ("Provides the ability read the VEX document for a project", Scope.PROJECT),
+ FINDING_UPDATE("Provides the ability to make analysis decisions on vulnerabilities and upload supported VEX documents for a project", Scope.PROJECT),
+ NOTIFICATION_RULE_MANAGEMENT("Allows configuration of notifications and email settings", Scope.SYSTEM),
+ POLICY_MANAGEMENT("Allows the creation, modification, and deletion of policy", Scope.SYSTEM),
+ POLICY_VIOLATION_CREATE("Provides the ability to create policy violations", Scope.PROJECT),
+ POLICY_VIOLATION_READ("Provides the ability to view policy violations", Scope.PROJECT),
+ POLICY_VIOLATION_UPDATE("Provides the ability to make analysis decisions on policy violations", Scope.PROJECT),
+ PORTFOLIO_ACCESS_CONTROL_BYPASS("Provides the ability to bypass portfolio access control, granting access to all projects", Scope.SYSTEM),
+ PORTFOLIO_MANAGEMENT("Allows the creation, modification, and deletion of data in the portfolio", Scope.SYSTEM),
+ PROJECT_DELETE("Provides the ability to delete resources within a project", Scope.PROJECT),
+ PROJECT_READ("Provides the ability to read resources within a project", Scope.PROJECT),
+ PROJECT_UPDATE("Provides the ability to update resources within a project", Scope.PROJECT),
+ SYSTEM_CONFIGURATION("Allows all access to configuration of the system including notifications, repositories, and email settings", Scope.SYSTEM),
+ TAG_MANAGEMENT("Allows the management of global tag definitions", Scope.SYSTEM),
+ VULNERABILITY_MANAGEMENT("Allows the management of custom vulnerabilities", Scope.SYSTEM);
+ // @formatter:on
+
+ enum Scope {
+ PROJECT, SYSTEM
+ }
private final String description;
+ private final Scope scope;
- Permissions(final String description) {
+ Permissions(final String description, final Scope scope) {
this.description = description;
+ this.scope = scope;
}
public String getDescription() {
return description;
}
+ public Scope getScope() {
+ return scope;
+ }
+
+ public boolean isProjectScope() {
+ return scope == Scope.PROJECT;
+ }
+
+ public boolean isSystemScope() {
+ return scope == Scope.SYSTEM;
+ }
+
public static class Constants {
- public static final String BOM_UPLOAD = "BOM_UPLOAD";
- public static final String VIEW_PORTFOLIO = "VIEW_PORTFOLIO";
- public static final String PORTFOLIO_ACCESS_CONTROL_BYPASS = Permissions.PORTFOLIO_ACCESS_CONTROL_BYPASS.name();
- public static final String PORTFOLIO_MANAGEMENT = "PORTFOLIO_MANAGEMENT";
- public static final String PORTFOLIO_MANAGEMENT_CREATE = "PORTFOLIO_MANAGEMENT_CREATE";
- public static final String PORTFOLIO_MANAGEMENT_READ = "PORTFOLIO_MANAGEMENT_READ";
- public static final String PORTFOLIO_MANAGEMENT_UPDATE = "PORTFOLIO_MANAGEMENT_UPDATE";
- public static final String PORTFOLIO_MANAGEMENT_DELETE = "PORTFOLIO_MANAGEMENT_DELETE";
- public static final String VIEW_VULNERABILITY = "VIEW_VULNERABILITY";
- public static final String VULNERABILITY_ANALYSIS = "VULNERABILITY_ANALYSIS";
- public static final String VULNERABILITY_ANALYSIS_CREATE = "VULNERABILITY_ANALYSIS_CREATE";
- public static final String VULNERABILITY_ANALYSIS_READ = "VULNERABILITY_ANALYSIS_READ";
- public static final String VULNERABILITY_ANALYSIS_UPDATE = "VULNERABILITY_ANALYSIS_UPDATE";
- public static final String VIEW_POLICY_VIOLATION = "VIEW_POLICY_VIOLATION";
- public static final String VULNERABILITY_MANAGEMENT = "VULNERABILITY_MANAGEMENT";
- public static final String VULNERABILITY_MANAGEMENT_CREATE = "VULNERABILITY_MANAGEMENT_CREATE";
- public static final String VULNERABILITY_MANAGEMENT_READ = "VULNERABILITY_MANAGEMENT_READ";
- public static final String VULNERABILITY_MANAGEMENT_UPDATE = "VULNERABILITY_MANAGEMENT_UPDATE";
- public static final String VULNERABILITY_MANAGEMENT_DELETE = "VULNERABILITY_MANAGEMENT_DELETE";
- public static final String POLICY_VIOLATION_ANALYSIS = "POLICY_VIOLATION_ANALYSIS";
public static final String ACCESS_MANAGEMENT = "ACCESS_MANAGEMENT";
- public static final String ACCESS_MANAGEMENT_CREATE = "ACCESS_MANAGEMENT_CREATE";
- public static final String ACCESS_MANAGEMENT_READ = "ACCESS_MANAGEMENT_READ";
- public static final String ACCESS_MANAGEMENT_UPDATE = "ACCESS_MANAGEMENT_UPDATE";
- public static final String ACCESS_MANAGEMENT_DELETE = "ACCESS_MANAGEMENT_DELETE";
- public static final String SYSTEM_CONFIGURATION = "SYSTEM_CONFIGURATION";
- public static final String SYSTEM_CONFIGURATION_CREATE = "SYSTEM_CONFIGURATION_CREATE";
- public static final String SYSTEM_CONFIGURATION_READ = "SYSTEM_CONFIGURATION_READ";
- public static final String SYSTEM_CONFIGURATION_UPDATE = "SYSTEM_CONFIGURATION_UPDATE";
- public static final String SYSTEM_CONFIGURATION_DELETE = "SYSTEM_CONFIGURATION_DELETE";
- public static final String PROJECT_CREATION_UPLOAD = "PROJECT_CREATION_UPLOAD";
+ public static final String BADGES_READ = "BADGES_READ";
+ public static final String BOM_CREATE = "BOM_CREATE";
+ public static final String BOM_READ = "BOM_READ";
+ public static final String FINDING_CREATE = "FINDING_CREATE";
+ public static final String FINDING_READ = "FINDING_READ";
+ public static final String FINDING_UPDATE = "FINDING_UPDATE";
+ public static final String NOTIFICATION_RULE_MANAGEMENT = "NOTIFICATION_RULE_MANAGEMENT";
public static final String POLICY_MANAGEMENT = "POLICY_MANAGEMENT";
- public static final String POLICY_MANAGEMENT_CREATE = "POLICY_MANAGEMENT_CREATE";
- public static final String POLICY_MANAGEMENT_READ = "POLICY_MANAGEMENT_READ";
- public static final String POLICY_MANAGEMENT_UPDATE = "POLICY_MANAGEMENT_UPDATE";
- public static final String POLICY_MANAGEMENT_DELETE = "POLICY_MANAGEMENT_DELETE";
+ public static final String POLICY_VIOLATION_CREATE = "POLICY_VIOLATION_CREATE";
+ public static final String POLICY_VIOLATION_READ = "POLICY_VIOLATION_READ";
+ public static final String POLICY_VIOLATION_UPDATE = "POLICY_VIOLATION_UPDATE";
+ public static final String PORTFOLIO_ACCESS_CONTROL_BYPASS = "PORTFOLIO_ACCESS_CONTROL_BYPASS";
+ public static final String PORTFOLIO_MANAGEMENT = "PORTFOLIO_MANAGEMENT";
+ public static final String PROJECT_DELETE = "PROJECT_DELETE";
+ public static final String PROJECT_READ = "PROJECT_READ";
+ public static final String PROJECT_UPDATE = "PROJECT_UPDATE";
+ public static final String SYSTEM_CONFIGURATION = "SYSTEM_CONFIGURATION";
public static final String TAG_MANAGEMENT = "TAG_MANAGEMENT";
- public static final String TAG_MANAGEMENT_DELETE = "TAG_MANAGEMENT_DELETE";
- public static final String VIEW_BADGES = "VIEW_BADGES";
+ public static final String VULNERABILITY_MANAGEMENT = "VULNERABILITY_MANAGEMENT";
}
}
diff --git a/apiserver/src/main/java/org/dependencytrack/model/validation/ValidRolePermission.java b/apiserver/src/main/java/org/dependencytrack/model/validation/ValidRolePermission.java
new file mode 100644
index 0000000000..cff3a57651
--- /dev/null
+++ b/apiserver/src/main/java/org/dependencytrack/model/validation/ValidRolePermission.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Dependency-Track.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) OWASP Foundation. All Rights Reserved.
+ */
+package org.dependencytrack.model.validation;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import jakarta.validation.ReportAsSingleViolation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @since 5.6.0
+ */
+@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE_USE })
+@Constraint(validatedBy = ValidRolePermissionValidator.class)
+@Retention(RUNTIME)
+@ReportAsSingleViolation
+public @interface ValidRolePermission {
+
+ String message() default "{org.dependencytrack.model.validation.ValidRolePermission.message}";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+}
diff --git a/apiserver/src/main/java/org/dependencytrack/model/validation/ValidRolePermissionValidator.java b/apiserver/src/main/java/org/dependencytrack/model/validation/ValidRolePermissionValidator.java
new file mode 100644
index 0000000000..ef0239ba99
--- /dev/null
+++ b/apiserver/src/main/java/org/dependencytrack/model/validation/ValidRolePermissionValidator.java
@@ -0,0 +1,63 @@
+/*
+ * This file is part of Dependency-Track.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) OWASP Foundation. All Rights Reserved.
+ */
+package org.dependencytrack.model.validation;
+
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.dependencytrack.auth.Permissions;
+
+/**
+ * @since 5.6.0
+ */
+public class ValidRolePermissionValidator implements ConstraintValidator {
+
+ private static final List PROJECT_PERMISSIONS = Stream.of(Permissions.values())
+ .filter(Permissions::isProjectScope)
+ .map(Permissions::name)
+ .toList();
+
+ private static final List SYSTEM_PERMISSIONS = Stream.of(Permissions.values())
+ .filter(Permissions::isSystemScope)
+ .map(Permissions::name)
+ .toList();
+
+ @Override
+ public boolean isValid(final String permission, final ConstraintValidatorContext validatorContext) {
+ if (SYSTEM_PERMISSIONS.contains(permission)) {
+ validatorContext.buildConstraintViolationWithTemplate("System permissions cannot be assigned to roles")
+ .addConstraintViolation();
+
+ return false;
+ }
+
+ if (!PROJECT_PERMISSIONS.contains(permission)) {
+ validatorContext.buildConstraintViolationWithTemplate("Invalid permission name")
+ .addConstraintViolation();
+
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/apiserver/src/main/java/org/dependencytrack/persistence/DatabaseSeedingInitTask.java b/apiserver/src/main/java/org/dependencytrack/persistence/DatabaseSeedingInitTask.java
index a9dbe19fc4..35d243e0b9 100644
--- a/apiserver/src/main/java/org/dependencytrack/persistence/DatabaseSeedingInitTask.java
+++ b/apiserver/src/main/java/org/dependencytrack/persistence/DatabaseSeedingInitTask.java
@@ -65,53 +65,45 @@ public final class DatabaseSeedingInitTask implements InitTask {
private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseSeedingInitTask.class);
private static final Map> DEFAULT_TEAM_PERMISSIONS = Map.of(
- "Administrators", Stream.of(Permissions.values())
- .map(Permissions::name)
- .toList(),
- "Portfolio Managers", List.of(
- Permissions.Constants.VIEW_PORTFOLIO,
- Permissions.Constants.PORTFOLIO_MANAGEMENT,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_READ,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE),
- "Automation", List.of(
- Permissions.Constants.VIEW_PORTFOLIO,
- Permissions.Constants.BOM_UPLOAD),
- "Badge Viewers", List.of(
- Permissions.Constants.VIEW_BADGES));
+ "Administrators", Stream.of(Permissions.values()).map(Permissions::name).toList(),
+ "Portfolio Managers", List.of(Permissions.Constants.PORTFOLIO_MANAGEMENT),
+ "Automation", List.of(Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.BOM_CREATE),
+ "Badge Viewers", List.of(Permissions.Constants.BADGES_READ));
private static final Map> DEFAULT_ROLE_PERMISSIONS = Map.of(
"Project Admin", List.of(
- Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_READ,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE,
- Permissions.Constants.VULNERABILITY_ANALYSIS,
- Permissions.Constants.VULNERABILITY_ANALYSIS_CREATE,
- Permissions.Constants.VULNERABILITY_ANALYSIS_READ,
- Permissions.Constants.VULNERABILITY_ANALYSIS_UPDATE,
- Permissions.Constants.POLICY_MANAGEMENT,
- Permissions.Constants.POLICY_MANAGEMENT_CREATE,
- Permissions.Constants.POLICY_MANAGEMENT_READ,
- Permissions.Constants.POLICY_MANAGEMENT_UPDATE,
- Permissions.Constants.POLICY_MANAGEMENT_DELETE),
+ Permissions.Constants.BADGES_READ,
+ Permissions.Constants.BOM_READ,
+ Permissions.Constants.BOM_CREATE,
+ Permissions.Constants.FINDING_CREATE,
+ Permissions.Constants.FINDING_READ,
+ Permissions.Constants.FINDING_UPDATE,
+ Permissions.Constants.POLICY_VIOLATION_CREATE,
+ Permissions.Constants.POLICY_VIOLATION_READ,
+ Permissions.Constants.POLICY_VIOLATION_UPDATE,
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE,
+ Permissions.Constants.PROJECT_DELETE),
"Project Auditor", List.of(
- Permissions.Constants.VIEW_PORTFOLIO,
- Permissions.Constants.VIEW_VULNERABILITY,
- Permissions.Constants.VIEW_POLICY_VIOLATION,
- Permissions.Constants.VULNERABILITY_ANALYSIS_READ),
+ Permissions.Constants.BADGES_READ,
+ Permissions.Constants.BOM_READ,
+ Permissions.Constants.FINDING_READ,
+ Permissions.Constants.POLICY_VIOLATION_READ,
+ Permissions.Constants.PROJECT_READ),
"Project Editor", List.of(
- Permissions.Constants.BOM_UPLOAD,
- Permissions.Constants.VIEW_PORTFOLIO,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_READ,
- Permissions.Constants.VIEW_VULNERABILITY,
- Permissions.Constants.VULNERABILITY_ANALYSIS_READ,
- Permissions.Constants.PROJECT_CREATION_UPLOAD),
+ Permissions.Constants.BOM_CREATE,
+ Permissions.Constants.BOM_READ,
+ Permissions.Constants.FINDING_READ,
+ Permissions.Constants.FINDING_UPDATE,
+ Permissions.Constants.POLICY_VIOLATION_CREATE,
+ Permissions.Constants.POLICY_VIOLATION_READ,
+ Permissions.Constants.POLICY_VIOLATION_UPDATE,
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE),
"Project Viewer", List.of(
- Permissions.Constants.VIEW_PORTFOLIO,
- Permissions.Constants.VIEW_VULNERABILITY,
- Permissions.Constants.VIEW_BADGES));
+ Permissions.Constants.BADGES_READ,
+ Permissions.Constants.BOM_READ,
+ Permissions.Constants.PROJECT_READ));
@Override
public int priority() {
diff --git a/apiserver/src/main/java/org/dependencytrack/persistence/ProjectQueryManager.java b/apiserver/src/main/java/org/dependencytrack/persistence/ProjectQueryManager.java
index 8d8026f4bf..c9bf0738dd 100644
--- a/apiserver/src/main/java/org/dependencytrack/persistence/ProjectQueryManager.java
+++ b/apiserver/src/main/java/org/dependencytrack/persistence/ProjectQueryManager.java
@@ -764,7 +764,7 @@ SELECT EXISTS(
ON ph."PARENT_PROJECT_ID" = upep."PROJECT_ID"
WHERE ph."CHILD_PROJECT_ID" = ?
AND upep."USER_ID" = ?
- AND upep."PERMISSION_NAME" = 'VIEW_PORTFOLIO'
+ AND upep."PERMISSION_NAME" = 'PROJECT_READ'
)
""")
.setParameters(project.getId(), user.getId());
diff --git a/apiserver/src/main/java/org/dependencytrack/persistence/QueryManager.java b/apiserver/src/main/java/org/dependencytrack/persistence/QueryManager.java
index 99f58dad46..cade6f9197 100644
--- a/apiserver/src/main/java/org/dependencytrack/persistence/QueryManager.java
+++ b/apiserver/src/main/java/org/dependencytrack/persistence/QueryManager.java
@@ -1210,9 +1210,9 @@ public Set getEffectivePermissions(Principal principal) {
List userRoles = getUserRoles(user.getUsername());
- // If a user has a role on any project, grant VIEW_PORTFOLIO permission
+ // If a user has a role on any project, grant PROJECT_READ permission
if (userRoles != null && !userRoles.isEmpty())
- permissions.add(Permissions.Constants.VIEW_PORTFOLIO);
+ permissions.add(Permissions.Constants.PROJECT_READ);
return permissions;
}
@@ -1701,7 +1701,7 @@ public Map.Entry> getProjectAclSqlCondition(final St
ON ph."PARENT_PROJECT_ID" = upep."PROJECT_ID"
WHERE ph."CHILD_PROJECT_ID" = "%s"."ID"
AND upep."USER_ID" = :projectAclUserId
- AND upep."PERMISSION_NAME" = 'VIEW_PORTFOLIO'
+ AND upep."PERMISSION_NAME" = 'PROJECT_READ'
)
""";
}
diff --git a/apiserver/src/main/java/org/dependencytrack/persistence/TagQueryManager.java b/apiserver/src/main/java/org/dependencytrack/persistence/TagQueryManager.java
index f6a30de74a..a89c3acd11 100644
--- a/apiserver/src/main/java/org/dependencytrack/persistence/TagQueryManager.java
+++ b/apiserver/src/main/java/org/dependencytrack/persistence/TagQueryManager.java
@@ -244,23 +244,15 @@ public void deleteTags(final Collection tagNames) {
hasSystemConfigurationUpdatePermission = true;
} else {
if (principal instanceof final ApiKey apiKey) {
- hasPortfolioManagementUpdatePermission = hasPermission(apiKey, Permissions.Constants.PORTFOLIO_MANAGEMENT)
- || hasPermission(apiKey, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE);
- hasPolicyManagementUpdatePermission = hasPermission(apiKey, Permissions.Constants.POLICY_MANAGEMENT)
- || hasPermission(apiKey, Permissions.Constants.POLICY_MANAGEMENT_UPDATE);
- hasSystemConfigurationUpdatePermission = hasPermission(apiKey, Permissions.Constants.SYSTEM_CONFIGURATION)
- || hasPermission(apiKey, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE);
- hasvulnerabilityManagementUpdatePermission = hasPermission(apiKey, Permissions.Constants.VULNERABILITY_MANAGEMENT)
- || hasPermission(apiKey, Permissions.Constants.VULNERABILITY_MANAGEMENT_UPDATE);
+ hasPortfolioManagementUpdatePermission = hasPermission(apiKey, Permissions.Constants.PORTFOLIO_MANAGEMENT);
+ hasPolicyManagementUpdatePermission = hasPermission(apiKey, Permissions.Constants.POLICY_MANAGEMENT);
+ hasSystemConfigurationUpdatePermission = hasPermission(apiKey, Permissions.Constants.SYSTEM_CONFIGURATION);
+ hasvulnerabilityManagementUpdatePermission = hasPermission(apiKey, Permissions.Constants.VULNERABILITY_MANAGEMENT);
} else if (principal instanceof final User user) {
- hasPortfolioManagementUpdatePermission = hasPermission(user, Permissions.Constants.PORTFOLIO_MANAGEMENT, /* includeTeams */ true)
- || hasPermission(user, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE, /* includeTeams */ true);
- hasPolicyManagementUpdatePermission = hasPermission(user, Permissions.Constants.POLICY_MANAGEMENT, /* includeTeams */ true)
- || hasPermission(user, Permissions.Constants.POLICY_MANAGEMENT_UPDATE, /* includeTeams */ true);
- hasSystemConfigurationUpdatePermission = hasPermission(user, Permissions.Constants.SYSTEM_CONFIGURATION, /* includeTeams */ true)
- || hasPermission(user, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE, /* includeTeams */ true);
- hasvulnerabilityManagementUpdatePermission = hasPermission(user, Permissions.Constants.VULNERABILITY_MANAGEMENT, /* includeTeams */ true)
- || hasPermission(user, Permissions.Constants.VULNERABILITY_MANAGEMENT_UPDATE, /* includeTeams */ true);
+ hasPortfolioManagementUpdatePermission = hasPermission(user, Permissions.Constants.PORTFOLIO_MANAGEMENT, /* includeTeams */ true);
+ hasPolicyManagementUpdatePermission = hasPermission(user, Permissions.Constants.POLICY_MANAGEMENT, /* includeTeams */ true);
+ hasSystemConfigurationUpdatePermission = hasPermission(user, Permissions.Constants.SYSTEM_CONFIGURATION, /* includeTeams */ true);
+ hasvulnerabilityManagementUpdatePermission = hasPermission(user, Permissions.Constants.VULNERABILITY_MANAGEMENT, /* includeTeams */ true);
}
}
@@ -268,8 +260,8 @@ public void deleteTags(final Collection tagNames) {
if (row.projectCount() > 0 && !hasPortfolioManagementUpdatePermission) {
errorByTagName.put(row.name(), """
The tag is assigned to %d project(s), but the authenticated principal \
- is missing the %s or %s permission.""".formatted(row.projectCount(),
- Permissions.PORTFOLIO_MANAGEMENT, Permissions.PORTFOLIO_MANAGEMENT_UPDATE));
+ is missing the %s permission.""".formatted(row.projectCount(),
+ Permissions.PORTFOLIO_MANAGEMENT));
continue;
}
@@ -285,22 +277,22 @@ public void deleteTags(final Collection tagNames) {
if (row.policyCount() > 0 && !hasPolicyManagementUpdatePermission) {
errorByTagName.put(row.name(), """
The tag is assigned to %d policies, but the authenticated principal \
- is missing the %s or %s permission.""".formatted(row.policyCount(),
- Permissions.POLICY_MANAGEMENT, Permissions.POLICY_MANAGEMENT_UPDATE));
+ is missing the %s permission.""".formatted(row.policyCount(),
+ Permissions.POLICY_MANAGEMENT));
}
if (row.notificationRuleCount() > 0 && !hasSystemConfigurationUpdatePermission) {
errorByTagName.put(row.name(), """
The tag is assigned to %d notification rules, but the authenticated principal \
- is missing the %s or %s permission.""".formatted(row.notificationRuleCount(),
- Permissions.SYSTEM_CONFIGURATION, Permissions.SYSTEM_CONFIGURATION_UPDATE));
+ is missing the %s permission.""".formatted(row.notificationRuleCount(),
+ Permissions.SYSTEM_CONFIGURATION));
}
if (row.vulnerabilityCount() > 0 && !hasvulnerabilityManagementUpdatePermission) {
errorByTagName.put(row.name(), """
The tag is assigned to %d vulnerabilities, but the authenticated principal \
- is missing the %s or %s permission.""".formatted(row.vulnerabilityCount(),
- Permissions.VULNERABILITY_MANAGEMENT, Permissions.VULNERABILITY_MANAGEMENT_UPDATE));
+ is missing the %s permission.""".formatted(row.vulnerabilityCount(),
+ Permissions.VULNERABILITY_MANAGEMENT));
}
}
diff --git a/apiserver/src/main/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethod.java b/apiserver/src/main/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethod.java
index 231c41640b..705f4c7b55 100644
--- a/apiserver/src/main/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethod.java
+++ b/apiserver/src/main/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethod.java
@@ -27,13 +27,15 @@
import org.datanucleus.store.rdbms.sql.expression.IntegerLiteral;
import org.datanucleus.store.rdbms.sql.expression.ObjectExpression;
import org.datanucleus.store.rdbms.sql.expression.SQLExpression;
+import org.datanucleus.store.rdbms.sql.expression.SQLLiteral;
import org.datanucleus.store.rdbms.sql.expression.StringExpression;
import org.datanucleus.store.rdbms.sql.expression.StringLiteral;
import org.datanucleus.store.rdbms.sql.method.SQLMethod;
import org.dependencytrack.model.Project;
import java.util.List;
-import java.util.StringJoiner;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* @since 5.6.0
@@ -45,11 +47,7 @@ public SQLExpression getExpression(
final SQLStatement stmt,
final SQLExpression expr,
final List args) {
- if (!(expr instanceof final ObjectExpression objectExpr))
- // DataNucleus should prevent this from ever happening since
- // the method is explicitly registered for java.lang.Object.
- throw new IllegalStateException("Expected expression to be of type %s, but got: %s".formatted(
- ObjectExpression.class.getName(), expr.getClass().getName()));
+ final ObjectExpression objectExpr = validateType(expr, ObjectExpression.class);
final String objectTypeName = objectExpr.getJavaTypeMapping().getType();
if (!Project.class.getName().equals(objectTypeName))
@@ -57,50 +55,37 @@ public SQLExpression getExpression(
"isAccessibleBy is only allowed for objects of type %s, but was called on %s".formatted(
Project.class.getName(), objectTypeName));
- if (args == null) {
- throw new IllegalArgumentException();
- } else if (args.size() != 1) {
- throw new IllegalArgumentException("Expected exactly one argument, but got " + args.size());
- }
-
// TODO: When a list, set, etc. is passed as argument, it will be of type CollectionLiteral.
// Array literals are easier to verify the type of, hence we're focusing on that for now.
+ switch (args) {
+ case null -> throw new IllegalArgumentException();
+ case List a when a.size() == 1 -> {
+ final ArrayLiteral arrayLiteralArg = validateType(args.getFirst(), ArrayLiteral.class);
- switch (args.getFirst()) {
- case IntegerLiteral userIdArg -> {
- return getUserExpression(stmt, objectExpr, userIdArg);
- }
- case ArrayLiteral arrayLiteralArg -> {
return getApiKeyExpression(stmt, objectExpr, arrayLiteralArg);
}
- default -> {
- throw new IllegalArgumentException("Expected argument to be of type %s or %s, but got %s"
- .formatted(ArrayLiteral.class.getName(),
- IntegerLiteral.class.getName(),
- args.getFirst().getClass().getName()));
+ case List a when a.size() == 2 -> {
+ final IntegerLiteral userIdArg = validateType(args.getFirst(), IntegerLiteral.class);
+ final ArrayLiteral arrayLiteralArg = validateType(args.getLast(), ArrayLiteral.class);
+
+ return getUserExpression(stmt, objectExpr, userIdArg, arrayLiteralArg);
}
+ default -> throw new IllegalArgumentException("Expected one or two arguments, but got " + args.size());
}
}
private SQLExpression getApiKeyExpression(final SQLStatement stmt, final ObjectExpression objectExpr, final ArrayLiteral arrayLiteralArg) {
- if (!(arrayLiteralArg.getValue() instanceof final Long[] teamIds))
- throw new IllegalArgumentException(
- "Expected array argument to be of type %s, but got %s".formatted(
- Long[].class.getName(), arrayLiteralArg.getValue().getClass().getName()));
+ final Long[] teamIds = validateType(arrayLiteralArg.getValue(), Long[].class);
- final JavaTypeMapping booleanTypeMapping = stmt.getSQLExpressionFactory().getMappingForType(Boolean.class);
- final JavaTypeMapping stringTypeMapping = stmt.getSQLExpressionFactory().getMappingForType(String.class);
+ final JavaTypeMapping booleanTypeMapping = getTypeMapping(stmt, Boolean.class);
+ final JavaTypeMapping stringTypeMapping = getTypeMapping(stmt, String.class);
// Transform the array literal to have the correct type for Postgres.
// Will result in the following expression: cast('{1,2,3}' as bigint[])
- final StringJoiner joiner = new StringJoiner(",", "{", "}");
- for (final Long teamId : teamIds) {
- joiner.add(String.valueOf(teamId));
- }
- final var teamIdsLiteral = new StringLiteral(
- stmt, stringTypeMapping, joiner.toString(), null);
- final var teamIdsExpr = new StringExpression(
- stmt, stringTypeMapping, "cast", List.of(teamIdsLiteral), List.of("bigint[]"));
+ final String arrayString = Stream.of(teamIds).map(String::valueOf).collect(Collectors.joining(",", "{", "}"));
+ final StringLiteral arrayLiteral = new StringLiteral(stmt, stringTypeMapping, arrayString, null);
+ final StringExpression castExpr = new StringExpression(
+ stmt, stringTypeMapping, "cast", List.of(arrayLiteral), List.of("bigint[]"));
// TODO: This should not rely on a SQL function, as functions yield a
// suboptimal query plan (https://github.com/DependencyTrack/hyades/issues/1801).
@@ -109,41 +94,61 @@ private SQLExpression getApiKeyExpression(final SQLStatement stmt, final ObjectE
// NB: objectExpr will compile to a reference of the object table's ID column, e.g.:
// * "A0"."ID"
// * "B0"."PROJECT_ID"
- final var hasProjectAccessFunctionExpr = new StringExpression(
- stmt, stringTypeMapping, "has_project_access", List.of(objectExpr, teamIdsExpr));
+ final StringExpression functionExpr = new StringExpression(
+ stmt, stringTypeMapping, "has_project_access", List.of(objectExpr, castExpr));
// Wrap the function call in a boolean expression. Final result(s) will be:
// * has_project_access("A0"."ID", cast('{1,2,3}' as bigint[])) = TRUE
// * has_project_access("B0"."PROJECT_ID", cast('{1,2,3}' as bigint[])) = TRUE
- final var booleanTrueLiteral = new BooleanLiteral(stmt, booleanTypeMapping, Boolean.TRUE, null);
+ final BooleanLiteral booleanTrueLiteral = new BooleanLiteral(stmt, booleanTypeMapping, Boolean.TRUE, null);
- return new BooleanExpression(hasProjectAccessFunctionExpr, Expression.OP_EQ, booleanTrueLiteral);
+ return new BooleanExpression(functionExpr, Expression.OP_EQ, booleanTrueLiteral);
}
- private SQLExpression getUserExpression(final SQLStatement stmt, final ObjectExpression objectExpr, final IntegerLiteral userIdArg) {
- if (!(userIdArg.getValue() instanceof final Long userId))
- throw new IllegalArgumentException(
- "Expected user ID argument to be of type %s, but got %s".formatted(
- Long.class.getName(), userIdArg.getValue().getClass().getName()));
+ private SQLExpression getUserExpression(final SQLStatement stmt, final ObjectExpression objectExpr, final IntegerLiteral userIdArg, final ArrayLiteral arrayLiteralArg) {
+ final Long userId = validateType(userIdArg.getValue(), Long.class);
+ final String[] permissions = validateType(arrayLiteralArg.getValue(), String[].class);
+
+ final JavaTypeMapping booleanTypeMapping = getTypeMapping(stmt, Boolean.class);
+ final JavaTypeMapping integerTypeMapping = getTypeMapping(stmt, Long.class);
+ final JavaTypeMapping stringTypeMapping = getTypeMapping(stmt, String.class);
- final JavaTypeMapping booleanTypeMapping = stmt.getSQLExpressionFactory().getMappingForType(Boolean.class);
- final JavaTypeMapping stringTypeMapping = stmt.getSQLExpressionFactory().getMappingForType(String.class);
- final JavaTypeMapping integerTypeMapping = stmt.getSQLExpressionFactory().getMappingForType(Long.class);
+ final IntegerLiteral userIdLiteral = new IntegerLiteral(stmt, integerTypeMapping, userId, "userId");
- final var userIdLiteral = new IntegerLiteral(stmt, integerTypeMapping, userId, "userId");
+ // Transform the array literal to have the correct type for Postgres.
+ // Will result in the following expression: cast('{one,two,three}' as text[])
+ final String arrayString = Stream.of(permissions).collect(Collectors.joining(",", "{", "}"));
+ final StringLiteral arrayLiteral = new StringLiteral(stmt, stringTypeMapping, arrayString, null);
+ final StringExpression castExpr = new StringExpression(
+ stmt, stringTypeMapping, "cast", List.of(arrayLiteral), List.of("text[]"));
// NB: objectExpr will compile to a reference of the object table's ID column, e.g.:
// * "A0"."ID"
// * "B0"."PROJECT_ID"
- final var hasProjectAccessFunctionExpr = new StringExpression(
- stmt, stringTypeMapping, "has_user_project_access", List.of(objectExpr, userIdLiteral));
+ final StringExpression functionExpr = new StringExpression(
+ stmt, stringTypeMapping, "has_user_project_access", List.of(objectExpr, userIdLiteral, castExpr));
// Wrap the function call in a boolean expression. Final result(s) will be:
// * has_user_project_access("A0"."ID", 1) = TRUE
// * has_user_project_access("B0"."PROJECT_ID", 1) = TRUE
- final var booleanTrueLiteral = new BooleanLiteral(stmt, booleanTypeMapping, Boolean.TRUE, null);
+ final BooleanLiteral booleanTrueLiteral = new BooleanLiteral(stmt, booleanTypeMapping, Boolean.TRUE, null);
+
+ return new BooleanExpression(functionExpr, Expression.OP_EQ, booleanTrueLiteral);
+ }
+
+ private JavaTypeMapping getTypeMapping(final SQLStatement stmt, final Class> type) {
+ return stmt.getSQLExpressionFactory().getMappingForType(type);
+ }
+
+ @SuppressWarnings("unchecked")
+ private T validateType(final Object arg, final Class expected) {
+ final String argType = arg instanceof SQLLiteral ? "argument" : "expression";
+
+ if (!expected.isInstance(arg))
+ throw new IllegalArgumentException("Expected %s to be of type %s, but got %s"
+ .formatted(argType, expected.getName(), arg.getClass().getName()));
- return new BooleanExpression(hasProjectAccessFunctionExpr, Expression.OP_EQ, booleanTrueLiteral);
+ return (T) arg;
}
}
diff --git a/apiserver/src/main/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizer.java b/apiserver/src/main/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizer.java
index 34e8efcd24..b7d0158138 100644
--- a/apiserver/src/main/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizer.java
+++ b/apiserver/src/main/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizer.java
@@ -33,6 +33,7 @@
import java.security.Principal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@@ -67,6 +68,7 @@ class ApiRequestStatementCustomizer implements StatementCustomizer {
static final String PARAMETER_PROJECT_ACL_TEAM_IDS = "projectAclTeamIds";
static final String PARAMETER_PROJECT_ACL_USER_ID = "projectAclUserId";
+ static final String PARAMETER_PROJECT_ACL_PERMISSIONS = "projectAclPermissions";
static final String TEMPLATE_PROJECT_ACL_CONDITION = /* language=SQL */ """
EXISTS(
SELECT 1
@@ -85,7 +87,7 @@ class ApiRequestStatementCustomizer implements StatementCustomizer {
ON ph."PARENT_PROJECT_ID" = upep."PROJECT_ID"
WHERE ph."CHILD_PROJECT_ID" = %s
AND upep."USER_ID" = :projectAclUserId
- AND upep."PERMISSION_NAME" = 'VIEW_PORTFOLIO'
+ AND upep."PERMISSION_NAME" = ALL(:projectAclPermissions)
)
""";
@@ -211,6 +213,8 @@ private void defineProjectAclCondition(final StatementContext ctx) throws SQLExc
ctx.define(ATTRIBUTE_API_PROJECT_ACL_CONDITION,
TEMPLATE_USER_PROJECT_ACL_CONDITION.formatted(config.projectAclProjectIdColumn()));
ctx.getBinding().addNamed(PARAMETER_PROJECT_ACL_USER_ID, user.getId(), QualifiedType.of(Long.class));
+ ctx.getBinding().addNamed(PARAMETER_PROJECT_ACL_PERMISSIONS, new LinkedHashSet(),
+ QualifiedType.of(parameterizeClass(Set.class, String.class)));
}
case ApiKey apiKey when !principalTeamIds.isEmpty() -> {
ctx.define(ATTRIBUTE_API_PROJECT_ACL_CONDITION,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java
index 3df88d6f5b..fc49b98abd 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java
@@ -78,7 +78,7 @@ public class AccessControlResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns the projects assigned to the specified team",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -91,7 +91,7 @@ public class AccessControlResource extends AlpineResource {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the team could not be found"),
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response retrieveProjects(@Parameter(description = "The UUID of the team to retrieve mappings for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@Parameter(description = "Optionally excludes inactive projects from being returned")
@@ -115,7 +115,7 @@ public Response retrieveProjects(@Parameter(description = "The UUID of the team
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns the projects accessible by the specified user",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
")
+ description = "Requires permission ACCESS_MANAGEMENT
")
@PaginatedApi
@ApiResponses(value = {
@ApiResponse(
@@ -128,7 +128,7 @@ public Response retrieveProjects(@Parameter(description = "The UUID of the team
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "User not found"),
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response retrieveUserProjects(
@Parameter(description = "The username to retrieve projects for", required = true) @PathParam("username") String username) {
@@ -169,7 +169,7 @@ public Response retrieveUserProjects(
description = "A mapping with the same team and project already exists",
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON))
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response addMapping(AclMappingRequest request) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -209,7 +209,7 @@ public Response addMapping(AclMappingRequest request) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes an ACL mapping",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENTTE
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Mapping removed successfully"),
@@ -219,7 +219,7 @@ public Response addMapping(AclMappingRequest request) {
description = "Team or project could not be found",
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON))
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteMapping(
@Parameter(description = "The UUID of the team to delete the mapping for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("teamUuid") @ValidUuid String teamUuid,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java
index 4db8ddd410..4b183cf66e 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java
@@ -24,6 +24,7 @@
import alpine.model.Team;
import alpine.model.User;
import alpine.server.auth.PermissionRequired;
+import alpine.server.filters.ResourceAccessRequired;
import com.google.protobuf.Any;
import com.google.protobuf.util.Timestamps;
import io.swagger.v3.oas.annotations.Operation;
@@ -93,7 +94,7 @@ public class AnalysisResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Retrieves an analysis trail",
- description = "Requires permission VIEW_VULNERABILITY
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -108,7 +109,10 @@ public class AnalysisResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project, component, or vulnerability could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_VULNERABILITY)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response retrieveAnalysis(@Parameter(description = "The UUID of the project", schema = @Schema(type = "string", format = "uuid"))
@QueryParam("project") @ValidUuid String projectUuid,
@Parameter(description = "The UUID of the component", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -149,7 +153,7 @@ public Response retrieveAnalysis(@Parameter(description = "The UUID of the proje
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Records an analysis decision",
- description = "Requires permission VULNERABILITY_ANALYSIS or VULNERABILITY_ANALYSIS_UPDATE
"
+ description = "Requires permission PROJECT_READ and FINDING_UPDATE
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -164,7 +168,10 @@ public Response retrieveAnalysis(@Parameter(description = "The UUID of the proje
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project, component, or vulnerability could not be found")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_ANALYSIS, Permissions.Constants.VULNERABILITY_ANALYSIS_UPDATE})
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_UPDATE },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response updateAnalysis(AnalysisRequest request) {
final Validator validator = getValidator();
failOnValidationError(
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/BadgeResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/BadgeResource.java
index b095f29c73..33ab1b821b 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/BadgeResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/BadgeResource.java
@@ -127,7 +127,7 @@ private boolean passesAuthorization(final QueryManager qm) {
return false;
}
- final String[] permissions = { Permissions.Constants.VIEW_BADGES };
+ final String[] permissions = { Permissions.Constants.BADGES_READ };
if (principal instanceof ApiKey) {
final ApiKey apiKey = (ApiKey)principal;
@@ -167,7 +167,7 @@ private boolean passesAuthorization(final QueryManager qm) {
@Produces(SVG_MEDIA_TYPE)
@Operation(
summary = "Returns current metrics for a specific project",
- description = "Requires permission VIEW_BADGES
"
+ description = "Requires permission BADGES_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -214,7 +214,7 @@ public Response getProjectVulnerabilitiesBadge(
@Produces(SVG_MEDIA_TYPE)
@Operation(
summary = "Returns current metrics for a specific project",
- description = "Requires permission VIEW_BADGES
"
+ description = "Requires permission BADGES_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -263,7 +263,7 @@ public Response getProjectVulnerabilitiesBadge(
@Produces(SVG_MEDIA_TYPE)
@Operation(
summary = "Returns a policy violations badge for a specific project",
- description = "Requires permission VIEW_BADGES
"
+ description = "Requires permission BADGES_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -310,7 +310,7 @@ public Response getProjectPolicyViolationsBadge(
@Produces(SVG_MEDIA_TYPE)
@Operation(
summary = "Returns a policy violations badge for a specific project",
- description = "Requires permission VIEW_BADGES
"
+ description = "Requires permission BADGES_READ
"
)
@ApiResponses(value = {
@ApiResponse(
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/BomResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/BomResource.java
index 1492d1c8e5..2c9e517206 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/BomResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/BomResource.java
@@ -121,7 +121,7 @@ public class BomResource extends AbstractApiResource {
@Produces({CycloneDxMediaType.APPLICATION_CYCLONEDX_XML, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON, MediaType.APPLICATION_OCTET_STREAM})
@Operation(
summary = "Returns dependency metadata for a project in CycloneDX format",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ and BOM_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -136,7 +136,9 @@ public class BomResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.BOM_READ },
+ operator = PermissionRequired.Operator.AND)
@ResourceAccessRequired
public Response exportProjectAsCycloneDx(
@Parameter(description = "The UUID of the project to export", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -197,7 +199,7 @@ public Response exportProjectAsCycloneDx(
@Produces({CycloneDxMediaType.APPLICATION_CYCLONEDX_XML, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON})
@Operation(
summary = "Returns dependency metadata for a specific component in CycloneDX format",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ and BOM_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -212,7 +214,9 @@ public Response exportProjectAsCycloneDx(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.BOM_READ },
+ operator = PermissionRequired.Operator.AND)
@ResourceAccessRequired
public Response exportComponentAsCycloneDx(
@Parameter(description = "The UUID of the component to export", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -255,8 +259,7 @@ public Response exportComponentAsCycloneDx(
then the projectName and projectVersion must be specified.
Optionally, if autoCreate is specified and true and the project does not exist,
the project will be created. In this scenario, the principal making the request will
- additionally need the PORTFOLIO_MANAGEMENT, PORTFOLIO_MANAGEMENT_CREATE,
- or PROJECT_CREATION_UPLOAD permission.
+ additionally need the PORTFOLIO_MANAGEMENT permission.
The BOM will be validated against the CycloneDX schema. If schema validation fails,
@@ -268,7 +271,7 @@ public Response exportComponentAsCycloneDx(
When uploading large BOMs, the POST endpoint is preferred,
as it does not have this limit.
- Requires permission BOM_UPLOAD
""",
+ Requires permission BOM_CREATE
""",
operationId = "UploadBomBase64Encoded"
)
@ApiResponses(value = {
@@ -293,7 +296,7 @@ public Response exportComponentAsCycloneDx(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.BOM_UPLOAD)
+ @PermissionRequired(Permissions.Constants.BOM_CREATE)
@ResourceAccessRequired
public Response uploadBom(@Parameter(required = true) BomSubmitRequest request) {
final Validator validator = getValidator();
@@ -319,7 +322,7 @@ public Response uploadBom(@Parameter(required = true) BomSubmitRequest request)
processingResult = qm.callInTransaction(() -> {
Project project = qm.getProject(request.getProjectName(), request.getProjectVersion());
if (project == null && request.isAutoCreate()) {
- if (hasPermission(Permissions.Constants.PORTFOLIO_MANAGEMENT) || hasPermission(Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE) || hasPermission(Permissions.Constants.PROJECT_CREATION_UPLOAD)) {
+ if (hasPermission(Permissions.Constants.PORTFOLIO_MANAGEMENT)) {
Project parent = null;
if (request.getParentUUID() != null || request.getParentName() != null) {
if (request.getParentUUID() != null) {
@@ -381,8 +384,7 @@ public Response uploadBom(@Parameter(required = true) BomSubmitRequest request)
then the projectName and projectVersion must be specified.
Optionally, if autoCreate is specified and true and the project does not exist,
the project will be created. In this scenario, the principal making the request will
- additionally need the PORTFOLIO_MANAGEMENT, PORTFOLIO_MANAGEMENT_CREATE,
- or PROJECT_CREATION_UPLOAD permission.
+ additionally need the PORTFOLIO_MANAGEMENT permission.
MediaType supported for BOM artifact is 'application/xml', 'application/json' or 'application/x.vnd.cyclonedx+protobuf'.
@@ -390,7 +392,7 @@ public Response uploadBom(@Parameter(required = true) BomSubmitRequest request)
a response with problem details in RFC 9457 format will be returned. In this case,
the response's content type will be application/problem+json.
- Requires permission BOM_UPLOAD
""",
+ Requires permission BOM_CREATE
""",
operationId = "UploadBom"
)
@ApiResponses(value = {
@@ -415,7 +417,8 @@ public Response uploadBom(@Parameter(required = true) BomSubmitRequest request)
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.BOM_UPLOAD)
+ @PermissionRequired(Permissions.Constants.BOM_CREATE)
+ @ResourceAccessRequired
public Response uploadBom(
@FormDataParam("project") String projectUuid,
@DefaultValue("false") @FormDataParam("autoCreate") boolean autoCreate,
@@ -443,7 +446,7 @@ public Response uploadBom(
final String trimmedProjectVersion = StringUtils.trimToNull(projectVersion);
Project project = qm.getProject(trimmedProjectName, trimmedProjectVersion);
if (project == null && autoCreate) {
- if (hasPermission(Permissions.Constants.PORTFOLIO_MANAGEMENT) || hasPermission(Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE) || hasPermission(Permissions.Constants.PROJECT_CREATION_UPLOAD)) {
+ if (hasPermission(Permissions.Constants.PORTFOLIO_MANAGEMENT)) {
Project parent = null;
if (parentUUID != null || parentName != null) {
if (parentUUID != null) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentPropertyResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentPropertyResource.java
index 7228182af2..faaf2314c8 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentPropertyResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentPropertyResource.java
@@ -66,7 +66,7 @@ public class ComponentPropertyResource extends AbstractConfigPropertyResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all properties for the specified component",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -81,7 +81,7 @@ public class ComponentPropertyResource extends AbstractConfigPropertyResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProperties(
@Parameter(description = "The UUID of the component to retrieve properties for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -113,7 +113,7 @@ public Response getProperties(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new component property",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_CREATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -129,7 +129,7 @@ public Response getProperties(
@ApiResponse(responseCode = "404", description = "The component could not be found"),
@ApiResponse(responseCode = "409", description = "A property with the specified component/group/name combination already exists")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response createProperty(
@Parameter(description = "The UUID of the component to create a property for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -177,7 +177,7 @@ public Response createProperty(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a config property",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_DELETE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Property removed successfully"),
@@ -188,7 +188,7 @@ public Response createProperty(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component or component property could not be found"),
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response deleteProperty(
@Parameter(description = "The UUID of the component to delete a property from", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid final String componentUuid,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java
index 56ed4b9af5..2320b8f65e 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java
@@ -114,7 +114,7 @@ public class ComponentResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all components for a given project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -131,7 +131,7 @@ public class ComponentResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getAllComponents(
@Parameter(description = "The UUID of the project to retrieve components for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -157,7 +157,7 @@ public Response getAllComponents(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific component",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -172,7 +172,7 @@ public Response getAllComponents(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentByUuid(
@Parameter(description = "The UUID of the component to retrieve", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -212,7 +212,7 @@ public Response getComponentByUuid(
summary = """
Provides the published date and hashes of the requested version of component,
as received from configured repositories for integrity analysis.""",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -224,7 +224,7 @@ public Response getComponentByUuid(
@ApiResponse(responseCode = "404", description = "The integrity meta information for the specified component cannot be found"),
@ApiResponse(responseCode = "400", description = "The package url being queried for is invalid")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getIntegrityMetaComponent(
@Parameter(description = "The package url of the component", required = true)
@@ -256,7 +256,7 @@ public Response getIntegrityMetaComponent(
summary = """
Provides the integrity check status of component with provided UUID,
based on the configured repository for integrity analysis.""",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -271,7 +271,7 @@ public Response getIntegrityMetaComponent(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The integrity analysis information for the specified component cannot be found"),
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getIntegrityStatus(
@Parameter(description = "UUID of the component for which integrity status information is needed", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -298,7 +298,7 @@ public Response getIntegrityStatus(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of components that have the specified component identity. This resource accepts coordinates (group, name, version) or purl, cpe, or swidTagId",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -314,7 +314,7 @@ public Response getIntegrityStatus(
description = "Access to the requested project is forbidden",
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON))
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentByIdentity(@Parameter(description = "The group of the component")
@QueryParam("group") String group,
@@ -365,7 +365,7 @@ public Response getComponentByIdentity(@Parameter(description = "The group of th
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of components that have the specified hash value",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -377,7 +377,7 @@ public Response getComponentByIdentity(@Parameter(description = "The group of th
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentByHash(
@Parameter(description = "The MD5, SHA-1, SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384, SHA3-512, BLAKE2b-256, BLAKE2b-384, BLAKE2b-512, or BLAKE3 hash of the component to retrieve", required = true)
@@ -394,7 +394,7 @@ public Response getComponentByHash(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new component",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -409,8 +409,7 @@ public Response getComponentByHash(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT,
- Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response createComponent(@Parameter(description = "The UUID of the project to create a component for", schema = @Schema(format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid, Component jsonComponent) {
final Validator validator = super.getValidator();
@@ -528,7 +527,7 @@ public Response createComponent(@Parameter(description = "The UUID of the projec
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a component",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -543,7 +542,7 @@ public Response createComponent(@Parameter(description = "The UUID of the projec
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the component could not be found"),
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response updateComponent(Component jsonComponent) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -673,7 +672,7 @@ public Response updateComponent(Component jsonComponent) {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the component could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response deleteComponent(
@Parameter(description = "The UUID of the component to delete", schema = @Schema(format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -699,13 +698,13 @@ public Response deleteComponent(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Requests the identification of internal components in the portfolio",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Identification requested successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response identifyInternalComponents() {
Event.dispatch(new InternalComponentIdentificationEvent());
return Response.status(Response.Status.NO_CONTENT).build();
@@ -716,7 +715,7 @@ public Response identifyInternalComponents() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns the expanded dependency graph to every occurrence of a component",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -731,7 +730,7 @@ public Response identifyInternalComponents() {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "- The UUID of the project could not be found\n- The UUID of the component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getDependencyGraphForComponent(
@Parameter(description = "The UUID of the project to get the expanded dependency graph for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -764,7 +763,7 @@ public Response getDependencyGraphForComponent(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns the occurrences of a component",
- description = "Requires permission VIEW_PORTFOLIO
")
+ description = "Requires permission PROJECT_READ
")
@PaginatedApi
@ApiResponses(value = {
@ApiResponse(
@@ -782,7 +781,7 @@ public Response getDependencyGraphForComponent(
description = "Component could not be found",
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getOccurrences(@PathParam("uuid") final UUID uuid) {
final List occurrences = withJdbiHandle(getAlpineRequest(), handle -> {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java
index ccce2208da..c40908efbf 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java
@@ -65,7 +65,7 @@ public class ConfigPropertyResource extends AbstractConfigPropertyResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all ConfigProperties for the specified groupName",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -75,7 +75,7 @@ public class ConfigPropertyResource extends AbstractConfigPropertyResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response getConfigProperties() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final List configProperties = qm.getConfigProperties();
@@ -97,7 +97,7 @@ public Response getConfigProperties() {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Updates a config property",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -108,7 +108,7 @@ public Response getConfigProperties() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The config property could not be found"),
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response updateConfigProperty(ConfigProperty json) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -130,7 +130,7 @@ public Response updateConfigProperty(ConfigProperty json) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates an array of config properties",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -141,7 +141,7 @@ public Response updateConfigProperty(ConfigProperty json) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "One or more config properties could not be found"),
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response updateConfigProperty(List list) {
final Validator validator = super.getValidator();
for (ConfigProperty item : list) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java
index f30db9f257..8beaf66a02 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java
@@ -79,7 +79,7 @@ public class DependencyGraphResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of specific components and services from project UUID",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -94,7 +94,7 @@ public class DependencyGraphResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "Any component can be found"),
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentsAndServicesByProjectUuid(@Parameter(description = "The UUID of the project", schema = @Schema(type = "string", format = "uuid"), required = true) final @PathParam("uuid") @ValidUuid String uuid) {
try (QueryManager qm = new QueryManager()) {
@@ -123,7 +123,7 @@ public Response getComponentsAndServicesByProjectUuid(@Parameter(description = "
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of specific components and services from component UUID",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -138,7 +138,7 @@ public Response getComponentsAndServicesByProjectUuid(@Parameter(description = "
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "Any component can be found"),
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentsAndServicesByComponentUuid(@Parameter(description = "The UUID of the component", schema = @Schema(type = "string", format = "uuid"), required = true) final @PathParam("uuid") @ValidUuid String uuid) {
try (QueryManager qm = new QueryManager()) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/FindingResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/FindingResource.java
index 7de54fe291..972a60d68e 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/FindingResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/FindingResource.java
@@ -102,7 +102,7 @@ public class FindingResource extends AbstractApiResource {
@Produces({MediaType.APPLICATION_JSON, MEDIA_TYPE_SARIF_JSON})
@Operation(
summary = "Returns a list of all findings for a specific project or generates SARIF file if Accept: application/sarif+json header is provided",
- description = "Requires permission VIEW_VULNERABILITY
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -122,7 +122,9 @@ public class FindingResource extends AbstractApiResource {
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
@PaginatedApi
- @PermissionRequired(Permissions.Constants.VIEW_VULNERABILITY)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ },
+ operator = PermissionRequired.Operator.AND)
public Response getFindingsByProject(@Parameter(description = "The UUID of the project", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@Parameter(description = "Optionally includes suppressed findings")
@@ -166,7 +168,7 @@ public Response getFindingsByProject(@Parameter(description = "The UUID of the p
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns the findings for the specified project as FPF",
- description = "Requires permission VIEW_VULNERABILITY
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -181,7 +183,9 @@ public Response getFindingsByProject(@Parameter(description = "The UUID of the p
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_VULNERABILITY)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ },
+ operator = PermissionRequired.Operator.AND)
public Response exportFindingsByProject(@Parameter(description = "The UUID of the project", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
@@ -204,14 +208,14 @@ public Response exportFindingsByProject(@Parameter(description = "The UUID of th
@Path("/portfolio/analyze")
@Operation(
summary = "Triggers Vulnerability Analysis for the entire portfolio",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_CREATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Analysis triggered successfully"),
@ApiResponse(responseCode = "304", description = "Analysis is already in progress"),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_CREATE}) // Require admin privileges due to system impact
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION) // Require admin privileges due to system impact
public Response analyzePortfolio() {
LOGGER.info("Portfolio analysis requested by " + super.getPrincipal().getName());
if (Event.isEventBeingProcessed(PortfolioRepositoryMetaAnalysisEvent.CHAIN_IDENTIFIER)) {
@@ -228,7 +232,7 @@ public Response analyzePortfolio() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Triggers Vulnerability Analysis on a specific project",
- description = "Requires permission VIEW_VULNERABILITY
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -243,7 +247,9 @@ public Response analyzePortfolio() {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_VULNERABILITY)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ },
+ operator = PermissionRequired.Operator.AND)
public Response analyzeProject(
@Parameter(description = "The UUID of the project to analyze", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -271,7 +277,7 @@ public Response analyzeProject(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all findings",
- description = "Requires permission VIEW_VULNERABILITY
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -283,7 +289,9 @@ public Response analyzeProject(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
})
@PaginatedApi
- @PermissionRequired(Permissions.Constants.VIEW_VULNERABILITY)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ },
+ operator = PermissionRequired.Operator.AND)
public Response getAllFindings(@Parameter(description = "Show inactive projects")
@QueryParam("showInactive") boolean showInactive,
@Parameter(description = "Show suppressed findings")
@@ -341,7 +349,7 @@ public Response getAllFindings(@Parameter(description = "Show inactive projects"
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all findings grouped by vulnerability",
- description = "Requires permission VIEW_VULNERABILITY
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -353,7 +361,9 @@ public Response getAllFindings(@Parameter(description = "Show inactive projects"
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
@PaginatedApi
- @PermissionRequired(Permissions.Constants.VIEW_VULNERABILITY)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ },
+ operator = PermissionRequired.Operator.AND)
public Response getAllFindings(@Parameter(description = "Show inactive projects")
@QueryParam("showInactive") boolean showInactive,
@Parameter(description = "Filter by severity")
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/IntegrationResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/IntegrationResource.java
index f378b16091..8090e86f21 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/IntegrationResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/IntegrationResource.java
@@ -53,7 +53,7 @@ public class IntegrationResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all ecosystems in OSV",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -63,7 +63,7 @@ public class IntegrationResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response getAllEcosystems() {
OsvMirrorTask osvMirrorTask = new OsvMirrorTask();
final List ecosystems = osvMirrorTask.getEcosystems();
@@ -75,7 +75,7 @@ public Response getAllEcosystems() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of available inactive ecosystems in OSV to be selected by user",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -85,7 +85,7 @@ public Response getAllEcosystems() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response getInactiveEcosystems() {
OsvMirrorTask osvMirrorTask = new OsvMirrorTask();
var selectedEcosystems = osvMirrorTask.getEnabledEcosystems();
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/LdapResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/LdapResource.java
index c8ec175cf8..eae61fb0a2 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/LdapResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/LdapResource.java
@@ -83,7 +83,7 @@ public class LdapResource extends AlpineResource {
This API performs a pass-through query to the configured LDAP server.
Search criteria results are cached using default Alpine CacheManager policy.
-
Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"""
+ Requires permission ACCESS_MANAGEMENT
"""
)
@ApiResponses(value = {
@ApiResponse(
@@ -94,7 +94,7 @@ public class LdapResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response retrieveLdapGroups() {
if (!LdapConnectionWrapper.LDAP_CONFIGURED) {
return Response.ok().build();
@@ -132,7 +132,7 @@ public Response retrieveLdapGroups() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns the DNs of all groups mapped to the specified team",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -143,7 +143,7 @@ public Response retrieveLdapGroups() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the team could not be found"),
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response retrieveLdapGroups(@Parameter(description = "The UUID of the team to retrieve mappings for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
try (QueryManager qm = new QueryManager()) {
@@ -162,7 +162,7 @@ public Response retrieveLdapGroups(@Parameter(description = "The UUID of the tea
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Adds a mapping",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -174,7 +174,7 @@ public Response retrieveLdapGroups(@Parameter(description = "The UUID of the tea
@ApiResponse(responseCode = "404", description = "The UUID of the team could not be found"),
@ApiResponse(responseCode = "409", description = "A mapping with the same team and dn already exists")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response addMapping(MappedLdapGroupRequest request) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -203,14 +203,14 @@ public Response addMapping(MappedLdapGroupRequest request) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes a mapping",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Mapping removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the mapping could not be found"),
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteMapping(
@Parameter(description = "The UUID of the mapping to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java
index be110eb2d2..390bedcb2a 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java
@@ -71,7 +71,7 @@ public class LicenseGroupResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all license groups",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_READ
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -83,7 +83,7 @@ public class LicenseGroupResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response getLicenseGroups() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final PaginatedResult result = qm.getLicenseGroups();
@@ -96,7 +96,7 @@ public Response getLicenseGroups() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific license group",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_READ
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -107,7 +107,7 @@ public Response getLicenseGroups() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The license group could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response getLicenseGroup(
@Parameter(description = "The UUID of the license group to retrieve", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -126,7 +126,7 @@ public Response getLicenseGroup(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new license group",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_CREATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -137,7 +137,7 @@ public Response getLicenseGroup(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A license group with the specified name already exists")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response createLicenseGroup(LicenseGroup jsonLicenseGroup) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -162,7 +162,7 @@ public Response createLicenseGroup(LicenseGroup jsonLicenseGroup) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a license group",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -173,7 +173,7 @@ public Response createLicenseGroup(LicenseGroup jsonLicenseGroup) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The license group could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response updateLicenseGroup(LicenseGroup jsonLicenseGroup) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -199,14 +199,14 @@ public Response updateLicenseGroup(LicenseGroup jsonLicenseGroup) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a license group",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_DELETE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "License group removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the license group could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response deleteLicenseGroup(
@Parameter(description = "The UUID of the license group to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -229,7 +229,7 @@ public Response deleteLicenseGroup(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Adds the license to the specified license group.",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -241,7 +241,7 @@ public Response deleteLicenseGroup(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The license group or license could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response addLicenseToLicenseGroup(
@Parameter(description = "A valid license group", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -275,7 +275,7 @@ public Response addLicenseToLicenseGroup(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes the license from the license group.",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -287,7 +287,7 @@ public Response addLicenseToLicenseGroup(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The license group or license could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response removeLicenseFromLicenseGroup(
@Parameter(description = "A valid license group", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java
index aadb127819..eeaafcf664 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java
@@ -141,7 +141,7 @@ public Response getLicense(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new custom license",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_CREATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -152,7 +152,7 @@ public Response getLicense(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A license with the specified ID already exists.")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_CREATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response createLicense(License jsonLicense) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -178,7 +178,7 @@ public Response createLicense(License jsonLicense) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a custom license",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_DELETE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "License removed successfully"),
@@ -186,7 +186,7 @@ public Response createLicense(License jsonLicense) {
@ApiResponse(responseCode = "404", description = "The license could not be found"),
@ApiResponse(responseCode = "409", description = "Only custom licenses can be deleted.")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_DELETE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response deleteLicense(
@Parameter(description = "The SPDX License ID of the license to delete", required = true)
@PathParam("licenseId") String licenseId) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java
index cbcfd185b6..732e46397e 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java
@@ -86,10 +86,7 @@ public class MetricsResource extends AbstractApiResource {
@GET
@Path("/vulnerability")
@Produces(MediaType.APPLICATION_JSON)
- @Operation(
- summary = "Returns the sum of all vulnerabilities in the database by year and month",
- description = "Requires permission VIEW_PORTFOLIO
"
- )
+ @Operation(summary = "Returns the sum of all vulnerabilities in the database by year and month")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
@@ -98,8 +95,6 @@ public class MetricsResource extends AbstractApiResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
- @ResourceAccessRequired
public Response getVulnerabilityMetrics() {
try (QueryManager qm = new QueryManager()) {
final List metrics = qm.getVulnerabilityMetrics();
@@ -112,7 +107,7 @@ public Response getVulnerabilityMetrics() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns current metrics for the entire portfolio",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -122,7 +117,7 @@ public Response getVulnerabilityMetrics() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getPortfolioCurrentMetrics() {
PortfolioMetrics metrics = withJdbiHandle(
@@ -138,7 +133,7 @@ public Response getPortfolioCurrentMetrics() {
summary = "Returns historical metrics for the entire portfolio from a specific date",
description = """
Date format must be YYYYMMDD
- Requires permission VIEW_PORTFOLIO
""")
+ Requires permission PROJECT_READ
""")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
@@ -147,7 +142,7 @@ public Response getPortfolioCurrentMetrics() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getPortfolioMetricsSince(
@Parameter(description = "The start date to retrieve metrics for", required = true)
@@ -179,7 +174,7 @@ public Response getPortfolioMetricsSince(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns X days of historical metrics for the entire portfolio",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -189,7 +184,7 @@ public Response getPortfolioMetricsSince(
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getPortfolioMetricsXDays(
@Parameter(description = "The number of days back to retrieve metrics for", required = true)
@@ -209,14 +204,15 @@ public Response getPortfolioMetricsXDays(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Requests a refresh of the portfolio metrics",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_READ
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Refresh requested successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_READ})
- public Response RefreshPortfolioMetrics() {
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
+ @ResourceAccessRequired
+ public Response refreshPortfolioMetrics() {
Event.dispatch(new PortfolioMetricsUpdateEvent());
return Response.ok().build();
}
@@ -226,7 +222,7 @@ public Response RefreshPortfolioMetrics() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns current metrics for a specific project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -241,7 +237,7 @@ public Response RefreshPortfolioMetrics() {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectCurrentMetrics(
@Parameter(description = "The UUID of the project to retrieve metrics for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -264,7 +260,7 @@ public Response getProjectCurrentMetrics(
summary = "Returns historical metrics for a specific project from a specific date",
description = """
Date format must be YYYYMMDD
- Requires permission VIEW_PORTFOLIO
"""
+ Requires permission PROJECT_READ
"""
)
@ApiResponses(value = {
@ApiResponse(
@@ -279,7 +275,7 @@ public Response getProjectCurrentMetrics(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectMetricsSince(
@Parameter(description = "The UUID of the project to retrieve metrics for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -295,7 +291,7 @@ public Response getProjectMetricsSince(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns X days of historical metrics for a specific project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -310,7 +306,7 @@ public Response getProjectMetricsSince(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectMetricsXDays(
@Parameter(description = "The UUID of the project to retrieve metrics for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -326,7 +322,7 @@ public Response getProjectMetricsXDays(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Requests a refresh of a specific projects metrics",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_READ
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Refresh requested successfully"),
@@ -337,8 +333,9 @@ public Response getProjectMetricsXDays(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_READ})
- public Response RefreshProjectMetrics(
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
+ @ResourceAccessRequired
+ public Response refreshProjectMetrics(
@Parameter(description = "The UUID of the project to refresh metrics on", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
@@ -358,7 +355,7 @@ public Response RefreshProjectMetrics(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns current metrics for a specific component",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -373,7 +370,7 @@ public Response RefreshProjectMetrics(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentCurrentMetrics(
@Parameter(description = "The UUID of the component to retrieve metrics for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -396,7 +393,7 @@ public Response getComponentCurrentMetrics(
summary = "Returns historical metrics for a specific component from a specific date",
description = """
Date format must be YYYYMMDD
- Requires permission VIEW_PORTFOLIO
"""
+ Requires permission PROJECT_READ
"""
)
@ApiResponses(value = {
@ApiResponse(
@@ -411,7 +408,7 @@ public Response getComponentCurrentMetrics(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentMetricsSince(
@Parameter(description = "The UUID of the component to retrieve metrics for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -430,7 +427,7 @@ public Response getComponentMetricsSince(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns X days of historical metrics for a specific component",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -445,7 +442,7 @@ public Response getComponentMetricsSince(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getComponentMetricsXDays(
@Parameter(description = "The UUID of the component to retrieve metrics for", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -461,7 +458,7 @@ public Response getComponentMetricsXDays(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Requests a refresh of a specific components metrics",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_READ
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Refresh requested successfully"),
@@ -472,8 +469,9 @@ public Response getComponentMetricsXDays(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_READ})
- public Response RefreshComponentMetrics(
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
+ @ResourceAccessRequired
+ public Response refreshComponentMetrics(
@Parameter(description = "The UUID of the component to refresh metrics on", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java
index 7a2df295a3..cdca6a24b2 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java
@@ -81,7 +81,7 @@ public class NotificationPublisherResource extends AlpineResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Returns a list of all notification publishers",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -91,7 +91,7 @@ public class NotificationPublisherResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response getAllNotificationPublishers() {
try (QueryManager qm = new QueryManager()) {
final List publishers = qm.getAllNotificationPublishers();
@@ -104,7 +104,7 @@ public Response getAllNotificationPublishers() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new notification publisher",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_CREATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -116,7 +116,7 @@ public Response getAllNotificationPublishers() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "Conflict with an existing publisher's name")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_CREATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response createNotificationPublisher(NotificationPublisher jsonNotificationPublisher) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -157,7 +157,7 @@ public Response createNotificationPublisher(NotificationPublisher jsonNotificati
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a notification publisher",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -170,7 +170,7 @@ public Response createNotificationPublisher(NotificationPublisher jsonNotificati
@ApiResponse(responseCode = "404", description = "The notification publisher could not be found"),
@ApiResponse(responseCode = "409", description = "Conflict with an existing publisher's name")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response updateNotificationPublisher(NotificationPublisher jsonNotificationPublisher) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -223,7 +223,7 @@ public Response updateNotificationPublisher(NotificationPublisher jsonNotificati
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a notification publisher and all related notification rules",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_DELETE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Notification publisher removed successfully"),
@@ -231,8 +231,7 @@ public Response updateNotificationPublisher(NotificationPublisher jsonNotificati
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the notification publisher could not be found")
})
- @PermissionRequired({ Permissions.Constants.SYSTEM_CONFIGURATION,
- Permissions.Constants.SYSTEM_CONFIGURATION_DELETE })
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response deleteNotificationPublisher(@Parameter(description = "The UUID of the notification publisher to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("notificationPublisherUuid") @ValidUuid String notificationPublisherUuid) {
try (QueryManager qm = new QueryManager()) {
@@ -258,13 +257,13 @@ public Response deleteNotificationPublisher(@Parameter(description = "The UUID o
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Restore the default notification publisher templates using the ones in the solution classpath",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_CREATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Default templates restored successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_CREATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response restoreDefaultTemplates() {
useJdbiTransaction(handle -> {
handle.attach(ConfigPropertyDao.class).setValue(
@@ -316,4 +315,4 @@ public Response testNotificationRule(
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Exception occured while sending the notification.").build();
}
}
-}
\ No newline at end of file
+}
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java
index 97abfcb67a..9645847f80 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java
@@ -76,7 +76,7 @@ public class NotificationRuleResource extends AbstractApiResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Returns a list of all notification rules",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -88,7 +88,7 @@ public class NotificationRuleResource extends AbstractApiResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response getAllNotificationRules() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final PaginatedResult result = qm.getNotificationRules();
@@ -100,7 +100,7 @@ public Response getAllNotificationRules() {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Creates a new notification rule",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_CREATE
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -111,7 +111,7 @@ public Response getAllNotificationRules() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the notification publisher could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_CREATE})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response createNotificationRule(NotificationRule jsonRule) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -140,7 +140,7 @@ public Response createNotificationRule(NotificationRule jsonRule) {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Updates a notification rule",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -151,7 +151,7 @@ public Response createNotificationRule(NotificationRule jsonRule) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the notification rule could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response updateNotificationRule(NotificationRule jsonRule) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -175,14 +175,14 @@ public Response updateNotificationRule(NotificationRule jsonRule) {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Deletes a notification rule",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_DELETE
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Notification rule removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the notification rule could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_DELETE})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response deleteNotificationRule(NotificationRule jsonRule) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -202,7 +202,7 @@ public Response deleteNotificationRule(NotificationRule jsonRule) {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Adds a project to a notification rule",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -218,7 +218,7 @@ public Response deleteNotificationRule(NotificationRule jsonRule) {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The notification rule or project could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response addProjectToRule(
@Parameter(description = "The UUID of the rule to add a project to", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("ruleUuid") @ValidUuid String ruleUuid,
@@ -254,7 +254,7 @@ public Response addProjectToRule(
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Removes a project from a notification rule",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_DELETE
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -270,7 +270,7 @@ public Response addProjectToRule(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The notification rule or project could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_DELETE})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response removeProjectFromRule(
@Parameter(description = "The UUID of the rule to remove the project from", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("ruleUuid") @ValidUuid String ruleUuid,
@@ -306,7 +306,7 @@ public Response removeProjectFromRule(
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Adds a team to a notification rule",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -318,7 +318,7 @@ public Response removeProjectFromRule(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The notification rule or team could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response addTeamToRule(
@Parameter(description = "The UUID of the rule to add a team to", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("ruleUuid") @ValidUuid String ruleUuid,
@@ -353,7 +353,7 @@ public Response addTeamToRule(
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Removes a team from a notification rule",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_DELETE
"
+ description = "Requires permission NOTIFICATION_RULE_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -365,7 +365,7 @@ public Response addTeamToRule(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The notification rule or team could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_DELETE})
+ @PermissionRequired(Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT)
public Response removeTeamFromRule(
@Parameter(description = "The UUID of the rule to remove the project from", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("ruleUuid") @ValidUuid String ruleUuid,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/OidcResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/OidcResource.java
index d062400670..4671a23a01 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/OidcResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/OidcResource.java
@@ -90,7 +90,7 @@ public Response isAvailable() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all groups",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -100,7 +100,7 @@ public Response isAvailable() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response retrieveGroups() {
try (QueryManager qm = new QueryManager()) {
final List oidcGroups = qm.getOidcGroups();
@@ -114,7 +114,7 @@ public Response retrieveGroups() {
@Consumes(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates group",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -124,7 +124,7 @@ public Response retrieveGroups() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response createGroup(final OidcGroup jsonGroup) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -148,7 +148,7 @@ public Response createGroup(final OidcGroup jsonGroup) {
@Consumes(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates group",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -158,7 +158,7 @@ public Response createGroup(final OidcGroup jsonGroup) {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response updateGroup(final OidcGroup jsonGroup) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -184,14 +184,14 @@ public Response updateGroup(final OidcGroup jsonGroup) {
@Consumes(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a group",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Group removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The group could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteGroup(@Parameter(description = "The UUID of the group to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid final String uuid) {
try (QueryManager qm = new QueryManager()) {
@@ -215,7 +215,7 @@ public Response deleteGroup(@Parameter(description = "The UUID of the group to d
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of teams associated with the specified group",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -226,7 +226,7 @@ public Response deleteGroup(@Parameter(description = "The UUID of the group to d
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the mapping could not be found"),
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response retrieveTeamsMappedToGroup(@Parameter(description = "The UUID of the mapping to retrieve the team for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid final String uuid) {
try (final QueryManager qm = new QueryManager()) {
@@ -248,7 +248,7 @@ public Response retrieveTeamsMappedToGroup(@Parameter(description = "The UUID of
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Adds a mapping",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -260,7 +260,7 @@ public Response retrieveTeamsMappedToGroup(@Parameter(description = "The UUID of
@ApiResponse(responseCode = "404", description = "The UUID of the team or group could not be found"),
@ApiResponse(responseCode = "409", description = "A mapping with the same team and group name already exists")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response addMapping(final MappedOidcGroupRequest request) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -296,14 +296,14 @@ public Response addMapping(final MappedOidcGroupRequest request) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a mapping",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Mapping removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the mapping could not be found"),
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteMappingByUuid(@Parameter(description = "The UUID of the mapping to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid final String uuid) {
try (QueryManager qm = new QueryManager()) {
@@ -325,14 +325,14 @@ public Response deleteMappingByUuid(@Parameter(description = "The UUID of the ma
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a mapping",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Mapping removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the mapping could not be found"),
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteMapping(@Parameter(description = "The UUID of the group to delete a mapping for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("groupUuid") @ValidUuid final String groupUuid,
@Parameter(description = "The UUID of the team to delete a mapping for", schema = @Schema(type = "string", format = "uuid"), required = true)
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java
index 8e85698250..f5fc24b530 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java
@@ -46,6 +46,7 @@
import jakarta.ws.rs.core.Response;
import org.dependencytrack.auth.Permissions;
import org.dependencytrack.model.Role;
+import org.dependencytrack.model.validation.ValidRolePermission;
import org.dependencytrack.model.validation.ValidUuid;
import org.dependencytrack.persistence.QueryManager;
import org.dependencytrack.resources.v1.vo.TeamPermissionsSetRequest;
@@ -77,7 +78,7 @@ public class PermissionResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all permissions",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -87,7 +88,7 @@ public class PermissionResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getAllPermissions() {
try (QueryManager qm = new QueryManager()) {
final List permissions = qm.getPermissions();
@@ -101,7 +102,7 @@ public Response getAllPermissions() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Adds the permission to the specified username.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -113,7 +114,7 @@ public Response getAllPermissions() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response addPermissionToUser(
@Parameter(description = "A valid username", required = true)
@PathParam("username") String username,
@@ -148,7 +149,7 @@ public Response addPermissionToUser(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes the permission from the user.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -160,7 +161,7 @@ public Response addPermissionToUser(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response removePermissionFromUser(
@Parameter(description = "A valid username", required = true)
@PathParam("username") String username,
@@ -194,7 +195,7 @@ public Response removePermissionFromUser(
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -206,7 +207,7 @@ public Response removePermissionFromUser(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response addPermissionToTeam(
@Parameter(description = "A valid team uuid", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -239,14 +240,14 @@ public Response addPermissionToTeam(
@Path("/{permission}/role/{uuid}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
")
+ @Operation(description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The updated role", content = @Content(schema = @Schema(implementation = Role.class))),
@ApiResponse(responseCode = "304", description = "The role already has the specified permission assigned"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The role could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response removePermissionFromRole(
@Parameter(description = "A valid role uuid", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -280,7 +281,7 @@ public Response removePermissionFromRole(
@Path("/{permission}/role/{uuid}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
")
+ @Operation(description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The updated role", content = @Content(schema = @Schema(implementation = Role.class))
),
@@ -288,12 +289,12 @@ public Response removePermissionFromRole(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The role could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response addPermissionToRole(
@Parameter(description = "A valid role uuid", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@Parameter(description = "A valid permission", required = true)
- @PathParam("permission") String permissionName) {
+ @PathParam("permission") @ValidRolePermission String permissionName) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
Role role = qm.getObjectByUuid(Role.class, uuid);
@@ -320,7 +321,7 @@ public Response addPermissionToRole(
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -332,7 +333,7 @@ public Response addPermissionToRole(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response removePermissionFromTeam(
@Parameter(description = "A valid team uuid", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -367,7 +368,7 @@ public Response removePermissionFromTeam(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Replaces a users's permissions with the specified list",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The updated user", content = @Content(schema = @Schema(implementation = User.class))),
@@ -376,7 +377,7 @@ public Response removePermissionFromTeam(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response setUserPermissions(
@Parameter(description = "A username and valid list permission") @Valid UserPermissionsSetRequest request) {
try (QueryManager qm = new QueryManager()) {
@@ -424,7 +425,7 @@ public Response setUserPermissions(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Replaces a team's permissions with the specified list",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The updated team", content = @Content(schema = @Schema(implementation = Team.class))),
@@ -433,7 +434,7 @@ public Response setUserPermissions(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The team could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response setTeamPermissions(@Parameter(description = "Team UUID and requested permissions") @Valid TeamPermissionsSetRequest request) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java
index 2fa99c5082..c30aeb3acc 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java
@@ -77,7 +77,7 @@ public class PolicyConditionResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new policy condition for an existing policy",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -88,7 +88,7 @@ public class PolicyConditionResource extends AlpineResource {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the policy could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response createPolicyCondition(
@Parameter(description = "The UUID of the policy", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -125,7 +125,7 @@ public Response createPolicyCondition(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a policy condition",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -136,7 +136,7 @@ public Response createPolicyCondition(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the policy condition could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response updatePolicyCondition(PolicyCondition jsonPolicyCondition) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -168,14 +168,14 @@ public Response updatePolicyCondition(PolicyCondition jsonPolicyCondition) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a policy condition from an existing policy",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Policy condition removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the policy condition could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response deletePolicyCondition(
@Parameter(description = "The UUID of the policy condition to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java
index ee2b460547..e019568708 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java
@@ -70,7 +70,7 @@ public class PolicyResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all policies",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_READ
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -82,7 +82,7 @@ public class PolicyResource extends AbstractApiResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response getPolicies() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final PaginatedResult result = qm.getPolicies();
@@ -95,7 +95,7 @@ public Response getPolicies() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific policy"
- , description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_READ
"
+ , description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -106,7 +106,7 @@ public Response getPolicies() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The policy could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response getPolicy(
@Parameter(description = "The UUID of the policy to retrieve", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -125,7 +125,7 @@ public Response getPolicy(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new policy",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_CREATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -136,7 +136,7 @@ public Response getPolicy(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A policy with the specified name already exists")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response createPolicy(Policy jsonPolicy) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -171,7 +171,7 @@ public Response createPolicy(Policy jsonPolicy) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a policy",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -182,7 +182,7 @@ public Response createPolicy(Policy jsonPolicy) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The policy could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response updatePolicy(Policy jsonPolicy) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -212,14 +212,14 @@ public Response updatePolicy(Policy jsonPolicy) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a policy"
- , description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_DELETE
"
+ , description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Policy removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the policy could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response deletePolicy(
@Parameter(description = "The UUID of the policy to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -242,7 +242,7 @@ public Response deletePolicy(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Adds a project to a policy",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -258,7 +258,7 @@ public Response deletePolicy(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The policy or project could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response addProjectToPolicy(
@Parameter(description = "The UUID of the policy to add a project to", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("policyUuid") @ValidUuid String policyUuid,
@@ -292,7 +292,7 @@ public Response addProjectToPolicy(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes a project from a policy",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_DELETE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -308,7 +308,7 @@ public Response addProjectToPolicy(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The policy or project could not be found")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response removeProjectFromPolicy(
@Parameter(description = "The UUID of the policy to remove the project from", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("policyUuid") @ValidUuid String policyUuid,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java
index f9394b614b..3f568fc41b 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java
@@ -20,6 +20,7 @@
import alpine.persistence.PaginatedResult;
import alpine.server.auth.PermissionRequired;
+import alpine.server.filters.ResourceAccessRequired;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.headers.Header;
@@ -71,7 +72,7 @@ public class PolicyViolationResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all policy violations for the entire portfolio",
- description = "Requires permission VIEW_POLICY_VIOLATION
"
+ description = "Requires permission PROJECT_READ and POLICY_VIOLATION_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -83,7 +84,10 @@ public class PolicyViolationResource extends AbstractApiResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_POLICY_VIOLATION)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.POLICY_VIOLATION_READ },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response getViolations(@Parameter(description = "Optionally includes suppressed violations")
@QueryParam("suppressed") boolean suppressed,
@Parameter(description = "Optionally includes inactive projects")
@@ -126,7 +130,7 @@ public Response getViolations(@Parameter(description = "Optionally includes supp
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all policy violations for a specific project",
- description = "Requires permission VIEW_POLICY_VIOLATION
"
+ description = "Requires permission PROJECT_READ and POLICY_VIOLATION_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -143,7 +147,10 @@ public Response getViolations(@Parameter(description = "Optionally includes supp
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_POLICY_VIOLATION)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.POLICY_VIOLATION_READ },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response getViolationsByProject(@Parameter(description = "The UUID of the project", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@Parameter(description = "Optionally includes suppressed violations")
@@ -167,7 +174,7 @@ public Response getViolationsByProject(@Parameter(description = "The UUID of the
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all policy violations for a specific component",
- description = "Requires permission VIEW_POLICY_VIOLATION
"
+ description = "Requires permission PROJECT_READ and POLICY_VIOLATION_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -184,7 +191,10 @@ public Response getViolationsByProject(@Parameter(description = "The UUID of the
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_POLICY_VIOLATION)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.POLICY_VIOLATION_READ },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response getViolationsByComponent(@Parameter(description = "The UUID of the component", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@Parameter(description = "Optionally includes suppressed violations")
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java
index ea22e102ab..36a350531b 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java
@@ -68,7 +68,7 @@ public class ProjectPropertyResource extends AbstractConfigPropertyResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all ProjectProperties for the specified project",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_READ
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -83,7 +83,7 @@ public class ProjectPropertyResource extends AbstractConfigPropertyResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response getProperties(
@Parameter(description = "The UUID of the project to retrieve properties for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -114,7 +114,7 @@ public Response getProperties(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new project property",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -130,7 +130,7 @@ public Response getProperties(
@ApiResponse(responseCode = "404", description = "The project could not be found"),
@ApiResponse(responseCode = "409", description = "A property with the specified project/group/name combination already exists")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response createProperty(
@Parameter(description = "The UUID of the project to create a property for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -177,7 +177,7 @@ public Response createProperty(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a project property",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -192,7 +192,7 @@ public Response createProperty(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found"),
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response updateProperty(
@Parameter(description = "The UUID of the project to create a property for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -226,7 +226,7 @@ public Response updateProperty(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a config property",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_DELETE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Project property removed successfully"),
@@ -237,7 +237,7 @@ public Response updateProperty(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project or project property could not be found"),
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response deleteProperty(
@Parameter(description = "The UUID of the project to delete a property from", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java
index d83b339ffd..ce70079d9e 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java
@@ -112,7 +112,7 @@ public class ProjectResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all projects",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -124,7 +124,7 @@ public class ProjectResource extends AbstractApiResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjects(@Parameter(description = "The optional name of the project to query on")
@QueryParam("name") String name,
@@ -154,7 +154,7 @@ public Response getProjects(@Parameter(description = "The optional name of the p
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all projects, in a concise representation.",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -166,7 +166,7 @@ public Response getProjects(@Parameter(description = "The optional name of the p
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectsConcise(
@Parameter(description = "Name to filter on. Must be exact match.")
@@ -199,7 +199,7 @@ public Response getProjectsConcise(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of a given project's children, in a concise representation.",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -211,7 +211,7 @@ public Response getProjectsConcise(
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectChildrenConcise(
@Parameter(description = "UUID of the project", required = true)
@@ -244,7 +244,7 @@ public Response getProjectChildrenConcise(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -259,7 +259,7 @@ public Response getProjectChildrenConcise(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProject(
@Parameter(description = "The UUID of the project to retrieve", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -280,7 +280,7 @@ public Response getProject(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns the latest version of a project by its name",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -295,7 +295,7 @@ public Response getProject(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getLatestProjectByName(
@Parameter(description = "The name of the project to retrieve the latest version of", required = true)
@@ -317,7 +317,7 @@ public Response getLatestProjectByName(
@Operation(
summary = "Returns a specific project by its name and version",
operationId = "getProjectByNameAndVersion",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -332,7 +332,7 @@ public Response getLatestProjectByName(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProject(
@Parameter(description = "The name of the project to query on", required = true)
@@ -355,7 +355,7 @@ public Response getProject(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all projects by tag",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -367,7 +367,7 @@ public Response getProject(
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectsByTag(
@Parameter(description = "The tag to query on", required = true)
@@ -386,7 +386,7 @@ public Response getProjectsByTag(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all projects by classifier",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -398,7 +398,7 @@ public Response getProjectsByTag(
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectsByClassifier(
@Parameter(description = "The classifier to query on", required = true)
@@ -431,7 +431,7 @@ public Response getProjectsByClassifier(
principal is a member of can be assigned. Principals with ACCESS_MANAGEMENT
permission can assign any team.
- Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_CREATE
"""
+ Requires permission PORTFOLIO_MANAGEMENT
"""
)
@ApiResponses(value = {
@ApiResponse(
@@ -451,7 +451,7 @@ public Response getProjectsByClassifier(
A project with the specified name already exists
""")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response createProject(final Project jsonProject) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -581,7 +581,7 @@ public Response createProject(final Project jsonProject) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a project",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -603,7 +603,8 @@ public Response createProject(final Project jsonProject) {
A project cannot select itself as a parent
""")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PROJECT_UPDATE)
+ @ResourceAccessRequired
public Response updateProject(Project jsonProject) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -688,7 +689,7 @@ public Response updateProject(Project jsonProject) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Partially updates a project",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -710,7 +711,8 @@ public Response updateProject(Project jsonProject) {
A project cannot select itself as a parent
""")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PROJECT_UPDATE)
+ @ResourceAccessRequired
public Response patchProject(
@Parameter(description = "The UUID of the project to modify", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -857,7 +859,7 @@ private boolean setIfDifferent(final Project source, final Project target, f
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a project",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_DELETE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Project removed successfully"),
@@ -869,7 +871,8 @@ private boolean setIfDifferent(final Project source, final Project target, f
@ApiResponse(responseCode = "404", description = "The UUID of the project could not be found"),
@ApiResponse(responseCode = "500", description = "Unable to delete components of the project")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.PROJECT_DELETE)
+ @ResourceAccessRequired
public Response deleteProject(
@Parameter(description = "The UUID of the project to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -905,7 +908,7 @@ public Response deleteProject(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Clones a project",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_CREATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -920,7 +923,7 @@ public Response deleteProject(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the project could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response cloneProject(CloneProjectRequest jsonRequest) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -987,7 +990,7 @@ public Response cloneProject(CloneProjectRequest jsonRequest) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all children for a project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -1004,7 +1007,7 @@ public Response cloneProject(CloneProjectRequest jsonRequest) {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getChildrenProjects(@Parameter(description = "The UUID of the project to get the children from", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -1027,7 +1030,7 @@ public Response getChildrenProjects(@Parameter(description = "The UUID of the pr
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all children for a project by classifier",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -1044,7 +1047,7 @@ public Response getChildrenProjects(@Parameter(description = "The UUID of the pr
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getChildrenProjectsByClassifier(
@Parameter(description = "The classifier to query on", required = true)
@@ -1071,7 +1074,7 @@ public Response getChildrenProjectsByClassifier(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all children for a project by tag",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -1088,7 +1091,7 @@ public Response getChildrenProjectsByClassifier(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getChildrenProjectsByTag(
@Parameter(description = "The tag to query on", required = true)
@@ -1115,7 +1118,7 @@ public Response getChildrenProjectsByTag(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all projects without the descendants of the selected project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -1132,7 +1135,7 @@ public Response getChildrenProjectsByTag(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getProjectsWithoutDescendantsOf(
@Parameter(description = "The UUID of the project which descendants will be excluded", schema = @Schema(type = "string", format = "uuid"), required = true)
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java
index cf039d93e1..35b018fe89 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java
@@ -76,7 +76,7 @@ public class RepositoryResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all repositories",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -88,7 +88,7 @@ public class RepositoryResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response getRepositories() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final PaginatedResult result = qm.getRepositories();
@@ -101,7 +101,7 @@ public Response getRepositories() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns repositories that support the specific type",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -113,7 +113,7 @@ public Response getRepositories() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response getRepositoriesByType(
@Parameter(description = "The type of repositories to retrieve", required = true)
@PathParam("type") RepositoryType type) {
@@ -169,7 +169,7 @@ public Response getRepositoryMetaComponent(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new repository",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_CREATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -180,7 +180,7 @@ public Response getRepositoryMetaComponent(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A repository with the specified identifier already exists")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_CREATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response createRepository(Repository jsonRepository) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -217,7 +217,7 @@ public Response createRepository(Repository jsonRepository) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a repository",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -228,7 +228,7 @@ public Response createRepository(Repository jsonRepository) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the repository could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response updateRepository(Repository jsonRepository) {
final Validator validator = super.getValidator();
failOnValidationError(validator.validateProperty(jsonRepository, "identifier"),
@@ -268,14 +268,14 @@ public Response updateRepository(Repository jsonRepository) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a repository",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_DELETE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Repository removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The UUID of the repository could not be found")
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_DELETE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response deleteRepository(
@Parameter(description = "The UUID of the repository to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/RoleResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/RoleResource.java
index 694ce1a39d..7e87b331a0 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/RoleResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/RoleResource.java
@@ -73,7 +73,7 @@ public class RoleResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all roles",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
")
+ description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
@@ -85,7 +85,7 @@ public class RoleResource extends AlpineResource {
content = @Content(array = @ArraySchema(schema = @Schema(implementation = Role.class)))),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getRoles() {
try (QueryManager qm = new QueryManager()) {
return Response.ok(qm.getRoles()).header(TOTAL_COUNT_HEADER, qm.getCount(Role.class)).build();
@@ -97,7 +97,7 @@ public Response getRoles() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific role",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
")
+ description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
@@ -106,7 +106,7 @@ public Response getRoles() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The role could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getRole(
@Parameter(
description = "The UUID of the role to retrieve",
@@ -126,13 +126,13 @@ public Response getRole(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new role",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
")
+ description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "The created role", content = @Content(schema = @Schema(implementation = Role.class))),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "The role already exists"),
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response createRole(@Valid CreateRoleRequest request) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -159,13 +159,13 @@ public Response createRole(@Valid CreateRoleRequest request) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a role's fields",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
")
+ description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The updated role", content = @Content(schema = @Schema(implementation = Role.class))),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The role could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response updateRole(Role jsonRole) {
failOnValidationError(super.getValidator().validateProperty(jsonRole, "name"));
@@ -188,13 +188,13 @@ public Response updateRole(Role jsonRole) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a role",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
")
+ description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Role removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The role could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteRole(
@Parameter(
description = "The UUID of the role to retrieve",
@@ -219,7 +219,7 @@ public Response deleteRole(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of roles assigned to the specified user",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
")
+ description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
@@ -228,7 +228,7 @@ public Response deleteRole(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getUserRoles(
@Parameter(description = "A valid username", required = true) @PathParam("username") String username) {
try (QueryManager qm = new QueryManager()) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java
index 30cfd756b3..5955f8c5ed 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java
@@ -76,7 +76,7 @@ class ServiceResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all services for a given project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -93,7 +93,7 @@ class ServiceResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getAllServices(@Parameter(description = "The UUID of the project", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -114,7 +114,7 @@ public Response getAllServices(@Parameter(description = "The UUID of the project
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific service",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -129,7 +129,7 @@ public Response getAllServices(@Parameter(description = "The UUID of the project
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The service could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getServiceByUuid(
@Parameter(description = "The UUID of the service to retrieve", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -152,7 +152,7 @@ public Response getServiceByUuid(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new service",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_CREATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -167,7 +167,7 @@ public Response getServiceByUuid(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response createService(@Parameter(description = "The UUID of the project", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid, ServiceComponent jsonService) {
final Validator validator = super.getValidator();
@@ -208,7 +208,7 @@ public Response createService(@Parameter(description = "The UUID of the project"
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a service",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -223,7 +223,7 @@ public Response createService(@Parameter(description = "The UUID of the project"
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the service could not be found"),
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response updateService(ServiceComponent jsonService) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -266,7 +266,7 @@ public Response updateService(ServiceComponent jsonService) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a service",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_DELETE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Service removed successfully"),
@@ -277,7 +277,7 @@ public Response updateService(ServiceComponent jsonService) {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The UUID of the service could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response deleteService(
@Parameter(description = "The UUID of the service to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/TagResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/TagResource.java
index 7b021e8bfb..bfdbd64870 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/TagResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/TagResource.java
@@ -72,7 +72,7 @@ public class TagResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all tags",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission TAG_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -83,8 +83,7 @@ public class TagResource extends AlpineResource {
)
})
@PaginatedApi
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
- @ResourceAccessRequired
+ @PermissionRequired(Permissions.Constants.TAG_MANAGEMENT)
public Response getAllTags() {
final List tagListRows;
try (final var qm = new QueryManager(getAlpineRequest())) {
@@ -120,7 +119,7 @@ public Response getAllTags() {
Principals with POLICY_MANAGEMENT permission can delete tags
with assigned policies.
- Requires permission TAG_MANAGEMENT or TAG_MANAGEMENT_DELETE
+ Requires permission TAG_MANAGEMENT
"""
)
@ApiResponses(value = {
@@ -134,7 +133,7 @@ public Response getAllTags() {
content = @Content(schema = @Schema(implementation = TagOperationProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.TAG_MANAGEMENT, Permissions.Constants.TAG_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.TAG_MANAGEMENT)
public Response deleteTags(
@Parameter(description = "Names of the tags to delete")
@Size(min = 1, max = 100) final Set<@NotBlank String> tagNames
@@ -151,7 +150,7 @@ public Response deleteTags(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all projects assigned to the given tag.",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -162,8 +161,7 @@ public Response deleteTags(
)
})
@PaginatedApi
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
- @ResourceAccessRequired
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response getTaggedProjects(
@Parameter(description = "Name of the tag to get projects for.", required = true)
@PathParam("name") final String tagName
@@ -190,7 +188,7 @@ public Response getTaggedProjects(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Tags one or more projects.",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -203,7 +201,7 @@ public Response getTaggedProjects(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response tagProjects(
@Parameter(description = "Name of the tag to assign", required = true)
@PathParam("name") final String tagName,
@@ -227,7 +225,7 @@ public Response tagProjects(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Untags one or more projects.",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -240,7 +238,7 @@ public Response tagProjects(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response untagProjects(
@Parameter(description = "Name of the tag", required = true)
@PathParam("name") final String tagName,
@@ -263,7 +261,7 @@ public Response untagProjects(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all policies assigned to the given tag.",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_READ
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -274,7 +272,7 @@ public Response untagProjects(
)
})
@PaginatedApi
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response getTaggedPolicies(
@Parameter(description = "Name of the tag to get policies for.", required = true)
@PathParam("name") final String tagName
@@ -301,7 +299,7 @@ public Response getTaggedPolicies(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Tags one or more policies.",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -314,7 +312,7 @@ public Response getTaggedPolicies(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response tagPolicies(
@Parameter(description = "Name of the tag to assign", required = true)
@PathParam("name") final String tagName,
@@ -338,7 +336,7 @@ public Response tagPolicies(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Untags one or more policies.",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -351,7 +349,7 @@ public Response tagPolicies(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response untagPolicies(
@Parameter(description = "Name of the tag", required = true)
@PathParam("name") final String tagName,
@@ -374,7 +372,7 @@ public Response untagPolicies(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all tags associated with a given policy",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission TAG_MANAGEMENT and POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -385,7 +383,7 @@ public Response untagPolicies(
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired({ Permissions.Constants.TAG_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT })
@ResourceAccessRequired
public Response getTagsForPolicy(
@Parameter(description = "The UUID of the policy", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -402,7 +400,7 @@ public Response getTagsForPolicy(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all notification rules assigned to the given tag.",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_READ
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -413,7 +411,7 @@ public Response getTagsForPolicy(
)
})
@PaginatedApi
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_READ})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response getTaggedNotificationRules(
@Parameter(description = "Name of the tag to get notification rules for", required = true)
@PathParam("name") final String tagName
@@ -440,7 +438,7 @@ public Response getTaggedNotificationRules(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Tags one or more notification rules.",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -453,7 +451,7 @@ public Response getTaggedNotificationRules(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response tagNotificationRules(
@Parameter(description = "Name of the tag to assign", required = true)
@PathParam("name") final String tagName,
@@ -477,7 +475,7 @@ public Response tagNotificationRules(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Untags one or more notification rules.",
- description = "Requires permission SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE
"
+ description = "Requires permission SYSTEM_CONFIGURATION
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -490,7 +488,7 @@ public Response tagNotificationRules(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.SYSTEM_CONFIGURATION, Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE})
+ @PermissionRequired(Permissions.Constants.SYSTEM_CONFIGURATION)
public Response untagNotificationRules(
@Parameter(description = "Name of the tag", required = true)
@PathParam("name") final String tagName,
@@ -513,7 +511,7 @@ public Response untagNotificationRules(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all vulnerabilities assigned to the given tag.",
- description = "Requires permission VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_READ
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -524,7 +522,7 @@ public Response untagNotificationRules(
)
})
@PaginatedApi
- @PermissionRequired({Permissions.Constants.VULNERABILITY_MANAGEMENT, Permissions.Constants.VULNERABILITY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
public Response getTaggedVulnerabilities(
@Parameter(description = "Name of the tag to get vulnerabilities for.", required = true)
@PathParam("name") final String tagName
@@ -551,7 +549,7 @@ public Response getTaggedVulnerabilities(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Untags one or more vulnerabilities.",
- description = "Requires permission VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_UPDATE
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -564,7 +562,7 @@ public Response getTaggedVulnerabilities(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)
)
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_MANAGEMENT, Permissions.Constants.VULNERABILITY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
public Response untagVulnerabilities(
@Parameter(description = "Name of the tag", required = true)
@PathParam("name") final String tagName,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/TeamResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/TeamResource.java
index a993298402..f8af8d246d 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/TeamResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/TeamResource.java
@@ -89,7 +89,7 @@ public class TeamResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all teams",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -101,7 +101,7 @@ public class TeamResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getTeams() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final PaginatedResult result = qm.getTeams();
@@ -114,7 +114,7 @@ public Response getTeams() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific team",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -125,7 +125,7 @@ public Response getTeams() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getTeam(
@Parameter(description = "The UUID of the team to retrieve", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -144,7 +144,7 @@ public Response getTeam(
@Produces({MediaType.APPLICATION_JSON, ProblemDetails.MEDIA_TYPE_JSON})
@Operation(
summary = "Creates a new team",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -159,7 +159,7 @@ public Response getTeam(
schema = @Schema(implementation = TeamAlreadyExistsProblemDetails.class),
mediaType = ProblemDetails.MEDIA_TYPE_JSON))
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response createTeam(Team jsonTeam) {
final Validator validator = super.getValidator();
failOnValidationError(validator.validateProperty(jsonTeam, "name"));
@@ -188,7 +188,7 @@ public Response createTeam(Team jsonTeam) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a team's fields",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -199,7 +199,7 @@ public Response createTeam(Team jsonTeam) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response updateTeam(Team jsonTeam) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -224,14 +224,14 @@ public Response updateTeam(Team jsonTeam) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a team",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Team removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteTeam(Team jsonTeam) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -287,7 +287,7 @@ public Response availableTeams() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Generates an API key and returns its value",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -298,7 +298,7 @@ public Response availableTeams() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response generateApiKey(
@Parameter(description = "The UUID of the team to generate a key for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -318,7 +318,7 @@ public Response generateApiKey(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Regenerates an API key by removing the specified key, generating a new one and returning its value",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -329,7 +329,7 @@ public Response generateApiKey(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The API key could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response regenerateApiKey(
@Parameter(description = "The public ID for the API key or for Legacy the complete Key to regenerate", required = true)
@PathParam("publicIdOrKey") String publicIdOrKey) {
@@ -358,7 +358,7 @@ public Response regenerateApiKey(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates an API key's comment",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -369,7 +369,7 @@ public Response regenerateApiKey(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The API key could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response updateApiKeyComment(
@Parameter(description = "The public ID for the API key or for Legacy the complete Key to comment on", required = true)
@PathParam("publicIdOrKey") final String publicIdOrKey,
@@ -403,14 +403,14 @@ public Response updateApiKeyComment(
@Path("/key/{publicIdOrKey}")
@Operation(
summary = "Deletes the specified API key",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "API key removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The API key could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteApiKey(
@Parameter(description = "The public ID for the API key or for Legacy the full Key to delete", required = true)
@PathParam("publicIdOrKey") String publicIdOrKey) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/UserResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/UserResource.java
index aa2077d38f..a3fced085d 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/UserResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/UserResource.java
@@ -272,7 +272,7 @@ public Response forceChangePassword(@FormParam("username") String username, @For
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all managed users",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -283,7 +283,7 @@ public Response forceChangePassword(@FormParam("username") String username, @For
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getManagedUsers() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final long totalCount = qm.getCount(ManagedUser.class);
@@ -297,7 +297,7 @@ public Response getManagedUsers() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all LDAP users",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -308,7 +308,7 @@ public Response getManagedUsers() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getLdapUsers() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final long totalCount = qm.getCount(LdapUser.class);
@@ -325,7 +325,7 @@ public Response getLdapUsers() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all OIDC users",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_READ
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -335,7 +335,7 @@ public Response getLdapUsers() {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response getOidcUsers() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final long totalCount = qm.getCount(OidcUser.class);
@@ -436,7 +436,7 @@ public Response updateSelf(ManagedUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new user that references an existing LDAP object.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -448,7 +448,7 @@ public Response updateSelf(ManagedUser jsonUser) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A user with the same username already exists. Cannot create new user")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response createLdapUser(LdapUser jsonUser) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -474,14 +474,14 @@ public Response createLdapUser(LdapUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a user.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "LDAP user removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteLdapUser(LdapUser jsonUser) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -505,7 +505,7 @@ public Response deleteLdapUser(LdapUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new user.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -517,7 +517,7 @@ public Response deleteLdapUser(LdapUser jsonUser) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A user with the same username already exists. Cannot create new user")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response createManagedUser(ManagedUser jsonUser) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -558,7 +558,7 @@ public Response createManagedUser(ManagedUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates a managed user.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -570,7 +570,7 @@ public Response createManagedUser(ManagedUser jsonUser) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response updateManagedUser(ManagedUser jsonUser) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -607,14 +607,14 @@ public Response updateManagedUser(ManagedUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a user.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "User removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteManagedUser(ManagedUser jsonUser) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -638,7 +638,7 @@ public Response deleteManagedUser(ManagedUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new user that references an existing OpenID Connect user.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_CREATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -650,7 +650,7 @@ public Response deleteManagedUser(ManagedUser jsonUser) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A user with the same username already exists. Cannot create new user")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response createOidcUser(final OidcUser jsonUser) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -676,14 +676,14 @@ public Response createOidcUser(final OidcUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes an OpenID Connect user.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "OIDC user removed successfully"),
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response deleteOidcUser(final OidcUser jsonUser) {
try (QueryManager qm = new QueryManager()) {
return qm.callInTransaction(() -> {
@@ -707,7 +707,7 @@ public Response deleteOidcUser(final OidcUser jsonUser) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Adds the username to the specified team.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -719,7 +719,7 @@ public Response deleteOidcUser(final OidcUser jsonUser) {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user or team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response addTeamToUser(
@Parameter(description = "A valid username", required = true)
@PathParam("username") String username,
@@ -754,7 +754,7 @@ public Response addTeamToUser(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes the username from the specified team.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_DELETE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -766,7 +766,7 @@ public Response addTeamToUser(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user or team could not be found")
})
- @PermissionRequired({Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response removeTeamFromUser(
@Parameter(description = "A valid username", required = true)
@PathParam("username") String username,
@@ -800,7 +800,7 @@ public Response removeTeamFromUser(
@Path("/membership")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
- @Operation(summary = "Sets specified teams to a user.", description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
")
+ @Operation(summary = "Sets specified teams to a user.", description = "Requires permission ACCESS_MANAGEMENT
")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The updated user", content = @Content(schema = @Schema(implementation = User.class))),
@ApiResponse(responseCode = "304", description = "The user is already a member of the specified team(s)"),
@@ -808,7 +808,7 @@ public Response removeTeamFromUser(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user or team(s) could not be found")
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response setUserTeams(
@Parameter(description = "Username and list of UUIDs to assign to user", required = true) @Valid TeamsSetRequest request) {
try (QueryManager qm = new QueryManager()) {
@@ -890,7 +890,7 @@ private UserSubject buildUserSubject(final String username, final String email)
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Assigns or updates a user's role for a project.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "User with the specified role assigned or updated", content = @Content(schema = @Schema(implementation = User.class))),
@@ -898,7 +898,7 @@ private UserSubject buildUserSubject(final String username, final String email)
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The user, role, or project could not be found", content = @Content(schema = @Schema(implementation = AccessManagementProblemDetails.class)))
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response assignProjectRoleToUser(
@Parameter(description = "User, Role and Project information", required = true) @Valid ModifyUserProjectRoleRequest request) {
try (QueryManager qm = new QueryManager()) {
@@ -938,7 +938,7 @@ public Response assignProjectRoleToUser(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes a specific role for a user from a project.",
- description = "Requires permission ACCESS_MANAGEMENT or ACCESS_MANAGEMENT_UPDATE
"
+ description = "Requires permission ACCESS_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "The specified role was successfully removed from the user"),
@@ -946,7 +946,7 @@ public Response assignProjectRoleToUser(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404",description = "The user, role, or project could not be found",content = @Content(schema = @Schema(implementation = AccessManagementProblemDetails.class)))
})
- @PermissionRequired({ Permissions.Constants.ACCESS_MANAGEMENT, Permissions.Constants.ACCESS_MANAGEMENT_UPDATE })
+ @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT)
public Response removeProjectRoleFromUser(
@Parameter(description = "User, Role and Project information", required = true) @Valid ModifyUserProjectRoleRequest request) {
try (QueryManager qm = new QueryManager()) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/VexResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/VexResource.java
index 1a7db52bc6..66e3ec4b74 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/VexResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/VexResource.java
@@ -21,6 +21,7 @@
import alpine.common.logging.Logger;
import alpine.event.framework.Event;
import alpine.server.auth.PermissionRequired;
+import alpine.server.filters.ResourceAccessRequired;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
@@ -87,7 +88,7 @@ public class VexResource extends AbstractApiResource {
@Produces({CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON, MediaType.APPLICATION_OCTET_STREAM})
@Operation(
summary = "Returns a VEX for a project in CycloneDX format",
- description = "Requires permission VULNERABILITY_ANALYSIS or VULNERABILITY_ANALYSIS_READ
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -102,7 +103,10 @@ public class VexResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_ANALYSIS, Permissions.Constants.VULNERABILITY_ANALYSIS_READ})
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response exportProjectAsCycloneDx(
@Parameter(description = "The UUID of the project to export", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -152,7 +156,7 @@ public Response exportProjectAsCycloneDx(
When uploading large VEX files, the POST endpoint is preferred,
as it does not have this limit.
- Requires permission VULNERABILITY_ANALYSIS or VULNERABILITY_ANALYSIS_UPDATE
"""
+ Requires permission PROJECT_READ and FINDING_UPDATE
"""
)
@ApiResponses(value = {
@ApiResponse(
@@ -175,7 +179,10 @@ public Response exportProjectAsCycloneDx(
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_ANALYSIS, Permissions.Constants.VULNERABILITY_ANALYSIS_UPDATE})
+ @PermissionRequired(
+ value = {Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_UPDATE},
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response uploadVex(VexSubmitRequest request) {
final Validator validator = getValidator();
if (request.getProject() != null) {
@@ -219,7 +226,7 @@ public Response uploadVex(VexSubmitRequest request) {
a response with problem details in RFC 9457 format will be returned. In this case,
the response's content type will be application/problem+json.
- Requires permission VULNERABILITY_ANALYSIS or VULNERABILITY_ANALYSIS_UPDATE
"""
+ Requires permission PROJECT_READ and FINDING_UPDATE
"""
)
@ApiResponses(value = {
@ApiResponse(
@@ -242,7 +249,10 @@ public Response uploadVex(VexSubmitRequest request) {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_ANALYSIS, Permissions.Constants.VULNERABILITY_ANALYSIS_UPDATE})
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_UPDATE },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response uploadVex(@FormDataParam("project") String projectUuid,
@FormDataParam("projectName") String projectName,
@FormDataParam("projectVersion") String projectVersion,
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java
index c2281e19e5..1a9e7af0c7 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java
@@ -22,6 +22,7 @@
import alpine.common.validation.ValidationTask;
import alpine.model.User;
import alpine.server.auth.PermissionRequired;
+import alpine.server.filters.ResourceAccessRequired;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
@@ -71,7 +72,7 @@ public class ViolationAnalysisResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Retrieves a violation analysis trail",
- description = "Requires permission VIEW_POLICY_VIOLATION
"
+ description = "Requires permission PROJECT_READ and POLICY_VIOLATION_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -86,7 +87,10 @@ public class ViolationAnalysisResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component or policy violation could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_POLICY_VIOLATION)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.POLICY_VIOLATION_READ },
+ operator = PermissionRequired.Operator.AND)
+ @ResourceAccessRequired
public Response retrieveAnalysis(@Parameter(description = "The UUID of the component", schema = @Schema(type = "string", format = "uuid"), required = true)
@QueryParam("component") @ValidUuid String componentUuid,
@Parameter(description = "The UUID of the policy violation", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -115,7 +119,7 @@ public Response retrieveAnalysis(@Parameter(description = "The UUID of the compo
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Records a violation analysis decision",
- description = "Requires permission POLICY_VIOLATION_ANALYSIS
"
+ description = "Requires permission PROJECT_UPDATE and POLICY_VIOLATION_UPDATE
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -130,7 +134,7 @@ public Response retrieveAnalysis(@Parameter(description = "The UUID of the compo
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component or policy violation could not be found")
})
- @PermissionRequired(Permissions.Constants.POLICY_VIOLATION_ANALYSIS)
+ @PermissionRequired({ Permissions.Constants.PROJECT_UPDATE, Permissions.Constants.POLICY_VIOLATION_UPDATE })
public Response updateAnalysis(ViolationAnalysisRequest request) {
final Validator validator = getValidator();
failOnValidationError(
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java
index 47bfa3a613..cd45ba0f24 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java
@@ -49,7 +49,7 @@ public class VulnerabilityPolicyBundleResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns vulnerability policy resource bundle",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_READ
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -59,7 +59,7 @@ public class VulnerabilityPolicyBundleResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response getVulnerabilityPolicyBundle() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
final VulnerabilityPolicyBundle bundle = qm.getVulnerabilityPolicyBundle();
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java
index 56294ea94c..f5e88d0c2a 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java
@@ -79,7 +79,7 @@ public class VulnerabilityPolicyResource extends AlpineResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all vulnerability policies",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_READ
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -91,7 +91,7 @@ public class VulnerabilityPolicyResource extends AlpineResource {
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response getVulnerabilityPolicies() {
VulnerabilityPolicyProviderFactory instance = VulnerabilityPolicyProviderFactory.getInstance();
VulnerabilityPolicyProvider vulnerabilityPolicyProvider = instance.policyProviderImpl();
@@ -105,7 +105,7 @@ public Response getVulnerabilityPolicies() {
@Operation(
summary = "Triggers policy bundle synchronization. Returns a workflow token if trigger succeeded.",
// responseContainer = "Map",
- description = "Requires permission POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE
"
+ description = "Requires permission POLICY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -117,7 +117,7 @@ public Response getVulnerabilityPolicies() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "Conflict")
})
- @PermissionRequired({Permissions.Constants.POLICY_MANAGEMENT, Permissions.Constants.POLICY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.POLICY_MANAGEMENT)
public Response triggerVulnerabilityPolicyBundleSync() {
if (!Config.getInstance().getPropertyAsBoolean(ConfigKey.VULNERABILITY_POLICY_ANALYSIS_ENABLED)) {
return Response
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java
index 08384dec8f..13817ab7d1 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java
@@ -96,7 +96,7 @@ public class VulnerabilityResource extends AbstractApiResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all vulnerabilities for a specific component",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -113,7 +113,7 @@ public class VulnerabilityResource extends AbstractApiResource {
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The component could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
@ResourceAccessRequired
public Response getVulnerabilitiesByComponent(@Parameter(description = "The UUID of the component to retrieve vulnerabilities for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -136,7 +136,7 @@ public Response getVulnerabilitiesByComponent(@Parameter(description = "The UUID
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all vulnerabilities for a specific project",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PROJECT_READ and FINDING_READ
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -152,7 +152,9 @@ public Response getVulnerabilitiesByComponent(@Parameter(description = "The UUID
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The project could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(
+ value = { Permissions.Constants.PROJECT_READ, Permissions.Constants.FINDING_READ},
+ operator = PermissionRequired.Operator.AND)
@ResourceAccessRequired
public Response getVulnerabilitiesByProject(@Parameter(description = "The UUID of the project to retrieve vulnerabilities for", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@@ -177,7 +179,7 @@ public Response getVulnerabilitiesByProject(@Parameter(description = "The UUID o
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific vulnerability",
- description = "Requires permission VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_READ
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -188,7 +190,7 @@ public Response getVulnerabilitiesByProject(@Parameter(description = "The UUID o
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The vulnerability could not be found")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_MANAGEMENT, Permissions.Constants.VULNERABILITY_MANAGEMENT_READ})
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
public Response getVulnerabilityByUuid(
@Parameter(description = "The UUID of the vulnerability", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid final String uuid) {
@@ -218,7 +220,7 @@ public Response getVulnerabilityByUuid(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a specific vulnerability",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -229,7 +231,7 @@ public Response getVulnerabilityByUuid(
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The vulnerability could not be found")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
@ResourceAccessRequired
public Response getVulnerabilityByVulnId(
@PathParam("source") final String source,
@@ -260,7 +262,7 @@ public Response getVulnerabilityByVulnId(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all projects affected by a specific vulnerability",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -272,8 +274,7 @@ public Response getVulnerabilityByVulnId(
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
- @ResourceAccessRequired
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response getAffectedProject(@PathParam("source") String source,
@PathParam("vuln") String vuln,
@Parameter(description = "Optionally excludes inactive projects from being returned", required = false)
@@ -298,7 +299,7 @@ public Response getAffectedProject(@PathParam("source") String source,
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all vulnerabilities",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@PaginatedApi
@ApiResponses(value = {
@@ -310,7 +311,7 @@ public Response getAffectedProject(@PathParam("source") String source,
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
@ResourceAccessRequired
public Response getAllVulnerabilities() {
try (QueryManager qm = new QueryManager(getAlpineRequest())) {
@@ -324,7 +325,7 @@ public Response getAllVulnerabilities() {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Creates a new vulnerability",
- description = "Requires permission VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_CREATE
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -335,7 +336,7 @@ public Response getAllVulnerabilities() {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "409", description = "A vulnerability with the specified vulnId already exists")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_MANAGEMENT, Permissions.Constants.VULNERABILITY_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
public Response createVulnerability(Vulnerability jsonVulnerability) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -403,7 +404,7 @@ public Response createVulnerability(Vulnerability jsonVulnerability) {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(
- description = "Requires permission VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_UPDATE
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -415,7 +416,7 @@ public Response createVulnerability(Vulnerability jsonVulnerability) {
@ApiResponse(responseCode = "404", description = "The vulnerability could not be found"),
@ApiResponse(responseCode = "406", description = "The vulnId may not be changed")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_MANAGEMENT, Permissions.Constants.VULNERABILITY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
public Response updateVulnerability(Vulnerability jsonVuln) {
final Validator validator = super.getValidator();
failOnValidationError(
@@ -491,7 +492,7 @@ public Response updateVulnerability(Vulnerability jsonVuln) {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Deletes a vulnerability",
- description = "Requires permission VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_DELETE
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Vulnerability removed successfully"),
@@ -500,7 +501,7 @@ public Response updateVulnerability(Vulnerability jsonVuln) {
@ApiResponse(responseCode = "404", description = "The UUID of the vulnerability could not be found"),
@ApiResponse(responseCode = "412", description = "Portfolio components or services are affected by this vulnerability. Unable to delete.")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_MANAGEMENT, Permissions.Constants.VULNERABILITY_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
public Response deleteVulnerability(
@Parameter(description = "The UUID of the vulnerability to delete", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -533,7 +534,7 @@ public Response deleteVulnerability(
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Generates an internal vulnerability identifier",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_CREATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -543,7 +544,7 @@ public Response deleteVulnerability(
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response generateInternalVulnerabilityIdentifier() {
final String vulnId = VulnerabilityUtil.randomInternalId();
return Response.ok(vulnId).build();
@@ -595,7 +596,7 @@ public void recalculateScoresAndSeverityFromVectors(Vulnerability vuln) throws M
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Assigns a vulnerability to a component",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Assignment successful"),
@@ -606,7 +607,7 @@ public void recalculateScoresAndSeverityFromVectors(Vulnerability vuln) throws M
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The vulnerability or component could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response assignVulnerability(@Parameter(description = "The vulnerability source", required = true)
@PathParam("source") String source,
@Parameter(description = "The vulnId", required = true)
@@ -637,7 +638,7 @@ public Response assignVulnerability(@Parameter(description = "The vulnerability
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Assigns a vulnerability to a component",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Assignment successful"),
@@ -648,7 +649,7 @@ public Response assignVulnerability(@Parameter(description = "The vulnerability
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The vulnerability or component could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response assignVulnerability(@Parameter(description = "The UUID of the vulnerability", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@Parameter(description = "The UUID of the component", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -677,7 +678,7 @@ public Response assignVulnerability(@Parameter(description = "The UUID of the vu
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes assignment of a vulnerability from a component",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_DELETE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Assignment removal successful"),
@@ -688,7 +689,7 @@ public Response assignVulnerability(@Parameter(description = "The UUID of the vu
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The vulnerability or component could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response unassignVulnerability(@Parameter(description = "The vulnerability source", required = true)
@PathParam("source") String source,
@Parameter(description = "The vulnId", required = true)
@@ -719,7 +720,7 @@ public Response unassignVulnerability(@Parameter(description = "The vulnerabilit
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Removes assignment of a vulnerability from a component",
- description = "Requires permission PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_DELETE
"
+ description = "Requires permission PORTFOLIO_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Assignment removal successful"),
@@ -730,7 +731,7 @@ public Response unassignVulnerability(@Parameter(description = "The vulnerabilit
content = @Content(schema = @Schema(implementation = ProblemDetails.class), mediaType = ProblemDetails.MEDIA_TYPE_JSON)),
@ApiResponse(responseCode = "404", description = "The vulnerability or component could not be found")
})
- @PermissionRequired({Permissions.Constants.PORTFOLIO_MANAGEMENT, Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE})
+ @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT)
public Response unassignVulnerability(@Parameter(description = "The UUID of the vulnerability", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid,
@Parameter(description = "The UUID of the component", schema = @Schema(type = "string", format = "uuid"), required = true)
@@ -759,7 +760,7 @@ public Response unassignVulnerability(@Parameter(description = "The UUID of the
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Updates tags for a vulnerability",
- description = "Requires permission VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_UPDATE
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -770,7 +771,7 @@ public Response unassignVulnerability(@Parameter(description = "The UUID of the
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "The vulnerability could not be found")
})
- @PermissionRequired({Permissions.Constants.VULNERABILITY_MANAGEMENT, Permissions.Constants.VULNERABILITY_MANAGEMENT_UPDATE})
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
public Response updateVulnerabilityTags(List tags,
@Parameter(description = "UUID of the vulnerability", schema = @Schema(type = "string", format = "uuid"), required = true)
@PathParam("uuid") @ValidUuid String uuid) {
@@ -794,7 +795,7 @@ public Response updateVulnerabilityTags(List tags,
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Returns a list of all vulnerabilities by tag",
- description = "Requires permission VIEW_PORTFOLIO
"
+ description = "Requires permission VULNERABILITY_MANAGEMENT
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -805,7 +806,7 @@ public Response updateVulnerabilityTags(List tags,
),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT)
@ResourceAccessRequired
public Response getVulnerabilitiesByTag(
@Parameter(description = "The tag to query on", required = true)
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java
index fc05c8e08d..d6ea0c625c 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java
@@ -58,7 +58,7 @@ public class WorkflowResource {
@Produces(MediaType.APPLICATION_JSON)
@Operation(
summary = "Retrieves workflow states associated with the token received from bom upload .",
- description = "Requires permission BOM_UPLOAD
"
+ description = "Requires permission BOM_CREATE
"
)
@ApiResponses(value = {
@ApiResponse(
@@ -69,7 +69,7 @@ public class WorkflowResource {
@ApiResponse(responseCode = "401", description = "Unauthorized"),
@ApiResponse(responseCode = "404", description = "Workflow does not exist")
})
- @PermissionRequired(Permissions.Constants.BOM_UPLOAD) // TODO: Should be a more generic permission.
+ @PermissionRequired(Permissions.Constants.BOM_CREATE) // TODO: Should be a more generic permission.
public Response getWorkflowStates(
@Parameter(description = "The UUID of the token to query", required = true)
@PathParam("uuid") @ValidUuid String uuid) {
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v2/MetricsResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v2/MetricsResource.java
index 3596f851b9..77cceb835b 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v2/MetricsResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v2/MetricsResource.java
@@ -45,7 +45,7 @@ public class MetricsResource extends AlpineResource implements MetricsApi {
private UriInfo uriInfo;
@Override
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
+ @PermissionRequired(Permissions.Constants.PROJECT_READ)
public Response getPortfolioCurrentMetrics() {
PortfolioMetrics metrics = withJdbiHandle(
getAlpineRequest(),
@@ -87,7 +87,6 @@ public Response getPortfolioCurrentMetrics() {
}
@Override
- @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO)
public Response getVulnerabilityMetrics(Integer limit, String pageToken) {
final Page metricsPage = inJdbiTransaction(
getAlpineRequest(),
diff --git a/apiserver/src/main/java/org/dependencytrack/resources/v2/WorkflowsResource.java b/apiserver/src/main/java/org/dependencytrack/resources/v2/WorkflowsResource.java
index 4c730f027e..02095d827d 100644
--- a/apiserver/src/main/java/org/dependencytrack/resources/v2/WorkflowsResource.java
+++ b/apiserver/src/main/java/org/dependencytrack/resources/v2/WorkflowsResource.java
@@ -37,7 +37,7 @@
public class WorkflowsResource implements WorkflowsApi {
@Override
- @PermissionRequired(Permissions.Constants.BOM_UPLOAD)
+ @PermissionRequired(Permissions.Constants.BOM_CREATE)
public Response getWorkflowStates(final UUID token) {
List workflowStates;
try (final var qm = new QueryManager()) {
diff --git a/apiserver/src/test/java/org/dependencytrack/auth/PermissionsTest.java b/apiserver/src/test/java/org/dependencytrack/auth/PermissionsTest.java
index 1f8992139f..6af167e06c 100644
--- a/apiserver/src/test/java/org/dependencytrack/auth/PermissionsTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/auth/PermissionsTest.java
@@ -21,132 +21,54 @@
import org.junit.Assert;
import org.junit.Test;
-import static org.dependencytrack.auth.Permissions.Constants.ACCESS_MANAGEMENT;
-import static org.dependencytrack.auth.Permissions.Constants.ACCESS_MANAGEMENT_CREATE;
-import static org.dependencytrack.auth.Permissions.Constants.ACCESS_MANAGEMENT_DELETE;
-import static org.dependencytrack.auth.Permissions.Constants.ACCESS_MANAGEMENT_READ;
-import static org.dependencytrack.auth.Permissions.Constants.ACCESS_MANAGEMENT_UPDATE;
-import static org.dependencytrack.auth.Permissions.Constants.BOM_UPLOAD;
-import static org.dependencytrack.auth.Permissions.Constants.POLICY_MANAGEMENT;
-import static org.dependencytrack.auth.Permissions.Constants.POLICY_MANAGEMENT_CREATE;
-import static org.dependencytrack.auth.Permissions.Constants.POLICY_MANAGEMENT_DELETE;
-import static org.dependencytrack.auth.Permissions.Constants.POLICY_MANAGEMENT_READ;
-import static org.dependencytrack.auth.Permissions.Constants.POLICY_MANAGEMENT_UPDATE;
-import static org.dependencytrack.auth.Permissions.Constants.POLICY_VIOLATION_ANALYSIS;
-import static org.dependencytrack.auth.Permissions.Constants.PORTFOLIO_ACCESS_CONTROL_BYPASS;
-import static org.dependencytrack.auth.Permissions.Constants.PORTFOLIO_MANAGEMENT;
-import static org.dependencytrack.auth.Permissions.Constants.PORTFOLIO_MANAGEMENT_CREATE;
-import static org.dependencytrack.auth.Permissions.Constants.PORTFOLIO_MANAGEMENT_DELETE;
-import static org.dependencytrack.auth.Permissions.Constants.PORTFOLIO_MANAGEMENT_READ;
-import static org.dependencytrack.auth.Permissions.Constants.PORTFOLIO_MANAGEMENT_UPDATE;
-import static org.dependencytrack.auth.Permissions.Constants.PROJECT_CREATION_UPLOAD;
-import static org.dependencytrack.auth.Permissions.Constants.SYSTEM_CONFIGURATION;
-import static org.dependencytrack.auth.Permissions.Constants.SYSTEM_CONFIGURATION_CREATE;
-import static org.dependencytrack.auth.Permissions.Constants.SYSTEM_CONFIGURATION_DELETE;
-import static org.dependencytrack.auth.Permissions.Constants.SYSTEM_CONFIGURATION_READ;
-import static org.dependencytrack.auth.Permissions.Constants.SYSTEM_CONFIGURATION_UPDATE;
-import static org.dependencytrack.auth.Permissions.Constants.TAG_MANAGEMENT;
-import static org.dependencytrack.auth.Permissions.Constants.TAG_MANAGEMENT_DELETE;
-import static org.dependencytrack.auth.Permissions.Constants.VIEW_BADGES;
-import static org.dependencytrack.auth.Permissions.Constants.VIEW_POLICY_VIOLATION;
-import static org.dependencytrack.auth.Permissions.Constants.VIEW_PORTFOLIO;
-import static org.dependencytrack.auth.Permissions.Constants.VIEW_VULNERABILITY;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_ANALYSIS;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_ANALYSIS_CREATE;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_ANALYSIS_READ;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_ANALYSIS_UPDATE;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_MANAGEMENT;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_MANAGEMENT_CREATE;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_MANAGEMENT_DELETE;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_MANAGEMENT_READ;
-import static org.dependencytrack.auth.Permissions.Constants.VULNERABILITY_MANAGEMENT_UPDATE;
-
public class PermissionsTest {
@Test
public void testPermissionEnums() {
- Assert.assertEquals(39, Permissions.values().length);
- Assert.assertEquals("BOM_UPLOAD", Permissions.BOM_UPLOAD.name());
- Assert.assertEquals("VIEW_PORTFOLIO", Permissions.VIEW_PORTFOLIO.name());
+ Assert.assertEquals("ACCESS_MANAGEMENT", Permissions.ACCESS_MANAGEMENT.name());
+ Assert.assertEquals("BADGES_READ", Permissions.BADGES_READ.name());
+ Assert.assertEquals("BOM_CREATE", Permissions.BOM_CREATE.name());
+ Assert.assertEquals("BOM_READ", Permissions.BOM_READ.name());
+ Assert.assertEquals("FINDING_CREATE", Permissions.FINDING_CREATE.name());
+ Assert.assertEquals("FINDING_READ", Permissions.FINDING_READ.name());
+ Assert.assertEquals("FINDING_UPDATE", Permissions.FINDING_UPDATE.name());
+ Assert.assertEquals("NOTIFICATION_RULE_MANAGEMENT", Permissions.NOTIFICATION_RULE_MANAGEMENT.name());
+ Assert.assertEquals("POLICY_MANAGEMENT", Permissions.POLICY_MANAGEMENT.name());
+ Assert.assertEquals("POLICY_VIOLATION_CREATE", Permissions.POLICY_VIOLATION_CREATE.name());
+ Assert.assertEquals("POLICY_VIOLATION_READ", Permissions.POLICY_VIOLATION_READ.name());
+ Assert.assertEquals("POLICY_VIOLATION_UPDATE", Permissions.POLICY_VIOLATION_UPDATE.name());
Assert.assertEquals("PORTFOLIO_ACCESS_CONTROL_BYPASS", Permissions.PORTFOLIO_ACCESS_CONTROL_BYPASS.name());
Assert.assertEquals("PORTFOLIO_MANAGEMENT", Permissions.PORTFOLIO_MANAGEMENT.name());
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_CREATE", Permissions.PORTFOLIO_MANAGEMENT_CREATE.name());
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_READ", Permissions.PORTFOLIO_MANAGEMENT_READ.name());
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_UPDATE", Permissions.PORTFOLIO_MANAGEMENT_UPDATE.name());
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_DELETE", Permissions.PORTFOLIO_MANAGEMENT_DELETE.name());
- Assert.assertEquals("VIEW_VULNERABILITY", Permissions.VIEW_VULNERABILITY.name());
- Assert.assertEquals("VULNERABILITY_ANALYSIS", Permissions.VULNERABILITY_ANALYSIS.name());
- Assert.assertEquals("VULNERABILITY_ANALYSIS_CREATE", Permissions.VULNERABILITY_ANALYSIS_CREATE.name());
- Assert.assertEquals("VULNERABILITY_ANALYSIS_READ", Permissions.VULNERABILITY_ANALYSIS_READ.name());
- Assert.assertEquals("VULNERABILITY_ANALYSIS_UPDATE", Permissions.VULNERABILITY_ANALYSIS_UPDATE.name());
- Assert.assertEquals("VIEW_POLICY_VIOLATION", Permissions.VIEW_POLICY_VIOLATION.name());
- Assert.assertEquals("VULNERABILITY_MANAGEMENT", Permissions.VULNERABILITY_MANAGEMENT.name());
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_CREATE", Permissions.VULNERABILITY_MANAGEMENT_CREATE.name());
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_READ", Permissions.VULNERABILITY_MANAGEMENT_READ.name());
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_UPDATE", Permissions.VULNERABILITY_MANAGEMENT_UPDATE.name());
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_DELETE", Permissions.VULNERABILITY_MANAGEMENT_DELETE.name());
- Assert.assertEquals("POLICY_VIOLATION_ANALYSIS", Permissions.POLICY_VIOLATION_ANALYSIS.name());
- Assert.assertEquals("ACCESS_MANAGEMENT", Permissions.ACCESS_MANAGEMENT.name());
- Assert.assertEquals("ACCESS_MANAGEMENT_CREATE", Permissions.ACCESS_MANAGEMENT_CREATE.name());
- Assert.assertEquals("ACCESS_MANAGEMENT_READ", Permissions.ACCESS_MANAGEMENT_READ.name());
- Assert.assertEquals("ACCESS_MANAGEMENT_UPDATE", Permissions.ACCESS_MANAGEMENT_UPDATE.name());
- Assert.assertEquals("ACCESS_MANAGEMENT_DELETE", Permissions.ACCESS_MANAGEMENT_DELETE.name());
+ Assert.assertEquals("PROJECT_DELETE", Permissions.PROJECT_DELETE.name());
+ Assert.assertEquals("PROJECT_READ", Permissions.PROJECT_READ.name());
+ Assert.assertEquals("PROJECT_UPDATE", Permissions.PROJECT_UPDATE.name());
Assert.assertEquals("SYSTEM_CONFIGURATION", Permissions.SYSTEM_CONFIGURATION.name());
- Assert.assertEquals("SYSTEM_CONFIGURATION_CREATE", Permissions.SYSTEM_CONFIGURATION_CREATE.name());
- Assert.assertEquals("SYSTEM_CONFIGURATION_READ", Permissions.SYSTEM_CONFIGURATION_READ.name());
- Assert.assertEquals("SYSTEM_CONFIGURATION_UPDATE", Permissions.SYSTEM_CONFIGURATION_UPDATE.name());
- Assert.assertEquals("SYSTEM_CONFIGURATION_DELETE", Permissions.SYSTEM_CONFIGURATION_DELETE.name());
- Assert.assertEquals("PROJECT_CREATION_UPLOAD", Permissions.PROJECT_CREATION_UPLOAD.name());
- Assert.assertEquals("POLICY_MANAGEMENT", Permissions.POLICY_MANAGEMENT.name());
- Assert.assertEquals("POLICY_MANAGEMENT_CREATE", Permissions.POLICY_MANAGEMENT_CREATE.name());
- Assert.assertEquals("POLICY_MANAGEMENT_READ", Permissions.POLICY_MANAGEMENT_READ.name());
- Assert.assertEquals("POLICY_MANAGEMENT_UPDATE", Permissions.POLICY_MANAGEMENT_UPDATE.name());
- Assert.assertEquals("POLICY_MANAGEMENT_DELETE", Permissions.POLICY_MANAGEMENT_DELETE.name());
Assert.assertEquals("TAG_MANAGEMENT", Permissions.TAG_MANAGEMENT.name());
- Assert.assertEquals("TAG_MANAGEMENT_DELETE", Permissions.TAG_MANAGEMENT_DELETE.name());
- Assert.assertEquals("VIEW_BADGES", Permissions.VIEW_BADGES.name());
+ Assert.assertEquals("VULNERABILITY_MANAGEMENT", Permissions.VULNERABILITY_MANAGEMENT.name());
}
@Test
public void testPermissionConstants() {
- Assert.assertEquals("BOM_UPLOAD", BOM_UPLOAD);
- Assert.assertEquals("VIEW_PORTFOLIO", VIEW_PORTFOLIO);
- Assert.assertEquals("PORTFOLIO_ACCESS_CONTROL_BYPASS", PORTFOLIO_ACCESS_CONTROL_BYPASS);
- Assert.assertEquals("PORTFOLIO_MANAGEMENT", PORTFOLIO_MANAGEMENT);
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_CREATE", PORTFOLIO_MANAGEMENT_CREATE);
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_READ", PORTFOLIO_MANAGEMENT_READ);
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_UPDATE", PORTFOLIO_MANAGEMENT_UPDATE);
- Assert.assertEquals("PORTFOLIO_MANAGEMENT_DELETE", PORTFOLIO_MANAGEMENT_DELETE);
- Assert.assertEquals("VIEW_VULNERABILITY", VIEW_VULNERABILITY);
- Assert.assertEquals("VULNERABILITY_ANALYSIS", VULNERABILITY_ANALYSIS);
- Assert.assertEquals("VULNERABILITY_ANALYSIS_CREATE", VULNERABILITY_ANALYSIS_CREATE);
- Assert.assertEquals("VULNERABILITY_ANALYSIS_READ", VULNERABILITY_ANALYSIS_READ);
- Assert.assertEquals("VULNERABILITY_ANALYSIS_UPDATE", VULNERABILITY_ANALYSIS_UPDATE);
- Assert.assertEquals("VIEW_POLICY_VIOLATION", VIEW_POLICY_VIOLATION);
- Assert.assertEquals("VULNERABILITY_MANAGEMENT", VULNERABILITY_MANAGEMENT);
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_CREATE", VULNERABILITY_MANAGEMENT_CREATE);
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_READ", VULNERABILITY_MANAGEMENT_READ);
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_UPDATE", VULNERABILITY_MANAGEMENT_UPDATE);
- Assert.assertEquals("VULNERABILITY_MANAGEMENT_DELETE", VULNERABILITY_MANAGEMENT_DELETE);
- Assert.assertEquals("POLICY_VIOLATION_ANALYSIS", POLICY_VIOLATION_ANALYSIS);
- Assert.assertEquals("ACCESS_MANAGEMENT", ACCESS_MANAGEMENT);
- Assert.assertEquals("ACCESS_MANAGEMENT_CREATE", ACCESS_MANAGEMENT_CREATE);
- Assert.assertEquals("ACCESS_MANAGEMENT_READ", ACCESS_MANAGEMENT_READ);
- Assert.assertEquals("ACCESS_MANAGEMENT_UPDATE", ACCESS_MANAGEMENT_UPDATE);
- Assert.assertEquals("ACCESS_MANAGEMENT_DELETE", ACCESS_MANAGEMENT_DELETE);
- Assert.assertEquals("SYSTEM_CONFIGURATION", SYSTEM_CONFIGURATION);
- Assert.assertEquals("SYSTEM_CONFIGURATION_CREATE", SYSTEM_CONFIGURATION_CREATE);
- Assert.assertEquals("SYSTEM_CONFIGURATION_READ", SYSTEM_CONFIGURATION_READ);
- Assert.assertEquals("SYSTEM_CONFIGURATION_UPDATE", SYSTEM_CONFIGURATION_UPDATE);
- Assert.assertEquals("SYSTEM_CONFIGURATION_DELETE", SYSTEM_CONFIGURATION_DELETE);
- Assert.assertEquals("PROJECT_CREATION_UPLOAD", PROJECT_CREATION_UPLOAD);
- Assert.assertEquals("POLICY_MANAGEMENT", POLICY_MANAGEMENT);
- Assert.assertEquals("POLICY_MANAGEMENT_CREATE", POLICY_MANAGEMENT_CREATE);
- Assert.assertEquals("POLICY_MANAGEMENT_READ", POLICY_MANAGEMENT_READ);
- Assert.assertEquals("POLICY_MANAGEMENT_UPDATE", POLICY_MANAGEMENT_UPDATE);
- Assert.assertEquals("POLICY_MANAGEMENT_DELETE", POLICY_MANAGEMENT_DELETE);
- Assert.assertEquals("TAG_MANAGEMENT", TAG_MANAGEMENT);
- Assert.assertEquals("TAG_MANAGEMENT_DELETE", TAG_MANAGEMENT_DELETE);
- Assert.assertEquals("VIEW_BADGES", VIEW_BADGES);
+ Assert.assertEquals("ACCESS_MANAGEMENT", Permissions.Constants.ACCESS_MANAGEMENT);
+ Assert.assertEquals("BADGES_READ", Permissions.Constants.BADGES_READ);
+ Assert.assertEquals("BOM_CREATE", Permissions.Constants.BOM_CREATE);
+ Assert.assertEquals("BOM_READ", Permissions.Constants.BOM_READ);
+ Assert.assertEquals("FINDING_CREATE", Permissions.Constants.FINDING_CREATE);
+ Assert.assertEquals("FINDING_READ", Permissions.Constants.FINDING_READ);
+ Assert.assertEquals("FINDING_UPDATE", Permissions.Constants.FINDING_UPDATE);
+ Assert.assertEquals("NOTIFICATION_RULE_MANAGEMENT", Permissions.Constants.NOTIFICATION_RULE_MANAGEMENT);
+ Assert.assertEquals("POLICY_MANAGEMENT", Permissions.Constants.POLICY_MANAGEMENT);
+ Assert.assertEquals("POLICY_VIOLATION_CREATE", Permissions.Constants.POLICY_VIOLATION_CREATE);
+ Assert.assertEquals("POLICY_VIOLATION_READ", Permissions.Constants.POLICY_VIOLATION_READ);
+ Assert.assertEquals("POLICY_VIOLATION_UPDATE", Permissions.Constants.POLICY_VIOLATION_UPDATE);
+ Assert.assertEquals("PORTFOLIO_ACCESS_CONTROL_BYPASS", Permissions.Constants.PORTFOLIO_ACCESS_CONTROL_BYPASS);
+ Assert.assertEquals("PORTFOLIO_MANAGEMENT", Permissions.Constants.PORTFOLIO_MANAGEMENT);
+ Assert.assertEquals("PROJECT_DELETE", Permissions.Constants.PROJECT_DELETE);
+ Assert.assertEquals("PROJECT_READ", Permissions.Constants.PROJECT_READ);
+ Assert.assertEquals("PROJECT_UPDATE", Permissions.Constants.PROJECT_UPDATE);
+ Assert.assertEquals("SYSTEM_CONFIGURATION", Permissions.Constants.SYSTEM_CONFIGURATION);
+ Assert.assertEquals("TAG_MANAGEMENT", Permissions.Constants.TAG_MANAGEMENT);
+ Assert.assertEquals("VULNERABILITY_MANAGEMENT", Permissions.Constants.VULNERABILITY_MANAGEMENT);
}
+
}
diff --git a/apiserver/src/test/java/org/dependencytrack/persistence/QueryManagerTest.java b/apiserver/src/test/java/org/dependencytrack/persistence/QueryManagerTest.java
index f3d8dbe65f..0821d1885c 100644
--- a/apiserver/src/test/java/org/dependencytrack/persistence/QueryManagerTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/persistence/QueryManagerTest.java
@@ -110,7 +110,7 @@ public void tryAcquireAdvisoryLockShouldThrowWhenNoActiveTransaction() {
private Object[] parametersForTestGetEffectivePermissionsRoles() {
return new Object[] {
new Object[] { false, Collections.emptySet() },
- new Object[] { true, Set.of("VIEW_PORTFOLIO") }
+ new Object[] { true, Set.of("PROJECT_READ") }
};
}
@@ -149,29 +149,29 @@ public void testGetEffectivePermissions() {
var team1 = teamCreator.apply("Effective Permissions Test Team 1", List.of(
Permissions.PORTFOLIO_MANAGEMENT,
- Permissions.VULNERABILITY_ANALYSIS,
+ Permissions.FINDING_UPDATE,
Permissions.VULNERABILITY_MANAGEMENT,
Permissions.ACCESS_MANAGEMENT,
Permissions.SYSTEM_CONFIGURATION,
Permissions.POLICY_MANAGEMENT));
var team2 = teamCreator.apply("Effective Permissions Test Team 2", List.of(
- Permissions.VIEW_PORTFOLIO,
- Permissions.VIEW_VULNERABILITY,
- Permissions.VIEW_POLICY_VIOLATION,
- Permissions.VIEW_BADGES));
+ Permissions.PROJECT_READ,
+ Permissions.FINDING_READ,
+ Permissions.POLICY_VIOLATION_READ,
+ Permissions.BADGES_READ));
var team3 = teamCreator.apply("Effective Permissions Test Team 3", List.of(
- Permissions.PORTFOLIO_MANAGEMENT_UPDATE,
- Permissions.VULNERABILITY_ANALYSIS_UPDATE,
- Permissions.VULNERABILITY_MANAGEMENT_UPDATE,
- Permissions.ACCESS_MANAGEMENT_UPDATE,
- Permissions.SYSTEM_CONFIGURATION_UPDATE,
- Permissions.POLICY_MANAGEMENT_UPDATE));
+ Permissions.PORTFOLIO_MANAGEMENT,
+ Permissions.FINDING_UPDATE,
+ Permissions.VULNERABILITY_MANAGEMENT,
+ Permissions.ACCESS_MANAGEMENT,
+ Permissions.SYSTEM_CONFIGURATION,
+ Permissions.POLICY_MANAGEMENT));
var noAccessTeam = teamCreator.apply("Effective Permissions Test with No Access", List.of(
- Permissions.BOM_UPLOAD,
- Permissions.PROJECT_CREATION_UPLOAD));
+ Permissions.BOM_CREATE,
+ Permissions.TAG_MANAGEMENT));
qm.addUserToTeam(ldapUser, team1);
qm.addUserToTeam(mgdUser, team2);
@@ -222,8 +222,8 @@ String[] getPermissionNames(List permissions) {
}
var permission = qm.createPermission(
- Permissions.POLICY_VIOLATION_ANALYSIS.name(),
- Permissions.POLICY_VIOLATION_ANALYSIS.getDescription());
+ Permissions.POLICY_VIOLATION_UPDATE.name(),
+ Permissions.POLICY_VIOLATION_UPDATE.getDescription());
for (var entry : new TestMatrixEntry[] {
new TestMatrixEntry(ldapUser, project1, team1, List.of(project2, project3)),
@@ -247,7 +247,7 @@ String[] getPermissionNames(List permissions) {
});
assertThat(entry.getPermissionNames(qm.getEffectivePermissions(entry.user(), entry.project())))
- .contains(Permissions.POLICY_VIOLATION_ANALYSIS.name());
+ .contains(Permissions.POLICY_VIOLATION_UPDATE.name());
}
}
diff --git a/apiserver/src/test/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethodTest.java b/apiserver/src/test/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethodTest.java
index 6a56fdb616..cc072e4997 100644
--- a/apiserver/src/test/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethodTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/persistence/datanucleus/method/ProjectIsAccessibleByMethodTest.java
@@ -208,7 +208,7 @@ public void shouldThrowWhenNoArgs() {
query.setFilter("this.isAccessibleBy()");
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(query::execute)
- .withMessage("Expected exactly one argument, but got 0");
+ .withMessage("Expected one or two arguments, but got 0");
}
@Test
@@ -220,8 +220,7 @@ public void shouldThrowWhenArgIsOfUnexpectedType() {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(query::execute)
.withMessage("""
- Expected argument to be of type org.datanucleus.store.rdbms.sql.expression.ArrayLiteral or \
- org.datanucleus.store.rdbms.sql.expression.IntegerLiteral, \
+ Expected argument to be of type org.datanucleus.store.rdbms.sql.expression.ArrayLiteral, \
but got org.datanucleus.store.rdbms.sql.expression.ParameterLiteral""");
}
@@ -234,8 +233,7 @@ public void shouldThrowWhenArgIsOfUnexpectedArrayType() {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(query::execute)
.withMessage("""
- Expected argument to be of type org.datanucleus.store.rdbms.sql.expression.ArrayLiteral or \
- org.datanucleus.store.rdbms.sql.expression.IntegerLiteral, \
+ Expected argument to be of type org.datanucleus.store.rdbms.sql.expression.ArrayLiteral, \
but got org.datanucleus.store.rdbms.sql.expression.ParameterLiteral""");
}
diff --git a/apiserver/src/test/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizerTest.java b/apiserver/src/test/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizerTest.java
index ed0dcd851d..ff42d76e09 100644
--- a/apiserver/src/test/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizerTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/persistence/jdbi/ApiRequestStatementCustomizerTest.java
@@ -432,12 +432,12 @@ WHERE EXISTS(
ON ph."PARENT_PROJECT_ID" = upep."PROJECT_ID"
WHERE ph."CHILD_PROJECT_ID" = "PROJECT"."ID"
AND upep."USER_ID" = :projectAclUserId
- AND upep."PERMISSION_NAME" = 'VIEW_PORTFOLIO'
+ AND upep."PERMISSION_NAME" = ALL(:projectAclPermissions)
)
""");
- assertThat(ctx.getBinding())
- .hasToString("{named:{projectAclUserId:%d}}".formatted(managedUser.getId()));
+ assertThat(ctx.getBinding()).hasToString(
+ "{named:{projectAclUserId:%d,projectAclPermissions:[]}}".formatted(managedUser.getId()));
}))
.createQuery(TEST_QUERY_TEMPLATE)
.mapTo(Integer.class)
@@ -705,11 +705,11 @@ WHERE EXISTS(
ON ph."PARENT_PROJECT_ID" = upep."PROJECT_ID"
WHERE ph."CHILD_PROJECT_ID" = "PROJECT"."PARENT_PROJECT_ID"
AND upep."USER_ID" = :projectAclUserId
- AND upep."PERMISSION_NAME" = 'VIEW_PORTFOLIO'
+ AND upep."PERMISSION_NAME" = ALL(:projectAclPermissions)
)
""");
- assertThat(ctx.getBinding()).hasToString("{named:{projectAclUserId:%s}}".formatted(user.getId()));
+ assertThat(ctx.getBinding()).hasToString("{named:{projectAclUserId:%s,projectAclPermissions:[]}}".formatted(user.getId()));
}))
.addCustomizer(new DefineApiProjectAclCondition.StatementCustomizer(
JdbiAttributes.ATTRIBUTE_API_PROJECT_ACL_CONDITION,
@@ -732,4 +732,4 @@ public void beforeExecution(final PreparedStatement stmt, final StatementContext
}
-}
\ No newline at end of file
+}
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/AccessControlResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/AccessControlResourceTest.java
index 751ce2af70..d72c0379a3 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/AccessControlResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/AccessControlResourceTest.java
@@ -261,7 +261,7 @@ public void retrieveProjectsByTeamTest() {
@Test
public void retrieveUserProjectsTest() {
- initializeWithPermissions(Permissions.ACCESS_MANAGEMENT_READ);
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT);
final var project1 = new Project();
project1.setName("Project 1");
@@ -287,7 +287,7 @@ public void retrieveUserProjectsTest() {
@Test
public void retrieveUserProjectsNoContentTest() {
- initializeWithPermissions(Permissions.ACCESS_MANAGEMENT_READ);
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT);
final ManagedUser user = qm.createManagedUser("user", TEST_PASSWORD_HASH);
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/AnalysisResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/AnalysisResourceTest.java
index e7969b32f4..07b17d5206 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/AnalysisResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/AnalysisResourceTest.java
@@ -41,6 +41,7 @@
import org.dependencytrack.model.AnalyzerIdentity;
import org.dependencytrack.model.Component;
import org.dependencytrack.model.Project;
+import org.dependencytrack.model.Role;
import org.dependencytrack.model.Severity;
import org.dependencytrack.model.Vulnerability;
import org.dependencytrack.notification.NotificationConstants;
@@ -82,7 +83,7 @@ public class AnalysisResourceTest extends ResourceTest {
@Test
public void retrieveAnalysisTest() {
- initializeWithPermissions(Permissions.VIEW_VULNERABILITY);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -131,7 +132,7 @@ public void retrieveAnalysisTest() {
@Test
public void retrieveAnalysisWithoutExistingAnalysisTest() {
- initializeWithPermissions(Permissions.VIEW_VULNERABILITY);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -162,7 +163,7 @@ public void retrieveAnalysisWithoutExistingAnalysisTest() {
@Test
public void noAnalysisExists() {
- initializeWithPermissions(Permissions.VIEW_VULNERABILITY);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
var component = new Component();
@@ -190,7 +191,7 @@ public void noAnalysisExists() {
@Test
public void retrieveAnalysisWithProjectNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_VULNERABILITY);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -221,7 +222,7 @@ public void retrieveAnalysisWithProjectNotFoundTest() {
@Test
public void retrieveAnalysisWithComponentNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_VULNERABILITY);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -252,7 +253,7 @@ public void retrieveAnalysisWithComponentNotFoundTest() {
@Test
public void retrieveAnalysisWithVulnerabilityNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_VULNERABILITY);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -298,7 +299,7 @@ public void retrieveAnalysisUnauthorizedTest() {
public void retrieveAnalysisWithAclTest() {
enablePortfolioAccessControl();
- initializeWithPermissions(Permissions.VIEW_VULNERABILITY);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_READ);
final var project = new Project();
project.setName("acme-app");
@@ -346,9 +347,16 @@ public void retrieveAnalysisWithAclTest() {
@Test
public void updateAnalysisCreateNewTest() throws Exception {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -369,7 +377,7 @@ public void updateAnalysisCreateNewTest() throws Exception {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -383,10 +391,10 @@ public void updateAnalysisCreateNewTest() throws Exception {
assertThat(responseJson.getJsonArray("analysisComments")).hasSize(2);
assertThat(responseJson.getJsonArray("analysisComments").getJsonObject(0))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Analysis: NOT_SET → NOT_AFFECTED"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(responseJson.getJsonArray("analysisComments").getJsonObject(1))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Analysis comment here"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(responseJson.getBoolean("isSuppressed")).isTrue();
assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 2, Duration.ofSeconds(5));
@@ -403,7 +411,7 @@ public void updateAnalysisCreateNewTest() throws Exception {
@Test
public void updateAnalysisCreateNewWithUserTest() throws Exception {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.FINDING_UPDATE);
ManagedUser testUser = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
String jwt = new JsonWebToken().createToken(testUser);
@@ -464,9 +472,16 @@ public void updateAnalysisCreateNewWithUserTest() throws Exception {
@Test
public void updateAnalysisCreateNewWithEmptyRequestTest() throws Exception {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -486,7 +501,7 @@ public void updateAnalysisCreateNewWithEmptyRequestTest() throws Exception {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -514,9 +529,16 @@ public void updateAnalysisCreateNewWithEmptyRequestTest() throws Exception {
@Test
public void updateAnalysisUpdateExistingTest() throws Exception {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -544,7 +566,7 @@ public void updateAnalysisUpdateExistingTest() throws Exception {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -563,22 +585,22 @@ public void updateAnalysisUpdateExistingTest() throws Exception {
.hasFieldOrPropertyWithValue("commenter", Json.createValue("Jane Doe"));
assertThat(analysisComments.getJsonObject(1))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Analysis: NOT_AFFECTED → EXPLOITABLE"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(2))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Justification: CODE_NOT_REACHABLE → NOT_SET"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(3))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Vendor Response: WILL_NOT_FIX → UPDATE"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(4))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Details: New analysis details here"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(5))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Unsuppressed"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(6))
.hasFieldOrPropertyWithValue("comment", Json.createValue("New analysis comment here"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(responseJson.getBoolean("isSuppressed")).isFalse();
assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 2, Duration.ofSeconds(5));
@@ -595,9 +617,16 @@ public void updateAnalysisUpdateExistingTest() throws Exception {
@Test
public void updateAnalysisWithNoChangesTest() throws Exception {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -625,7 +654,7 @@ public void updateAnalysisWithNoChangesTest() throws Exception {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -648,9 +677,16 @@ public void updateAnalysisWithNoChangesTest() throws Exception {
@Test
public void updateAnalysisUpdateExistingWithEmptyRequestTest() throws Exception {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -677,7 +713,7 @@ public void updateAnalysisUpdateExistingWithEmptyRequestTest() throws Exception
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -696,13 +732,13 @@ public void updateAnalysisUpdateExistingWithEmptyRequestTest() throws Exception
.hasFieldOrPropertyWithValue("commenter", Json.createValue("Jane Doe"));
assertThat(analysisComments.getJsonObject(1))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Analysis: NOT_AFFECTED → NOT_SET"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(2))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Justification: CODE_NOT_REACHABLE → NOT_SET"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(3))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Vendor Response: WILL_NOT_FIX → NOT_SET"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 2, Duration.ofSeconds(5));
final Notification projectNotification = deserializeValue(KafkaTopics.NOTIFICATION_PROJECT_CREATED, kafkaMockProducer.history().get(0));
@@ -718,9 +754,16 @@ public void updateAnalysisUpdateExistingWithEmptyRequestTest() throws Exception
@Test
public void updateAnalysisWithProjectNotFoundTest() {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -741,7 +784,7 @@ public void updateAnalysisWithProjectNotFoundTest() {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_NOT_FOUND);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -750,9 +793,16 @@ public void updateAnalysisWithProjectNotFoundTest() {
@Test
public void updateAnalysisWithComponentNotFoundTest() {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -773,7 +823,7 @@ public void updateAnalysisWithComponentNotFoundTest() {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_NOT_FOUND);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -782,9 +832,16 @@ public void updateAnalysisWithComponentNotFoundTest() {
@Test
public void updateAnalysisWithVulnerabilityNotFoundTest() {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
var component = new Component();
component.setProject(project);
@@ -805,7 +862,7 @@ public void updateAnalysisWithVulnerabilityNotFoundTest() {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_NOT_FOUND);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -818,9 +875,16 @@ public void updateAnalysisWithVulnerabilityNotFoundTest() {
// see https://github.com/DependencyTrack/dependency-track/issues/1409
@Test
public void updateAnalysisIssue1409Test() throws InterruptedException {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
+
+ qm.addRoleToUser(user, role, project);
final var component = new Component();
component.setProject(project);
@@ -844,7 +908,7 @@ public void updateAnalysisIssue1409Test() throws InterruptedException {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity(analysisRequest, MediaType.APPLICATION_JSON));
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
assertThat(response.getHeaderString(TOTAL_COUNT_HEADER)).isNull();
@@ -860,19 +924,19 @@ public void updateAnalysisIssue1409Test() throws InterruptedException {
assertThat(analysisComments).hasSize(5);
assertThat(analysisComments.getJsonObject(0))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Analysis: IN_TRIAGE → NOT_AFFECTED"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(1))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Justification: NOT_SET → PROTECTED_BY_MITIGATING_CONTROL"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(2))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Vendor Response: NOT_SET → UPDATE"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(3))
.hasFieldOrPropertyWithValue("comment", Json.createValue("Details: New analysis details here"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(analysisComments.getJsonObject(4))
.hasFieldOrPropertyWithValue("comment", Json.createValue("New analysis comment here"))
- .hasFieldOrPropertyWithValue("commenter", Json.createValue("Test Users"));
+ .hasFieldOrPropertyWithValue("commenter", Json.createValue("testuser"));
assertThat(responseJson.getBoolean("isSuppressed")).isFalse();
assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 2, Duration.ofSeconds(5));
@@ -905,7 +969,7 @@ public void updateAnalysisUnauthorizedTest() {
public void updateAnalysisWithAclTest() {
enablePortfolioAccessControl();
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ initializeWithPermissions(Permissions.VULNERABILITY_MANAGEMENT);
final var project = new Project();
project.setName("acme-app");
@@ -954,12 +1018,20 @@ public void updateAnalysisWithAclTest() {
@Test
public void updateAnalysisWithAssociatedVulnerabilityPolicyTest() {
- initializeWithPermissions(Permissions.VULNERABILITY_ANALYSIS);
+ enablePortfolioAccessControl();
+
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission(Permissions.Constants.PROJECT_READ, null),
+ qm.createPermission(Permissions.Constants.FINDING_UPDATE, null)));
final var project = new Project();
project.setName("acme-app");
qm.persist(project);
+ qm.addRoleToUser(user, role, project);
+
final var component = new Component();
component.setProject(project);
component.setName("acme-lib");
@@ -1001,7 +1073,7 @@ public void updateAnalysisWithAssociatedVulnerabilityPolicyTest() {
final Response response = jersey.target(V1_ANALYSIS)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.put(Entity.entity("""
{
"project": "%s",
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/BadgeResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/BadgeResourceTest.java
index d207a8d3d3..885341d70c 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/BadgeResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/BadgeResourceTest.java
@@ -56,7 +56,7 @@ public void before() throws Exception {
@Test
public void projectVulnerabilitiesByUuidTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/" + project.getUuid())
.queryParam(API_KEY, apiKey)
@@ -69,7 +69,7 @@ public void projectVulnerabilitiesByUuidTest() {
@Test
public void projectVulnerabilitiesByUuidWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/" + project.getUuid()).request()
.header(X_API_KEY, apiKey)
@@ -81,7 +81,7 @@ public void projectVulnerabilitiesByUuidWithHeaderAuthenticationTest() {
@Test
public void projectVulnerabilitiesByUuidMissingAuthenticationWithUnauthenticatedAccessEnabledTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
enableUnauthenticatedBadgeAccess();
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/" + project.getUuid()).request()
@@ -93,7 +93,7 @@ public void projectVulnerabilitiesByUuidMissingAuthenticationWithUnauthenticated
@Test
public void projectVulnerabilitiesByUuidProjectNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Response response = jersey.target(V1_BADGE + "/vulns/project/" + UUID.randomUUID())
.queryParam(API_KEY, apiKey)
.request()
@@ -103,7 +103,7 @@ public void projectVulnerabilitiesByUuidProjectNotFoundTest() {
@Test
public void projectVulnerabilitiesByUuidMissingAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/" + project.getUuid()).request()
.get(Response.class);
@@ -122,7 +122,7 @@ public void projectVulnerabilitiesByUuidMissingPermissionTest() {
@Test
public void projectVulnerabilitiesByUuidWithAclAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -146,7 +146,7 @@ public void projectVulnerabilitiesByUuidWithAclAccessTest() {
@Test
public void projectVulnerabilitiesByUuidWithAclAccessWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -169,7 +169,7 @@ public void projectVulnerabilitiesByUuidWithAclAccessWithHeaderAuthenticationTes
@Test
public void projectVulnerabilitiesByUuidWithAclNoAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -190,7 +190,7 @@ public void projectVulnerabilitiesByUuidWithAclNoAccessTest() {
@Test
public void projectVulnerabilitiesByNameAndVersionTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/Acme%20Example/1.0.0")
.queryParam(API_KEY, apiKey)
@@ -203,7 +203,7 @@ public void projectVulnerabilitiesByNameAndVersionTest() {
@Test
public void projectVulnerabilitiesByNameAndVersionWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
enableUnauthenticatedBadgeAccess();
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/Acme%20Example/1.0.0").request()
@@ -214,7 +214,7 @@ public void projectVulnerabilitiesByNameAndVersionWithHeaderAuthenticationTest()
}
public void projectVulnerabilitiesByNameAndVersionMissingAuthenticationWithUnauthenticatedAccessEnabledTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/Acme%20Example/1.0.0")
.queryParam(API_KEY, apiKey)
@@ -227,7 +227,7 @@ public void projectVulnerabilitiesByNameAndVersionMissingAuthenticationWithUnaut
@Test
public void projectVulnerabilitiesByNameAndVersionProjectNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Response response = jersey.target(V1_BADGE + "/vulns/project/ProjectNameDoesNotExist/1.0.0")
.queryParam(API_KEY, apiKey)
.request()
@@ -237,7 +237,7 @@ public void projectVulnerabilitiesByNameAndVersionProjectNotFoundTest() {
@Test
public void projectVulnerabilitiesByNameAndVersionVersionNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/Acme%20Example/1.2.0")
.queryParam(API_KEY, apiKey)
@@ -248,7 +248,7 @@ public void projectVulnerabilitiesByNameAndVersionVersionNotFoundTest() {
@Test
public void projectVulnerabilitiesByNameAndVersionMissingAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/vulns/project/Acme%20Example/1.0.0").request()
.get(Response.class);
@@ -267,7 +267,7 @@ public void projectVulnerabilitiesByNameAndVersionMissingPermissionTest() {
@Test
public void projectVulnerabilitiesByNameAndVersionWithAclAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -291,7 +291,7 @@ public void projectVulnerabilitiesByNameAndVersionWithAclAccessTest() {
@Test
public void projectVulnerabilitiesByNameAndVersionWithAclAccessWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -314,7 +314,7 @@ public void projectVulnerabilitiesByNameAndVersionWithAclAccessWithHeaderAuthent
@Test
public void projectVulnerabilitiesByNameAndVersionWithAclNoAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -335,7 +335,7 @@ public void projectVulnerabilitiesByNameAndVersionWithAclNoAccessTest() {
@Test
public void projectPolicyViolationsByUuidTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/" + project.getUuid())
.queryParam(API_KEY, apiKey)
@@ -348,7 +348,7 @@ public void projectPolicyViolationsByUuidTest() {
@Test
public void projectPolicyViolationsByUuidWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/" + project.getUuid()).request()
.header(X_API_KEY, apiKey)
@@ -360,7 +360,7 @@ public void projectPolicyViolationsByUuidWithHeaderAuthenticationTest() {
@Test
public void projectPolicyViolationsByUuidMissingAuthenticationWithUnauthenticatedAccessEnabledTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
enableUnauthenticatedBadgeAccess();
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/" + project.getUuid())
@@ -373,7 +373,7 @@ public void projectPolicyViolationsByUuidMissingAuthenticationWithUnauthenticate
@Test
public void projectPolicyViolationsByUuidProjectNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Response response = jersey.target(V1_BADGE + "/violations/project/" + UUID.randomUUID())
.queryParam(API_KEY, apiKey)
.request()
@@ -383,7 +383,7 @@ public void projectPolicyViolationsByUuidProjectNotFoundTest() {
@Test
public void projectPolicyViolationsByUuidMissingAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Project project = qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/" + project.getUuid()).request()
.get(Response.class);
@@ -402,7 +402,7 @@ public void projectPolicyViolationsByUuidMissingPermissionTest() {
@Test
public void projectPolicyViolationsByUuidWithAclAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -426,7 +426,7 @@ public void projectPolicyViolationsByUuidWithAclAccessTest() {
@Test
public void projectPolicyViolationsByUuidWithAclAccessWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -449,7 +449,7 @@ public void projectPolicyViolationsByUuidWithAclAccessWithHeaderAuthenticationTe
@Test
public void projectPolicyViolationsByUuidWithAclNoAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -470,7 +470,7 @@ public void projectPolicyViolationsByUuidWithAclNoAccessTest() {
@Test
public void projectPolicyViolationsByNameAndVersionTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/Acme%20Example/1.0.0")
.queryParam(API_KEY, apiKey)
@@ -483,7 +483,7 @@ public void projectPolicyViolationsByNameAndVersionTest() {
@Test
public void projectPolicyViolationsByNameAndVersionWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/Acme%20Example/1.0.0").request()
.header(X_API_KEY, apiKey)
@@ -495,7 +495,7 @@ public void projectPolicyViolationsByNameAndVersionWithHeaderAuthenticationTest(
@Test
public void projectPolicyViolationsByNameAndVersionMissingAuthenticationWithUnauthenticatedAccessEnabledTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
enableUnauthenticatedBadgeAccess();
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/Acme%20Example/1.0.0")
@@ -508,7 +508,7 @@ public void projectPolicyViolationsByNameAndVersionMissingAuthenticationWithUnau
@Test
public void projectPolicyViolationsByNameAndVersionProjectNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
Response response = jersey.target(V1_BADGE + "/violations/project/ProjectNameDoesNotExist/1.0.0")
.queryParam(API_KEY, apiKey)
.request()
@@ -518,7 +518,7 @@ public void projectPolicyViolationsByNameAndVersionProjectNotFoundTest() {
@Test
public void projectPolicyViolationsByNameAndVersionVersionNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/Acme%20Example/1.2.0")
.queryParam(API_KEY, apiKey)
@@ -529,7 +529,7 @@ public void projectPolicyViolationsByNameAndVersionVersionNotFoundTest() {
@Test
public void projectPolicyViolationsByNameAndVersionMissingAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createProject("Acme Example", null, "1.0.0", null, null, null, null, false);
Response response = jersey.target(V1_BADGE + "/violations/project/Acme%20Example/1.0.0").request()
.get(Response.class);
@@ -548,7 +548,7 @@ public void projectPolicyViolationsByNameAndVersionMissingPermissionTest() {
@Test
public void projectPolicyViolationsByNameAndVersionWithAclAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -570,7 +570,7 @@ public void projectPolicyViolationsByNameAndVersionWithAclAccessTest() {
@Test
public void projectPolicyViolationsByNameAndVersionWithAclAccessWithHeaderAuthenticationTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -591,7 +591,7 @@ public void projectPolicyViolationsByNameAndVersionWithAclAccessWithHeaderAuthen
@Test
public void projectPolicyViolationsByNameAndVersionWithAclNoAccessTest() {
- initializeWithPermissions(Permissions.VIEW_BADGES);
+ initializeWithPermissions(Permissions.BADGES_READ);
qm.createConfigProperty(
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ConfigPropertyConstants.ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java
index 7ed128ac69..8f91984de5 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java
@@ -21,7 +21,6 @@
import alpine.common.util.UuidUtil;
import alpine.model.IConfigProperty;
import alpine.model.ManagedUser;
-import alpine.model.Permission;
import alpine.server.auth.JsonWebToken;
import alpine.server.filters.ApiFilter;
import alpine.server.filters.AuthenticationFeature;
@@ -140,7 +139,7 @@ public void before() throws Exception {
@Test
public void exportProjectAsCycloneDxTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
Component c = new Component();
@@ -159,7 +158,7 @@ public void exportProjectAsCycloneDxTest() {
@Test
public void exportProjectAsCycloneDxInvalidTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
Response response = jersey.target(V1_BOM + "/cyclonedx/project/" + UUID.randomUUID()).request()
.header(X_API_KEY, apiKey)
@@ -229,8 +228,10 @@ public void exportProjectAsCycloneDxAclUserTest() {
}
""");
- final Permission permission = qm.createPermission("VIEW_PORTFOLIO", null);
- final Role role = qm.createRole("Test Role", List.of(permission));
+ final Role role = qm.createRole("Test Role", List.of(
+ qm.createPermission("PROJECT_READ", null),
+ qm.createPermission("BOM_READ", null)));
+
qm.addRoleToUser(testUser, role, project);
response = responseSupplier.get();
@@ -239,7 +240,7 @@ public void exportProjectAsCycloneDxAclUserTest() {
@Test
public void exportProjectAsCycloneDxInventoryTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
var vulnerability = new Vulnerability();
vulnerability.setVulnId("INT-001");
@@ -474,7 +475,7 @@ public void exportProjectAsCycloneDxInventoryTest() {
@Test
public void exportProjectAsCycloneDxLicenseTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
Component c = new Component();
@@ -551,7 +552,7 @@ public void exportProjectAsCycloneDxLicenseTest() {
@Test
public void exportProjectAsCycloneDxInventoryWithVulnerabilitiesTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
var vulnerability = new Vulnerability();
vulnerability.setVulnId("INT-001");
@@ -749,7 +750,7 @@ public void exportProjectAsCycloneDxInventoryWithVulnerabilitiesTest() {
@Test
public void exportProjectAsCycloneDxVdrTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
var vulnerability = new Vulnerability();
vulnerability.setVulnId("INT-001");
@@ -940,7 +941,7 @@ public void exportProjectAsCycloneDxVdrTest() {
@Test
public void exportComponentAsCycloneDx() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
Component c = new Component();
@@ -959,7 +960,7 @@ public void exportComponentAsCycloneDx() {
@Test
public void exportComponentAsCycloneDxInvalid() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.BOM_READ);
Response response = jersey.target(V1_BOM + "/cyclonedx/component/" + UUID.randomUUID()).request()
.header(X_API_KEY, apiKey)
@@ -1008,7 +1009,7 @@ public void exportComponentAsCycloneDxAclTest() {
@Test
public void uploadBomTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
File file = new File(IOUtils.resourceToURL("/unit/bom-1.xml").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
@@ -1063,7 +1064,7 @@ public void uploadBomTest() throws Exception {
@Test
public void uploadNonCycloneDxBomTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
String bomString = Base64.getEncoder().encodeToString("""
SPDXVersion: SPDX-2.2
@@ -1085,7 +1086,7 @@ public void uploadNonCycloneDxBomTest() {
@Test
public void uploadInvalidCycloneDxBomTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
String bomString = Base64.getEncoder().encodeToString("""
{
@@ -1121,7 +1122,7 @@ public void uploadInvalidCycloneDxBomTest() {
@Test
public void uploadInvalidFormatBomTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
File file = new File(IOUtils.resourceToURL("/unit/bom-invalid.json").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
@@ -1141,7 +1142,7 @@ public void uploadInvalidFormatBomTest() throws Exception {
@Test
public void uploadBomInvalidProjectTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
File file = new File(IOUtils.resourceToURL("/unit/bom-1.xml").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
BomSubmitRequest request = new BomSubmitRequest(UUID.randomUUID().toString(), null, null, null, false, false, bomString);
@@ -1156,7 +1157,7 @@ public void uploadBomInvalidProjectTest() throws Exception {
@Test
public void uploadBomAutoCreateTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
File file = new File(IOUtils.resourceToURL("/unit/bom-1.xml").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
BomSubmitRequest request = new BomSubmitRequest(null, "Acme Example", "1.0", null, true, false, bomString);
@@ -1174,7 +1175,7 @@ public void uploadBomAutoCreateTest() throws Exception {
@Test
public void uploadBomUnauthorizedTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
File file = new File(IOUtils.resourceToURL("/unit/bom-1.xml").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
@@ -1189,7 +1190,7 @@ public void uploadBomUnauthorizedTest() throws Exception {
@Test
public void uploadBomAutoCreateTestWithParentTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
File file = new File(IOUtils.resourceToURL("/unit/bom-1.xml").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
// Upload parent project
@@ -1253,7 +1254,7 @@ public void uploadBomAutoCreateTestWithParentTest() throws Exception {
@Test
public void uploadBomInvalidParentTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
File file = new File(IOUtils.resourceToURL("/unit/bom-1.xml").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
BomSubmitRequest request = new BomSubmitRequest(null, "Acme Example", "1.0", null, true, UUID.randomUUID().toString(), null, null, false, bomString);
@@ -1295,7 +1296,7 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr
@Test
@Parameters(method = "uploadBomSchemaValidationTestParameters")
public void uploadBomSchemaValidationTest(final Path filePath) throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
File file = filePath.toFile();
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
@@ -1308,7 +1309,7 @@ public void uploadBomSchemaValidationTest(final Path filePath) throws Exception
@Test
public void uploadBomInvalidJsonTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
final var project = new Project();
project.setName("acme-app");
@@ -1376,7 +1377,7 @@ public void uploadBomInvalidJsonTest() throws Exception {
@Test
public void uploadBomInvalidXmlTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
final var project = new Project();
project.setName("acme-app");
@@ -1440,7 +1441,7 @@ public void uploadBomInvalidXmlTest() throws Exception {
@Test
public void uploadBomTooLargeViaPutTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
final var project = new Project();
project.setName("acme-app");
@@ -1471,7 +1472,7 @@ public void uploadBomTooLargeViaPutTest() {
@Test
public void uploadBomAutoCreateWithTagsMultipartTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
final var multiPart = new FormDataMultiPart()
.field("bom", resourceToString("/unit/bom-1.xml", StandardCharsets.UTF_8), MediaType.APPLICATION_XML_TYPE)
.field("projectName", "Acme Example")
@@ -1504,7 +1505,7 @@ public void uploadBomAutoCreateWithTagsMultipartTest() throws Exception {
@Test
public void uploadBomProtobufFormatTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
final var project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
final var bomProto = Bom.newBuilder().setSpecVersion("1.6").build();
final var multiPart = new FormDataMultiPart()
@@ -1535,7 +1536,7 @@ public void uploadBomProtobufFormatTest() {
@Test
public void uploadBomAutoCreateWithTagsTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
File file = new File(IOUtils.resourceToURL("/unit/bom-1.xml").toURI());
String bomString = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(file));
List tags = Stream.of("tag1", "tag2").map(name -> {
@@ -1567,7 +1568,7 @@ public void validateCycloneDxBomWithMultipleNamespacesTest() throws Exception {
@Test
public void uploadBomWithValidationModeDisabledTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
qm.createConfigProperty(
BOM_VALIDATION_MODE.getGroupName(),
@@ -1612,7 +1613,7 @@ public void uploadBomWithValidationModeDisabledTest() {
@Test
public void uploadBomWithValidationModeEnabledForTagsTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
qm.createConfigProperty(
BOM_VALIDATION_MODE.getGroupName(),
@@ -1679,7 +1680,7 @@ public void uploadBomWithValidationModeEnabledForTagsTest() {
@Test
public void uploadBomWithValidationModeDisabledForTagsTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
qm.createConfigProperty(
BOM_VALIDATION_MODE.getGroupName(),
@@ -1746,7 +1747,7 @@ public void uploadBomWithValidationModeDisabledForTagsTest() {
@Test
public void uploadBomWithValidationTagsInvalidTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
qm.createConfigProperty(
BOM_VALIDATION_MODE.getGroupName(),
@@ -1816,7 +1817,7 @@ public void uploadBomWithValidationTagsInvalidTest() {
@Test
public void uploadBomAutoCreateLatestWithAclTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
enablePortfolioAccessControl();
final var accessLatestProject = new Project();
@@ -1840,7 +1841,7 @@ public void uploadBomAutoCreateLatestWithAclTest() throws Exception {
@Test
public void uploadBomAutoCreateLatestWithAclNoAccessTest() throws Exception {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
enablePortfolioAccessControl();
final var noAccessLatestProject = new Project();
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/MetricsResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/MetricsResourceTest.java
index f4a8b8ab58..1fffe31b7e 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/MetricsResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/MetricsResourceTest.java
@@ -57,7 +57,7 @@ public class MetricsResourceTest extends ResourceTest {
@Test
public void getProjectCurrentMetricsAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -88,7 +88,7 @@ public void getProjectCurrentMetricsAclTest() {
@Test
public void getProjectMetricsSinceAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -119,7 +119,7 @@ public void getProjectMetricsSinceAclTest() {
@Test
public void getProjectMetricsXDaysAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -150,7 +150,7 @@ public void getProjectMetricsXDaysAclTest() {
@Test
public void refreshProjectMetricsAclTest() {
- initializeWithPermissions(Permissions.PORTFOLIO_MANAGEMENT);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -181,7 +181,7 @@ public void refreshProjectMetricsAclTest() {
@Test
public void getComponentCurrentMetricsAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -217,7 +217,7 @@ public void getComponentCurrentMetricsAclTest() {
@Test
public void getComponentMetricsSinceAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -253,7 +253,7 @@ public void getComponentMetricsSinceAclTest() {
@Test
public void getComponentMetricsXDaysAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -289,7 +289,7 @@ public void getComponentMetricsXDaysAclTest() {
@Test
public void refreshComponentMetricsAclTest() {
- initializeWithPermissions(Permissions.PORTFOLIO_MANAGEMENT);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -325,7 +325,7 @@ public void refreshComponentMetricsAclTest() {
@Test
public void getCurrentPortfolioMetricsEmptyTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final Response response = jersey
@@ -375,7 +375,7 @@ public void getCurrentPortfolioMetricsEmptyTest() {
@Test
public void getCurrentPortfolioMetricsAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var accessibleProjectA = new Project();
@@ -467,7 +467,7 @@ public void getCurrentPortfolioMetricsAclTest() {
@Test
public void getPortfolioMetricsXDaysAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var accessibleProjectA = new Project();
@@ -714,7 +714,7 @@ public void getPortfolioMetricsXDaysAclTest() {
@Test
public void getPortfolioMetricsSinceAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var accessibleProjectA = new Project();
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/NotificationRuleResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/NotificationRuleResourceTest.java
index aa74b5a2ad..a8e9e56cc0 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/NotificationRuleResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/NotificationRuleResourceTest.java
@@ -23,9 +23,11 @@
import alpine.notification.NotificationLevel;
import alpine.server.filters.ApiFilter;
import alpine.server.filters.AuthenticationFeature;
+import alpine.server.filters.AuthorizationFeature;
import net.javacrumbs.jsonunit.core.Option;
import org.dependencytrack.JerseyTestRule;
import org.dependencytrack.ResourceTest;
+import org.dependencytrack.auth.Permissions;
import org.dependencytrack.model.NotificationPublisher;
import org.dependencytrack.model.NotificationRule;
import org.dependencytrack.model.Project;
@@ -65,7 +67,8 @@ public class NotificationRuleResourceTest extends ResourceTest {
public static JerseyTestRule jersey = new JerseyTestRule(
new ResourceConfig(NotificationRuleResource.class)
.register(ApiFilter.class)
- .register(AuthenticationFeature.class));
+ .register(AuthenticationFeature.class)
+ .register(AuthorizationFeature.class));
@Before
public void before() throws Exception {
@@ -76,6 +79,8 @@ public void before() throws Exception {
@Test
public void getAllNotificationRulesTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
qm.createNotificationRule("Rule 1", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
qm.createNotificationRule("Rule 2", NotificationScope.PORTFOLIO, NotificationLevel.WARNING, publisher);
@@ -99,6 +104,8 @@ public void getAllNotificationRulesTest() {
@Test
public void createNotificationRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = new NotificationRule();
rule.setName("Example Rule");
@@ -125,6 +132,8 @@ public void createNotificationRuleTest() {
@Test
public void createNotificationRuleInvalidPublisherTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = new NotificationPublisher();
publisher.setUuid(UUID.randomUUID());
NotificationRule rule = new NotificationRule();
@@ -146,6 +155,8 @@ public void createNotificationRuleInvalidPublisherTest() {
@Test
public void updateNotificationRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Rule 1", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
rule.setName("Example Rule");
@@ -167,6 +178,8 @@ public void updateNotificationRuleTest() {
@Test
public void updateNotificationRuleInvalidTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Rule 1", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
rule = qm.detach(NotificationRule.class, rule.getId());
@@ -182,6 +195,8 @@ public void updateNotificationRuleInvalidTest() {
@Test
public void deleteNotificationRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Rule 1", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
rule.setName("Example Rule");
@@ -195,6 +210,8 @@ public void deleteNotificationRuleTest() {
@Test
public void addProjectToRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -212,6 +229,8 @@ public void addProjectToRuleTest() {
@Test
public void addProjectToRuleInvalidRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + UUID.randomUUID().toString() + "/project/" + project.getUuid().toString()).request()
@@ -225,6 +244,8 @@ public void addProjectToRuleInvalidRuleTest() {
@Test
public void addProjectToRuleInvalidScopeTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.SYSTEM, NotificationLevel.INFORMATIONAL, publisher);
@@ -239,6 +260,8 @@ public void addProjectToRuleInvalidScopeTest() {
@Test
public void addProjectToRuleInvalidProjectTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + rule.getUuid().toString() + "/project/" + UUID.randomUUID().toString()).request()
@@ -252,6 +275,8 @@ public void addProjectToRuleInvalidProjectTest() {
@Test
public void addProjectToRuleDuplicateProjectTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -268,6 +293,7 @@ public void addProjectToRuleDuplicateProjectTest() {
@Test
public void addProjectToRuleAclTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
enablePortfolioAccessControl();
final var project = new Project();
@@ -302,6 +328,8 @@ public void addProjectToRuleAclTest() {
@Test
public void removeProjectFromRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -318,6 +346,8 @@ public void removeProjectFromRuleTest() {
@Test
public void removeProjectFromRuleInvalidRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + UUID.randomUUID().toString() + "/project/" + project.getUuid().toString()).request()
@@ -331,6 +361,8 @@ public void removeProjectFromRuleInvalidRuleTest() {
@Test
public void removeProjectFromRuleInvalidScopeTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.SYSTEM, NotificationLevel.INFORMATIONAL, publisher);
@@ -345,6 +377,8 @@ public void removeProjectFromRuleInvalidScopeTest() {
@Test
public void removeProjectFromRuleInvalidProjectTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + rule.getUuid().toString() + "/project/" + UUID.randomUUID().toString()).request()
@@ -358,6 +392,8 @@ public void removeProjectFromRuleInvalidProjectTest() {
@Test
public void removeProjectFromRuleDuplicateProjectTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Project project = qm.createProject("Acme Example", null, null, null, null, null, null, false);
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -370,6 +406,7 @@ public void removeProjectFromRuleDuplicateProjectTest() {
@Test
public void removeProjectFromRuleAclTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
enablePortfolioAccessControl();
final var project = new Project();
@@ -404,7 +441,9 @@ public void removeProjectFromRuleAclTest() {
}
@Test
- public void addTeamToRuleTest(){
+ public void addTeamToRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -421,7 +460,9 @@ public void addTeamToRuleTest(){
}
@Test
- public void addTeamToRuleInvalidRuleTest(){
+ public void addTeamToRuleInvalidRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + UUID.randomUUID().toString() + "/team/" + team.getUuid().toString()).request()
@@ -435,6 +476,8 @@ public void addTeamToRuleInvalidRuleTest(){
@Test
public void addTeamToRuleInvalidTeamTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + rule.getUuid().toString() + "/team/" + UUID.randomUUID().toString()).request()
@@ -449,6 +492,8 @@ public void addTeamToRuleInvalidTeamTest() {
@Test
public void addTeamToRuleDuplicateTeamTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -464,7 +509,9 @@ public void addTeamToRuleDuplicateTeamTest() {
}
@Test
- public void addTeamToRuleInvalidPublisherTest(){
+ public void addTeamToRuleInvalidPublisherTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -479,6 +526,8 @@ public void addTeamToRuleInvalidPublisherTest(){
@Test
public void addTeamToRuleWithCustomEmailPublisherTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
final Team team = qm.createTeam("Team Example");
final NotificationPublisher publisher = qm.createNotificationPublisher("foo", "description", SendMailPublisher.name(), "template", "templateMimeType", false);
final NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -523,6 +572,8 @@ public void addTeamToRuleWithCustomEmailPublisherTest() {
@Test
public void removeTeamFromRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -539,6 +590,8 @@ public void removeTeamFromRuleTest() {
@Test
public void removeTeamFromRuleInvalidRuleTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + UUID.randomUUID().toString() + "/team/" + team.getUuid().toString()).request()
@@ -552,6 +605,8 @@ public void removeTeamFromRuleInvalidRuleTest() {
@Test
public void removeTeamFromRuleInvalidTeamTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
Response response = jersey.target(V1_NOTIFICATION_RULE + "/" + rule.getUuid().toString() + "/team/" + UUID.randomUUID().toString()).request()
@@ -565,6 +620,8 @@ public void removeTeamFromRuleInvalidTeamTest() {
@Test
public void removeTeamFromRuleDuplicateTeamTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.EMAIL.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -576,7 +633,9 @@ public void removeTeamFromRuleDuplicateTeamTest() {
}
@Test
- public void removeTeamToRuleInvalidPublisherTest(){
+ public void removeTeamToRuleInvalidPublisherTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
Team team = qm.createTeam("Team Example");
NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
NotificationRule rule = qm.createNotificationRule("Example Rule", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
@@ -591,6 +650,8 @@ public void removeTeamToRuleInvalidPublisherTest(){
@Test
public void updateNotificationRuleWithTagsTest() {
+ initializeWithPermissions(Permissions.NOTIFICATION_RULE_MANAGEMENT);
+
final NotificationPublisher publisher = qm.getNotificationPublisher(DefaultNotificationPublishers.SLACK.getPublisherName());
final NotificationRule rule = qm.createNotificationRule("Rule 1", NotificationScope.PORTFOLIO, NotificationLevel.INFORMATIONAL, publisher);
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/PermissionResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/PermissionResourceTest.java
index 68ef8f7e16..a530e47e35 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/PermissionResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/PermissionResourceTest.java
@@ -23,6 +23,8 @@
import alpine.model.Team;
import alpine.server.filters.ApiFilter;
import alpine.server.filters.AuthenticationFeature;
+
+import org.apache.http.HttpStatus;
import org.dependencytrack.JerseyTestRule;
import org.dependencytrack.ResourceTest;
import org.dependencytrack.auth.Permissions;
@@ -71,7 +73,7 @@ public void getAllPermissionsTest() {
Assert.assertNull(response.getHeaderString(TOTAL_COUNT_HEADER));
JsonArray json = parseJsonArray(response);
Assert.assertNotNull(json);
- Assert.assertEquals(39, json.size());
+ Assert.assertEquals(20, json.size());
Assert.assertEquals("ACCESS_MANAGEMENT", json.getJsonObject(0).getString("name"));
Assert.assertEquals("Allows the management of users, teams, and API keys", json.getJsonObject(0).getString("description"));
}
@@ -179,7 +181,7 @@ public void removePermissionFromUserInvalidPermissionTest() {
public void removePermissionFromUserNoChangesTest() {
ManagedUser user = qm.createManagedUser("user1", TEST_USER_PASSWORD_HASH);
String username = user.getUsername();
- Response response = jersey.target(V1_PERMISSION + "/BOM_UPLOAD/user/" + username).request()
+ Response response = jersey.target(V1_PERMISSION + "/BOM_CREATE/user/" + username).request()
.header(X_API_KEY, apiKey)
.delete();
Assert.assertEquals(304, response.getStatus(), 0);
@@ -289,7 +291,7 @@ public void removePermissionFromTeamInvalidPermissionTest() {
public void removePermissionFromTeamNoChangesTest() {
Team team = qm.createTeam("team1");
String teamUuid = team.getUuid().toString();
- Response response = jersey.target(V1_PERMISSION + "/BOM_UPLOAD/team/" + teamUuid).request()
+ Response response = jersey.target(V1_PERMISSION + "/BOM_CREATE/team/" + teamUuid).request()
.header(X_API_KEY, apiKey)
.delete();
Assert.assertEquals(304, response.getStatus(), 0);
@@ -303,14 +305,14 @@ public void setUserPermissionsTest() {
List permissionSet1 = List.of(
qm.getPermission("ACCESS_MANAGEMENT"),
- qm.getPermission("ACCESS_MANAGEMENT_CREATE"),
- qm.getPermission("ACCESS_MANAGEMENT_DELETE"));
+ qm.getPermission("SYSTEM_CONFIGURATION"),
+ qm.getPermission("VULNERABILITY_MANAGEMENT"));
List permissionSet2 = List.of(
- qm.getPermission("BOM_UPLOAD"),
- qm.getPermission("VIEW_PORTFOLIO"),
+ qm.getPermission("BOM_CREATE"),
+ qm.getPermission("POLICY_MANAGEMENT"),
qm.getPermission("PORTFOLIO_MANAGEMENT"),
- qm.getPermission("PORTFOLIO_MANAGEMENT_CREATE"));
+ qm.getPermission("TAG_MANAGEMENT"));
JsonObject permissionRequest1 = Json.createObjectBuilder()
.add("username", username)
@@ -398,14 +400,14 @@ public void setTeamPermissionsTest() {
List permissionSet1 = List.of(
qm.getPermission("ACCESS_MANAGEMENT"),
- qm.getPermission("ACCESS_MANAGEMENT_CREATE"),
- qm.getPermission("ACCESS_MANAGEMENT_DELETE"));
+ qm.getPermission("SYSTEM_CONFIGURATION"),
+ qm.getPermission("VULNERABILITY_MANAGEMENT"));
List permissionSet2 = List.of(
- qm.getPermission("BOM_UPLOAD"),
- qm.getPermission("VIEW_PORTFOLIO"),
+ qm.getPermission("BOM_CREATE"),
+ qm.getPermission("POLICY_MANAGEMENT"),
qm.getPermission("PORTFOLIO_MANAGEMENT"),
- qm.getPermission("PORTFOLIO_MANAGEMENT_CREATE"));
+ qm.getPermission("TAG_MANAGEMENT"));
JsonObject permissionRequet1 = Json.createObjectBuilder()
.add("team", teamUuid.toString())
@@ -455,28 +457,32 @@ public void setTeamPermissionsTest() {
@Test
public void addPermissionToRoleTest() {
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT, Permissions.PROJECT_UPDATE);
+
Role role = qm.createRole("Test Role", new ArrayList());
- Response response = jersey.target(V1_PERMISSION + "/PORTFOLIO_MANAGEMENT/role/" + role.getUuid()).request()
+ Response response = jersey.target(V1_PERMISSION + "/PROJECT_UPDATE/role/" + role.getUuid()).request()
.header(X_API_KEY, apiKey)
.post(Entity.entity(null, MediaType.APPLICATION_JSON));
- Assert.assertEquals(200, response.getStatus(), 0);
+ Assert.assertEquals(HttpStatus.SC_OK, response.getStatus(), 0);
JsonObject json = parseJsonObject(response);
Assert.assertNotNull(json);
Assert.assertEquals("Test Role", json.getString("name"));
Assert.assertEquals(1, json.getJsonArray("permissions").size());
- Assert.assertEquals("PORTFOLIO_MANAGEMENT",
+ Assert.assertEquals("PROJECT_UPDATE",
json.getJsonArray("permissions").getJsonObject(0).getString("name"));
}
@Test
public void addPermissionToRoleInvalidRoleTest() {
- Response response = jersey.target(V1_PERMISSION + "/PORTFOLIO_MANAGEMENT/role/" + UUID.randomUUID()).request()
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT, Permissions.POLICY_VIOLATION_READ);
+
+ Response response = jersey.target(V1_PERMISSION + "/POLICY_VIOLATION_READ/role/" + UUID.randomUUID()).request()
.header(X_API_KEY, apiKey)
.post(Entity.entity(null, MediaType.APPLICATION_JSON));
- Assert.assertEquals(404, response.getStatus(), 0);
+ Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatus(), 0);
Assert.assertNull(response.getHeaderString(TOTAL_COUNT_HEADER));
String body = getPlainTextBody(response);
Assert.assertEquals("The role could not be found.", body);
@@ -484,13 +490,17 @@ public void addPermissionToRoleInvalidRoleTest() {
@Test
public void addPermissionToRoleInvalidPermissionTest() {
- Role role = qm.createRole("Test Role", new ArrayList());
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT);
- Response response = jersey.target(V1_PERMISSION + "/BLAH/role/" + role.getUuid()).request()
+ Role role = qm.createRole("Test Role", List.of());
+
+ qm.delete(qm.getPermission(Permissions.Constants.FINDING_READ));
+
+ Response response = jersey.target(V1_PERMISSION + "/FINDING_READ/role/" + role.getUuid()).request()
.header(X_API_KEY, apiKey)
.post(Entity.entity(null, MediaType.APPLICATION_JSON));
- Assert.assertEquals(404, response.getStatus(), 0);
+ Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatus(), 0);
Assert.assertNull(response.getHeaderString(TOTAL_COUNT_HEADER));
String body = getPlainTextBody(response);
Assert.assertEquals("The permission could not be found.", body);
@@ -498,29 +508,27 @@ public void addPermissionToRoleInvalidPermissionTest() {
@Test
public void addPermissionToRoleDuplicateTest() {
- List permissionSet1 = List.of(
- qm.getPermission("PORTFOLIO_MANAGEMENT"));
- Role role = qm.createRole("Test Role", permissionSet1);
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT, Permissions.PROJECT_UPDATE);
- Response response = jersey.target(V1_PERMISSION + "/PORTFOLIO_MANAGEMENT/role/" + role.getUuid()).request()
+ Role role = qm.createRole("Test Role", List.of(qm.getPermission("PROJECT_UPDATE")));
+
+ Response response = jersey.target(V1_PERMISSION + "/PROJECT_UPDATE/role/" + role.getUuid()).request()
.header(X_API_KEY, apiKey)
.post(Entity.entity(null, MediaType.APPLICATION_JSON));
- Assert.assertEquals(304, response.getStatus(), 0);
+ Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, response.getStatus(), 0);
Assert.assertNull(response.getHeaderString(TOTAL_COUNT_HEADER));
}
@Test
public void removePermissionFromRoleTest() {
- List permissionSet1 = List.of(
- qm.getPermission("PORTFOLIO_MANAGEMENT"));
- Role role = qm.createRole("Test Role", permissionSet1);
+ Role role = qm.createRole("Test Role", List.of(qm.getPermission("PORTFOLIO_MANAGEMENT")));
Response response = jersey.target(V1_PERMISSION + "/PORTFOLIO_MANAGEMENT/role/" + role.getUuid()).request()
.header(X_API_KEY, apiKey)
.delete();
- Assert.assertEquals(200, response.getStatus(), 0);
+ Assert.assertEquals(HttpStatus.SC_OK, response.getStatus(), 0);
JsonObject json = parseJsonObject(response);
Assert.assertNotNull(json);
Assert.assertEquals("Test Role", json.getString("name"));
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyConditionResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyConditionResourceTest.java
index f9fe0ae20e..7532887b6f 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyConditionResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyConditionResourceTest.java
@@ -54,7 +54,7 @@ public class PolicyConditionResourceTest extends ResourceTest {
@Test
public void testCreateCondition() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final var policy = new Policy();
policy.setName("foo");
@@ -86,7 +86,7 @@ public void testCreateCondition() {
@Test
public void testCreateConditionWhenPolicyDoesNotExist() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final Response response = jersey.target("%s/cec42e01-62a7-4c86-9b8f-cd6650be2888/condition".formatted(V1_POLICY))
.request()
@@ -119,7 +119,7 @@ public void testCreateConditionWhenUnauthorized() {
@Test
public void testCreateConditionWithExpression() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final Policy policy = qm.createPolicy("policy", Operator.ANY, ViolationState.FAIL);
@@ -148,7 +148,7 @@ public void testCreateConditionWithExpression() {
@Test
public void testCreateConditionWithInvalidExpression() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final Policy policy = qm.createPolicy("policy", Operator.ANY, ViolationState.FAIL);
@@ -180,7 +180,7 @@ public void testCreateConditionWithInvalidExpression() {
@Test
public void testUpdateCondition() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final var policy = new Policy();
policy.setName("foo");
@@ -222,7 +222,7 @@ public void testUpdateCondition() {
@Test
public void testUpdateConditionWhenConditionDoesNotExist() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final Response response = jersey.target("%s/condition".formatted(V1_POLICY))
.request()
@@ -257,7 +257,7 @@ public void testUpdateConditionWhenUnauthorized() {
@Test
public void testUpdateConditionWithExpression() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final Policy policy = qm.createPolicy("policy", Operator.ANY, ViolationState.FAIL);
final PolicyCondition condition = qm.createPolicyCondition(policy,
@@ -290,7 +290,7 @@ public void testUpdateConditionWithExpression() {
@Test
public void testUpdateConditionWithInvalidExpression() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final Policy policy = qm.createPolicy("policy", Operator.ANY, ViolationState.FAIL);
final PolicyCondition condition = qm.createPolicyCondition(policy,
@@ -325,7 +325,7 @@ public void testUpdateConditionWithInvalidExpression() {
@Test
public void testDeleteCondition() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final var policy = new Policy();
policy.setName("foo");
@@ -354,7 +354,7 @@ public void testDeleteCondition() {
@Test
public void testDeleteConditionWhenConditionDoesNotExist() {
- initializeWithPermissions(Permissions.POLICY_MANAGEMENT_UPDATE);
+ initializeWithPermissions(Permissions.POLICY_MANAGEMENT);
final Response response = jersey.target("%s/condition/%s".formatted(V1_POLICY, UUID.randomUUID()))
.request()
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyViolationResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyViolationResourceTest.java
index bfa4086180..3a060b089d 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyViolationResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/PolicyViolationResourceTest.java
@@ -59,7 +59,7 @@ public class PolicyViolationResourceTest extends ResourceTest {
@Test
public void getViolationsTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -111,7 +111,7 @@ public void getViolationsUnauthorizedTest() {
@Test
public void getViolationsByProjectTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -183,7 +183,7 @@ public void getViolationsByProjectTest() {
@Test
public void getViolationsByProjectIssue2766() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project projectA = qm.createProject("acme-app-a", null, "1.0", null, null, null, null, false);
final var componentA = new Component();
@@ -234,7 +234,7 @@ public void getViolationsByProjectUnauthorizedTest() {
@Test
public void getViolationsByProjectNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Response response = jersey.target(V1_POLICY_VIOLATION)
.path("/project/" + UUID.randomUUID())
@@ -248,7 +248,7 @@ public void getViolationsByProjectNotFoundTest() {
@Test
public void getViolationsByProjectAclTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -279,7 +279,7 @@ public void getViolationsByProjectAclTest() {
@Test
public void getViolationsByComponentTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -332,7 +332,7 @@ public void getViolationsByComponentUnauthorizedTest() {
@Test
public void getViolationsByComponentNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Response response = jersey.target(V1_POLICY_VIOLATION)
.path("/component/" + UUID.randomUUID())
@@ -346,7 +346,7 @@ public void getViolationsByComponentNotFoundTest() {
@Test
public void getViolationsByComponentAclTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -381,7 +381,7 @@ public void getViolationsByComponentAclTest() {
@Test
public void getViolationsWithAclEnabledTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project projectA = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
final Project projectA_child = qm.createProject("Acme Example - Child", null, "1.0", null, projectA, null, null, false);
@@ -500,7 +500,7 @@ public void getViolationsWithAclEnabledTest() {
@Test
public void getViolationsWithArrayFilter() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -605,7 +605,7 @@ public void getViolationsWithArrayFilter() {
@Test
public void getViolationsWithInputFilter() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project projectA = qm.createProject("Project A", null, "1.0", null, null, null, null, false);
final Project projectB = qm.createProject("Project B", null, "1.0", null, null, null, null, false);
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/ProjectResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/ProjectResourceTest.java
index 6ad420b90d..c42e4eed9f 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/ProjectResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/ProjectResourceTest.java
@@ -58,6 +58,7 @@
import org.dependencytrack.model.ProjectMetrics;
import org.dependencytrack.model.ProjectProperty;
import org.dependencytrack.model.RepositoryType;
+import org.dependencytrack.model.Role;
import org.dependencytrack.model.ServiceComponent;
import org.dependencytrack.model.Tag;
import org.dependencytrack.model.Vulnerability;
@@ -2112,11 +2113,23 @@ public void createProjectInaccessibleParentTest() {
@Test
public void updateProjectTest() {
- Project project = qm.createProject("ABC", null, "1.0", null, null, null, null, false);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
+ enablePortfolioAccessControl();
+
+ final Project project = qm.createProject("ABC", null, "1.0", null, null, null, null, false);
project.setDescription("Test project");
+
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, project);
+
Response response = jersey.target(V1_PROJECT)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.post(Entity.entity(project, MediaType.APPLICATION_JSON));
Assert.assertEquals(200, response.getStatus(), 0);
JsonObject json = parseJsonObject(response);
@@ -2144,15 +2157,19 @@ public void updateProjectNotFoundTest() {
@Test
public void updateProjectNotPermittedTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
enablePortfolioAccessControl();
final var project = new Project();
project.setName("acme-app");
qm.persist(project);
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
final Response response = jersey.target(V1_PROJECT)
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.post(Entity.json(/* language=JSON */ """
{
"uuid": "%s",
@@ -2375,14 +2392,25 @@ public void deleteProjectAclTest() {
@Test
public void patchProjectNotModifiedTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
+ enablePortfolioAccessControl();
+
final var tags = Stream.of("tag1", "tag2").map(qm::createTag).collect(Collectors.toUnmodifiableList());
final var p1 = qm.createProject("ABC", "Test project", "1.0", tags, null, null, null, false);
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, p1);
+
final var jsonProject = new Project();
jsonProject.setDescription(p1.getDescription());
final var response = jersey.target(V1_PROJECT + "/" + p1.getUuid())
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.method("PATCH", Entity.json(jsonProject));
Assert.assertEquals(Response.Status.NOT_MODIFIED.getStatusCode(), response.getStatus());
@@ -2391,14 +2419,26 @@ public void patchProjectNotModifiedTest() {
@Test
public void patchProjectNameVersionConflictTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
+ enablePortfolioAccessControl();
+
final var tags = Stream.of("tag1", "tag2").map(qm::createTag).collect(Collectors.toUnmodifiableList());
final var p1 = qm.createProject("ABC", "Test project", "1.0", tags, null, null, null, false);
qm.createProject("ABC", "Test project", "0.9", null, null, null, null, false);
+
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, p1);
+
final var jsonProject = new Project();
jsonProject.setVersion("0.9");
final var response = jersey.target(V1_PROJECT + "/" + p1.getUuid())
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.method("PATCH", Entity.json(jsonProject));
Assert.assertEquals(Response.Status.CONFLICT.getStatusCode(), response.getStatus());
@@ -2444,10 +2484,23 @@ public void patchProjectNotPermittedTest() {
@Test
public void patchProjectParentTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
+ enablePortfolioAccessControl();
+
final Project parent = qm.createProject("ABC", null, "1.0", null, null, null, null, false);
final Project project = qm.createProject("DEF", null, "2.0", null, parent, null, null, false);
final Project newParent = qm.createProject("GHI", null, "3.0", null, null, null, null, false);
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, parent);
+ qm.addRoleToUser(user, role, project);
+ qm.addRoleToUser(user, role, newParent);
+
final JsonObject jsonProject = Json.createObjectBuilder()
.add("parent", Json.createObjectBuilder()
.add("uuid", newParent.getUuid().toString()))
@@ -2455,7 +2508,7 @@ public void patchProjectParentTest() {
final Response response = jersey.target(V1_PROJECT + "/" + project.getUuid())
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.method(HttpMethod.PATCH, Entity.json(jsonProject.toString()));
@@ -2488,7 +2541,17 @@ public void patchProjectParentTest() {
@Test
public void patchProjectExternalReferencesTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
+ enablePortfolioAccessControl();
+
final var project = qm.createProject("referred-project", "ExtRef test project", "1.0", null, null, null, null, false);
+
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(Permissions.Constants.PROJECT_READ, Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, project);
+
final var ref1 = new ExternalReference();
ref1.setType(org.cyclonedx.model.ExternalReference.Type.VCS);
ref1.setUrl("https://github.com/DependencyTrack/awesomeness");
@@ -2502,7 +2565,7 @@ public void patchProjectExternalReferencesTest() {
final var response = jersey.target(V1_PROJECT + "/" + project.getUuid())
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.method("PATCH", Entity.json(jsonProject));
@@ -2521,9 +2584,20 @@ public void patchProjectExternalReferencesTest() {
@Test
public void patchProjectParentNotFoundTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
+ enablePortfolioAccessControl();
+
final Project parent = qm.createProject("ABC", null, "1.0", null, null, null, null, false);
final Project project = qm.createProject("DEF", null, "2.0", null, parent, null, null, false);
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, project);
+
final JsonObject jsonProject = Json.createObjectBuilder()
.add("parent", Json.createObjectBuilder()
.add("uuid", UUID.randomUUID().toString()))
@@ -2531,7 +2605,7 @@ public void patchProjectParentNotFoundTest() {
final Response response = jersey.target(V1_PROJECT + "/" + project.getUuid())
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.method(HttpMethod.PATCH, Entity.json(jsonProject.toString()));
@@ -2546,6 +2620,7 @@ public void patchProjectParentNotFoundTest() {
@Test
public void patchProjectParentInaccessibleTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
enablePortfolioAccessControl();
final var parentProject = new Project();
@@ -2557,10 +2632,18 @@ public void patchProjectParentInaccessibleTest() {
project.addAccessTeam(super.team);
qm.persist(project);
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, project);
+
final Supplier responseSupplier = () -> jersey
.target(V1_PROJECT + "/" + project.getUuid())
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.method(HttpMethod.PATCH, Entity.json(/* language=JSON */ """
{
@@ -2583,8 +2666,20 @@ public void patchProjectParentInaccessibleTest() {
@Test
public void patchProjectSuccessfullyPatchedTest() {
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.PROJECT_UPDATE);
+ enablePortfolioAccessControl();
+
final var tags = Stream.of("tag1", "tag2").map(qm::createTag).collect(Collectors.toUnmodifiableList());
final var p1 = qm.createProject("ABC", "Test project", "1.0", tags, null, null, null, false);
+
+ final ManagedUser user = qm.createManagedUser("testuser", TEST_USER_PASSWORD_HASH);
+ final String jwt = new JsonWebToken().createToken(user);
+
+ final Role role = qm.createRole("Test Role", qm.getPermissionsByName(List.of(
+ Permissions.Constants.PROJECT_READ,
+ Permissions.Constants.PROJECT_UPDATE)));
+ qm.addRoleToUser(user, role, p1);
+
final var projectManufacturerContact = new OrganizationalContact();
projectManufacturerContact.setName("manufacturerContactName");
final var projectManufacturer = new OrganizationalEntity();
@@ -2625,7 +2720,7 @@ public void patchProjectSuccessfullyPatchedTest() {
jsonProject.setSupplier(jsonProjectSupplier);
final var response = jersey.target(V1_PROJECT + "/" + p1.getUuid())
.request()
- .header(X_API_KEY, apiKey)
+ .header("Authorization", "Bearer " + jwt)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.method("PATCH", Entity.json(jsonProject));
Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/RoleResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/RoleResourceTest.java
index 7f73489f24..89ef76678a 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/RoleResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/RoleResourceTest.java
@@ -106,7 +106,7 @@ public void getRoleByInvalidUuidTest() {
@Test
public void createRoleTest() {
- initializeWithPermissions(Permissions.ACCESS_MANAGEMENT_CREATE);
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT);
Response response = jersey.target(V1_ROLE).request()
.header(X_API_KEY, apiKey)
@@ -125,7 +125,7 @@ public void createRoleTest() {
@Test
public void testCreateRoleAlreadyExists() {
- initializeWithPermissions(Permissions.ACCESS_MANAGEMENT_CREATE);
+ initializeWithPermissions(Permissions.ACCESS_MANAGEMENT);
Response response = jersey.target(V1_ROLE).request()
.header(X_API_KEY, apiKey)
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/TagResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/TagResourceTest.java
index 4ad09c5ca6..cbd816e584 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/TagResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/TagResourceTest.java
@@ -61,7 +61,7 @@ public class TagResourceTest extends ResourceTest {
@Test
public void getTagsTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.TAG_MANAGEMENT);
qm.createConfigProperty(
ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -147,7 +147,7 @@ public void getTagsTest() {
@Test
public void getTagsWithPaginationTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.TAG_MANAGEMENT);
for (int i = 0; i < 5; i++) {
qm.createTag("tag-" + (i + 1));
}
@@ -216,7 +216,7 @@ public void getTagsWithPaginationTest() {
@Test
public void getTagsWithFilterTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.TAG_MANAGEMENT);
qm.createTag("foo");
qm.createTag("bar");
@@ -242,7 +242,7 @@ public void getTagsWithFilterTest() {
@Test
public void getTagsSortByProjectCountTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.TAG_MANAGEMENT);
final var projectA = new Project();
projectA.setName("acme-app-a");
qm.persist(projectA);
@@ -375,7 +375,7 @@ public void deleteTagsWhenAssignedToProjectWithoutPortfolioManagementPermissionT
"title": "Tag operation failed",
"detail": "The tag(s) bar could not be deleted",
"errors": {
- "bar": "The tag is assigned to 1 project(s), but the authenticated principal is missing the PORTFOLIO_MANAGEMENT or PORTFOLIO_MANAGEMENT_UPDATE permission."
+ "bar": "The tag is assigned to 1 project(s), but the authenticated principal is missing the PORTFOLIO_MANAGEMENT permission."
}
}
""");
@@ -490,7 +490,7 @@ public void deleteTagsWhenAssignedToPolicyWithoutPolicyManagementPermissionTest(
"title": "Tag operation failed",
"detail": "The tag(s) bar could not be deleted",
"errors": {
- "bar": "The tag is assigned to 1 policies, but the authenticated principal is missing the POLICY_MANAGEMENT or POLICY_MANAGEMENT_UPDATE permission."
+ "bar": "The tag is assigned to 1 policies, but the authenticated principal is missing the POLICY_MANAGEMENT permission."
}
}
""");
@@ -502,7 +502,7 @@ public void deleteTagsWhenAssignedToPolicyWithoutPolicyManagementPermissionTest(
@Test
public void getTaggedProjectsTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PORTFOLIO_MANAGEMENT);
qm.createConfigProperty(
ACCESS_MANAGEMENT_ACL_ENABLED.getGroupName(),
ACCESS_MANAGEMENT_ACL_ENABLED.getPropertyName(),
@@ -559,7 +559,7 @@ public void getTaggedProjectsTest() {
@Test
public void getTaggedProjectsWithPaginationTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PORTFOLIO_MANAGEMENT);
final Tag tag = qm.createTag("foo");
for (int i = 0; i < 5; i++) {
@@ -619,7 +619,7 @@ public void getTaggedProjectsWithPaginationTest() {
@Test
public void getTaggedProjectsWithTagNotExistsTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PORTFOLIO_MANAGEMENT);
qm.createTag("foo");
final Response response = jersey.target(V1_TAG + "/foo/project")
.request()
@@ -632,7 +632,7 @@ public void getTaggedProjectsWithTagNotExistsTest() {
@Test
public void getTaggedProjectsWithNonLowerCaseTagNameTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PORTFOLIO_MANAGEMENT);
final Response response = jersey.target(V1_TAG + "/Foo/project")
.request()
.header(X_API_KEY, apiKey)
@@ -1284,7 +1284,7 @@ public void untagPoliciesWhenNotTaggedTest() {
@Test
public void getTagsForPolicyWithOrderingTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.TAG_MANAGEMENT, Permissions.POLICY_MANAGEMENT);
for (int i = 1; i < 5; i++) {
qm.createTag("Tag " + i);
}
@@ -1307,7 +1307,7 @@ public void getTagsForPolicyWithOrderingTest() {
@Test
public void getTagsForPolicyWithPolicyProjectsFilterTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.TAG_MANAGEMENT, Permissions.POLICY_MANAGEMENT);
for (int i = 1; i < 5; i++) {
qm.createTag("Tag " + i);
}
@@ -1333,7 +1333,7 @@ public void getTagsForPolicyWithPolicyProjectsFilterTest() {
@Test
public void getTagWithNonUuidNameTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.TAG_MANAGEMENT);
// NB: This is just to ensure that requests to /api/v1/tag/
// are not matched with the deprecated "getTagsForPolicy" endpoint.
// Once we implement an endpoint to request individual tags,
@@ -1400,7 +1400,7 @@ public void deleteTagsWhenAssignedToNotificationRuleWithoutSystemConfigurationPe
"title": "Tag operation failed",
"detail": "The tag(s) bar could not be deleted",
"errors": {
- "bar": "The tag is assigned to 1 notification rules, but the authenticated principal is missing the SYSTEM_CONFIGURATION or SYSTEM_CONFIGURATION_UPDATE permission."
+ "bar": "The tag is assigned to 1 notification rules, but the authenticated principal is missing the SYSTEM_CONFIGURATION permission."
}
}
""");
@@ -2076,7 +2076,7 @@ public void deleteTagsWhenAssignedToVulnerabilityWithoutVulnerabilityManagementP
"title": "Tag operation failed",
"detail": "The tag(s) bar could not be deleted",
"errors": {
- "bar": "The tag is assigned to 1 vulnerabilities, but the authenticated principal is missing the VULNERABILITY_MANAGEMENT or VULNERABILITY_MANAGEMENT_UPDATE permission."
+ "bar": "The tag is assigned to 1 vulnerabilities, but the authenticated principal is missing the VULNERABILITY_MANAGEMENT permission."
}
}
""");
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/TeamResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/TeamResourceTest.java
index 02b0dff16c..ea723abddb 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/TeamResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/TeamResourceTest.java
@@ -191,7 +191,7 @@ public void getTeamByInvalidUuidTest() {
@Test
public void getTeamSelfTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD, Permissions.PROJECT_CREATION_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE, Permissions.PORTFOLIO_MANAGEMENT);
var response = jersey.target(V1_TEAM + "/self").request().header(X_API_KEY, apiKey).get(Response.class);
Assert.assertEquals(200, response.getStatus());
final var json = parseJsonObject(response);
@@ -199,8 +199,8 @@ public void getTeamSelfTest() {
Assert.assertEquals(team.getUuid().toString(), json.getString("uuid"));
final var permissions = json.getJsonArray("permissions");
Assert.assertEquals(2, permissions.size());
- Assert.assertEquals(Permissions.BOM_UPLOAD.toString(), permissions.get(0).asJsonObject().getString("name"));
- Assert.assertEquals(Permissions.PROJECT_CREATION_UPLOAD.toString(), permissions.get(1).asJsonObject().getString("name"));
+ Assert.assertEquals(Permissions.BOM_CREATE.toString(), permissions.get(0).asJsonObject().getString("name"));
+ Assert.assertEquals(Permissions.PORTFOLIO_MANAGEMENT.toString(), permissions.get(1).asJsonObject().getString("name"));
// missing api-key
response = jersey.target(V1_TEAM + "/self").request().get(Response.class);
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/VexResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/VexResourceTest.java
index bd3c7fc15d..6d922642b8 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/VexResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/VexResourceTest.java
@@ -260,7 +260,7 @@ public void exportProjectAsCycloneDxAclTest() {
@Test
public void uploadVexInvalidJsonTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
final var project = new Project();
project.setName("acme-app");
@@ -308,7 +308,7 @@ public void uploadVexInvalidJsonTest() {
@Test
public void uploadVexInvalidXmlTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
final var project = new Project();
project.setName("acme-app");
@@ -654,7 +654,7 @@ public void exportVexWithDifferentVulnAnalysisValidJsonTest() {
@Test
public void uploadVexWithValidationModeDisabledTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
qm.createConfigProperty(
BOM_VALIDATION_MODE.getGroupName(),
@@ -699,7 +699,7 @@ public void uploadVexWithValidationModeDisabledTest() {
@Test
public void uploadVexWithValidationModeEnabledForTagsTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
qm.createConfigProperty(
BOM_VALIDATION_MODE.getGroupName(),
@@ -766,7 +766,7 @@ public void uploadVexWithValidationModeEnabledForTagsTest() {
@Test
public void uploadVexWithValidationModeDisabledForTagsTest() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
qm.createConfigProperty(
BOM_VALIDATION_MODE.getGroupName(),
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v1/ViolationAnalysisResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v1/ViolationAnalysisResourceTest.java
index 6e2a8ed98c..c81d442787 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v1/ViolationAnalysisResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v1/ViolationAnalysisResourceTest.java
@@ -75,7 +75,7 @@ public class ViolationAnalysisResourceTest extends ResourceTest {
@Test
public void retrieveAnalysisTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -135,7 +135,7 @@ public void retrieveAnalysisUnauthorizedTest() {
@Test
public void retrieveAnalysisComponentNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Response response = jersey.target(V1_VIOLATION_ANALYSIS)
.queryParam("component", UUID.randomUUID())
@@ -150,7 +150,7 @@ public void retrieveAnalysisComponentNotFoundTest() {
@Test
public void retrieveAnalysisViolationNotFoundTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -173,7 +173,7 @@ public void retrieveAnalysisViolationNotFoundTest() {
@Test
public void retrieveAnalysisAclTest() {
- initializeWithPermissions(Permissions.VIEW_POLICY_VIOLATION);
+ initializeWithPermissions(Permissions.PROJECT_READ, Permissions.POLICY_VIOLATION_READ);
enablePortfolioAccessControl();
final var project = new Project();
@@ -211,7 +211,7 @@ public void retrieveAnalysisAclTest() {
@Test
public void updateAnalysisCreateNewTest() throws Exception {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -271,7 +271,7 @@ public void updateAnalysisCreateNewTest() throws Exception {
@Test
public void updateAnalysisCreateNewWithEmptyRequestTest() throws Exception {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -321,7 +321,7 @@ public void updateAnalysisCreateNewWithEmptyRequestTest() throws Exception {
@Test
public void updateAnalysisUpdateExistingTest() throws Exception {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -389,7 +389,7 @@ public void updateAnalysisUpdateExistingTest() throws Exception {
@Test
public void updateAnalysisUpdateExistingNoChangesTest() throws Exception {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -437,7 +437,7 @@ public void updateAnalysisUpdateExistingNoChangesTest() throws Exception {
@Test
public void updateAnalysisUpdateExistingWithEmptyRequestTest() throws Exception {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -510,7 +510,7 @@ public void updateAnalysisUnauthorizedTest() {
@Test
public void updateAnalysisComponentNotFoundTest() {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
final var request = new ViolationAnalysisRequest(UUID.randomUUID().toString(),
UUID.randomUUID().toString(), ViolationAnalysisState.REJECTED, "Some comment", false);
@@ -526,7 +526,7 @@ public void updateAnalysisComponentNotFoundTest() {
@Test
public void updateAnalysisViolationNotFoundTest() {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
final Project project = qm.createProject("Acme Example", null, "1.0", null, null, null, null, false);
@@ -550,7 +550,7 @@ public void updateAnalysisViolationNotFoundTest() {
@Test
public void updateAnalysisAclTest() {
- initializeWithPermissions(Permissions.POLICY_VIOLATION_ANALYSIS);
+ initializeWithPermissions(Permissions.PROJECT_UPDATE, Permissions.POLICY_VIOLATION_UPDATE);
enablePortfolioAccessControl();
final var project = new Project();
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v2/MetricsResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v2/MetricsResourceTest.java
index 91fda35170..e0d67d5098 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v2/MetricsResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v2/MetricsResourceTest.java
@@ -48,7 +48,7 @@ public class MetricsResourceTest extends ResourceTest {
@Test
public void getCurrentPortfolioMetricsEmptyTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final Response response = jersey
@@ -97,7 +97,7 @@ public void getCurrentPortfolioMetricsEmptyTest() {
@Test
public void getCurrentPortfolioMetricsAclTest() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
+ initializeWithPermissions(Permissions.PROJECT_READ);
enablePortfolioAccessControl();
final var accessibleProjectA = new Project();
@@ -189,7 +189,6 @@ public void getCurrentPortfolioMetricsAclTest() {
@Test
public void getVulnerabilityMetricsPaginated() {
- initializeWithPermissions(Permissions.VIEW_PORTFOLIO);
enablePortfolioAccessControl();
for (int i = 1; i < 4; i++) {
@@ -264,4 +263,4 @@ public void getVulnerabilityMetricsPaginated() {
}
""");
}
-}
\ No newline at end of file
+}
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v2/TeamsResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v2/TeamsResourceTest.java
index ad9f50b2e3..e181ad2bc0 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v2/TeamsResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v2/TeamsResourceTest.java
@@ -112,8 +112,8 @@ public void createTeamShouldCreateTeam() {
initializeWithPermissions(Permissions.ACCESS_MANAGEMENT);
qm.createPermission(
- Permissions.VIEW_PORTFOLIO.name(),
- Permissions.VIEW_PORTFOLIO.getDescription());
+ Permissions.PORTFOLIO_MANAGEMENT.name(),
+ Permissions.PORTFOLIO_MANAGEMENT.getDescription());
final Response response = jersey.target("/teams")
.request()
@@ -122,7 +122,7 @@ public void createTeamShouldCreateTeam() {
{
"name": "foo",
"permissions": [
- "VIEW_PORTFOLIO"
+ "PORTFOLIO_MANAGEMENT"
]
}
"""));
@@ -134,7 +134,7 @@ public void createTeamShouldCreateTeam() {
final Team team = qm.getTeam("foo");
assertThat(team).isNotNull();
- assertThat(team.getPermissions()).extracting(Permission::getName).containsOnly("VIEW_PORTFOLIO");
+ assertThat(team.getPermissions()).extracting(Permission::getName).containsOnly("PORTFOLIO_MANAGEMENT");
}
@Test
@@ -150,7 +150,7 @@ public void createTeamShouldReturnConflictWhenAlreadyExists() {
{
"name": "foo",
"permissions": [
- "VIEW_PORTFOLIO"
+ "PORTFOLIO_MANAGEMENT"
]
}
"""));
@@ -178,11 +178,11 @@ public void getTeamShouldReturnTeam() {
final Team team = qm.createTeam("foo");
team.setPermissions(List.of(
qm.createPermission(
- Permissions.VIEW_PORTFOLIO.name(),
- Permissions.VIEW_PORTFOLIO.getDescription()),
+ Permissions.PORTFOLIO_MANAGEMENT.name(),
+ Permissions.PORTFOLIO_MANAGEMENT.getDescription()),
qm.createPermission(
- Permissions.VIEW_VULNERABILITY.name(),
- Permissions.VIEW_VULNERABILITY.getDescription())));
+ Permissions.VULNERABILITY_MANAGEMENT.name(),
+ Permissions.VULNERABILITY_MANAGEMENT.getDescription())));
final Response response = jersey.target("/teams/foo")
.request()
@@ -193,8 +193,8 @@ public void getTeamShouldReturnTeam() {
{
"name": "foo",
"permissions": [
- "VIEW_PORTFOLIO",
- "VIEW_VULNERABILITY"
+ "PORTFOLIO_MANAGEMENT",
+ "VULNERABILITY_MANAGEMENT"
]
}
""");
@@ -586,4 +586,4 @@ public void deleteTeamMembershipShouldReturnNotFoundWhenMembershipDoesNotExist()
""");
}
-}
\ No newline at end of file
+}
diff --git a/apiserver/src/test/java/org/dependencytrack/resources/v2/WorkflowsResourceTest.java b/apiserver/src/test/java/org/dependencytrack/resources/v2/WorkflowsResourceTest.java
index 5e9edbf004..951da60ff3 100644
--- a/apiserver/src/test/java/org/dependencytrack/resources/v2/WorkflowsResourceTest.java
+++ b/apiserver/src/test/java/org/dependencytrack/resources/v2/WorkflowsResourceTest.java
@@ -47,7 +47,7 @@ public class WorkflowsResourceTest extends ResourceTest {
@Test
public void getWorkflowStatusOk() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
UUID uuid = UUID.randomUUID();
WorkflowState workflowState1 = new WorkflowState();
@@ -104,7 +104,7 @@ public void getWorkflowStatusOk() {
@Test
public void getWorkflowStatusNotFound() {
- initializeWithPermissions(Permissions.BOM_UPLOAD);
+ initializeWithPermissions(Permissions.BOM_CREATE);
WorkflowState workflowState1 = new WorkflowState();
workflowState1.setParent(null);
@@ -130,4 +130,4 @@ public void getWorkflowStatusNotFound() {
}
""");
}
-}
\ No newline at end of file
+}
diff --git a/persistence-migration/src/main/resources/migration/changelog-main.xml b/persistence-migration/src/main/resources/migration/changelog-main.xml
index e55e42262c..9b8fd7510e 100644
--- a/persistence-migration/src/main/resources/migration/changelog-main.xml
+++ b/persistence-migration/src/main/resources/migration/changelog-main.xml
@@ -13,5 +13,6 @@
+
\ No newline at end of file
diff --git a/persistence-migration/src/main/resources/migration/changelog-v5.7.0.xml b/persistence-migration/src/main/resources/migration/changelog-v5.7.0.xml
new file mode 100644
index 0000000000..be00b16ae5
--- /dev/null
+++ b/persistence-migration/src/main/resources/migration/changelog-v5.7.0.xml
@@ -0,0 +1,364 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DO $$
+ DECLARE
+ -- List of tables to update
+ referencing_tables TEXT[] := ARRAY['TEAMS_PERMISSIONS', 'USERS_PERMISSIONS', 'ROLES_PERMISSIONS'];
+ tbl_name TEXT;
+ id_col TEXT;
+ BEGIN
+ -- Loop through our arrays by index
+ FOREACH tbl_name IN ARRAY referencing_tables
+ LOOP
+ id_col := regexp_replace(tbl_name, '([A-Z]+?)S_PERMISSIONS', '\1') || '_ID';
+
+ -- Build dynamic INSERT statement
+ EXECUTE format($fmt$
+ -- Input mapping of old permission names to their updated counterparts
+ WITH cte_permission_map (old_names, new_names) AS (
+ VALUES
+ ('ACCESS_MANAGEMENT%%', ARRAY['ACCESS_MANAGEMENT']),
+ ('BOM_UPLOAD', ARRAY['BOM_CREATE', 'BOM_READ']),
+ ('POLICY_MANAGEMENT%%', ARRAY['POLICY_MANAGEMENT', 'POLICY_VIOLATION_CREATE']),
+ ('POLICY_VIOLATION_ANALYSIS', ARRAY['POLICY_VIOLATION_UPDATE']),
+ ('PORTFOLIO_MANAGEMENT%%', ARRAY['PORTFOLIO_MANAGEMENT', 'PROJECT_UPDATE', 'PROJECT_DELETE']),
+ ('PROJECT_CREATION_UPLOAD', ARRAY['PORTFOLIO_MANAGEMENT', 'BOM_CREATE', 'BOM_READ']),
+ ('SYSTEM_CONFIGURATION%%', ARRAY['SYSTEM_CONFIGURATION', 'NOTIFICATION_RULE_MANAGEMENT']),
+ ('TAG_MANAGEMENT%%', ARRAY['TAG_MANAGEMENT']),
+ ('VIEW_BADGES', ARRAY['BADGES_READ']),
+ ('VIEW_POLICY_VIOLATION', ARRAY['POLICY_VIOLATION_READ']),
+ ('VIEW_PORTFOLIO', ARRAY['PROJECT_READ']),
+ ('VIEW_VULNERABILITY', ARRAY['FINDING_READ']),
+ ('VULNERABILITY_ANALYSIS', ARRAY['VULNERABILITY_MANAGEMENT']),
+ ('VULNERABILITY_ANALYSIS_CREATE', ARRAY['FINDING_CREATE']),
+ ('VULNERABILITY_ANALYSIS_READ', ARRAY['FINDING_READ']),
+ ('VULNERABILITY_ANALYSIS_UPDATE', ARRAY['FINDING_UPDATE']),
+ ('VULNERABILITY_MANAGEMENT%%', ARRAY['VULNERABILITY_MANAGEMENT'])
+ ),
+ -- Get IDs of entities mapped to old permissions
+ cte_entities AS (
+ SELECT t.%I AS id
+ FROM %I AS t
+ INNER JOIN "PERMISSION" AS p
+ ON p."ID" = t."PERMISSION_ID"
+ INNER JOIN cte_permission_map
+ ON p."NAME" LIKE cte_permission_map.old_names
+ ),
+ -- Get IDs of new permissions
+ cte_new_permissions AS (
+ SELECT p_new."ID" AS id
+ FROM cte_permission_map
+ INNER JOIN "PERMISSION_NEW" AS p_new
+ ON p_new."NAME" = ANY(cte_permission_map.new_names)
+ )
+ INSERT INTO %I (%I, "PERMISSION_ID")
+ SELECT cte_entities.id, cte_new_permissions.id
+ FROM cte_entities, cte_new_permissions
+ ON CONFLICT DO NOTHING;
+ $fmt$, id_col, tbl_name, tbl_name || '_NEW', id_col
+ );
+
+ RAISE NOTICE 'Updated table "%" on column "%" → new permission', tbl_name, id_col;
+ END LOOP;
+ END $$
+ LANGUAGE plpgsql;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ALTER TABLE "PERMISSION" RENAME CONSTRAINT "PERMISSION_NEW_PK" TO "PERMISSION_PK";
+
+ ALTER TABLE "USERS_PERMISSIONS" RENAME CONSTRAINT "USERS_PERMISSIONS_NEW_PK" TO "USERS_PERMISSIONS_PK";
+ ALTER TABLE "USERS_PERMISSIONS" RENAME CONSTRAINT "USERS_PERMISSIONS_NEW_USER_FK" TO "USERS_PERMISSIONS_USER_FK";
+ ALTER TABLE "USERS_PERMISSIONS" RENAME CONSTRAINT "USERS_PERMISSIONS_NEW_PERMISSION_FK" TO "USERS_PERMISSIONS_PERMISSION_FK";
+
+ ALTER TABLE "TEAMS_PERMISSIONS" RENAME CONSTRAINT "TEAMS_PERMISSIONS_NEW_PK" TO "TEAMS_PERMISSIONS_PK";
+ ALTER TABLE "TEAMS_PERMISSIONS" RENAME CONSTRAINT "TEAMS_PERMISSIONS_NEW_TEAM_FK" TO "TEAMS_PERMISSIONS_TEAM_FK";
+ ALTER TABLE "TEAMS_PERMISSIONS" RENAME CONSTRAINT "TEAMS_PERMISSIONS_NEW_PERMISSION_FK" TO "TEAMS_PERMISSIONS_PERMISSION_FK";
+
+ ALTER TABLE "ROLES_PERMISSIONS" RENAME CONSTRAINT "ROLES_PERMISSIONS_NEW_PK" TO "ROLES_PERMISSIONS_PK";
+ ALTER TABLE "ROLES_PERMISSIONS" RENAME CONSTRAINT "ROLES_PERMISSIONS_NEW_ROLE_FK" TO "ROLES_PERMISSIONS_ROLE_FK";
+ ALTER TABLE "ROLES_PERMISSIONS" RENAME CONSTRAINT "ROLES_PERMISSIONS_NEW_PERMISSION_FK" TO "ROLES_PERMISSIONS_PERMISSION_FK";
+
+
+
+
+
+
+
+
+ DROP TRIGGER IF EXISTS trigger_effective_permissions_mx_on_teams_permissions_insert ON "TEAMS_PERMISSIONS";
+ DROP TRIGGER IF EXISTS trigger_effective_permissions_mx_on_teams_permissions_delete ON "TEAMS_PERMISSIONS";
+ DROP TRIGGER IF EXISTS trigger_effective_permissions_mx_on_teams_permissions_update ON "TEAMS_PERMISSIONS";
+
+ -- INSERT trigger for TEAMS_PERMISSIONS
+ CREATE TRIGGER trigger_effective_permissions_mx_on_teams_permissions_insert
+ AFTER INSERT ON "TEAMS_PERMISSIONS"
+ REFERENCING NEW TABLE AS new_table
+ FOR EACH STATEMENT
+ EXECUTE FUNCTION effective_permissions_mx_on_insert();
+
+ -- DELETE trigger for TEAMS_PERMISSIONS
+ CREATE TRIGGER trigger_effective_permissions_mx_on_teams_permissions_delete
+ AFTER DELETE ON "TEAMS_PERMISSIONS"
+ REFERENCING OLD TABLE AS old_table
+ FOR EACH STATEMENT
+ EXECUTE FUNCTION effective_permissions_mx_on_delete();
+
+ -- UPDATE trigger for TEAMS_PERMISSIONS
+ CREATE TRIGGER trigger_effective_permissions_mx_on_teams_permissions_update
+ AFTER UPDATE ON "TEAMS_PERMISSIONS"
+ REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table
+ FOR EACH STATEMENT
+ EXECUTE FUNCTION effective_permissions_mx_on_update();
+
+ DROP TRIGGER IF EXISTS trigger_effective_permissions_mx_on_roles_permissions_insert ON "ROLES_PERMISSIONS";
+ DROP TRIGGER IF EXISTS trigger_effective_permissions_mx_on_roles_permissions_delete ON "ROLES_PERMISSIONS";
+ DROP TRIGGER IF EXISTS trigger_effective_permissions_mx_on_roles_permissions_update ON "ROLES_PERMISSIONS";
+
+ -- INSERT trigger for ROLES_PERMISSIONS
+ CREATE TRIGGER trigger_effective_permissions_mx_on_roles_permissions_insert
+ AFTER INSERT ON "ROLES_PERMISSIONS"
+ REFERENCING NEW TABLE AS new_table
+ FOR EACH STATEMENT
+ EXECUTE FUNCTION role_effective_permissions_mx_on_insert();
+
+ -- DELETE trigger for ROLES_PERMISSIONS
+ CREATE TRIGGER trigger_effective_permissions_mx_on_roles_permissions_delete
+ AFTER DELETE ON "ROLES_PERMISSIONS"
+ REFERENCING OLD TABLE AS old_table
+ FOR EACH STATEMENT
+ EXECUTE FUNCTION role_effective_permissions_mx_on_delete();
+
+ -- UPDATE trigger for ROLES_PERMISSIONS
+ CREATE TRIGGER trigger_effective_permissions_mx_on_roles_permissions_update
+ AFTER UPDATE ON "ROLES_PERMISSIONS"
+ REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table
+ FOR EACH STATEMENT
+ EXECUTE FUNCTION role_effective_permissions_mx_on_update();
+
+
+
+
+ DROP TRIGGER IF EXISTS trigger_prevent_direct_effective_permissions_writes ON "USER_PROJECT_EFFECTIVE_PERMISSIONS";
+
+ -- Backfill the USER_PROJECT_EFFECTIVE_PERMISSIONS table for existing PROJECT_ACCESS_TEAMS entries
+ DO $$
+ BEGIN
+ PERFORM recalc_user_project_effective_permissions((SELECT ARRAY_AGG("ID") FROM "PROJECT"));
+ END $$
+ LANGUAGE plpgsql;
+
+ -- Prevent direct inserts/updates/writes to USER_PROJECT_EFFECTIVE_PERMISSIONS
+ CREATE TRIGGER trigger_prevent_direct_effective_permissions_writes
+ BEFORE DELETE OR INSERT OR UPDATE ON "USER_PROJECT_EFFECTIVE_PERMISSIONS"
+ FOR EACH STATEMENT
+ EXECUTE FUNCTION prevent_direct_effective_permissions_writes();
+
+ DROP FUNCTION IF EXISTS has_user_project_access(BIGINT, BIGINT);
+
+
+
diff --git a/persistence-migration/src/main/resources/migration/procedures/function_has-user-project-access.sql b/persistence-migration/src/main/resources/migration/procedures/function_has-user-project-access.sql
index e021b538fe..b94bdef09d 100644
--- a/persistence-migration/src/main/resources/migration/procedures/function_has-user-project-access.sql
+++ b/persistence-migration/src/main/resources/migration/procedures/function_has-user-project-access.sql
@@ -4,6 +4,7 @@
CREATE OR REPLACE FUNCTION has_user_project_access(
project_id BIGINT
, user_id BIGINT
+, permissions TEXT[] DEFAULT '{PROJECT_READ}'
) RETURNS BOOL
LANGUAGE "sql"
PARALLEL SAFE
@@ -17,6 +18,6 @@ SELECT EXISTS(
ON ph."PARENT_PROJECT_ID" = upep."PROJECT_ID"
WHERE ph."CHILD_PROJECT_ID" = project_id
AND upep."USER_ID" = user_id
- AND upep."PERMISSION_NAME" = 'VIEW_PORTFOLIO'
+ AND upep."PERMISSION_NAME" = ALL(permissions)
)
$$;
\ No newline at end of file