Incorporated the review comments.

Signed-off-by: Gaurav <gaurav.sahay@in.bosch.com>
This commit is contained in:
Gaurav
2016-08-08 13:24:12 +02:00
27 changed files with 428 additions and 306 deletions

View File

@@ -484,12 +484,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
throwMetadataKeyAlreadyExists(metadata.getId().getKey());
}
final DistributionSet latestDistributionSet = findDistributionSetById(metadata.getDistributionSet().getId());
// merge base distribution set so optLockRevision gets updated and audit
// log written because
// modifying metadata is modifying the base distribution set itself for
// auditing purposes.
entityManager.merge((JpaDistributionSet) latestDistributionSet).setLastModifiedAt(0L);
touch(metadata.getDistributionSet());
return distributionSetMetadataRepository.save(metadata);
}
@@ -504,7 +499,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
for (final JpaDistributionSetMetadata distributionSetMetadata : metadata) {
checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId());
}
metadata.forEach(m -> entityManager.merge((JpaDistributionSet) findDistributionSetById(m.getDistributionSet().getId())).setLastModifiedAt(0L));
metadata.forEach(m -> touch(m.getDistributionSet()));
return new ArrayList<>(
(Collection<? extends DistributionSetMetadata>) distributionSetMetadataRepository.save(metadata));
@@ -520,8 +515,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
findOne(metadata.getDistributionSet(), metadata.getKey());
// touch it to update the lock revision because we are modifying the
// DS indirectly
final DistributionSet latestDistributionSet = findDistributionSetById(metadata.getDistributionSet().getId());
entityManager.merge((JpaDistributionSet) latestDistributionSet).setLastModifiedAt(0L);
touch(metadata.getDistributionSet());;
return distributionSetMetadataRepository.save(metadata);
}
@@ -529,11 +523,23 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying
public void deleteDistributionSetMetadata(final DistributionSet distributionSet, final String key) {
final DistributionSet latestDistributionSet = findDistributionSetById(distributionSet.getId());
entityManager.merge((JpaDistributionSet) latestDistributionSet).setLastModifiedAt(0L);
touch(distributionSet);
distributionSetMetadataRepository.delete(new DsMetadataCompositeKey(distributionSet, key));
}
/**
* Method to get the latest distribution set based on ds ID after the metadata changes for that distribution set.
* @param distributionSet Distribution set
*/
private void touch(final DistributionSet distributionSet) {
final DistributionSet latestDistributionSet = findDistributionSetById(distributionSet.getId());
// merge base distribution set so optLockRevision gets updated and audit
// log written because
// modifying metadata is modifying the base distribution set itself for
// auditing purposes.
entityManager.merge((JpaDistributionSet) latestDistributionSet).setLastModifiedAt(0L);
}
@Override
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
final Pageable pageable) {

View File

@@ -1,42 +1,47 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa.model;
import org.eclipse.persistence.descriptors.DescriptorEvent;
/**
*
* Holds details of action(Create/Update) and @link{DescriptorEvent}.
*
*/
public class DescriptorEventDetails {
enum ActionType {
CREATE, UPDATE;
}
private DescriptorEvent descriptorEvent;
private ActionType actiontype;
public DescriptorEventDetails(ActionType actionType,
DescriptorEvent descriptorEvent) {
this.descriptorEvent = descriptorEvent;
this.actiontype = actionType;
}
public DescriptorEvent getDescriptorEvent() {
return descriptorEvent;
}
public ActionType getActiontype() {
return actiontype;
}
}
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa.model;
import org.eclipse.persistence.descriptors.DescriptorEvent;
/**
*
* Holds details of action(Create/Update) and @link{DescriptorEvent}.
*
*/
public class DescriptorEventDetails {
enum ActionType {
CREATE, UPDATE;
}
private final DescriptorEvent descriptorEvent;
private final ActionType actiontype;
/**
* Constructor
* @param actionType Action type
* @param descriptorEvent Descriptor Event
*/
public DescriptorEventDetails(final ActionType actionType,
final DescriptorEvent descriptorEvent) {
this.descriptorEvent = descriptorEvent;
this.actiontype = actionType;
}
public DescriptorEvent getDescriptorEvent() {
return descriptorEvent;
}
public ActionType getActiontype() {
return actiontype;
}
}

View File

@@ -1,42 +1,53 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa.model.helper;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.queries.UpdateObjectQuery;
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
public static <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
final Class<T> clazz, final DescriptorEvent event) {
final T rolloutGroup = clazz.cast(event.getObject());
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery())
.getObjectChangeSet();
return changeSet
.getChanges()
.stream()
.filter(record -> record instanceof DirectToFieldChangeRecord)
.map(record -> (DirectToFieldChangeRecord) record)
.collect(
Collectors.toMap(
record -> record.getAttribute(),
record -> new AbstractPropertyChangeEvent<T>(
rolloutGroup, null).new Values(record
.getOldValue(), record.getNewValue())));
}
}
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa.model.helper;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.queries.UpdateObjectQuery;
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
/**
*Helper class to get the change set for the property changes in the Entity.
*
* @param <T>
*/
public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
/**
* To get the map of entity property change set
* @param clazz
* @param event
* @return the map of the changeSet
*/
public static <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
final Class<T> clazz, final DescriptorEvent event) {
final T rolloutGroup = clazz.cast(event.getObject());
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery())
.getObjectChangeSet();
return changeSet
.getChanges()
.stream()
.filter(record -> record instanceof DirectToFieldChangeRecord)
.map(record -> (DirectToFieldChangeRecord) record)
.collect(
Collectors.toMap(
record -> record.getAttribute(),
record -> new AbstractPropertyChangeEvent<T>(
rolloutGroup, null).new Values(record
.getOldValue(), record.getNewValue())));
}
}

