Migrated common artifact repo funtions into abstract class. (#666)
* Migrated common art repo funtions into abstract class. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove dead code from permission util. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove dead code. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix typo. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix typo. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix test. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix stats resource. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -8,29 +8,18 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.artifact.repository;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
/**
|
||||
@@ -46,12 +35,8 @@ import com.google.common.io.Files;
|
||||
* SHA1-hash {@code (/basepath/[two digit sha1]/[two digit sha1])}.
|
||||
*/
|
||||
@Validated
|
||||
public class ArtifactFilesystemRepository implements ArtifactRepository {
|
||||
public class ArtifactFilesystemRepository extends AbstractArtifactRepository {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ArtifactFilesystemRepository.class);
|
||||
|
||||
private static final String TEMP_FILE_PREFIX = "tmp";
|
||||
private static final String TEMP_FILE_SUFFIX = "artifactrepo";
|
||||
private final ArtifactFilesystemProperties artifactResourceProperties;
|
||||
|
||||
/**
|
||||
@@ -65,33 +50,6 @@ public class ArtifactFilesystemRepository implements ArtifactRepository {
|
||||
this.artifactResourceProperties = artifactResourceProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArtifactFilesystem store(final String tenant, final InputStream content, final String filename,
|
||||
final String contentType) {
|
||||
return store(tenant, content, filename, contentType, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
// suppress warning, of not strong enough hashing algorithm, SHA-1 and MD5
|
||||
// is not used security related
|
||||
@SuppressWarnings("squid:S2070")
|
||||
public ArtifactFilesystem store(final String tenant, final InputStream content, final String filename,
|
||||
final String contentType, final DbArtifactHash hash) {
|
||||
|
||||
final MessageDigest mdSHA1;
|
||||
final MessageDigest mdMD5;
|
||||
try {
|
||||
mdSHA1 = MessageDigest.getInstance("SHA1");
|
||||
mdMD5 = MessageDigest.getInstance("MD5");
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
throw new ArtifactStoreException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
final File file = createTempFile();
|
||||
final AbstractDbArtifact artifact = store(content, contentType, hash, mdSHA1, mdMD5, file);
|
||||
return renameFileToSHA1Naming(tenant, file, artifact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBySha1(final String tenant, final String sha1Hash) {
|
||||
FileUtils.deleteQuietly(getFile(tenant, sha1Hash));
|
||||
@@ -107,75 +65,24 @@ public class ArtifactFilesystemRepository implements ArtifactRepository {
|
||||
return new ArtifactFilesystem(file, sha1, new DbArtifactHash(sha1, null), file.length(), null);
|
||||
}
|
||||
|
||||
private AbstractDbArtifact store(final InputStream content, final String contentType, final DbArtifactHash hash,
|
||||
final MessageDigest mdSHA1, final MessageDigest mdMD5, final File file) {
|
||||
AbstractDbArtifact artifact;
|
||||
try (final DigestOutputStream outputstream = openFileOutputStream(file, mdSHA1, mdMD5)) {
|
||||
final long artifactSize = ByteStreams.copy(content, outputstream);
|
||||
outputstream.flush();
|
||||
final String sha1Hash = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest());
|
||||
final String md5Hash = BaseEncoding.base16().lowerCase().encode(mdMD5.digest());
|
||||
|
||||
artifact = new ArtifactFilesystem(file, sha1Hash, new DbArtifactHash(sha1Hash, md5Hash), artifactSize,
|
||||
contentType);
|
||||
|
||||
checkHashes(artifact, hash);
|
||||
} catch (final IOException e) {
|
||||
throw new ArtifactStoreException(e.getMessage(), e);
|
||||
} catch (final HashNotMatchException e) {
|
||||
if (!file.delete()) {
|
||||
LOG.error("Could not delete temp file {}", file);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return artifact;
|
||||
@Override
|
||||
protected AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16,
|
||||
final String contentType, final File file) throws IOException {
|
||||
return renameFileToSHA1Naming(tenant, file, new ArtifactFilesystem(file, sha1Hash16,
|
||||
new DbArtifactHash(sha1Hash16, mdMD5Hash16), file.length(), contentType));
|
||||
}
|
||||
|
||||
private ArtifactFilesystem renameFileToSHA1Naming(final String tenant, final File file,
|
||||
final AbstractDbArtifact artifact) {
|
||||
final AbstractDbArtifact artifact) throws IOException {
|
||||
final File fileSHA1Naming = getFile(tenant, artifact.getHashes().getSha1());
|
||||
final ArtifactFilesystem fileSystemArtifact = new ArtifactFilesystem(fileSHA1Naming, artifact.getArtifactId(),
|
||||
artifact.getHashes(), artifact.getSize(), artifact.getContentType());
|
||||
if (fileSHA1Naming.exists()) {
|
||||
FileUtils.deleteQuietly(file);
|
||||
} else {
|
||||
try {
|
||||
Files.move(file, fileSHA1Naming);
|
||||
} catch (final IOException e) {
|
||||
throw new ArtifactStoreException("Could not store the file " + fileSHA1Naming, e);
|
||||
}
|
||||
Files.move(file, fileSHA1Naming);
|
||||
}
|
||||
|
||||
if (!file.delete()) {
|
||||
LOG.debug("Could not delete temp file {}", file);
|
||||
}
|
||||
|
||||
return fileSystemArtifact;
|
||||
}
|
||||
|
||||
private AbstractDbArtifact checkHashes(final AbstractDbArtifact artifact, final DbArtifactHash hash) {
|
||||
if (hash == null) {
|
||||
return artifact;
|
||||
}
|
||||
if (hash.getSha1() != null && !artifact.getHashes().getSha1().equals(hash.getSha1())) {
|
||||
throw new HashNotMatchException("The given sha1 hash " + hash.getSha1()
|
||||
+ " does not match with the calcualted sha1 hash " + artifact.getHashes().getSha1(),
|
||||
HashNotMatchException.SHA1);
|
||||
}
|
||||
if (hash.getMd5() != null && !artifact.getHashes().getMd5().equals(hash.getMd5())) {
|
||||
throw new HashNotMatchException("The given md5 hash " + hash.getMd5()
|
||||
+ " does not match with the calcualted md5 hash " + artifact.getHashes().getMd5(),
|
||||
HashNotMatchException.MD5);
|
||||
}
|
||||
return artifact;
|
||||
}
|
||||
|
||||
private File createTempFile() {
|
||||
try {
|
||||
return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
|
||||
} catch (final IOException e) {
|
||||
throw new ArtifactStoreException("Cannot create tempfile", e);
|
||||
}
|
||||
return new ArtifactFilesystem(fileSHA1Naming, artifact.getArtifactId(), artifact.getHashes(),
|
||||
artifact.getSize(), artifact.getContentType());
|
||||
}
|
||||
|
||||
private File getFile(final String tenant, final String sha1) {
|
||||
@@ -192,18 +99,9 @@ public class ArtifactFilesystemRepository implements ArtifactRepository {
|
||||
return Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant), folder1, folder2);
|
||||
}
|
||||
|
||||
private DigestOutputStream openFileOutputStream(final File file, final MessageDigest mdSHA1,
|
||||
final MessageDigest mdMD5) throws FileNotFoundException {
|
||||
return new DigestOutputStream(
|
||||
new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(file)), mdMD5), mdSHA1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByTenant(final String tenant) {
|
||||
FileUtils.deleteQuietly(Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant)).toFile());
|
||||
}
|
||||
|
||||
private static String sanitizeTenant(final String tenant) {
|
||||
return tenant.trim().toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ArtifactFilesystemRepositoryTest {
|
||||
@Description("Verfies that an artifact can be successfully stored in the file-system repository")
|
||||
public void storeSuccessfully() throws IOException {
|
||||
final byte[] fileContent = randomBytes();
|
||||
final ArtifactFilesystem artifact = storeRandomArtifact(fileContent);
|
||||
final AbstractDbArtifact artifact = storeRandomArtifact(fileContent);
|
||||
|
||||
final byte[] readContent = new byte[fileContent.length];
|
||||
IOUtils.read(artifact.getFileInputStream(), readContent);
|
||||
@@ -50,7 +50,7 @@ public class ArtifactFilesystemRepositoryTest {
|
||||
public void getStoredArtifactBasedOnSHA1Hash() {
|
||||
|
||||
final byte[] fileContent = randomBytes();
|
||||
final ArtifactFilesystem artifact = storeRandomArtifact(fileContent);
|
||||
final AbstractDbArtifact artifact = storeRandomArtifact(fileContent);
|
||||
|
||||
final AbstractDbArtifact artifactBySha1 = artifactFilesystemRepository.getArtifactBySha1(TENANT,
|
||||
artifact.getHashes().getSha1());
|
||||
@@ -60,7 +60,7 @@ public class ArtifactFilesystemRepositoryTest {
|
||||
@Test
|
||||
@Description("Verfies that an artifact can be deleted in the file-system repository")
|
||||
public void deleteStoredArtifactBySHA1Hash() {
|
||||
final ArtifactFilesystem artifact = storeRandomArtifact(randomBytes());
|
||||
final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes());
|
||||
|
||||
artifactFilesystemRepository.deleteBySha1(TENANT, artifact.getHashes().getSha1());
|
||||
|
||||
@@ -70,7 +70,7 @@ public class ArtifactFilesystemRepositoryTest {
|
||||
@Test
|
||||
@Description("Verfies that all artifacts of a tenant can be deleted in the file-system repository")
|
||||
public void deleteStoredArtifactOfTenant() {
|
||||
final ArtifactFilesystem artifact = storeRandomArtifact(randomBytes());
|
||||
final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes());
|
||||
|
||||
artifactFilesystemRepository.deleteByTenant(TENANT);
|
||||
|
||||
@@ -86,7 +86,7 @@ public class ArtifactFilesystemRepositoryTest {
|
||||
Assertions.fail("did not expect an exception while deleting a file which does not exists");
|
||||
}
|
||||
|
||||
final ArtifactFilesystem artifact = storeRandomArtifact(randomBytes());
|
||||
final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes());
|
||||
try {
|
||||
artifactFilesystemRepository.deleteBySha1("tenantWhichDoesNotExist", artifact.getHashes().getSha1());
|
||||
} catch (final Exception e) {
|
||||
@@ -94,12 +94,10 @@ public class ArtifactFilesystemRepositoryTest {
|
||||
}
|
||||
}
|
||||
|
||||
private ArtifactFilesystem storeRandomArtifact(final byte[] fileContent) {
|
||||
private AbstractDbArtifact storeRandomArtifact(final byte[] fileContent) {
|
||||
final String fileName = "filename.tmp";
|
||||
final ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContent);
|
||||
final ArtifactFilesystem store = artifactFilesystemRepository.store(TENANT, inputStream, fileName,
|
||||
"application/txt");
|
||||
return store;
|
||||
return artifactFilesystemRepository.store(TENANT, inputStream, fileName, "application/txt", null);
|
||||
}
|
||||
|
||||
private static byte[] randomBytes() {
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2018 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.artifact.repository;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
/**
|
||||
* Abstract utility class for ArtifactRepository implementations with common
|
||||
* functionality, e.g. computation of hashes.
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractArtifactRepository implements ArtifactRepository {
|
||||
|
||||
private static final String TEMP_FILE_PREFIX = "tmp";
|
||||
private static final String TEMP_FILE_SUFFIX = "artifactrepo";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractArtifactRepository.class);
|
||||
|
||||
@Override
|
||||
// suppress warning, of not strong enough hashing algorithm, SHA-1 and MD5
|
||||
// is not used security related
|
||||
@SuppressWarnings("squid:S2070")
|
||||
public AbstractDbArtifact store(final String tenant, final InputStream content, final String filename,
|
||||
final String contentType, final DbArtifactHash hash) {
|
||||
final MessageDigest mdSHA1;
|
||||
final MessageDigest mdMD5;
|
||||
try {
|
||||
mdSHA1 = MessageDigest.getInstance("SHA1");
|
||||
mdMD5 = MessageDigest.getInstance("MD5");
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
throw new ArtifactStoreException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
LOG.debug("Creating temporary file and store the inputstream to it");
|
||||
|
||||
final File file = createTempFile();
|
||||
|
||||
try (final DigestOutputStream outputstream = openFileOutputStream(file, mdSHA1, mdMD5)) {
|
||||
ByteStreams.copy(content, outputstream);
|
||||
outputstream.flush();
|
||||
final String sha1Hash16 = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest());
|
||||
final String md5Hash16 = BaseEncoding.base16().lowerCase().encode(mdMD5.digest());
|
||||
|
||||
LOG.debug("Temporary file {} stored. Calculated sha1: {} and md5: {} hashes", file, sha1Hash16, md5Hash16);
|
||||
|
||||
checkHashes(sha1Hash16, md5Hash16, hash);
|
||||
|
||||
return store(sanitizeTenant(tenant), sha1Hash16, md5Hash16, contentType, file);
|
||||
} catch (final IOException e) {
|
||||
throw new ArtifactStoreException(e.getMessage(), e);
|
||||
} finally {
|
||||
if (file.exists() && !file.delete()) {
|
||||
LOG.error("Could not delete temp file {}", file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkHashes(final String sha1Hash16, final String md5Hash16, final DbArtifactHash hash) {
|
||||
if (hash == null) {
|
||||
return;
|
||||
}
|
||||
if (hash.getSha1() != null && !sha1Hash16.equals(hash.getSha1())) {
|
||||
throw new HashNotMatchException("The given sha1 hash " + hash.getSha1()
|
||||
+ " does not match with the calcualted sha1 hash " + sha1Hash16, HashNotMatchException.SHA1);
|
||||
}
|
||||
if (hash.getMd5() != null && !md5Hash16.equals(hash.getMd5())) {
|
||||
throw new HashNotMatchException(
|
||||
"The given md5 hash " + hash.getMd5() + " does not match with the calcualted md5 hash " + md5Hash16,
|
||||
HashNotMatchException.MD5);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16,
|
||||
final String contentType, final File file) throws IOException;
|
||||
|
||||
private static File createTempFile() {
|
||||
try {
|
||||
return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
|
||||
} catch (final IOException e) {
|
||||
throw new ArtifactStoreException("Cannot create tempfile", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static DigestOutputStream openFileOutputStream(final File file, final MessageDigest mdSHA1,
|
||||
final MessageDigest mdMD5) throws FileNotFoundException {
|
||||
return new DigestOutputStream(
|
||||
new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(file)), mdMD5), mdSHA1);
|
||||
}
|
||||
|
||||
protected static String sanitizeTenant(final String tenant) {
|
||||
return tenant.trim().toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,28 +23,6 @@ import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
*
|
||||
*/
|
||||
public interface ArtifactRepository {
|
||||
|
||||
/**
|
||||
* Stores an artifact into the repository.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to store the artifact
|
||||
* @param content
|
||||
* the content to store
|
||||
* @param filename
|
||||
* the filename of the artifact
|
||||
* @param contentType
|
||||
* the content type of the artifact
|
||||
* @return the stored artifact
|
||||
*
|
||||
* @throws MethodNotSupportedException
|
||||
* if implementation does not support the operation
|
||||
* @throws ArtifactStoreException
|
||||
* in case storing of the artifact was not successful
|
||||
*/
|
||||
AbstractDbArtifact store(@NotEmpty String tenant, @NotNull InputStream content, @NotEmpty String filename,
|
||||
String contentType);
|
||||
|
||||
/**
|
||||
* Stores an artifact into the repository.
|
||||
*
|
||||
|
||||
@@ -33,9 +33,5 @@
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Body for system statistics.
|
||||
@@ -22,12 +23,22 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSystemStatisticsRest {
|
||||
|
||||
@JsonProperty
|
||||
private long overallTargets;
|
||||
|
||||
@JsonProperty
|
||||
private long overallArtifacts;
|
||||
|
||||
@JsonProperty
|
||||
private long overallArtifactVolumeInBytes;
|
||||
|
||||
@JsonProperty
|
||||
private long overallActions;
|
||||
|
||||
@JsonProperty
|
||||
private long overallTenants;
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtSystemTenantServiceUsage> tenantStats;
|
||||
|
||||
public long getOverallTargets() {
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Response body for system usage report.
|
||||
@@ -22,19 +23,25 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSystemTenantServiceUsage {
|
||||
|
||||
private final String tenantName;
|
||||
@JsonProperty
|
||||
private String tenantName;
|
||||
|
||||
@JsonProperty
|
||||
private long targets;
|
||||
|
||||
@JsonProperty
|
||||
private long artifacts;
|
||||
|
||||
@JsonProperty
|
||||
private long actions;
|
||||
|
||||
@JsonProperty
|
||||
private long overallArtifactVolumeInBytes;
|
||||
|
||||
@JsonProperty
|
||||
private Map<String, String> usageData;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenantName
|
||||
*/
|
||||
public MgmtSystemTenantServiceUsage(final String tenantName) {
|
||||
public void setTenantName(final String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,8 @@ public class MgmtSystemManagementResource implements MgmtSystemManagementRestApi
|
||||
}
|
||||
|
||||
private static MgmtSystemTenantServiceUsage convertTenant(final TenantUsage tenant) {
|
||||
final MgmtSystemTenantServiceUsage result = new MgmtSystemTenantServiceUsage(tenant.getTenantName());
|
||||
final MgmtSystemTenantServiceUsage result = new MgmtSystemTenantServiceUsage();
|
||||
result.setTenantName(tenant.getTenantName());
|
||||
result.setActions(tenant.getActions());
|
||||
result.setArtifacts(tenant.getArtifacts());
|
||||
result.setOverallArtifactVolumeInBytes(tenant.getOverallArtifactVolumeInBytes());
|
||||
|
||||
@@ -12,9 +12,6 @@ import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -35,12 +32,6 @@ import org.springframework.security.core.GrantedAuthority;
|
||||
* including metadata, {@link TargetTag}s, {@link TargetRegistrationRule}s<br/>
|
||||
* XX_Repository CRUD which covers: {@link DistributionSet}s,
|
||||
* {@link SoftwareModule}s, DS Tags<br/>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class SpPermission {
|
||||
|
||||
@@ -113,21 +104,9 @@ public final class SpPermission {
|
||||
*/
|
||||
public static final String DELETE_REPOSITORY = "DELETE_REPOSITORY";
|
||||
|
||||
/**
|
||||
* Permission to monitor the SP system. E.g. retrieving health, monitor
|
||||
* checks through REST API provided by the spring actuator.
|
||||
*/
|
||||
public static final String SYSTEM_MONITOR = "SYSTEM_MONITOR";
|
||||
|
||||
/**
|
||||
* Permission to retrieve diagnosis of the SP system. E.g. retrieving
|
||||
* metrics, configuration through REST API provided by the spring actuator.
|
||||
*/
|
||||
public static final String SYSTEM_DIAG = "SYSTEM_DIAG";
|
||||
|
||||
/**
|
||||
* Permission to administrate the system on a global, i.e. tenant
|
||||
* independent scale. Thta inlcuds the deletion of tenants.
|
||||
* independent scale. That includes the deletion of tenants.
|
||||
*/
|
||||
public static final String SYSTEM_ADMIN = "SYSTEM_ADMIN";
|
||||
|
||||
@@ -173,31 +152,11 @@ public final class SpPermission {
|
||||
/**
|
||||
* Return all permission.
|
||||
*
|
||||
* @return all permission
|
||||
* @param exclusionRoles
|
||||
* roles which will excluded
|
||||
* @return all permissions
|
||||
*/
|
||||
public static List<String> getAllAuthorities() {
|
||||
return getAllAuthorities(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all permission.
|
||||
*
|
||||
* @param exclusionRoles
|
||||
* roles which will excluded
|
||||
* @return all permissions
|
||||
*/
|
||||
public static List<String> getAllAuthorities(final String... exclusionRoles) {
|
||||
return getAllAuthorities(Arrays.asList(exclusionRoles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all permission.
|
||||
*
|
||||
* @param exclusionRoles
|
||||
* roles which will excluded
|
||||
* @return all permissions
|
||||
*/
|
||||
public static List<String> getAllAuthorities(final Collection<String> exclusionRoles) {
|
||||
final List<String> allPermissions = new ArrayList<>();
|
||||
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
|
||||
for (final Field field : declaredFields) {
|
||||
@@ -205,7 +164,7 @@ public final class SpPermission {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
final String role = (String) field.get(null);
|
||||
addIfNotExcluded(exclusionRoles, allPermissions, role);
|
||||
allPermissions.add(role);
|
||||
} catch (final IllegalAccessException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
@@ -214,13 +173,6 @@ public final class SpPermission {
|
||||
return allPermissions;
|
||||
}
|
||||
|
||||
private static void addIfNotExcluded(final Collection<String> exclusionRoles, final List<String> allPermissions,
|
||||
final String role) {
|
||||
if (!(exclusionRoles.contains(role))) {
|
||||
allPermissions.add(role);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all the spring security evaluation expressions for the
|
||||
* {@link PreAuthorize} annotation for method security.
|
||||
@@ -239,9 +191,6 @@ public final class SpPermission {
|
||||
* isAuthenticated() Returns true if the user is not anonymous
|
||||
* isFullyAuthenticated() Returns true if the user is not an anonymous or a remember-me user
|
||||
* }
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final class SpringEvalExpressions {
|
||||
@@ -464,14 +413,6 @@ public final class SpPermission {
|
||||
public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION
|
||||
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
|
||||
|
||||
/**
|
||||
* Spring security eval hasAuthority expression to check if spring
|
||||
* context contains {@link SpPermission#SYSTEM_MONITOR} or
|
||||
* {@link #IS_SYSTEM_CODE}.
|
||||
*/
|
||||
public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX
|
||||
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
|
||||
|
||||
private SpringEvalExpressions() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
@@ -31,8 +31,7 @@ public final class PermissionTest {
|
||||
@Test
|
||||
@Description("Verify the get permission function")
|
||||
public void testGetPermissions() {
|
||||
final int allPermission = 19;
|
||||
final int permissionWithoutSystem = allPermission - 3;
|
||||
final int allPermission = 17;
|
||||
final Collection<String> allAuthorities = SpPermission.getAllAuthorities();
|
||||
final List<GrantedAuthority> allAuthoritiesList = PermissionUtils.createAllAuthorityList();
|
||||
assertThat(allAuthorities).hasSize(allPermission);
|
||||
@@ -41,16 +40,5 @@ public final class PermissionTest {
|
||||
assertThat(allAuthoritiesList.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList()))
|
||||
.containsAll(allAuthorities);
|
||||
|
||||
final Collection<String> authoritiesWithoutSystem = SpPermission.getAllAuthorities(SpPermission.SYSTEM_ADMIN,
|
||||
SpPermission.SYSTEM_DIAG, SpPermission.SYSTEM_MONITOR);
|
||||
final List<GrantedAuthority> authoritiesListWithoutSystem = PermissionUtils.createAuthorityList(SpPermission
|
||||
.getAllAuthorities(SpPermission.SYSTEM_ADMIN, SpPermission.SYSTEM_DIAG, SpPermission.SYSTEM_MONITOR));
|
||||
|
||||
assertThat(authoritiesWithoutSystem).hasSize(permissionWithoutSystem);
|
||||
// times 2 because we add also all authorities as prefix 'ROLE_';
|
||||
assertThat(authoritiesListWithoutSystem).hasSize(permissionWithoutSystem * 2);
|
||||
assertThat(authoritiesListWithoutSystem.stream().map(authority -> authority.getAuthority())
|
||||
.collect(Collectors.toList())).containsAll(authoritiesWithoutSystem);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,24 +26,6 @@ public class SpPermissionChecker implements Serializable {
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the monitor View Permission.
|
||||
*
|
||||
* @return SYSTEM_MONITOR boolean value
|
||||
*/
|
||||
public boolean hasSpMonitorViewPermission() {
|
||||
return permissionService.hasPermission(SpPermission.SYSTEM_MONITOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the diagnosis retrieval Permission.
|
||||
*
|
||||
* @return SYSTEM_DIAG boolean value
|
||||
*/
|
||||
public boolean hasSpdiagnosisViewPermission() {
|
||||
return permissionService.hasPermission(SpPermission.SYSTEM_DIAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the read Target & Dist Permission.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user