From 391a8fb5d26f203b2af7744abde1dc45b1dc1f16 Mon Sep 17 00:00:00 2001 From: Shubham Varshney Date: Wed, 31 Jan 2024 21:02:35 +0530 Subject: [PATCH] document/add cloudfront signed url --- build.gradle | 4 + settings.gradle | 6 + ...plateServiceJavaSpringBootApplication.java | 41 +++++- .../shubham/commons/aws/CloudFrontUtils.java | 83 +++++++++++ .../code/shubham/commons/aws/S3Utils.java | 38 ++--- .../commons/enums/DownloadURLSource.java | 7 + .../filters/RequestResponseLoggingFilter.java | 6 +- .../keystore/dao/entities/KeyStore.java | 137 ++++++++++++++++++ .../dao/repositories/KeyRepository.java | 12 ++ .../keystore/services/CryptoService.java | 79 ++++++++++ .../commons/keystore/services/KeyService.java | 48 ++++++ .../shubham/commons/utils/ResponseUtils.java | 31 +++- .../commons/validators/IValidator.java | 2 + .../core/blobstore/services/BlobService.java | 32 ++-- .../SaveDocumentRequestValidator.java | 2 +- .../core/blobstoremodels/BlobResponse.java | 2 +- .../dao/entities/Document.java | 4 +- .../dao/repositories/DocumentRepository.java | 9 +- .../document/services/DocumentService.java | 77 ++++++++++ .../factories/DocumentDownloadURLFactory.java | 55 +++++++ .../v1/controllers/DocumentController.java} | 34 ++--- .../SaveDocumentRequestValidator.java | 12 +- .../core/documentmodels/DocumentDTO.java | 18 +++ .../SaveDocumentRequest.java | 11 +- .../services/DocumentService.java | 44 ------ .../core/iam/services/AccountService.java | 10 ++ .../web/v1/controllers/AccountController.java | 6 +- .../core/iamcommons/IAccountService.java | 2 + src/main/resources/application.yml | 11 ++ 29 files changed, 684 insertions(+), 139 deletions(-) create mode 100644 src/main/java/code/shubham/commons/aws/CloudFrontUtils.java create mode 100644 src/main/java/code/shubham/commons/enums/DownloadURLSource.java create mode 100644 src/main/java/code/shubham/commons/keystore/dao/entities/KeyStore.java create mode 100644 src/main/java/code/shubham/commons/keystore/dao/repositories/KeyRepository.java create mode 100644 src/main/java/code/shubham/commons/keystore/services/CryptoService.java create mode 100644 src/main/java/code/shubham/commons/keystore/services/KeyService.java rename src/main/java/code/shubham/core/{documentstore => document}/dao/entities/Document.java (92%) rename src/main/java/code/shubham/core/{documentstore => document}/dao/repositories/DocumentRepository.java (50%) create mode 100644 src/main/java/code/shubham/core/document/services/DocumentService.java create mode 100644 src/main/java/code/shubham/core/document/services/factories/DocumentDownloadURLFactory.java rename src/main/java/code/shubham/core/{documentstore/web/v1/controllers/DocumentStoreController.java => document/web/v1/controllers/DocumentController.java} (61%) rename src/main/java/code/shubham/core/{documentstore => document}/web/v1/validators/SaveDocumentRequestValidator.java (60%) create mode 100644 src/main/java/code/shubham/core/documentmodels/DocumentDTO.java rename src/main/java/code/shubham/core/{documentstoremodels => documentmodels}/SaveDocumentRequest.java (67%) delete mode 100644 src/main/java/code/shubham/core/documentstore/services/DocumentService.java diff --git a/build.gradle b/build.gradle index d728e8f..85688b0 100644 --- a/build.gradle +++ b/build.gradle @@ -88,7 +88,11 @@ dependencies { 'org.springframework.kafka:spring-kafka', + 'code.shubham:crypto-utils:0.0.1', + 'software.amazon.awssdk:s3:2.22.1', + 'com.amazonaws:aws-java-sdk-cloudfront:1.12.646', + 'org.bouncycastle:bcprov-jdk18on:1.77' ) runtimeOnly ( 'com.mysql:mysql-connector-j', diff --git a/settings.gradle b/settings.gradle index 8b15f5d..68bc5ba 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,11 @@ rootProject.name = 'template-service-java-springboot' +sourceControl { + gitRepository ("https://github.com/shubhamv108/crypto-utils.git") { + producesModule ("code.shubham:crypto-utils") + } +} + //include "shared", "api", "services:webservice" // diff --git a/src/main/java/code/shubham/TemplateServiceJavaSpringBootApplication.java b/src/main/java/code/shubham/TemplateServiceJavaSpringBootApplication.java index 38a7ab4..d2e2564 100644 --- a/src/main/java/code/shubham/TemplateServiceJavaSpringBootApplication.java +++ b/src/main/java/code/shubham/TemplateServiceJavaSpringBootApplication.java @@ -1,14 +1,51 @@ package code.shubham; import code.shubham.commons.annotations.SpringBootApp; +import code.shubham.commons.aws.CloudFrontUtils; +import code.shubham.commons.keystore.dao.entities.KeyStore; +import code.shubham.commons.keystore.dao.repositories.KeyRepository; +import code.shubham.encryption.keys.asymmetric.RSAUtil; +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Security; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; + +@Slf4j @SpringBootApp -public class TemplateServiceJavaSpringBootApplication { +public class TemplateServiceJavaSpringBootApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(TemplateServiceJavaSpringBootApplication.class, args); } + @Autowired + private KeyRepository keyRepository; + + @Override + public void run(String... args) throws Exception { + // final PrivateKey privateKey = CloudFrontUtils.readPrivateKeyFromFile(args[0]); + // final KeyStore entity = + // this.keyRepository.findByPurpose("DOCUMENTS-CDN-CLOUD_FRONT-PRIVATE_KEY"); + // if (entity == null) + // this.keyRepository.save( + // KeyStore.builder() + // .key(privateKey.getEncoded()) + // .purpose("DOCUMENTS-CDN-CLOUD_FRONT-PRIVATE_KEY") + // .build()); + // System.out.println ("Key algorithm: " + privateKey.getAlgorithm()); + } + } diff --git a/src/main/java/code/shubham/commons/aws/CloudFrontUtils.java b/src/main/java/code/shubham/commons/aws/CloudFrontUtils.java new file mode 100644 index 0000000..39f08b9 --- /dev/null +++ b/src/main/java/code/shubham/commons/aws/CloudFrontUtils.java @@ -0,0 +1,83 @@ +package code.shubham.commons.aws; + +import com.amazonaws.services.cloudfront.CloudFrontUrlSigner; +import com.amazonaws.services.cloudfront.model.KeyPairIds; +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Security; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Date; + +@Slf4j +public class CloudFrontUtils { + + public static String signedURL(final String distributionDomain, final String s3ObjectKey, final String keyPairId, + final PrivateKey privateKey, final Date dateLessThan) { + return CloudFrontUrlSigner.getSignedURLWithCannedPolicy("https://" + distributionDomain + "/" + s3ObjectKey, + keyPairId, privateKey, dateLessThan); + } + + public static String keyPair(final String distributionDomain, final String s3ObjectKey, final String keyPairId, + final PrivateKey privateKey, final Date dateLessThan) { + return CloudFrontUrlSigner.getSignedURLWithCannedPolicy("https://" + distributionDomain + "/" + s3ObjectKey, + keyPairId, privateKey, dateLessThan); + } + + public static PrivateKey readPrivateKeyFromFile(final String filePath) + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + Security.addProvider(new BouncyCastleProvider()); + File file = new File(filePath); + FileInputStream fileStream = new FileInputStream(file); + + PrivateKey var10; + try { + DataInputStream dataStream = new DataInputStream(fileStream); + + try { + byte[] keyBytes = new byte[(int) file.length()]; + dataStream.readFully(keyBytes); + String temp = new String(keyBytes, "UTF-8"); + String header = temp.replace("-----BEGIN PRIVATE KEY-----", ""); + header = header.replace("-----END PRIVATE KEY-----", ""); + header.replace("\n", ""); + byte[] decoded = java.util.Base64.getMimeDecoder().decode(header); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded); + KeyFactory kf = KeyFactory.getInstance("RSA"); + var10 = kf.generatePrivate(spec); + } + catch (Throwable var13) { + try { + dataStream.close(); + } + catch (Throwable var12) { + var13.addSuppressed(var12); + } + log.error("", var13); + throw var13; + } + + dataStream.close(); + } + catch (Throwable var14) { + try { + fileStream.close(); + } + catch (Throwable var11) { + var14.addSuppressed(var11); + } + log.error("", var14); + throw var14; + } + return var10; + } + +} diff --git a/src/main/java/code/shubham/commons/aws/S3Utils.java b/src/main/java/code/shubham/commons/aws/S3Utils.java index 59124dd..16511ed 100644 --- a/src/main/java/code/shubham/commons/aws/S3Utils.java +++ b/src/main/java/code/shubham/commons/aws/S3Utils.java @@ -11,6 +11,7 @@ import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; +import software.amazon.awssdk.services.s3.presigner.model.UploadPartPresignRequest; import java.time.Duration; import java.util.Map; @@ -30,8 +31,7 @@ public static String createPresignedUrl(final String region, final String bucket .build(); final PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() - .signatureDuration(Duration.ofMinutes(10)) // The URL expires in 10 - // minutes. + .signatureDuration(Duration.ofMinutes(10)) .putObjectRequest(objectRequest) .build(); @@ -44,15 +44,14 @@ public static String createPresignedUrl(final String region, final String bucket } } - /* Create a pre-signed URL to download an object in a subsequent GET request. */ - public static String createPresignedGetUrl(final String region, final String bucketName, String keyName) { + public static String createPresignedGetUrl(final String region, final String bucketName, final String keyName, + long durationInMilliSeconds) { try (final S3Presigner presigner = S3Presigner.builder().region(Region.of(region)).build()) { GetObjectRequest objectRequest = GetObjectRequest.builder().bucket(bucketName).key(keyName).build(); GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder() - .signatureDuration(Duration.ofMinutes(10)) // The URL will expire in 10 - // minutes. + .signatureDuration(Duration.ofMillis(durationInMilliSeconds)) .getObjectRequest(objectRequest) .build(); @@ -68,9 +67,12 @@ public static boolean doesObjectExist(final String region, final String bucket, try { final S3Client s3 = S3Client.builder().region(Region.of(region)).build(); - final GetObjectAttributesResponse response = s3 - .getObjectAttributes(GetObjectAttributesRequest.builder().bucket(bucket).key(key).build()); - return !response.deleteMarker() && Optional.ofNullable(checksum) + final GetObjectAttributesResponse response = s3.getObjectAttributes(GetObjectAttributesRequest.builder() + .bucket(bucket) + .key(key) + .objectAttributes(ObjectAttributes.CHECKSUM, ObjectAttributes.OBJECT_SIZE) + .build()); + return Optional.ofNullable(response.deleteMarker()).orElse(true) && Optional.ofNullable(checksum) .map(sum -> sum.equals(response.checksum().checksumCRC32C())) .orElse(true); } @@ -84,22 +86,4 @@ public static boolean doesObjectExist(final String region, final String bucket, } } - public static boolean getMetadata(final String region, final String bucket, final String key) { - try { - final S3Client s3 = S3Client.builder().region(Region.of(region)).build(); - - final GetObjectAttributesResponse response = s3 - .getObjectAttributes(GetObjectAttributesRequest.builder().bucket(bucket).key(key).build()); - } - catch (NoSuchKeyException exception) { - log.error("No such key!!!", exception); - return false; - } - catch (SdkException exception) { - log.error("Exception while invoking S3::getObjectAttributes", exception); - throw new InternalServerException("Something went wrong"); - } - return true; - } - } diff --git a/src/main/java/code/shubham/commons/enums/DownloadURLSource.java b/src/main/java/code/shubham/commons/enums/DownloadURLSource.java new file mode 100644 index 0000000..bce28b7 --- /dev/null +++ b/src/main/java/code/shubham/commons/enums/DownloadURLSource.java @@ -0,0 +1,7 @@ +package code.shubham.commons.enums; + +public enum DownloadURLSource { + + S3, CLOUD_FRONT + +} diff --git a/src/main/java/code/shubham/commons/filters/RequestResponseLoggingFilter.java b/src/main/java/code/shubham/commons/filters/RequestResponseLoggingFilter.java index 0c310fe..4be0554 100644 --- a/src/main/java/code/shubham/commons/filters/RequestResponseLoggingFilter.java +++ b/src/main/java/code/shubham/commons/filters/RequestResponseLoggingFilter.java @@ -2,6 +2,7 @@ import code.shubham.commons.Constants; import code.shubham.commons.utils.MetricsLogger; +import code.shubham.commons.utils.StringUtils; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -48,7 +49,6 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo final String responseBody = new String(responseArray, responseCacheWrapperObject.getCharacterEncoding()); responseCacheWrapperObject.copyBodyToResponse(); - final Long requestStartTimestamp = (Long) request.getAttribute(Constants.RequestKey.REQUEST_START_TIMESTAMP); log.info("Response:{StatusCode: {}, Headers: {}, Body: {}}", response.getStatus(), responseHeaders, responseBody); this.metricsLogger.log(request); @@ -64,6 +64,10 @@ private Map getHeaders(final Iterator headerNames, headers.put(headerName, headersValue.apply(headerName)); } } + final String location = (String) headersValue.apply("Location"); + if (StringUtils.isNotEmpty(location)) + headers.put("Location", location); + return headers; } diff --git a/src/main/java/code/shubham/commons/keystore/dao/entities/KeyStore.java b/src/main/java/code/shubham/commons/keystore/dao/entities/KeyStore.java new file mode 100644 index 0000000..468370c --- /dev/null +++ b/src/main/java/code/shubham/commons/keystore/dao/entities/KeyStore.java @@ -0,0 +1,137 @@ +package code.shubham.commons.keystore.dao.entities; + +import code.shubham.commons.dao.base.entities.BaseAbstractAuditableEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Lob; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import javax.crypto.SecretKey; +import java.io.ByteArrayInputStream; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; + +@Slf4j +@Builder +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "key_stores") +public class KeyStore extends BaseAbstractAuditableEntity { + + @Column(name = "alias") + private String alias; + + @Lob + @Column(name = "p12_key", nullable = false, columnDefinition = "BLOB") + private byte[] key; + + @Column(name = "password") + private String password; + + @Column(name = "type") + private String type; + + @Column(name = "purpose", unique = true, nullable = false) + private String purpose; + + public PrivateKey getPrivateKeyWithSpec() { + try { + final PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(this.key); + KeyFactory kf = KeyFactory.getInstance("RSA"); + return kf.generatePrivate(spec); + } + catch (final NoSuchAlgorithmException | InvalidKeySpecException e) { + log.error("", e); + throw new RuntimeException(e); + } + } + + public PrivateKey getPrivateKey() { + ByteArrayInputStream inputStream = null; + PrivateKey privateKey = null; + try { + final java.security.KeyStore ks = java.security.KeyStore.getInstance("PKCS12"); + inputStream = new ByteArrayInputStream(this.key); + ks.load(inputStream, this.password.toCharArray()); + privateKey = (PrivateKey) ks.getKey(this.alias, this.password.toCharArray()); + } + catch (final Exception exception) { + log.error("", exception); + } + finally { + if (inputStream != null) { + try { + inputStream.close(); + } + catch (final Exception exception) { + log.error("", exception); + } + } + } + return privateKey; + } + + public PublicKey getPublicKey() { + ByteArrayInputStream inputStream = null; + PublicKey publicKey = null; + try { + final java.security.KeyStore ks = java.security.KeyStore.getInstance("PKCS12"); + inputStream = new ByteArrayInputStream(this.key); + ks.load(inputStream, this.password.toCharArray()); + publicKey = ks.getCertificate(this.alias).getPublicKey(); + } + catch (final Exception exception) { + log.error("", exception); + } + finally { + if (inputStream != null) { + try { + inputStream.close(); + } + catch (final Exception exception) { + log.error("", exception); + } + } + } + return publicKey; + } + + public SecretKey getSecretKey() { + ByteArrayInputStream inputStream = null; + SecretKey secretKey = null; + try { + final java.security.KeyStore ks = java.security.KeyStore.getInstance("PKCS12"); + inputStream = new ByteArrayInputStream(this.key); + ks.load(inputStream, this.password.toCharArray()); + secretKey = (SecretKey) ks.getKey(this.alias, this.password.toCharArray()); + } + catch (final Exception exception) { + log.error("", exception); + } + finally { + if (inputStream != null) { + try { + inputStream.close(); + } + catch (final Exception exception) { + log.error("", exception); + } + } + } + return secretKey; + } + +} \ No newline at end of file diff --git a/src/main/java/code/shubham/commons/keystore/dao/repositories/KeyRepository.java b/src/main/java/code/shubham/commons/keystore/dao/repositories/KeyRepository.java new file mode 100644 index 0000000..70de5a7 --- /dev/null +++ b/src/main/java/code/shubham/commons/keystore/dao/repositories/KeyRepository.java @@ -0,0 +1,12 @@ +package code.shubham.commons.keystore.dao.repositories; + +import code.shubham.commons.keystore.dao.entities.KeyStore; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface KeyRepository extends JpaRepository { + + KeyStore findByPurpose(String purpose); + +} \ No newline at end of file diff --git a/src/main/java/code/shubham/commons/keystore/services/CryptoService.java b/src/main/java/code/shubham/commons/keystore/services/CryptoService.java new file mode 100644 index 0000000..275bc68 --- /dev/null +++ b/src/main/java/code/shubham/commons/keystore/services/CryptoService.java @@ -0,0 +1,79 @@ +package code.shubham.commons.keystore.services; + +import code.shubham.CryptoUtil; +import code.shubham.commons.utils.StringUtils; +import code.shubham.hash.HashUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Service +@RequiredArgsConstructor +public class CryptoService { + + private final KeyService keyService; + + /** + * Time in milliseconds when captured auth value will be expired. default value 30 + * minutes + */ + @Value("${auth.value.expiry.milli.seconds:1800000}") + private long timeForCaptureAuthValueExpiry; + + /** + * flag to skip the check for captured auth value expiry time + */ + @Value("${skip.auth.value.expiry.milli.seconds.check:-1}") + private int skipExpiryFlag; + + private final Map authTypeEncryptionKeyMap = new HashMap<>(); + + public String encryptUsingSecretKey(final String dataValue, final String authType) { + String encryptionKey = this.authTypeEncryptionKeyMap.get(authType); + byte[] secretKey = this.keyService.getSecretKeyAsBytes(encryptionKey); + return new String(CryptoUtil.encryptUsingSecretKey(secretKey, dataValue.getBytes())); + } + + public String decryptUsingSecretKey(final String dataValue, final String authType) { + String encryptionKey = this.authTypeEncryptionKeyMap.get(authType); + byte[] secretKey = this.keyService.getSecretKeyAsBytes(encryptionKey); + return new String(CryptoUtil.decryptUsingSecretKey(secretKey, dataValue.getBytes())); + } + + public String decryptUsingPrivateKey(final String encodedAuthValue, final String authType) { + String encryptionKey = this.authTypeEncryptionKeyMap.get(authType); + byte[] decodedAuthValue = HashUtil.decodeBase64(encodedAuthValue); + byte[] privateKey = this.keyService.getPrivateKeyAsBytes(encryptionKey); + return new String(CryptoUtil.decryptUsingPrivateKey(privateKey, decodedAuthValue)); + } + + public String parseAndGetAuthValue(final String decryptedAuthValue, final String authType) { + String authValue = ""; + long authValueCaptureTimestamp = 0; + + if (StringUtils.isNotEmpty(decryptedAuthValue)) { + String[] parts = decryptedAuthValue.split("_"); + if (parts.length > 1) { + authValue = parts[1].trim(); + } + if (parts.length > 0) { + authValueCaptureTimestamp = Long.valueOf(parts[0].trim()); + } + } + + if (this.skipExpiryFlag != -1 && authValueCaptureTimestamp > 0 + && (System.currentTimeMillis() - authValueCaptureTimestamp > this.timeForCaptureAuthValueExpiry)) { + log.error("" + authType + " capture very old (captured at : " + new Date(authValueCaptureTimestamp) + + " => returning blank value"); + authValue = ""; + } + return authValue; + } + +} \ No newline at end of file diff --git a/src/main/java/code/shubham/commons/keystore/services/KeyService.java b/src/main/java/code/shubham/commons/keystore/services/KeyService.java new file mode 100644 index 0000000..382d73a --- /dev/null +++ b/src/main/java/code/shubham/commons/keystore/services/KeyService.java @@ -0,0 +1,48 @@ +package code.shubham.commons.keystore.services; + +import code.shubham.commons.keystore.dao.entities.KeyStore; +import code.shubham.commons.keystore.dao.repositories.KeyRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.spec.InvalidKeySpecException; + +@Service +@RequiredArgsConstructor +public class KeyService { + + private final KeyRepository repository; + + /** + * Gets the public key. + * @param keyType the key type + * @return the encryption key + */ + public byte[] getPublicKey(final String keyType) { + KeyStore keyStore = this.repository.findByPurpose(keyType); + return keyStore.getPublicKey().getEncoded(); + } + + public PrivateKey getPrivateKey(final String keyType) { + final KeyStore keyStore = this.repository.findByPurpose(keyType); + return keyStore.getPrivateKey(); + } + + public PrivateKey getPrivateKeyWithPSec(final String keyType) { + final KeyStore keyStore = this.repository.findByPurpose(keyType); + return keyStore.getPrivateKeyWithSpec(); + } + + public byte[] getPrivateKeyAsBytes(final String keyType) { + final KeyStore keyStore = this.repository.findByPurpose(keyType); + return keyStore.getPrivateKey().getEncoded(); + } + + public byte[] getSecretKeyAsBytes(final String keyType) { + final KeyStore keyStore = this.repository.findByPurpose(keyType); + return keyStore.getSecretKey().getEncoded(); + } + +} diff --git a/src/main/java/code/shubham/commons/utils/ResponseUtils.java b/src/main/java/code/shubham/commons/utils/ResponseUtils.java index e4f097c..8ee7769 100644 --- a/src/main/java/code/shubham/commons/utils/ResponseUtils.java +++ b/src/main/java/code/shubham/commons/utils/ResponseUtils.java @@ -1,11 +1,16 @@ package code.shubham.commons.utils; import code.shubham.commons.models.ServiceResponse; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; public class ResponseUtils { @@ -45,25 +50,35 @@ public static ResponseEntity getResponseEntity(int statusCode, Object data, O } public static ResponseEntity getResponseEntity(int statusCode, Object data, - java.util.Map> headers) { + Map> headers) { return getResponseEntity(statusCode, data, null, headers); } public static ResponseEntity getResponseEntity(int statusCode, Object data, - java.util.Map> headers, String headerKey, String... headerValues) { - headers.put(headerKey, java.util.Arrays.asList(headerValues)); + Map> headers, String headerKey, String... headerValues) { + headers.put(headerKey, Arrays.asList(headerValues)); return getResponseEntity(statusCode, data, null, headers); } - public static ResponseEntity getResponseEntity(int statusCode, Object data, Object errors, - java.util.Map> headers) { - ServiceResponse response = ServiceResponse.builder().statusCode(statusCode).data(data).error(errors).build(); - org.springframework.http.HttpHeaders httpHeaders = null; + public static ResponseEntity getResponseEntity(final int statusCode, final Object data, final Object errors, + final Map> headers) { + final ServiceResponse response = ServiceResponse.builder() + .statusCode(statusCode) + .data(data) + .error(errors) + .build(); + HttpHeaders httpHeaders = null; if (headers != null) { - httpHeaders = new org.springframework.http.HttpHeaders(); + httpHeaders = new HttpHeaders(); headers.forEach(httpHeaders::addAll); } return ResponseEntity.status(statusCode).headers(httpHeaders).body(response); } + public static ResponseEntity redirect(final String redirectURI) throws URISyntaxException { + final HttpHeaders headers = new HttpHeaders(); + headers.setLocation(new URI(redirectURI)); + return ResponseEntity.status(HttpStatus.TEMPORARY_REDIRECT).headers(headers).build(); + } + } diff --git a/src/main/java/code/shubham/commons/validators/IValidator.java b/src/main/java/code/shubham/commons/validators/IValidator.java index 95f6216..2ad7aab 100644 --- a/src/main/java/code/shubham/commons/validators/IValidator.java +++ b/src/main/java/code/shubham/commons/validators/IValidator.java @@ -6,6 +6,8 @@ public interface IValidator { String MUST_NOT_BE_EMPTY = "%s must not be empty."; + String MUST_BE_VALID_ID = "%s must be valid id."; + IValidator validate(OBJECT object); IValidator validateOrThrowException(OBJECT object); diff --git a/src/main/java/code/shubham/core/blobstore/services/BlobService.java b/src/main/java/code/shubham/core/blobstore/services/BlobService.java index 1ea15c1..f2d23d8 100644 --- a/src/main/java/code/shubham/core/blobstore/services/BlobService.java +++ b/src/main/java/code/shubham/core/blobstore/services/BlobService.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -24,7 +25,10 @@ public class BlobService { private String defaultRegion; public BlobResponse getPreSignedUploadUrl(final String owner, final String bucket, final String key, - final Map metadata) { + Map metadata) { + if (metadata == null) + metadata = new HashMap<>(); + final Blob blob = this.repository.save(Blob.builder() .bucket(bucket) .keyName(key) @@ -34,27 +38,31 @@ public BlobResponse getPreSignedUploadUrl(final String owner, final String bucke metadata.remove("checksum"); return BlobResponse.builder() .blobId(blob.getId()) - .uploadUrl(S3Utils.createPresignedUrl(this.defaultRegion, blob.getBucket(), blob.getFullKey(), metadata)) + .url(S3Utils.createPresignedUrl(this.defaultRegion, blob.getBucket(), blob.getFullKey(), metadata)) .build(); } public Boolean doesBlobExist(final Long id, final String owner) { - return this.get(id, owner).map(blob -> true).orElse(false); - } - - public Optional get(final Long id, final String owner) { - return this.repository.findByIdAndOwner(id, owner) - .filter(blob -> S3Utils.doesObjectExist(this.defaultRegion, blob.getBucket(), blob.getFullKey(), - blob.getChecksum())); + return this.get(id, owner).isPresent(); } public BlobResponse getPreSignedDownloadUrl(final Long id, final String owner) { - final Blob blob = this.get(id, owner) - .orElseThrow(() -> new InvalidRequestException("id", "No such blob exists with id: %s", id.toString())); + final Blob blob = this.getOrThrowException(id, owner); return BlobResponse.builder() .blobId(blob.getId()) - .uploadUrl(S3Utils.createPresignedGetUrl(this.defaultRegion, blob.getBucket(), blob.getFullKey())) + .url(S3Utils.createPresignedGetUrl(this.defaultRegion, blob.getBucket(), blob.getFullKey(), 600000)) .build(); } + public Blob getOrThrowException(final Long id, final String owner) { + return this.get(id, owner) + .orElseThrow(() -> new InvalidRequestException("id", "No such blob exists with id: %s", id.toString())); + } + + public Optional get(final Long id, final String owner) { + return this.repository.findByIdAndOwner(id, owner) + .filter(blob -> S3Utils.doesObjectExist(this.defaultRegion, blob.getBucket(), blob.getFullKey(), + blob.getChecksum())); + } + } diff --git a/src/main/java/code/shubham/core/blobstore/web/v1/validators/SaveDocumentRequestValidator.java b/src/main/java/code/shubham/core/blobstore/web/v1/validators/SaveDocumentRequestValidator.java index 72874f5..2709859 100644 --- a/src/main/java/code/shubham/core/blobstore/web/v1/validators/SaveDocumentRequestValidator.java +++ b/src/main/java/code/shubham/core/blobstore/web/v1/validators/SaveDocumentRequestValidator.java @@ -3,7 +3,7 @@ import code.shubham.commons.utils.StringUtils; import code.shubham.commons.validators.AbstractRequestValidator; import code.shubham.commons.validators.IValidator; -import code.shubham.core.documentstoremodels.SaveDocumentRequest; +import code.shubham.core.documentmodels.SaveDocumentRequest; public class SaveDocumentRequestValidator extends AbstractRequestValidator { diff --git a/src/main/java/code/shubham/core/blobstoremodels/BlobResponse.java b/src/main/java/code/shubham/core/blobstoremodels/BlobResponse.java index 3392cbc..a6200de 100644 --- a/src/main/java/code/shubham/core/blobstoremodels/BlobResponse.java +++ b/src/main/java/code/shubham/core/blobstoremodels/BlobResponse.java @@ -12,6 +12,6 @@ public class BlobResponse { private Long blobId; @NotNull - private String uploadUrl; + private String url; } diff --git a/src/main/java/code/shubham/core/documentstore/dao/entities/Document.java b/src/main/java/code/shubham/core/document/dao/entities/Document.java similarity index 92% rename from src/main/java/code/shubham/core/documentstore/dao/entities/Document.java rename to src/main/java/code/shubham/core/document/dao/entities/Document.java index 41a50a3..4d7f884 100644 --- a/src/main/java/code/shubham/core/documentstore/dao/entities/Document.java +++ b/src/main/java/code/shubham/core/document/dao/entities/Document.java @@ -1,4 +1,4 @@ -package code.shubham.core.documentstore.dao.entities; +package code.shubham.core.document.dao.entities; import code.shubham.commons.dao.base.entities.BaseAbstractAuditableEntity; import jakarta.persistence.Column; @@ -27,7 +27,7 @@ public class Document extends BaseAbstractAuditableEntity { private String name; @Column(nullable = false) - private Long owner; + private String owner; @Column(nullable = false) private Long blobId; diff --git a/src/main/java/code/shubham/core/documentstore/dao/repositories/DocumentRepository.java b/src/main/java/code/shubham/core/document/dao/repositories/DocumentRepository.java similarity index 50% rename from src/main/java/code/shubham/core/documentstore/dao/repositories/DocumentRepository.java rename to src/main/java/code/shubham/core/document/dao/repositories/DocumentRepository.java index 1c26b57..120b3f3 100644 --- a/src/main/java/code/shubham/core/documentstore/dao/repositories/DocumentRepository.java +++ b/src/main/java/code/shubham/core/document/dao/repositories/DocumentRepository.java @@ -1,15 +1,14 @@ -package code.shubham.core.documentstore.dao.repositories; +package code.shubham.core.document.dao.repositories; -import code.shubham.core.documentstore.dao.entities.Document; +import code.shubham.core.document.dao.entities.Document; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import java.util.List; import java.util.Optional; @Repository -public interface DocumentRepository extends JpaRepository { +public interface DocumentRepository extends JpaRepository { - Optional findByOwnerAndName(Long owner, String name); + Optional findByOwnerAndName(String owner, String name); } diff --git a/src/main/java/code/shubham/core/document/services/DocumentService.java b/src/main/java/code/shubham/core/document/services/DocumentService.java new file mode 100644 index 0000000..dcd7b36 --- /dev/null +++ b/src/main/java/code/shubham/core/document/services/DocumentService.java @@ -0,0 +1,77 @@ +package code.shubham.core.document.services; + +import code.shubham.commons.contexts.AccountIDContextHolder; +import code.shubham.commons.enums.DownloadURLSource; +import code.shubham.commons.exceptions.InvalidRequestException; +import code.shubham.core.blobstore.dao.entities.Blob; +import code.shubham.core.blobstore.services.BlobService; +import code.shubham.core.blobstoremodels.BlobResponse; +import code.shubham.core.document.dao.entities.Document; +import code.shubham.core.document.dao.repositories.DocumentRepository; +import code.shubham.core.document.services.factories.DocumentDownloadURLFactory; +import code.shubham.core.documentmodels.DocumentDTO; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.Optional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class DocumentService { + + @Value("${aws.default.region}") + private String defaultRegion; + + @Value("${documents.download.url.source}") + private DownloadURLSource downloadURLSource; + + @Value("${documents.bucket.name}") + private String defaultBucket; + + private final DocumentRepository repository; + + private final BlobService blobService; + + private final DocumentDownloadURLFactory downloadURLFactory; + + public BlobResponse getUploadURL(final Map metadata) { + return this.blobService.getPreSignedUploadUrl(AccountIDContextHolder.get().toString(), this.defaultBucket, + AccountIDContextHolder.get().toString(), metadata); + } + + public DocumentDTO save(final Document document) { + if (!this.blobService.doesBlobExist(document.getBlobId(), document.getOwner().toString())) + throw new InvalidRequestException("blobId", "blob does not exist"); + + final Optional existing = this.repository.findByOwnerAndName(document.getOwner(), document.getName()); + if (existing.isPresent()) { + existing.get().setBlobId(document.getBlobId()); + return this.convert(this.repository.save(existing.get())); + } + return this.convert(this.repository.save(document)); + } + + public String getDownloadURL(final Long id) { + return this.repository.findById(id) + .map(document -> this.blobService.get(document.getBlobId(), document.getOwner())) + .filter(Optional::isPresent) + .map(Optional::get) + .map(Blob::getFullKey) + .map(key -> this.downloadURLFactory.get(this.downloadURLSource, key)) + .orElseThrow(() -> new InvalidRequestException("id", "No document found with id: %s", id.toString())); + + } + + private DocumentDTO convert(final Document document) { + return DocumentDTO.builder() + .documentId(document.getId()) + .name(document.getName()) + .owner(document.getOwner()) + .build(); + } + +} diff --git a/src/main/java/code/shubham/core/document/services/factories/DocumentDownloadURLFactory.java b/src/main/java/code/shubham/core/document/services/factories/DocumentDownloadURLFactory.java new file mode 100644 index 0000000..9e75f50 --- /dev/null +++ b/src/main/java/code/shubham/core/document/services/factories/DocumentDownloadURLFactory.java @@ -0,0 +1,55 @@ +package code.shubham.core.document.services.factories; + +import code.shubham.commons.aws.CloudFrontUtils; +import code.shubham.commons.aws.S3Utils; +import code.shubham.commons.enums.DownloadURLSource; +import code.shubham.commons.keystore.services.KeyService; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.util.Date; + +@Component +@RequiredArgsConstructor +public class DocumentDownloadURLFactory { + + @Value("${aws.default.region}") + private String defaultRegion; + + @Value("${documents.bucket.name}") + private String defaultBucket; + + @Value("${documents.cdn.domain}") + private String cdnDomain; + + @Value("${documents.cdn.key.pair}") + private String cdnKeyPair; + + @Value("${documents.cdn.key.type}") + private String cdnKeyType; + + @Value("${documents.download.url.ttl.milliseconds}") + private Long downloadURLTTLInMilliseconds; + + private final KeyService keyService; + + public String get(final DownloadURLSource source, final String key) { + switch (source) { + case S3 -> { + return S3Utils.createPresignedGetUrl(this.defaultRegion, this.defaultBucket, key, + this.downloadURLTTLInMilliseconds); + } + case CLOUD_FRONT -> { + return CloudFrontUtils.signedURL(this.cdnDomain, key, this.cdnKeyPair, + this.keyService.getPrivateKeyWithPSec(this.cdnKeyType), + new Date(System.currentTimeMillis() + this.downloadURLTTLInMilliseconds)); + } + } + + return null; + } + +} diff --git a/src/main/java/code/shubham/core/documentstore/web/v1/controllers/DocumentStoreController.java b/src/main/java/code/shubham/core/document/web/v1/controllers/DocumentController.java similarity index 61% rename from src/main/java/code/shubham/core/documentstore/web/v1/controllers/DocumentStoreController.java rename to src/main/java/code/shubham/core/document/web/v1/controllers/DocumentController.java index 26f7b79..f861f91 100644 --- a/src/main/java/code/shubham/core/documentstore/web/v1/controllers/DocumentStoreController.java +++ b/src/main/java/code/shubham/core/document/web/v1/controllers/DocumentController.java @@ -1,26 +1,25 @@ -package code.shubham.core.documentstore.web.v1.controllers; +package code.shubham.core.document.web.v1.controllers; -import code.shubham.commons.contexts.AccountIDContextHolder; import code.shubham.commons.utils.ResponseUtils; import code.shubham.commons.utils.Utils; -import code.shubham.core.blobstore.services.BlobService; -import code.shubham.core.documentstore.dao.entities.Document; -import code.shubham.core.documentstore.services.DocumentService; -import code.shubham.core.documentstore.web.v1.validators.SaveDocumentRequestValidator; -import code.shubham.core.documentstoremodels.SaveDocumentRequest; +import code.shubham.core.document.dao.entities.Document; +import code.shubham.core.document.services.DocumentService; +import code.shubham.core.document.web.v1.validators.SaveDocumentRequestValidator; +import code.shubham.core.documentmodels.SaveDocumentRequest; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import software.amazon.awssdk.http.HttpStatusCode; +import java.net.URISyntaxException; import java.util.Map; @RestController @@ -29,34 +28,31 @@ @Tag(name = "Document Store") @ConditionalOnProperty(prefix = "service", name = "module", havingValue = "web") @RequiredArgsConstructor -public class DocumentStoreController { - - @Value("${documents.bucket.name}") - private String defaultBucket; - - private final BlobService blobService; +public class DocumentController { private final DocumentService service; @GetMapping("/uploadURL") public ResponseEntity getDocumentUploadURL(@RequestBody(required = false) final Map metadata) { - return ResponseUtils.getDataResponseEntity(200, - this.blobService.getPreSignedUploadUrl(AccountIDContextHolder.get().toString(), this.defaultBucket, - AccountIDContextHolder.get().toString(), metadata)); + return ResponseUtils.getDataResponseEntity(200, this.service.getUploadURL(metadata)); } @PostMapping public ResponseEntity save(@RequestBody final SaveDocumentRequest request) { new SaveDocumentRequestValidator().validateOrThrowException(request); - Utils.validateAccountOrThrowException(request.getUserId()); + Utils.validateAccountOrThrowException(request.getAccountId()); return ResponseUtils.getDataResponseEntity(HttpStatusCode.CREATED, this.service.save(Document.builder() - .owner(request.getUserId()) + .owner(request.getAccountId().toString()) .name(request.getName()) .blobId(request.getBlobId()) .build())); } + @GetMapping("/{id}") + public ResponseEntity getDownloadURL(@PathVariable("id") final Long id) throws URISyntaxException { + return ResponseUtils.redirect(this.service.getDownloadURL(id)); + } } diff --git a/src/main/java/code/shubham/core/documentstore/web/v1/validators/SaveDocumentRequestValidator.java b/src/main/java/code/shubham/core/document/web/v1/validators/SaveDocumentRequestValidator.java similarity index 60% rename from src/main/java/code/shubham/core/documentstore/web/v1/validators/SaveDocumentRequestValidator.java rename to src/main/java/code/shubham/core/document/web/v1/validators/SaveDocumentRequestValidator.java index ee8a641..32aeacd 100644 --- a/src/main/java/code/shubham/core/documentstore/web/v1/validators/SaveDocumentRequestValidator.java +++ b/src/main/java/code/shubham/core/document/web/v1/validators/SaveDocumentRequestValidator.java @@ -1,9 +1,9 @@ -package code.shubham.core.documentstore.web.v1.validators; +package code.shubham.core.document.web.v1.validators; import code.shubham.commons.utils.StringUtils; import code.shubham.commons.validators.AbstractRequestValidator; import code.shubham.commons.validators.IValidator; -import code.shubham.core.documentstoremodels.SaveDocumentRequest; +import code.shubham.core.documentmodels.SaveDocumentRequest; public class SaveDocumentRequestValidator extends AbstractRequestValidator { @@ -12,10 +12,10 @@ public IValidator validate(final SaveDocumentRequest reques super.validate(request); if (StringUtils.isEmpty(request.getName())) this.putMessage("name", MUST_NOT_BE_EMPTY, "name"); - if (null == request.getBlobId()) - this.putMessage("blobId", MUST_NOT_BE_EMPTY, "blobId"); - if (null == request.getBlobId()) - this.putMessage("userId", MUST_NOT_BE_EMPTY, "userId"); + if (this.isNotValidId(request.getBlobId())) + this.putMessage("blobId", MUST_BE_VALID_ID, "blobId"); + if (this.isNotValidId(request.getAccountId())) + this.putMessage("accountId", MUST_BE_VALID_ID, "accountId"); return this; } diff --git a/src/main/java/code/shubham/core/documentmodels/DocumentDTO.java b/src/main/java/code/shubham/core/documentmodels/DocumentDTO.java new file mode 100644 index 0000000..14099e3 --- /dev/null +++ b/src/main/java/code/shubham/core/documentmodels/DocumentDTO.java @@ -0,0 +1,18 @@ +package code.shubham.core.documentmodels; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class DocumentDTO { + + private Long documentId; + + private String name; + + private String owner; + +} diff --git a/src/main/java/code/shubham/core/documentstoremodels/SaveDocumentRequest.java b/src/main/java/code/shubham/core/documentmodels/SaveDocumentRequest.java similarity index 67% rename from src/main/java/code/shubham/core/documentstoremodels/SaveDocumentRequest.java rename to src/main/java/code/shubham/core/documentmodels/SaveDocumentRequest.java index 50134d4..a52c609 100644 --- a/src/main/java/code/shubham/core/documentstoremodels/SaveDocumentRequest.java +++ b/src/main/java/code/shubham/core/documentmodels/SaveDocumentRequest.java @@ -1,7 +1,6 @@ -package code.shubham.core.documentstoremodels; +package code.shubham.core.documentmodels; import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Builder; @@ -19,15 +18,9 @@ public class SaveDocumentRequest { private String name; @NotNull - @NotEmpty - @Min(36) - @Max(36) private Long blobId; @NotNull - @NotEmpty - @Min(17) - @Max(19) - private Long userId; + private Long accountId; } diff --git a/src/main/java/code/shubham/core/documentstore/services/DocumentService.java b/src/main/java/code/shubham/core/documentstore/services/DocumentService.java deleted file mode 100644 index 9189b9f..0000000 --- a/src/main/java/code/shubham/core/documentstore/services/DocumentService.java +++ /dev/null @@ -1,44 +0,0 @@ -package code.shubham.core.documentstore.services; - -import code.shubham.commons.exceptions.InvalidRequestException; -import code.shubham.commons.kafka.KafkaPublisher; -import code.shubham.core.blobstore.services.BlobService; -import code.shubham.core.documentstore.dao.entities.Document; -import code.shubham.core.documentstore.dao.repositories.DocumentRepository; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Optional; - -@Slf4j -@Service -public class DocumentService { - - private final DocumentRepository repository; - - private final BlobService blobService; - - private final KafkaPublisher kafkaPublisher; - - @Autowired - public DocumentService(final DocumentRepository repository, final BlobService blobService, - final KafkaPublisher kafkaPublisher) { - this.repository = repository; - this.blobService = blobService; - this.kafkaPublisher = kafkaPublisher; - } - - public Document save(final Document document) { - if (!this.blobService.doesBlobExist(document.getBlobId(), document.getOwner().toString())) - throw new InvalidRequestException("blobId", "blob does not exist"); - - final Optional existing = this.repository.findByOwnerAndName(document.getOwner(), document.getName()); - if (existing.isPresent()) { - existing.get().setBlobId(document.getBlobId()); - return this.repository.save(existing.get()); - } - return this.repository.save(document); - } - -} diff --git a/src/main/java/code/shubham/core/iam/services/AccountService.java b/src/main/java/code/shubham/core/iam/services/AccountService.java index 92d5bae..3211c5e 100644 --- a/src/main/java/code/shubham/core/iam/services/AccountService.java +++ b/src/main/java/code/shubham/core/iam/services/AccountService.java @@ -54,4 +54,14 @@ public GetAccountResponse getById(final Long accountId) { .orElse(null); } + @Override + public GetAccountResponse fetchByEmail(final String email) { + return this.repository.findByEmail(email) + .map(account -> GetAccountResponse.builder() + .account(new AccountDTO(account.getId(), account.getEmail())) + .roles(this.userRoleService.getAllRoles(account.getId())) + .build()) + .orElse(null); + } + } diff --git a/src/main/java/code/shubham/core/iam/web/v1/controllers/AccountController.java b/src/main/java/code/shubham/core/iam/web/v1/controllers/AccountController.java index 3e14bb4..c13b3dd 100644 --- a/src/main/java/code/shubham/core/iam/web/v1/controllers/AccountController.java +++ b/src/main/java/code/shubham/core/iam/web/v1/controllers/AccountController.java @@ -1,5 +1,6 @@ package code.shubham.core.iam.web.v1.controllers; +import code.shubham.commons.contexts.AccountIDContextHolder; import code.shubham.commons.utils.ResponseUtils; import code.shubham.core.iam.services.AccountService; import code.shubham.core.iammodels.GetOrCreateAccount; @@ -22,8 +23,9 @@ public class AccountController { private final AccountService accountService; @GetMapping - public ResponseEntity getOrCreateUser(@RequestBody GetOrCreateAccount.Request request) { - return ResponseUtils.getDataResponseEntity(HttpStatus.OK, this.accountService.getOrCreate(request)); + public ResponseEntity getByContextId() { + return ResponseUtils.getDataResponseEntity(HttpStatus.OK, + this.accountService.getById(AccountIDContextHolder.get())); } @GetMapping("/{accountId}") diff --git a/src/main/java/code/shubham/core/iamcommons/IAccountService.java b/src/main/java/code/shubham/core/iamcommons/IAccountService.java index e58af5f..4e14cf2 100644 --- a/src/main/java/code/shubham/core/iamcommons/IAccountService.java +++ b/src/main/java/code/shubham/core/iamcommons/IAccountService.java @@ -9,4 +9,6 @@ public interface IAccountService { GetAccountResponse getById(Long accountId); + GetAccountResponse fetchByEmail(String email); + } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 235d976..5b05337 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -95,6 +95,17 @@ springdoc: documents: bucket: name: documentssstore + download: + url: + source: CLOUD_FRONT + ttl: + milliseconds: 600000 + cdn: + domain: dbz3h8mp9u1cr.cloudfront.net + key: + pair: APKAWIRY6IEW2RCDQJVH + type: DOCUMENTS-CDN-CLOUD_FRONT-PRIVATE_KEY + order: item: