From 531ddf233dff6a13561439c1e09395d0fac9cd97 Mon Sep 17 00:00:00 2001 From: rashmiangadi11 Date: Thu, 8 Aug 2024 12:31:27 +0530 Subject: [PATCH] Revert "SDMEXT-616: Implementing user token flow;Ccahing of user token: basic create attachment flow" --- pom.xml | 24 +- sdm/pom.xml | 20 +- .../SDMAttachmentsHandler.java} | 22 +- .../com/sap/cds/handler/TokenGenerator.java | 78 +++++++ .../cds/{sdm => }/model/SDMCredentials.java | 2 +- .../com/sap/cds/sdm/caching/CacheConfig.java | 56 ----- .../com/sap/cds/sdm/caching/CacheKey.java | 13 -- .../cds/sdm/configuration/Registration.java | 101 --------- .../sap/cds/sdm/constants/SDMConstants.java | 10 - .../com/sap/cds/sdm/handler/TokenHandler.java | 209 ------------------ .../SDMCreateEventHandler.java | 99 --------- .../com/sap/cds/sdm/model/CmisDocument.java | 19 -- .../com/sap/cds/sdm/persistence/DBQuery.java | 3 - .../sap/cds/sdm/service/RegisterService.java | 7 - .../sdm/service/SDMAttachmentsService.java | 77 ------- .../com/sap/cds/sdm/service/SDMService.java | 14 -- .../sap/cds/sdm/service/SDMServiceImpl.java | 62 ------ .../java/com/sap/cds/sdm/util/HelperUtil.java | 3 - ...s.services.runtime.CdsRuntimeConfiguration | 1 - .../sdm/attachments-annotations.cds | 28 ++- .../cds/com.sap.cds/sdm/attachments.cds | 1 - ...st.java => SDMAttachmentsHandlerTest.java} | 8 +- 22 files changed, 142 insertions(+), 715 deletions(-) rename sdm/src/main/java/com/sap/cds/{sdm/service/handler/SDMAttachmentsServiceHandler.java => handler/SDMAttachmentsHandler.java} (67%) create mode 100644 sdm/src/main/java/com/sap/cds/handler/TokenGenerator.java rename sdm/src/main/java/com/sap/cds/{sdm => }/model/SDMCredentials.java (93%) delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/caching/CacheConfig.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/caching/CacheKey.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/configuration/Registration.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/handler/TokenHandler.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateEventHandler.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/model/CmisDocument.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/persistence/DBQuery.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/service/RegisterService.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/service/SDMAttachmentsService.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/service/SDMService.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java delete mode 100644 sdm/src/main/java/com/sap/cds/sdm/util/HelperUtil.java delete mode 100644 sdm/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration rename sdm/src/test/java/com/sap/cds/handler/{SDMAttachmentsServiceHandlerTest.java => SDMAttachmentsHandlerTest.java} (66%) diff --git a/pom.xml b/pom.xml index 9a0b2a91..b82ab073 100644 --- a/pom.xml +++ b/pom.xml @@ -81,6 +81,7 @@ cds-services-api + org.junit.jupiter junit-jupiter-api @@ -93,6 +94,8 @@ 5.10.2 test + + org.assertj assertj-core @@ -100,6 +103,7 @@ test + org.mockito mockito-core @@ -114,7 +118,22 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.0.0-M5 + + + **/SDMAttachmentsHandlerTest.* + + + + junit.platform.output.capture.stdout + false + + + junit.platform.output.capture.stderr + false + + + @@ -168,6 +187,7 @@ + org.apache.maven.plugins maven-enforcer-plugin @@ -203,4 +223,4 @@ - + \ No newline at end of file diff --git a/sdm/pom.xml b/sdm/pom.xml index 2b78ac29..58353ffa 100644 --- a/sdm/pom.xml +++ b/sdm/pom.xml @@ -30,7 +30,7 @@ sdm 7.6.0 - com.sap.cds.sdm.generated + sdm.generated src/test/gen 17 17 @@ -38,7 +38,6 @@ 1.18.30 0.8.7 1.13 - 3.1.3 @@ -69,6 +68,12 @@ cds-services-impl test + + + + + + ch.qos.logback logback-classic @@ -87,17 +92,11 @@ 4.13.2 test - - com.squareup.okhttp3 - okhttp - 4.9.0 - com.sap.cds cds-feature-attachments ${attachments_version} - com.sap.cds cds-starter-cloudfoundry com.sap.cloud.environment.servicebinding @@ -109,11 +108,6 @@ commons-codec ${commons-codec.version} - - org.ehcache - ehcache - ${ehcache-version} - diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandler.java b/sdm/src/main/java/com/sap/cds/handler/SDMAttachmentsHandler.java similarity index 67% rename from sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandler.java rename to sdm/src/main/java/com/sap/cds/handler/SDMAttachmentsHandler.java index 9ba971a9..659a21e8 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandler.java +++ b/sdm/src/main/java/com/sap/cds/handler/SDMAttachmentsHandler.java @@ -1,6 +1,5 @@ -package com.sap.cds.sdm.service.handler; +package com.sap.cds.handler; -import com.sap.cds.feature.attachments.generated.cds4j.sap.attachments.Attachments; import com.sap.cds.feature.attachments.service.AttachmentService; import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentCreateEventContext; import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentMarkAsDeletedEventContext; @@ -8,18 +7,19 @@ import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentRestoreEventContext; import com.sap.cds.services.handler.EventHandler; import com.sap.cds.services.handler.annotations.On; -import com.sap.cds.services.handler.annotations.ServiceName; -import java.io.IOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -@ServiceName(value = "*", type = AttachmentService.class) -public class SDMAttachmentsServiceHandler implements EventHandler { +public class SDMAttachmentsHandler implements EventHandler { + private static final Logger logger = LoggerFactory.getLogger(SDMAttachmentsHandler.class); @On(event = AttachmentService.EVENT_CREATE_ATTACHMENT) - public void createAttachment(AttachmentCreateEventContext context) throws IOException { - var contentId = (String) context.getAttachmentIds().get(Attachments.ID); - context.setIsInternalStored(true); - context.setContentId(contentId); - context.setCompleted(); + public void createAttachment(AttachmentCreateEventContext context) { + logger.info( + "Default Attachment Service handler called for creating attachment for entity name: {}", + context.getAttachmentEntity().getQualifiedName()); + logger.info("Other details: {}", context.getAttachmentIds()); + logger.info("Other details entity: {}", context.getAttachmentEntity()); } @On(event = AttachmentService.EVENT_MARK_ATTACHMENT_AS_DELETED) diff --git a/sdm/src/main/java/com/sap/cds/handler/TokenGenerator.java b/sdm/src/main/java/com/sap/cds/handler/TokenGenerator.java new file mode 100644 index 00000000..d32a102c --- /dev/null +++ b/sdm/src/main/java/com/sap/cds/handler/TokenGenerator.java @@ -0,0 +1,78 @@ +package com.sap.cds.handler; + +import static java.util.Objects.requireNonNull; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sap.cds.model.SDMCredentials; +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; +import com.sap.cloud.environment.servicebinding.api.ServiceBinding; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.codec.binary.Base64; + +public class TokenGenerator { + private static Map uaaCredentials; + private static final ObjectMapper mapper = new ObjectMapper(); + + public static byte[] toBytes(String str) { + return requireNonNull(str).getBytes(StandardCharsets.UTF_8); + } + + public static String toString(byte[] bytes) { + return new String(requireNonNull(bytes), StandardCharsets.UTF_8); + } + + private static SDMCredentials getSDMCredentianls() { + List allServiceBindings = + DefaultServiceBindingAccessor.getInstance().getServiceBindings(); + + // filter for a specific binding + ServiceBinding sdmBinding = + allServiceBindings.stream() + .filter(binding -> "sdm".equalsIgnoreCase(binding.getServiceName().orElse(null))) + .findFirst() + .get(); + SDMCredentials sdmCredentials = new SDMCredentials(); + uaaCredentials = sdmBinding.getCredentials(); + sdmCredentials.setBaseTokenUrl(uaaCredentials.get("url").toString()); + sdmCredentials.setUrl(sdmBinding.getCredentials().get("uri").toString()); + sdmCredentials.setClientId(uaaCredentials.get("clientid").toString()); + sdmCredentials.setClientSecret(uaaCredentials.get("clientsecret").toString()); + return sdmCredentials; + } + + public static String getAccessToken() throws IOException, ProtocolException { + SDMCredentials sdmCredentials = getSDMCredentianls(); + String userCredentials = sdmCredentials.getClientId() + ":" + sdmCredentials.getClientSecret(); + String authHeaderValue = "Basic " + Base64.encodeBase64String(toBytes(userCredentials)); + String bodyParams = "grant_type=client_credentials"; + byte[] postData = toBytes(bodyParams); + URL url = new URL(sdmCredentials.getBaseTokenUrl()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("Authorization", authHeaderValue); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + conn.setRequestProperty("charset", "utf-8"); + conn.setRequestProperty("Content-Length", "" + postData.length); + conn.setUseCaches(false); + conn.setDoInput(true); + conn.setDoOutput(true); + try (DataOutputStream os = new DataOutputStream(conn.getOutputStream())) { + os.write(postData); + } + String resp; + try (DataInputStream is = new DataInputStream(conn.getInputStream()); + BufferedReader br = new BufferedReader(new InputStreamReader(is))) { + resp = br.lines().collect(Collectors.joining("\n")); + } + conn.disconnect(); + return mapper.readValue(resp, JsonNode.class).get("access_token").asText(); + } +} diff --git a/sdm/src/main/java/com/sap/cds/sdm/model/SDMCredentials.java b/sdm/src/main/java/com/sap/cds/model/SDMCredentials.java similarity index 93% rename from sdm/src/main/java/com/sap/cds/sdm/model/SDMCredentials.java rename to sdm/src/main/java/com/sap/cds/model/SDMCredentials.java index b56877d1..668e63f8 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/model/SDMCredentials.java +++ b/sdm/src/main/java/com/sap/cds/model/SDMCredentials.java @@ -1,4 +1,4 @@ -package com.sap.cds.sdm.model; +package com.sap.cds.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.AllArgsConstructor; diff --git a/sdm/src/main/java/com/sap/cds/sdm/caching/CacheConfig.java b/sdm/src/main/java/com/sap/cds/sdm/caching/CacheConfig.java deleted file mode 100644 index 73f063ea..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/caching/CacheConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.sap.cds.sdm.caching; - -import java.util.concurrent.TimeUnit; -import org.ehcache.Cache; -import org.ehcache.CacheManager; -import org.ehcache.config.builders.*; -import org.ehcache.expiry.Duration; -import org.ehcache.expiry.Expirations; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CacheConfig { - - private static CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(); - private static Cache userTokenCache; - private static Cache clientCredentialsTokenCache; - private static final int HEAP_SIZE = 1000; - private static final int USER_TOKEN_EXPIRY = 660; - private static final int ACCESS_TOKEN_EXPIRY = 660; - private static final Logger logger = LoggerFactory.getLogger(CacheConfig.class); - - private CacheConfig() { - throw new IllegalStateException("CacheConfig class"); - } - - public static void initializeCache() { - // Expiring the cache after 11 hours - logger.info("Cache for user token and access token initialized"); - cacheManager.init(); - - userTokenCache = - cacheManager.createCache( - "userToken", - CacheConfigurationBuilder.newCacheConfigurationBuilder( - CacheKey.class, String.class, ResourcePoolsBuilder.heap(HEAP_SIZE)) - .withExpiry( - Expirations.timeToLiveExpiration( - new Duration(USER_TOKEN_EXPIRY, TimeUnit.MINUTES)))); - clientCredentialsTokenCache = - cacheManager.createCache( - "clientCredentialsToken", - CacheConfigurationBuilder.newCacheConfigurationBuilder( - String.class, String.class, ResourcePoolsBuilder.heap(HEAP_SIZE)) - .withExpiry( - Expirations.timeToLiveExpiration( - new Duration(ACCESS_TOKEN_EXPIRY, TimeUnit.MINUTES)))); - } - - public static Cache getUserTokenCache() { - return userTokenCache; - } - - public static Cache getClientCredentialsTokenCache() { - return clientCredentialsTokenCache; - } -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/caching/CacheKey.java b/sdm/src/main/java/com/sap/cds/sdm/caching/CacheKey.java deleted file mode 100644 index f4f9f680..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/caching/CacheKey.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.sap.cds.sdm.caching; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class CacheKey { - private String email; - private String expiration; -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/configuration/Registration.java b/sdm/src/main/java/com/sap/cds/sdm/configuration/Registration.java deleted file mode 100644 index 5fa463ff..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/configuration/Registration.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.sap.cds.sdm.configuration; - -import com.sap.cds.feature.attachments.handler.applicationservice.helper.ThreadLocalDataStorage; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.CreateAttachmentEvent; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.DefaultModifyAttachmentEventFactory; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.DoNothingAttachmentEvent; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.MarkAsDeletedAttachmentEvent; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.ModifyAttachmentEvent; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.ModifyAttachmentEventFactory; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.UpdateAttachmentEvent; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.transaction.CreationChangeSetListener; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.transaction.ListenerProvider; -import com.sap.cds.feature.attachments.service.AttachmentService; -import com.sap.cds.feature.attachments.utilities.LoggingMarker; -import com.sap.cds.sdm.caching.CacheConfig; -import com.sap.cds.sdm.handler.applicationservice.SDMCreateEventHandler; -import com.sap.cds.sdm.service.SDMAttachmentsService; -import com.sap.cds.sdm.service.handler.SDMAttachmentsServiceHandler; -import com.sap.cds.services.handler.EventHandler; -import com.sap.cds.services.outbox.OutboxService; -import com.sap.cds.services.runtime.CdsRuntimeConfiguration; -import com.sap.cds.services.runtime.CdsRuntimeConfigurer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.Marker; - -/** - * The class {@link Registration} is a configuration class that registers the services and event - * handlers for the attachments feature. - */ -public class Registration implements CdsRuntimeConfiguration { - - private static final Logger logger = LoggerFactory.getLogger(Registration.class); - private static final Marker marker = LoggingMarker.ATTACHMENT_SERVICE_REGISTRATION.getMarker(); - - @Override - public void services(CdsRuntimeConfigurer configurer) { - configurer.service(buildAttachmentService()); - } - - @Override - public void eventHandlers(CdsRuntimeConfigurer configurer) { - logger.info(marker, "Registering event handler for attachment service"); - CacheConfig.initializeCache(); - var attachmentService = - configurer - .getCdsRuntime() - .getServiceCatalog() - .getService(AttachmentService.class, AttachmentService.DEFAULT_NAME); - var outbox = - configurer - .getCdsRuntime() - .getServiceCatalog() - .getService( - OutboxService.class, - OutboxService.PERSISTENT_UNORDERED_NAME); // need to check if required - var outboxedAttachmentService = outbox.outboxed(attachmentService); - - configurer.eventHandler(new SDMAttachmentsServiceHandler()); - - var deleteContentEvent = new MarkAsDeletedAttachmentEvent(outboxedAttachmentService); - var eventFactory = - buildAttachmentEventFactory( - attachmentService, deleteContentEvent, outboxedAttachmentService); - ThreadLocalDataStorage storage = new ThreadLocalDataStorage(); - - configurer.eventHandler(buildCreateHandler(eventFactory, storage)); - } - - private AttachmentService buildAttachmentService() { - logger.info(marker, "Registering SDM attachment service"); - - return new SDMAttachmentsService(); - } - - protected DefaultModifyAttachmentEventFactory buildAttachmentEventFactory( - AttachmentService attachmentService, - ModifyAttachmentEvent deleteContentEvent, - AttachmentService outboxedAttachmentService) { - var creationChangeSetListener = createCreationFailedListener(outboxedAttachmentService); - var createAttachmentEvent = - new CreateAttachmentEvent(attachmentService, creationChangeSetListener); - var updateAttachmentEvent = - new UpdateAttachmentEvent(createAttachmentEvent, deleteContentEvent); - - var doNothingAttachmentEvent = new DoNothingAttachmentEvent(); - return new DefaultModifyAttachmentEventFactory( - createAttachmentEvent, updateAttachmentEvent, deleteContentEvent, doNothingAttachmentEvent); - } - - private ListenerProvider createCreationFailedListener( - AttachmentService outboxedAttachmentService) { - return (contentId, cdsRuntime) -> - new CreationChangeSetListener(contentId, cdsRuntime, outboxedAttachmentService); - } - - protected EventHandler buildCreateHandler( - ModifyAttachmentEventFactory factory, ThreadLocalDataStorage storage) { - return new SDMCreateEventHandler(factory, storage); - } -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java b/sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java deleted file mode 100644 index 6de9c417..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sap.cds.sdm.constants; - -public class SDMConstants { - private SDMConstants() { - throw new IllegalStateException("Constants class"); - } - - public static final String REPOSITORY_ID = System.getenv("REPOSITORY_ID"); - public static final String TENANT_ID = "X-zid"; -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/handler/TokenHandler.java b/sdm/src/main/java/com/sap/cds/sdm/handler/TokenHandler.java deleted file mode 100644 index 8debbabd..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/handler/TokenHandler.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.sap.cds.sdm.handler; - -import static com.sap.cloud.security.xsuaa.client.OAuth2TokenServiceConstants.*; -import static com.sap.cloud.security.xsuaa.client.OAuth2TokenServiceConstants.ASSERTION; -import static java.util.Objects.requireNonNull; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.sap.cds.sdm.caching.CacheConfig; -import com.sap.cds.sdm.caching.CacheKey; -import com.sap.cds.sdm.constants.SDMConstants; -import com.sap.cds.sdm.model.SDMCredentials; -import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; -import com.sap.cloud.environment.servicebinding.api.ServiceBinding; -import com.sap.cloud.security.xsuaa.client.OAuth2ServiceException; -import com.sap.cloud.security.xsuaa.http.HttpHeaders; -import com.sap.cloud.security.xsuaa.http.MediaType; -import java.io.*; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.commons.codec.binary.Base64; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicNameValuePair; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TokenHandler { - private static final Logger logger = LoggerFactory.getLogger(TokenHandler.class); - - private static final ObjectMapper mapper = new ObjectMapper(); - - private TokenHandler() { - throw new IllegalStateException("TokenHandler class"); - } - - public static byte[] toBytes(String str) { - return requireNonNull(str).getBytes(StandardCharsets.UTF_8); - } - - public static String toString(byte[] bytes) { - return new String(requireNonNull(bytes), StandardCharsets.UTF_8); - } - - public static SDMCredentials getSDMCredentials() { - List allServiceBindings = - DefaultServiceBindingAccessor.getInstance().getServiceBindings(); - // filter for a specific binding - ServiceBinding sdmBinding = - allServiceBindings.stream() - .filter(binding -> "sdm".equalsIgnoreCase(binding.getServiceName().orElse(null))) - .findFirst() - .get(); - SDMCredentials sdmCredentials = new SDMCredentials(); - Map uaaCredentials = sdmBinding.getCredentials(); - Map uaa = (Map) uaaCredentials.get("uaa"); - - sdmCredentials.setBaseTokenUrl(uaa.get("url").toString()); - sdmCredentials.setUrl(sdmBinding.getCredentials().get("uri").toString()); - sdmCredentials.setClientId(uaa.get("clientid").toString()); - sdmCredentials.setClientSecret(uaa.get("clientsecret").toString()); - return sdmCredentials; - } - - public static String getAccessToken(SDMCredentials sdmCredentials) throws IOException { - // Fetch the token from Cache if present use it else generate and store - String cachedToken = CacheConfig.getClientCredentialsTokenCache().get("clientCredentialsToken"); - if (cachedToken == null) { - String userCredentials = - sdmCredentials.getClientId() + ":" + sdmCredentials.getClientSecret(); - String authHeaderValue = "Basic " + Base64.encodeBase64String(toBytes(userCredentials)); - String bodyParams = "grant_type=client_credentials"; - byte[] postData = toBytes(bodyParams); - String authurl = sdmCredentials.getBaseTokenUrl() + "/oauth/token"; - URL url = new URL(authurl); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty("Authorization", authHeaderValue); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - conn.setRequestProperty("charset", "utf-8"); - conn.setRequestProperty("Content-Length", "" + postData.length); - conn.setUseCaches(false); - conn.setDoInput(true); - conn.setDoOutput(true); - try (DataOutputStream os = new DataOutputStream(conn.getOutputStream())) { - os.write(postData); - } - String resp; - try (DataInputStream is = new DataInputStream(conn.getInputStream()); - BufferedReader br = new BufferedReader(new InputStreamReader(is))) { - resp = br.lines().collect(Collectors.joining("\n")); - } - conn.disconnect(); - cachedToken = mapper.readValue(resp, JsonNode.class).get("access_token").asText(); - CacheConfig.getClientCredentialsTokenCache().put("clientCredentialsToken", cachedToken); - } - return cachedToken; - } - - public static String getDIToken(String token, SDMCredentials sdmCredentials) - throws OAuth2ServiceException { - JsonObject payloadObj = getTokenFields(token); - String email = payloadObj.get("email").getAsString(); - String token_expiry = payloadObj.get("exp").getAsString(); - CacheKey cacheKey = new CacheKey(); - cacheKey.setEmail(email); - cacheKey.setExpiration(token_expiry); - String cachedToken = CacheConfig.getUserTokenCache().get(cacheKey); - if (cachedToken == null) { - cachedToken = generateDITokenFromTokenExchange(token, sdmCredentials, payloadObj); - } - return cachedToken; - } - - private static String generateDITokenFromTokenExchange( - String token, SDMCredentials sdmCredentials, JsonObject payloadObj) - throws OAuth2ServiceException { - String cachedToken = null; - CloseableHttpClient httpClient = null; - try { - httpClient = HttpClients.createDefault(); - if (sdmCredentials.getClientId() == null) { - throw new IOException("No SDM binding found"); - } - Map parameters = fillTokenExchangeBody(token, sdmCredentials); - HttpPost httpPost = new HttpPost(sdmCredentials.getBaseTokenUrl() + "/oauth/token"); - httpPost.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.value()); - httpPost.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED.value()); - httpPost.setHeader(SDMConstants.TENANT_ID, getTokenFields(token).get("zid").getAsString()); - - List basicNameValuePairs = - parameters.entrySet().stream() - .map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue())) - .collect(Collectors.toList()); - httpPost.setEntity(new UrlEncodedFormEntity(basicNameValuePairs)); - HttpResponse response = httpClient.execute(httpPost); - String responseBody = extractResponseBodyAsString(response); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - logger.error("Error fetching token with JWT bearer : " + responseBody); - } - Map accessTokenMap = new JSONObject(responseBody).toMap(); - cachedToken = String.valueOf(accessTokenMap.get("access_token")); - String expiryTime = payloadObj.get("exp").getAsString(); - CacheKey cacheKey = new CacheKey(); - cacheKey.setEmail(payloadObj.get("email").getAsString()); - cacheKey.setExpiration(expiryTime); - CacheConfig.getUserTokenCache().put(cacheKey, cachedToken); - } catch (UnsupportedEncodingException e) { - throw new OAuth2ServiceException("Unexpected error parsing URI: " + e.getMessage()); - } catch (ClientProtocolException e) { - throw new OAuth2ServiceException( - "Unexpected error while fetching client protocol: " + e.getMessage()); - } catch (IOException e) { - logger.error("Error in POST request while fetching token with JWT bearer", e.getMessage()); - } finally { - safeClose(httpClient); - } - return cachedToken; - } - - public static JsonObject getTokenFields(String token) { - String[] chunks = token.split("\\."); - java.util.Base64.Decoder decoder = java.util.Base64.getUrlDecoder(); - String payload = new String(decoder.decode(chunks[1])); - JsonElement jelement = new JsonParser().parse(payload); - return jelement.getAsJsonObject(); - } - - private static Map fillTokenExchangeBody(String token, SDMCredentials sdmEnv) { - Map parameters = new HashMap<>(); - parameters.put(GRANT_TYPE, GRANT_TYPE_JWT_BEARER); - parameters.put(CLIENT_ID, sdmEnv.getClientId()); - parameters.put(CLIENT_SECRET, sdmEnv.getClientSecret()); - parameters.put(ASSERTION, token); - return parameters; - } - - private static String extractResponseBodyAsString(HttpResponse response) throws IOException { - // Ensure that InputStream and BufferedReader are automatically closed - try (InputStream inputStream = response.getEntity().getContent(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { - return bufferedReader.lines().collect(Collectors.joining(System.lineSeparator())); - } - } - - private static void safeClose(CloseableHttpClient httpClient) { - if (httpClient != null) { - try { - httpClient.close(); - } catch (IOException ex) { - logger.error("Failed to close httpclient " + ex.getMessage()); - } - } - } -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateEventHandler.java b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateEventHandler.java deleted file mode 100644 index 6a833483..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateEventHandler.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.sap.cds.sdm.handler.applicationservice; - -import com.sap.cds.CdsData; -import com.sap.cds.CdsDataProcessor; -import com.sap.cds.feature.attachments.handler.applicationservice.helper.ModifyApplicationHandlerHelper; -import com.sap.cds.feature.attachments.handler.applicationservice.helper.ReadonlyDataContextEnhancer; -import com.sap.cds.feature.attachments.handler.applicationservice.helper.ThreadDataStorageReader; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.ModifyAttachmentEventFactory; -import com.sap.cds.feature.attachments.handler.common.ApplicationHandlerHelper; -import com.sap.cds.reflect.CdsBaseType; -import com.sap.cds.reflect.CdsEntity; -import com.sap.cds.sdm.model.CmisDocument; -import com.sap.cds.sdm.service.SDMService; -import com.sap.cds.sdm.service.SDMServiceImpl; -import com.sap.cds.services.authentication.AuthenticationInfo; -import com.sap.cds.services.authentication.JwtTokenAuthenticationInfo; -import com.sap.cds.services.cds.ApplicationService; -import com.sap.cds.services.cds.CdsCreateEventContext; -import com.sap.cds.services.cds.CqnService; -import com.sap.cds.services.handler.EventHandler; -import com.sap.cds.services.handler.annotations.Before; -import com.sap.cds.services.handler.annotations.HandlerOrder; -import com.sap.cds.services.handler.annotations.ServiceName; -import com.sap.cds.services.utils.OrderConstants; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -@ServiceName(value = "*", type = ApplicationService.class) -public class SDMCreateEventHandler implements EventHandler { - - private final ModifyAttachmentEventFactory eventFactory; - private final ThreadDataStorageReader storageReader; - private final CdsDataProcessor processor = CdsDataProcessor.create(); - - public SDMCreateEventHandler( - ModifyAttachmentEventFactory eventFactory, ThreadDataStorageReader storageReader) { - this.eventFactory = eventFactory; - this.storageReader = storageReader; - } - - @Before(event = CqnService.EVENT_CREATE) - @HandlerOrder(OrderConstants.Before.CHECK_CAPABILITIES) - public void processBeforeForDraft(CdsCreateEventContext context, List data) { - ReadonlyDataContextEnhancer.enhanceReadonlyDataInContext(context, data, storageReader.get()); - } - - @Before(event = CqnService.EVENT_CREATE) - @HandlerOrder(HandlerOrder.LATE) - public void processBefore(CdsCreateEventContext context, List data) throws IOException { - doCreate(context, data); - } - - private void doCreate(CdsCreateEventContext context, List data) throws IOException { - AuthenticationInfo authInfo = context.getAuthenticationInfo(); - JwtTokenAuthenticationInfo jwtTokenInfo = authInfo.as(JwtTokenAuthenticationInfo.class); - String jwtToken = jwtTokenInfo.getToken(); - createDocument(data, jwtToken); - - if (ApplicationHandlerHelper.noContentFieldInData(context.getTarget(), data)) { - return; - } - - setKeysInData(context.getTarget(), data); - ModifyApplicationHandlerHelper.handleAttachmentForEntities( - context.getTarget(), data, new ArrayList<>(), eventFactory, context); - } - - private void setKeysInData(CdsEntity entity, List data) { - processor - .addGenerator( - (path, element, type) -> - element.isKey() && element.getType().isSimpleType(CdsBaseType.UUID), - (path, element, isNull) -> UUID.randomUUID().toString()) - .process(data, entity); - } - - private void createDocument(List data, String jwtToken) throws IOException { - for (Map entity : data) { - // Handle attachments if present - List> attachments = (List>) entity.get("attachments"); - if (attachments != null) { - for (Map attachment : attachments) { - CmisDocument cmisDocument = new CmisDocument(); - cmisDocument.setFileName(attachment.get("fileName").toString()); - InputStream contentStream = (InputStream) attachment.get("content"); - cmisDocument.setContent(contentStream); - cmisDocument.setParentId(attachment.get("up__ID").toString()); - - SDMService sdmService = new SDMServiceImpl(); - sdmService.createDocument(cmisDocument, jwtToken); - } - } - } - } -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/model/CmisDocument.java b/sdm/src/main/java/com/sap/cds/sdm/model/CmisDocument.java deleted file mode 100644 index 305bf7ec..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/model/CmisDocument.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.sap.cds.sdm.model; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import java.io.InputStream; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@JsonIgnoreProperties(ignoreUnknown = true) -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class CmisDocument { - private String fileName; - private InputStream content; - private String parentId; -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/persistence/DBQuery.java b/sdm/src/main/java/com/sap/cds/sdm/persistence/DBQuery.java deleted file mode 100644 index 41ea4f2f..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/persistence/DBQuery.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.sap.cds.sdm.persistence; - -public class DBQuery {} diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/RegisterService.java b/sdm/src/main/java/com/sap/cds/sdm/service/RegisterService.java deleted file mode 100644 index 01eadd91..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/service/RegisterService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sap.cds.sdm.service; - -import com.sap.cds.services.Service; - -public interface RegisterService extends Service { - String SDM_NAME = "SDMAttachmentService$Default"; -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/SDMAttachmentsService.java b/sdm/src/main/java/com/sap/cds/sdm/service/SDMAttachmentsService.java deleted file mode 100644 index b93fa969..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/service/SDMAttachmentsService.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.sap.cds.sdm.service; - -import com.sap.cds.feature.attachments.generated.cds4j.sap.attachments.MediaData; -import com.sap.cds.feature.attachments.service.AttachmentService; -import com.sap.cds.feature.attachments.service.model.service.AttachmentModificationResult; -import com.sap.cds.feature.attachments.service.model.service.CreateAttachmentInput; -import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentCreateEventContext; -import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentMarkAsDeletedEventContext; -import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentReadEventContext; -import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentRestoreEventContext; -import com.sap.cds.services.ServiceDelegator; -import java.io.InputStream; -import java.time.Instant; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SDMAttachmentsService extends ServiceDelegator - implements AttachmentService, RegisterService { - private static final Logger logger = LoggerFactory.getLogger(SDMAttachmentsService.class); - - public SDMAttachmentsService() { - super(SDM_NAME); - } - - @Override - public InputStream readAttachment(String contentId) { - logger.info("Reading attachment with document id: {}", contentId); - - var readContext = AttachmentReadEventContext.create(); - readContext.setContentId(contentId); - readContext.setData(MediaData.create()); - - emit(readContext); - - return readContext.getData().getContent(); - } - - @Override - public AttachmentModificationResult createAttachment(CreateAttachmentInput input) { - logger.info( - "Creating attachment for entity name: {}", input.attachmentEntity().getQualifiedName()); - var createContext = AttachmentCreateEventContext.create(); - createContext.setAttachmentIds(input.attachmentIds()); - createContext.setAttachmentEntity(input.attachmentEntity()); - var mediaData = MediaData.create(); - mediaData.setFileName(input.fileName()); - mediaData.setMimeType(input.mimeType()); - mediaData.setContent(input.content()); - createContext.setData(mediaData); - - emit(createContext); - - return new AttachmentModificationResult( - Boolean.TRUE.equals(createContext.getIsInternalStored()), - createContext.getContentId(), - createContext.getData().getStatus()); - } - - @Override - public void markAttachmentAsDeleted(String contentId) { - logger.info("Marking attachment as deleted for document id: {}", contentId); - - var deleteContext = AttachmentMarkAsDeletedEventContext.create(); - deleteContext.setContentId(contentId); - - emit(deleteContext); - } - - @Override - public void restoreAttachment(Instant restoreTimestamp) { - logger.info("Restoring deleted attachment for timestamp: {}", restoreTimestamp); - var restoreContext = AttachmentRestoreEventContext.create(); - restoreContext.setRestoreTimestamp(restoreTimestamp); - - emit(restoreContext); - } -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/SDMService.java b/sdm/src/main/java/com/sap/cds/sdm/service/SDMService.java deleted file mode 100644 index 02f380dc..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/service/SDMService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sap.cds.sdm.service; - -import com.sap.cds.sdm.model.CmisDocument; -import java.io.IOException; - -public interface SDMService { - public String createDocument(CmisDocument cmisDocument, String jwtToken) throws IOException; - - public void readDocument(); - - public void deleteDocument(); - - public String createFolder(); -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java b/sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java deleted file mode 100644 index 816d23a5..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.sap.cds.sdm.service; - -import com.sap.cds.sdm.constants.SDMConstants; -import com.sap.cds.sdm.handler.TokenHandler; -import com.sap.cds.sdm.model.CmisDocument; -import com.sap.cds.sdm.model.SDMCredentials; -import java.io.IOException; -import okhttp3.*; -import org.apache.commons.io.IOUtils; - -public class SDMServiceImpl implements SDMService { - @Override - public String createDocument(CmisDocument cmisDocument, String jwtToken) throws IOException { - OkHttpClient client = new OkHttpClient(); - SDMCredentials sdmCredentials = TokenHandler.getSDMCredentials(); - String accessToken = TokenHandler.getDIToken(jwtToken, sdmCredentials); - String sdmUrl = sdmCredentials.getUrl() + "browser/" + SDMConstants.REPOSITORY_ID + "/root"; - - RequestBody requestBody = - new MultipartBody.Builder() - .setType(MultipartBody.FORM) - .addFormDataPart("cmisaction", "createDocument") - .addFormDataPart("propertyId[0]", "cmis:name") - .addFormDataPart("propertyValue[0]", cmisDocument.getFileName()) - .addFormDataPart("propertyId[1]", "cmis:objectTypeId") - .addFormDataPart("propertyValue[1]", "cmis:document") - .addFormDataPart("succinct", "true") - .addFormDataPart( - "filename", - cmisDocument.getFileName(), - RequestBody.create( - IOUtils.toByteArray(cmisDocument.getContent()), - MediaType.parse("application/octet-stream"))) - .build(); - - Request request = - new Request.Builder() - .url(sdmUrl) - .addHeader("Authorization", "Bearer " + accessToken) - .post(requestBody) - .build(); - - try (Response response = client.newCall(request).execute()) { - if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); - return response.body().string(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public void readDocument() {} - - @Override - public void deleteDocument() {} - - @Override - public String createFolder() { - return null; - } -} diff --git a/sdm/src/main/java/com/sap/cds/sdm/util/HelperUtil.java b/sdm/src/main/java/com/sap/cds/sdm/util/HelperUtil.java deleted file mode 100644 index 089b9d03..00000000 --- a/sdm/src/main/java/com/sap/cds/sdm/util/HelperUtil.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.sap.cds.sdm.util; - -public class HelperUtil {} diff --git a/sdm/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration b/sdm/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration deleted file mode 100644 index f67e8468..00000000 --- a/sdm/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration +++ /dev/null @@ -1 +0,0 @@ -com.sap.cds.sdm.configuration.Registration \ No newline at end of file diff --git a/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments-annotations.cds b/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments-annotations.cds index c140e59d..bc3ccf0e 100644 --- a/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments-annotations.cds +++ b/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments-annotations.cds @@ -3,10 +3,21 @@ using { sap.attachments.Attachments } from './attachments'; -annotate MediaData with @UI.MediaResource: { Stream: content } { - content @Core.MediaType: mimeType @odata.draft.skip; - mimeType @Core.IsMediaType; - status @readonly; +annotate MediaData with @UI.MediaResource: {Stream: content} { + content @( + title : '{i18n>attachment_content}', + Core.MediaType : mimeType, + ContentDisposition.Filename: fileName, + ContentDisposition.Type : 'inline' + ); + mimeType @( + title: '{i18n>attachment_mimeType}', + Core.IsMediaType + ); + fileName @(title: '{i18n>attachment_fileName}'); + status @(title: '{i18n>attachment_status}'); + contentId @(UI.Hidden: true); + scannedAt @(UI.Hidden: true); } annotate Attachments with @UI: { @@ -22,12 +33,11 @@ annotate Attachments with @UI: { {Value: createdBy}, {Value: note} ] +} { + note @(title: '{i18n>attachment_note}'); + modifiedAt @(odata.etag); } -{ - content - @Core.ContentDisposition: { Filename: fileName } - @Core.Immutable -} + annotate Attachments with @Common: {SideEffects #ContentChanged: { SourceProperties: [content], TargetProperties: ['status'] diff --git a/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments.cds b/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments.cds index e2953295..4ca411e3 100644 --- a/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments.cds +++ b/sdm/src/main/resources/cds/com.sap.cds/sdm/attachments.cds @@ -24,5 +24,4 @@ aspect MediaData @(_is_media_data) { aspect Attachments : cuid, managed, MediaData { note : String; - } diff --git a/sdm/src/test/java/com/sap/cds/handler/SDMAttachmentsServiceHandlerTest.java b/sdm/src/test/java/com/sap/cds/handler/SDMAttachmentsHandlerTest.java similarity index 66% rename from sdm/src/test/java/com/sap/cds/handler/SDMAttachmentsServiceHandlerTest.java rename to sdm/src/test/java/com/sap/cds/handler/SDMAttachmentsHandlerTest.java index 18ab6834..483dea77 100644 --- a/sdm/src/test/java/com/sap/cds/handler/SDMAttachmentsServiceHandlerTest.java +++ b/sdm/src/test/java/com/sap/cds/handler/SDMAttachmentsHandlerTest.java @@ -2,18 +2,18 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.sap.cds.sdm.service.handler.SDMAttachmentsServiceHandler; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockitoAnnotations; -public class SDMAttachmentsServiceHandlerTest { - private SDMAttachmentsServiceHandler handler; +public class SDMAttachmentsHandlerTest { + + private SDMAttachmentsHandler handler; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - handler = new SDMAttachmentsServiceHandler(); + handler = new SDMAttachmentsHandler(); } @Test