View File

@@ -1,63 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa;
import static org.fest.assertions.Assertions.assertThat;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.access.prepost.PreAuthorize;
public class MethodSecurityUtil {
private static final Set<String> METHOD_SECURITY_EXCLUSION = new HashSet<>();
static {
METHOD_SECURITY_EXCLUSION.add("equals");
METHOD_SECURITY_EXCLUSION.add("toString");
METHOD_SECURITY_EXCLUSION.add("hashCode");
METHOD_SECURITY_EXCLUSION.add("clone");
METHOD_SECURITY_EXCLUSION.add("setEnvironment");
// this method shouldn't be public on the DeploymentManagemeht but it is
METHOD_SECURITY_EXCLUSION.add("setOverrideObsoleteUpdateActions");
METHOD_SECURITY_EXCLUSION.add("isOverrideObsoleteUpdateActions");
// this method must be public accessible without security because it's
// necessary to acccess
// the security-token of a target without being authenticated because
// the security-token is
// the authentication process
// ControllerManagement#getSecurityTokenByControllerId()
METHOD_SECURITY_EXCLUSION.add("getSecurityTokenByControllerId");
}
/**
* asserts that the given methods are annotated with the
* {@link PreAuthorize} annotation for security. Inherited methods are not
* checked. The following methods are excluded due inherited from
* {@link Object}, like equals() or toString().
*
* @param clazz
* the class to retrieve the public declared methods
*/
public static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class<?> clazz) {
final Method[] declaredMethods = clazz.getDeclaredMethods();
for (final Method method : declaredMethods) {
if (!METHOD_SECURITY_EXCLUSION.contains(method.getName()) && !method.isSynthetic()
&& Modifier.isPublic(method.getModifiers())) {
final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
assertThat(annotation).as(
"The public method " + method.getName() + " is not annoated with @PreAuthorize, security leak?")
.isNotNull();
}
}
}
}

View File

@@ -14,10 +14,10 @@ import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Random;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.repository.report.model.TenantUsage;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.junit.Test;
@@ -30,15 +30,6 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("System Management")
public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB {
@Test
@Description("Ensures that you can create a tenant without setting the necessary security context which holds a current tenant")
public void createInitialTenantWithoutSecurityContext() {
securityRule.clear();
final String tenantToBeCreated = "newTenantToCreate";
final TenantMetaData tenantMetadata = systemManagement.getTenantMetadata(tenantToBeCreated);
assertThat(tenantMetadata).isNotNull();
}
@Test
@Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in")
public void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() throws Exception {
@@ -109,26 +100,27 @@ public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB
for (int i = 0; i < tenants; i++) {
final String tenantname = "tenant" + i;
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname), () -> {
systemManagement.getTenantMetadata(tenantname);
if (artifactSize > 0) {
createTestArtifact(random);
createDeletedTestArtifact(random);
}
if (targets > 0) {
final List<Target> createdTargets = createTestTargets(targets);
if (updates > 0) {
for (int x = 0; x < updates; x++) {
final DistributionSet ds = testdataFactory.createDistributionSet("to be deployed" + x,
true);
deploymentManagement.assignDistributionSet(ds, createdTargets);
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname, true, true,
SpringEvalExpressions.SYSTEM_ROLE), () -> {
systemManagement.getTenantMetadata(tenantname);
if (artifactSize > 0) {
createTestArtifact(random);
createDeletedTestArtifact(random);
}
}
}
if (targets > 0) {
final List<Target> createdTargets = createTestTargets(targets);
if (updates > 0) {
for (int x = 0; x < updates; x++) {
final DistributionSet ds = testdataFactory
.createDistributionSet("to be deployed" + x, true);
return null;
});
deploymentManagement.assignDistributionSet(ds, createdTargets);
}
}
}
return null;
});
}
return random;