Add actions contxt management (#2680)

* based on TARGET permissions - action is accessible iff it its target is accessible
* add some more (id) serch fields
* (backward incompatible) software module search supports now search by name (type.name) and the old search by type (indead by type key) is now with type.key

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-09-19 15:47:20 +03:00
committed by GitHub
parent dce133dfae
commit 8bdcc51985
2 changed files with 57 additions and 2 deletions

View File

@@ -64,12 +64,12 @@ public class DefaultAccessController<A extends Enum<A> & RsqlQueryField, T> impl
return Optional.empty();
}
return Optional.ofNullable(getScopes(operation)) // if get scopes returns null, no scopes return no spec - all entities are accessible
return Optional.ofNullable(getScopes(operation)) // if "get scopes" returns null, no scopes return no spec - all entities are accessible
.map(scopes -> // to RSQL
scopes.size() == 1
? scopes.get(0) // single scope
: "(" + String.join(") or (", scopes) + ")") // join multiple scopes with 'or' - union
.map(scope -> RsqlUtility.getInstance().buildRsqlSpecification(scope, rsqlQueryFieldType));
.map(rsql -> RsqlUtility.getInstance().buildRsqlSpecification(rsql, rsqlQueryFieldType));
}
@Override

View File

@@ -9,13 +9,19 @@
*/
package org.eclipse.hawkbit.repository.jpa.acm;
import java.util.List;
import lombok.Getter;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.DistributionSetFields;
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
import org.eclipse.hawkbit.repository.RsqlQueryField;
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields;
import org.eclipse.hawkbit.repository.TagFields;
import org.eclipse.hawkbit.repository.TargetFields;
import org.eclipse.hawkbit.repository.TargetTypeFields;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
@@ -36,6 +42,13 @@ public class DefaultAccessControllerConfiguration {
return new DefaultAccessController<>(TargetFields.class, SpPermission.TARGET);
}
// after adding support for internal action field search support it add matchIfMissing = true
@Bean
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.action.enabled", havingValue = "true", matchIfMissing = false)
AccessController<JpaAction> actionAccessController() {
return new DefaultAccessController<>(ActionFieldsInternal.class, SpPermission.TARGET);
}
@Bean
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.target-type.enabled", havingValue = "true")
AccessController<JpaTargetType> targetTypeAccessController() {
@@ -65,4 +78,46 @@ public class DefaultAccessControllerConfiguration {
AccessController<JpaDistributionSetType> distributionSetTypeAccessController() {
return new DefaultAccessController<>(DistributionSetTypeFields.class, SpPermission.DISTRIBUTION_SET_TYPE);
}
// contains the same fields as TargetFields, but with "target." prefix for JPA queries in order to be applied to JpaAction repository
@Getter
public enum ActionFieldsInternal implements RsqlQueryField {
ID("controllerId"),
NAME("name"),
DESCRIPTION("description"),
CREATEDAT("createdAt"),
CREATEDBY("createdBy"),
LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"),
CONTROLLERID("controllerId"),
UPDATESTATUS("updateStatus"),
IPADDRESS("address"),
ATTRIBUTE("controllerAttributes"),
GROUP("group"),
ASSIGNEDDS("assignedDistributionSet",
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName()),
INSTALLEDDS("installedDistributionSet",
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName()),
TAG("tags", TagFields.NAME.getJpaEntityFieldName()),
LASTCONTROLLERREQUESTAT("lastTargetQuery"),
METADATA("metadata"),
TARGETTYPE("targetType",
TargetTypeFields.ID.getJpaEntityFieldName(),
TargetTypeFields.KEY.getJpaEntityFieldName(),
TargetTypeFields.NAME.getJpaEntityFieldName());
private final String jpaEntityFieldName;
private final List<String> subEntityAttributes;
ActionFieldsInternal(final String jpaEntityFieldName, final String... subEntityAttributes) {
this.jpaEntityFieldName = "target." + jpaEntityFieldName;
this.subEntityAttributes = List.of(subEntityAttributes);
}
@Override
public boolean isMap() {
return this == ATTRIBUTE || this == METADATA;
}
}
}