Skip to content

Commit 150bf7c

Browse files
Merge branch 'develop' into dependabot
2 parents 5f041ff + b416bea commit 150bf7c

23 files changed

Lines changed: 1297 additions & 130 deletions

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3131

3232
<excluded.generation.package>sdm/generated/</excluded.generation.package>
33-
<cds.services.version>3.5.0</cds.services.version>
33+
<cds.services.version>3.10.3</cds.services.version>
3434

3535
<generation-folder>src/gen</generation-folder>
3636

sdm/pom.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,6 @@
319319
<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
320320
<artifactId>resilience4j</artifactId>
321321
</exclusion>
322-
<exclusion>
323-
<groupId>com.sap.cloud.security</groupId>
324-
<artifactId>env</artifactId>
325-
</exclusion>
326322
<exclusion>
327323
<groupId>org.bouncycastle</groupId>
328324
<artifactId>bcprov-jdk18on</artifactId>

sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ private SDMConstants() {
99
}
1010

1111
public static final String REPOSITORY_ID = System.getenv("REPOSITORY_ID");
12+
public static final String SYSTEM_USER = "system-internal";
13+
public static final String DESTINATION_EXCEPTION =
14+
"Unable to get the destination for sdm service binding";
15+
1216
public static final String SDM_ANNOTATION_ADDITIONALPROPERTY_NAME =
1317
"SDM.Attachments.AdditionalProperty.name";
1418
public static final String SDM_ANNOTATION_ADDITIONALPROPERTY =
@@ -73,6 +77,8 @@ private SDMConstants() {
7377
public static final String FAILED_TO_FETCH_UP_ID = "Failed to fetch up_id";
7478
public static final String FAILED_TO_FETCH_FACET =
7579
"Invalid facet format, unable to extract required information.";
80+
public static final String FILENAME_WHITESPACE_WARNING_MESSAGE =
81+
"The following file(s) could not be updated because the filename(s) cannot be empty.";
7682

7783
public static String nameConstraintMessage(
7884
List<String> fileNameWithRestrictedCharacters, String operation) {

sdm/src/main/java/com/sap/cds/sdm/handler/TokenHandler.java

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
package com.sap.cds.sdm.handler;
22

33
import static com.sap.cds.sdm.constants.SDMConstants.NAMED_USER_FLOW;
4+
import static com.sap.cloud.sdk.cloudplatform.connectivity.OnBehalfOf.TECHNICAL_USER_CURRENT_TENANT;
45
import static java.util.Objects.requireNonNull;
56

67
import com.sap.cds.sdm.constants.SDMConstants;
78
import com.sap.cds.sdm.model.SDMCredentials;
9+
import com.sap.cds.sdm.service.SDMPropertySupplier;
10+
import com.sap.cds.sdm.service.SDMUser;
811
import com.sap.cds.services.environment.CdsProperties;
912
import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor;
1013
import com.sap.cloud.environment.servicebinding.api.ServiceBinding;
11-
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpClientFactory;
12-
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
13-
import com.sap.cloud.sdk.cloudplatform.connectivity.OAuth2DestinationBuilder;
14-
import com.sap.cloud.sdk.cloudplatform.connectivity.OnBehalfOf;
14+
import com.sap.cloud.environment.servicebinding.api.ServiceIdentifier;
15+
import com.sap.cloud.sdk.cloudplatform.connectivity.*;
1516
import com.sap.cloud.security.config.ClientCredentials;
1617
import java.nio.charset.StandardCharsets;
1718
import java.time.Duration;
1819
import java.util.List;
1920
import java.util.Map;
21+
import java.util.Optional;
2022
import org.apache.http.client.HttpClient;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
2125

2226
public class TokenHandler {
2327
private static final String SDM_TOKEN_ENDPOINT = "url";
@@ -29,13 +33,20 @@ public class TokenHandler {
2933

3034
private TokenHandler() {}
3135

36+
private static final Logger logger = LoggerFactory.getLogger(TokenHandler.class);
37+
3238
public static TokenHandler getTokenHandlerInstance() {
3339
if (instance == null) {
3440
instance = new TokenHandler();
3541
}
3642
return instance;
3743
}
3844

45+
static {
46+
OAuth2ServiceBindingDestinationLoader.registerPropertySupplier(
47+
ServiceIdentifier.of("sdm"), SDMPropertySupplier::new);
48+
}
49+
3950
public byte[] toBytes(String str) {
4051
return requireNonNull(str).getBytes(StandardCharsets.UTF_8);
4152
}
@@ -127,4 +138,48 @@ public HttpClient getHttpClient(
127138

128139
return builder.build().createHttpClient(destination);
129140
}
141+
142+
public HttpClient getHttpClientForAuthoritiesFlow(
143+
CdsProperties.ConnectionPool connectionPoolConfig, String user) {
144+
145+
Optional<HttpDestination> destinations = getHttpDestination(user);
146+
if (destinations.isPresent()) {
147+
DefaultHttpClientFactory.DefaultHttpClientFactoryBuilder builder =
148+
DefaultHttpClientFactory.builder();
149+
150+
if (connectionPoolConfig == null) {
151+
Duration timeout = Duration.ofSeconds(SDMConstants.CONNECTION_TIMEOUT);
152+
builder.timeoutMilliseconds((int) timeout.toMillis());
153+
builder.maxConnectionsPerRoute(SDMConstants.MAX_CONNECTIONS);
154+
builder.maxConnectionsTotal(SDMConstants.MAX_CONNECTIONS);
155+
} else {
156+
builder.timeoutMilliseconds((int) connectionPoolConfig.getTimeout().toMillis());
157+
builder.maxConnectionsPerRoute(connectionPoolConfig.getMaxConnectionsPerRoute());
158+
builder.maxConnectionsTotal(connectionPoolConfig.getMaxConnections());
159+
}
160+
161+
return builder.build().createHttpClient(destinations.get());
162+
}
163+
return null;
164+
}
165+
166+
private Optional<HttpDestination> getHttpDestination(String userName) {
167+
HttpDestination httpDestination;
168+
try {
169+
httpDestination =
170+
ServiceBindingDestinationLoader.defaultLoaderChain()
171+
.getDestination(getSDMDestinationOptions(userName));
172+
} catch (Exception exception) {
173+
logger.error("Error with fetching httpdestination " + exception.getCause());
174+
httpDestination = null;
175+
}
176+
return Optional.ofNullable(httpDestination);
177+
}
178+
179+
public static ServiceBindingDestinationOptions getSDMDestinationOptions(String userName) {
180+
return ServiceBindingDestinationOptions.forService(ServiceIdentifier.of("sdm"))
181+
.onBehalfOf(TECHNICAL_USER_CURRENT_TENANT)
182+
.withOption(SDMUser.of(userName))
183+
.build();
184+
}
130185
}

sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public void updateName(CdsCreateEventContext context, List<CdsData> data, String
7171
List<String> filesNotFound = new ArrayList<>();
7272
List<String> filesWithUnsupportedProperties = new ArrayList<>();
7373
Map<String, String> badRequest = new HashMap<>();
74+
List<String> fileWithWhiteSpace = new ArrayList<>();
7475
List<String> noSDMRoles = new ArrayList<>();
7576
for (Map<String, Object> entity : data) {
7677
List<Map<String, Object>> attachments = (List<Map<String, Object>>) entity.get(composition);
@@ -95,7 +96,8 @@ public void updateName(CdsCreateEventContext context, List<CdsData> data, String
9596
composition,
9697
attachmentEntity,
9798
secondaryPropertiesWithInvalidDefinitions,
98-
noSDMRoles);
99+
noSDMRoles,
100+
fileWithWhiteSpace);
99101
handleWarnings(
100102
context,
101103
fileNameWithRestrictedCharacters,
@@ -104,6 +106,7 @@ public void updateName(CdsCreateEventContext context, List<CdsData> data, String
104106
filesWithUnsupportedProperties,
105107
badRequest,
106108
propertyTitles,
109+
fileWithWhiteSpace,
107110
noSDMRoles);
108111
}
109112
}
@@ -130,7 +133,8 @@ private void processEntity(
130133
String composition,
131134
Optional<CdsEntity> attachmentEntity,
132135
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
133-
List<String> noSDMRoles)
136+
List<String> noSDMRoles,
137+
List<String> fileWithWhiteSpace)
134138
throws IOException {
135139
List<Map<String, Object>> attachments = (List<Map<String, Object>>) entity.get(composition);
136140
if (attachments != null) {
@@ -146,7 +150,8 @@ private void processEntity(
146150
composition,
147151
attachmentEntity,
148152
secondaryPropertiesWithInvalidDefinitions,
149-
noSDMRoles);
153+
noSDMRoles,
154+
fileWithWhiteSpace);
150155
}
151156
SecondaryPropertiesKey secondaryPropertiesKey =
152157
new SecondaryPropertiesKey(); // Emptying cache after attachments are updated in loop
@@ -166,6 +171,7 @@ private void processAttachment(
166171
String composition,
167172
Optional<CdsEntity> attachmentEntity,
168173
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
174+
List<String> fileWithWhiteSpace,
169175
List<String> noSDMRoles)
170176
throws IOException {
171177
String id = (String) attachment.get("ID");
@@ -230,8 +236,11 @@ private void processAttachment(
230236
throw new ServiceException("Filename cannot be empty");
231237
}
232238
} else {
233-
if (filenameInRequest == null) {
234-
throw new ServiceException("Filename cannot be empty");
239+
if (filenameInRequest == null || filenameInRequest.trim().length() == 0) {
240+
fileWithWhiteSpace.add(fileNameInDB);
241+
replacePropertiesInAttachment(
242+
attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties);
243+
235244
} else if (!fileNameInDB.equals(
236245
filenameInRequest)) { // If the file name in DB is not equal to the file name in
237246
// request, it means that the file name has been modified
@@ -322,6 +331,7 @@ private void handleWarnings(
322331
List<String> filesWithUnsupportedProperties,
323332
Map<String, String> badRequest,
324333
Map<String, String> propertyTitles,
334+
List<String> fileWithWhiteSpace,
325335
List<String> noSDMRoles) {
326336
if (!fileNameWithRestrictedCharacters.isEmpty()) {
327337
context
@@ -363,6 +373,14 @@ private void handleWarnings(
363373
if (!noSDMRoles.isEmpty()) {
364374
context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "create"));
365375
}
376+
if (!fileWithWhiteSpace.isEmpty()) {
377+
context
378+
.getMessages()
379+
.warn(
380+
String.format(
381+
SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE,
382+
String.join(", ", fileWithWhiteSpace)));
383+
}
366384
}
367385

368386
private List<String> getEntityCompositions(CdsCreateEventContext context) {

sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandler.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ private void renameDocument(
8282
List<String> filesWithUnsupportedProperties = new ArrayList<>();
8383
Map<String, String> badRequest = new HashMap<>();
8484
Map<String, String> propertyTitles = new HashMap<>();
85+
List<String> fileWithWhiteSpace = new ArrayList<>();
8586
List<String> noSDMRoles = new ArrayList<>();
8687
for (Map<String, Object> entity : data) {
8788
List<Map<String, Object>> attachments = (List<Map<String, Object>>) entity.get(composition);
@@ -109,7 +110,8 @@ private void renameDocument(
109110
filesWithUnsupportedProperties,
110111
badRequest,
111112
secondaryPropertiesWithInvalidDefinitions,
112-
noSDMRoles);
113+
noSDMRoles,
114+
fileWithWhiteSpace);
113115
}
114116
}
115117
handleWarnings(
@@ -120,7 +122,8 @@ private void renameDocument(
120122
filesWithUnsupportedProperties,
121123
badRequest,
122124
propertyTitles,
123-
noSDMRoles);
125+
noSDMRoles,
126+
fileWithWhiteSpace);
124127
}
125128

126129
private void processAttachments(
@@ -133,7 +136,8 @@ private void processAttachments(
133136
List<String> filesWithUnsupportedProperties,
134137
Map<String, String> badRequest,
135138
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
136-
List<String> noSDMRoles)
139+
List<String> noSDMRoles,
140+
List<String> fileWithWhiteSpace)
137141
throws IOException {
138142
Iterator<Map<String, Object>> iterator = attachments.iterator();
139143
while (iterator.hasNext()) {
@@ -148,7 +152,8 @@ private void processAttachments(
148152
filesWithUnsupportedProperties,
149153
badRequest,
150154
secondaryPropertiesWithInvalidDefinitions,
151-
noSDMRoles);
155+
noSDMRoles,
156+
fileWithWhiteSpace);
152157
}
153158
SecondaryPropertiesKey secondaryPropertiesKey = new SecondaryPropertiesKey();
154159
secondaryPropertiesKey.setRepositoryId(SDMConstants.REPOSITORY_ID);
@@ -168,7 +173,8 @@ public void processAttachment(
168173
List<String> filesWithUnsupportedProperties,
169174
Map<String, String> badRequest,
170175
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
171-
List<String> noSDMRoles)
176+
List<String> noSDMRoles,
177+
List<String> fileWithWhiteSpace)
172178
throws IOException {
173179
String id = (String) attachment.get("ID");
174180
Map<String, String> secondaryTypeProperties =
@@ -222,8 +228,10 @@ public void processAttachment(
222228
throw new ServiceException("Filename cannot be empty");
223229
}
224230
} else {
225-
if (filenameInRequest == null) {
226-
throw new ServiceException("Filename cannot be empty");
231+
if (filenameInRequest == null || filenameInRequest.trim().length() == 0) {
232+
fileWithWhiteSpace.add(fileNameInDB);
233+
replacePropertiesInAttachment(
234+
attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties);
227235
} else if (!fileNameInDB.equals(filenameInRequest)) {
228236
updatedSecondaryProperties.put("filename", filenameInRequest);
229237
}
@@ -313,7 +321,8 @@ private void handleWarnings(
313321
List<String> filesWithUnsupportedProperties,
314322
Map<String, String> badRequest,
315323
Map<String, String> propertyTitles,
316-
List<String> noSDMRoles) {
324+
List<String> noSDMRoles,
325+
List<String> fileWithWhiteSpace) {
317326
if (!fileNameWithRestrictedCharacters.isEmpty()) {
318327
context
319328
.getMessages()
@@ -353,6 +362,14 @@ private void handleWarnings(
353362
if (!noSDMRoles.isEmpty()) {
354363
context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "update"));
355364
}
365+
if (!fileWithWhiteSpace.isEmpty()) {
366+
context
367+
.getMessages()
368+
.warn(
369+
String.format(
370+
SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE,
371+
String.join(", ", fileWithWhiteSpace)));
372+
}
356373
}
357374

358375
private List<String> getEntityCompositions(CdsUpdateEventContext context) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.sap.cds.sdm.service;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultOAuth2PropertySupplier;
5+
import com.sap.cloud.sdk.cloudplatform.connectivity.OAuth2Options;
6+
import com.sap.cloud.sdk.cloudplatform.connectivity.ServiceBindingDestinationOptions;
7+
import io.reactivex.annotations.NonNull;
8+
import java.net.URI;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
public class SDMPropertySupplier extends DefaultOAuth2PropertySupplier {
12+
13+
public SDMPropertySupplier(ServiceBindingDestinationOptions options) {
14+
super(options);
15+
}
16+
17+
@NonNull
18+
@Override
19+
public URI getServiceUri() {
20+
return getCredentialOrThrow(URI.class, "endpoints", "ecmservice", "url");
21+
}
22+
23+
@NotNull
24+
@Override
25+
public OAuth2Options getOAuth2Options() {
26+
var builder = OAuth2Options.builder();
27+
var user = this.options.getOption(SDMUser.class);
28+
if (!user.isEmpty()) {
29+
var objectMapper = new ObjectMapper();
30+
var azAttrNode = objectMapper.createObjectNode();
31+
// add X-EcmUserEnc attribute
32+
azAttrNode.put("X-EcmUserEnc", user.get());
33+
34+
// add X-EcmAddPrincipals attribute
35+
azAttrNode.put("X-EcmAddPrincipals", user.get());
36+
var authoritiesNode = objectMapper.createObjectNode();
37+
authoritiesNode.set("az_attr", azAttrNode);
38+
builder.withTokenRetrievalParameter("authorities", authoritiesNode.toString());
39+
}
40+
return builder.build();
41+
}
42+
}

sdm/src/main/java/com/sap/cds/sdm/service/SDMService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public String getFolderIdByPath(
3333

3434
public Boolean isRepositoryVersioned(JSONObject repoInfo, String repositoryId) throws IOException;
3535

36-
public int deleteDocument(String cmisaction, String objectId) throws IOException;
36+
public int deleteDocument(String cmisaction, String objectId, String user) throws IOException;
3737

3838
public void readDocument(
3939
String objectId, SDMCredentials sdmCredentials, AttachmentReadEventContext context)

0 commit comments

Comments
 (0)