-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Currently only implemented for S3 storage type.
- Loading branch information
1 parent
b722d22
commit e7a6a43
Showing
12 changed files
with
216 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/main/java/org/radarbase/appserver/config/PreAuthPermissionEvaluator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.radarbase.appserver.config; | ||
|
||
import org.radarbase.appserver.config.AuthConfig.AuthPermission; | ||
import org.springframework.security.access.PermissionEvaluator; | ||
import org.springframework.security.core.Authentication; | ||
|
||
import java.io.Serializable; | ||
|
||
public class PreAuthPermissionEvaluator implements PermissionEvaluator { | ||
|
||
@Override | ||
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { | ||
if (targetDomainObject instanceof String && permission instanceof AuthPermission) { | ||
String subjectId = (String) targetDomainObject; | ||
AuthPermission authPermission = (AuthPermission) permission; | ||
if (AuthPermission.UPLOAD == authPermission) { | ||
// TODO check lookup of subjectId in authentication object. | ||
if (authentication.getName().equals(subjectId)) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { | ||
return false; | ||
} | ||
} | ||
|
13 changes: 13 additions & 0 deletions
13
src/main/java/org/radarbase/appserver/config/S3StorageProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package org.radarbase.appserver.config; | ||
|
||
import lombok.Data; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
@Data | ||
@ConfigurationProperties("storage.s3") | ||
public class S3StorageProperties { | ||
private String url; | ||
private String accessKey; | ||
private String secretKey; | ||
private String bucketName; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
src/main/java/org/radarbase/appserver/controller/UploadController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package org.radarbase.appserver.controller; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.validation.Valid; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.radarbase.appserver.config.AuthConfig.AuthEntities; | ||
import org.radarbase.appserver.config.AuthConfig.AuthPermissions; | ||
import org.radarbase.appserver.dto.FilePathDto; | ||
import org.radarbase.appserver.service.StorageService; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.access.prepost.PreAuthorize; | ||
import org.springframework.web.bind.annotation.CrossOrigin; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
import org.springframework.web.servlet.mvc.support.RedirectAttributes; | ||
import radar.spring.auth.common.Authorized; | ||
|
||
/** | ||
* Resource Endpoint for uploading assets to a data store. | ||
* | ||
* @author Pim van Nierop | ||
*/ | ||
@Slf4j | ||
@CrossOrigin | ||
@RestController | ||
@ConditionalOnProperty(value = "file-upload.enabled", havingValue = "true") | ||
public class UploadController { | ||
|
||
@Autowired | ||
private StorageService storageService; | ||
|
||
@Authorized(permission = AuthPermissions.CREATE, entity = AuthEntities.MEASUREMENT) | ||
@PostMapping( | ||
"/" + PathsUtil.PROJECT_PATH + "/" + PathsUtil.PROJECT_ID_CONSTANT + | ||
"/" + PathsUtil.USER_PATH + "/" + PathsUtil.SUBJECT_ID_CONSTANT + | ||
"/" + PathsUtil.TOPIC_PATH + "/" + PathsUtil.TOPIC_ID_CONSTANT + | ||
"/upload") | ||
@PreAuthorize("hasPermission(#subjectId, T(org.radarbase.appserver.config.AuthConfig.AuthPermission).UPLOAD") // Only the user can upload files on their own behalf. | ||
public ResponseEntity<FilePathDto> subjectFileUpload( | ||
@RequestParam("file") MultipartFile file, | ||
@PathVariable String projectId, | ||
@PathVariable String subjectId, | ||
@PathVariable String topicId) { | ||
log.info("Storing file for project: {}, subject: {}, topic: {}", projectId, subjectId, topicId); | ||
String filePath = storageService.store(file, projectId, subjectId, topicId); | ||
return ResponseEntity.ok(new FilePathDto(filePath)); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/org/radarbase/appserver/dto/FilePathDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.radarbase.appserver.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
public class FilePathDto { | ||
private String path; | ||
} |
60 changes: 60 additions & 0 deletions
60
src/main/java/org/radarbase/appserver/service/S3StorageService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package org.radarbase.appserver.service; | ||
|
||
import io.minio.BucketExistsArgs; | ||
import io.minio.MinioClient; | ||
import io.minio.PutObjectArgs; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.radarbase.appserver.config.S3StorageProperties; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import javax.annotation.PostConstruct; | ||
|
||
@Slf4j | ||
@Service | ||
@ConditionalOnExpression("${file-upload.enabled:false} and 's3' == '${storage.type:}'") | ||
public class S3StorageService implements StorageService { | ||
|
||
@Autowired | ||
private S3StorageProperties s3StorageProperties; | ||
|
||
private MinioClient minioClient; | ||
private String bucketName; | ||
|
||
@PostConstruct | ||
public void init() { | ||
try { | ||
minioClient = | ||
MinioClient.builder() | ||
.endpoint(s3StorageProperties.getUrl()) | ||
.credentials(s3StorageProperties.getAccessKey(), s3StorageProperties.getSecretKey()) | ||
.build(); | ||
bucketName = s3StorageProperties.getBucketName(); | ||
boolean found = | ||
minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); | ||
if (!found) { | ||
throw new RuntimeException(String.format("S3 bucket '%s' does not exist", bucketName)); | ||
} | ||
} catch (Exception e) { | ||
throw new RuntimeException("Could not connect to S3", e); | ||
} | ||
} | ||
|
||
public String store(MultipartFile file, String projectId, String subjectId, String topicId) { | ||
String filePath = String.format("%s/%s/%s/%s", projectId, subjectId, topicId, file.getName()); | ||
log.debug("Storing file at path: {}", filePath); | ||
try { | ||
minioClient.putObject(PutObjectArgs | ||
.builder() | ||
.bucket(bucketName) | ||
.object(filePath) | ||
.stream(file.getInputStream(), file.getSize(), -1) | ||
.build()); | ||
} catch (Exception e) { | ||
throw new RuntimeException("Could not store file", e); | ||
} | ||
return filePath; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/org/radarbase/appserver/service/StorageService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.radarbase.appserver.service; | ||
|
||
import io.minio.errors.ErrorResponseException; | ||
import io.minio.errors.InsufficientDataException; | ||
import io.minio.errors.InternalException; | ||
import io.minio.errors.InvalidResponseException; | ||
import io.minio.errors.ServerException; | ||
import io.minio.errors.XmlParserException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import java.io.IOException; | ||
import java.security.InvalidKeyException; | ||
import java.security.NoSuchAlgorithmException; | ||
|
||
public interface StorageService { | ||
String store(MultipartFile file, String projectId, String subjectId, String topicId); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,4 +18,4 @@ | |
# * | ||
# */ | ||
# | ||
spring.profiles.active=prod | ||
spring.profiles.active=prod |