Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

concord-server: close MultipartInput explicitly #1084

Merged
merged 1 commit into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,14 @@ public Response continueSession(@Context UriInfo uriInfo,
@PathParam("formName") String formName,
MultipartInput data) {

if (isV2(processInstanceId)) {
return customFormServiceV2.continueSession(uriInfo, headers, processInstanceId, formName, data);
} else {
return customFormServiceV1.continueSession(uriInfo, headers, processInstanceId, formName, data);
try {
if (isV2(processInstanceId)) {
return customFormServiceV2.continueSession(uriInfo, headers, processInstanceId, formName, data);
} else {
return customFormServiceV1.continueSession(uriInfo, headers, processInstanceId, formName, data);
}
} finally {
data.close();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private FormSessionResponse startSession(ProcessKey processKey, String formName)
// copy shared resources (if present)
copySharedResources(processKey, dst);
} catch (IOException e) {
log.warn("startSession ['{}', '{}'] -> error while preparing a custom form: {}", processKey, formName, e);
log.warn("startSession ['{}', '{}'] -> error while preparing a custom form: {}", processKey, formName, e.getMessage());
throw new ConcordApplicationException("Error while preparing a custom form", e);
}

Expand Down Expand Up @@ -182,8 +182,12 @@ public Response continueSession(@Context UriInfo uriInfo,
@PathParam("formName") String formName,
MultipartInput data) {

ProcessKey processKey = assertKey(processInstanceId);
return continueSession(uriInfo, headers, processKey, formName, MultipartUtils.toMap(data));
try {
ProcessKey processKey = assertKey(processInstanceId);
return continueSession(uriInfo, headers, processKey, formName, MultipartUtils.toMap(data));
} finally {
data.close();
}
}

private Response continueSession(UriInfo uriInfo, HttpHeaders headers, ProcessKey processKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,12 @@ public Response continueSession(@Context UriInfo uriInfo,
@PathParam("formName") String formName,
MultipartInput data) {

ProcessKey processKey = assertKey(processInstanceId);
return continueSession(uriInfo, headers, processKey, formName, MultipartUtils.toMap(data));
try {
ProcessKey processKey = assertKey(processInstanceId);
return continueSession(uriInfo, headers, processKey, formName, MultipartUtils.toMap(data));
} finally {
data.close();
}
}

private Response continueSession(UriInfo uriInfo, HttpHeaders headers, ProcessKey processKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,25 @@ public GenericOperationResult access(
public ProcessCardOperationResponse createOrUpdate(
@Parameter(schema = @Schema(type = "object", implementation = ProcessCardRequest.class)) MultipartInput input) throws IOException {

ProcessCardRequest r = ProcessCardRequest.from(input);

UUID orgId = organizationManager.assertAccess(r.getOrgId(), r.getOrgName(), false).getId();
UUID projectId = assertProject(orgId, r);
UUID repoId = getRepo(projectId, r);
String name = r.getName();
Optional<String> entryPoint = Optional.ofNullable(r.getEntryPoint());
String description = r.getDescription();
Map<String, Object> data = r.getData();
UUID id = r.getId();
Integer orderId = r.getOrderId();

try (InputStream icon = r.getIcon();
InputStream form = r.getForm()) {
return processCardManager.createOrUpdate(id, projectId, repoId, name, entryPoint, description, icon, form, data, orderId);
try {
ProcessCardRequest r = ProcessCardRequest.from(input);

UUID orgId = organizationManager.assertAccess(r.getOrgId(), r.getOrgName(), false).getId();
UUID projectId = assertProject(orgId, r);
UUID repoId = getRepo(projectId, r);
String name = r.getName();
Optional<String> entryPoint = Optional.ofNullable(r.getEntryPoint());
String description = r.getDescription();
Map<String, Object> data = r.getData();
UUID id = r.getId();
Integer orderId = r.getOrderId();

try (InputStream icon = r.getIcon();
InputStream form = r.getForm()) {
return processCardManager.createOrUpdate(id, projectId, repoId, name, entryPoint, description, icon, form, data, orderId);
}
} finally {
input.close();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;

public class GetDataRequest {

public static GetDataRequest from(MultipartInput input) {
return new GetDataRequest(input);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ public SecretOperationResponse create(@PathParam("orgName") @ConcordKey String o
}
} catch (IOException e) {
throw new ConcordApplicationException("Error while processing the request: " + e.getMessage(), e);
} finally {
input.close();
}
}

Expand Down Expand Up @@ -201,33 +203,37 @@ public Response getData(@PathParam("orgName") @ConcordKey String orgName,
@PathParam("secretName") @ConcordKey String secretName,
@Parameter(schema = @Schema(type = "object", implementation = GetDataRequest.class)) MultipartInput input) {

GetDataRequest request = GetDataRequest.from(input);
try {
GetDataRequest request = GetDataRequest.from(input);

OrganizationEntry org = orgManager.assertAccess(orgName, false);
String password = request.getPassword();
OrganizationEntry org = orgManager.assertAccess(orgName, false);
String password = request.getPassword();

SecretDao.SecretDataEntry entry;
try {
entry = secretManager.getRaw(SecretManager.AccessScope.apiRequest(), org.getId(), secretName, password);
if (entry == null) {
throw new WebApplicationException("Secret not found: " + secretName, Status.NOT_FOUND);
SecretDao.SecretDataEntry entry;
try {
entry = secretManager.getRaw(SecretManager.AccessScope.apiRequest(), org.getId(), secretName, password);
if (entry == null) {
throw new WebApplicationException("Secret not found: " + secretName, Status.NOT_FOUND);
}
} catch (SecurityException e) {
log.warn("fetchSecret -> error: {}", e.getMessage());
throw new SecretException("Error while fetching a secret '" + secretName + "': " + e.getMessage());
} catch (ValidationErrorsException e) {
log.warn("fetchSecret -> error: {}", e.getMessage());
return null;
}
} catch (SecurityException e) {
log.warn("fetchSecret -> error: {}", e.getMessage());
throw new SecretException("Error while fetching a secret '" + secretName + "': " + e.getMessage());
} catch (ValidationErrorsException e) {
log.warn("fetchSecret -> error: {}", e.getMessage());
return null;
}

try {
return Response.ok((StreamingOutput) output -> output.write(entry.getData()),
MediaType.APPLICATION_OCTET_STREAM)
.header(Constants.Headers.SECRET_TYPE, entry.getType().name())
.build();
} catch (Exception e) {
log.error("fetchSecret ['{}'] -> error while fetching a secret", secretName, e);
throw new ConcordApplicationException("Error while fetching a secret '" + secretName + "': " + e.getMessage());
try {
return Response.ok((StreamingOutput) output -> output.write(entry.getData()),
MediaType.APPLICATION_OCTET_STREAM)
.header(Constants.Headers.SECRET_TYPE, entry.getType().name())
.build();
} catch (Exception e) {
log.error("fetchSecret ['{}'] -> error while fetching a secret", secretName, e);
throw new ConcordApplicationException("Error while fetching a secret '" + secretName + "': " + e.getMessage());
}
} finally {
input.close();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,34 +104,38 @@ public GenericOperationResult update(@PathParam("orgName") @ConcordKey String or
@PathParam("secretName") @ConcordKey String secretName,
@Parameter(schema = @Schema(type = "object", implementation = Object.class)) MultipartInput input) {

OrganizationEntry org = orgManager.assertAccess(orgName, true);
Set<UUID> projectIds = getProjectIds(
org.getId(),
MultipartUtils.getUUIDList(input, Constants.Multipart.PROJECT_IDS),
MultipartUtils.getStringList(input, Constants.Multipart.PROJECT_NAMES),
MultipartUtils.getUuid(input, Constants.Multipart.PROJECT_ID),
MultipartUtils.getString(input, Constants.Multipart.PROJECT_NAME)
);
try {
SecretUpdateParams newSecretParams = SecretUpdateParams.builder()
.newOrgId(MultipartUtils.getUuid(input, Constants.Multipart.ORG_ID))
.newOrgName(MultipartUtils.getString(input, Constants.Multipart.ORG_NAME))
.newProjectIds(projectIds)
.removeProjectLink(MultipartUtils.getBoolean(input, "removeProjectLink", false))
.newOwnerId(MultipartUtils.getUuid(input, "ownerId"))
.currentPassword(MultipartUtils.getString(input, Constants.Multipart.STORE_PASSWORD))
.newPassword(MultipartUtils.getString(input, Constants.Multipart.NEW_STORE_PASSWORD))
.newSecret(buildSecret(input))
.newName(MultipartUtils.getString(input, Constants.Multipart.NAME))
.newVisibility(SecretResourceUtils.getVisibility(input))
.build();

secretManager.update(org.getId(), secretName, newSecretParams);
} catch (IOException e) {
throw new ConcordApplicationException("Error while processing the request: " + e.getMessage(), e);
}
OrganizationEntry org = orgManager.assertAccess(orgName, true);
Set<UUID> projectIds = getProjectIds(
org.getId(),
MultipartUtils.getUUIDList(input, Constants.Multipart.PROJECT_IDS),
MultipartUtils.getStringList(input, Constants.Multipart.PROJECT_NAMES),
MultipartUtils.getUuid(input, Constants.Multipart.PROJECT_ID),
MultipartUtils.getString(input, Constants.Multipart.PROJECT_NAME)
);
try {
SecretUpdateParams newSecretParams = SecretUpdateParams.builder()
.newOrgId(MultipartUtils.getUuid(input, Constants.Multipart.ORG_ID))
.newOrgName(MultipartUtils.getString(input, Constants.Multipart.ORG_NAME))
.newProjectIds(projectIds)
.removeProjectLink(MultipartUtils.getBoolean(input, "removeProjectLink", false))
.newOwnerId(MultipartUtils.getUuid(input, "ownerId"))
.currentPassword(MultipartUtils.getString(input, Constants.Multipart.STORE_PASSWORD))
.newPassword(MultipartUtils.getString(input, Constants.Multipart.NEW_STORE_PASSWORD))
.newSecret(buildSecret(input))
.newName(MultipartUtils.getString(input, Constants.Multipart.NAME))
.newVisibility(SecretResourceUtils.getVisibility(input))
.build();

secretManager.update(org.getId(), secretName, newSecretParams);
} catch (IOException e) {
throw new ConcordApplicationException("Error while processing the request: " + e.getMessage(), e);
}

return new GenericOperationResult(OperationResult.UPDATED);
return new GenericOperationResult(OperationResult.UPDATED);
} finally {
input.close();
}
}

public Secret buildSecret(MultipartInput input) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,26 +271,30 @@ public StartProcessResponse start(@Parameter(schema = @Schema(type = "object", i
@Parameter(hidden = true) @Deprecated @QueryParam("out") String[] out,
@Context HttpServletRequest request) {

boolean sync2 = MultipartUtils.getBoolean(input, Constants.Multipart.SYNC, false);
if (sync || sync2) {
throw syncIsForbidden();
}

Payload payload;
try {
payload = payloadManager.createPayload(input, request);
boolean sync2 = MultipartUtils.getBoolean(input, Constants.Multipart.SYNC, false);
if (sync || sync2) {
throw syncIsForbidden();
}

// TODO remove after deprecating the old endpoints
payload = PayloadBuilder.basedOn(payload)
.parentInstanceId(parentInstanceId)
.mergeOutExpressions(out)
.build();
} catch (IOException e) {
log.error("start -> error creating a payload: {}", e.getMessage());
throw new ConcordApplicationException("Error creating a payload", e);
}
Payload payload;
try {
payload = payloadManager.createPayload(input, request);

return toResponse(processManager.start(payload));
// TODO remove after deprecating the old endpoints
payload = PayloadBuilder.basedOn(payload)
.parentInstanceId(parentInstanceId)
.mergeOutExpressions(out)
.build();
} catch (IOException e) {
log.error("start -> error creating a payload: {}", e.getMessage());
throw new ConcordApplicationException("Error creating a payload", e);
}

return toResponse(processManager.start(payload));
} finally {
input.close();
}
}

/**
Expand All @@ -310,27 +314,31 @@ public StartProcessResponse start(@PathParam("entryPoint") String entryPoint,
@Deprecated @DefaultValue("false") @QueryParam("sync") boolean sync,
@QueryParam("out") String[] out) {

if (sync) {
throw syncIsForbidden();
}
try {
if (sync) {
throw syncIsForbidden();
}

assertPartialKey(parentInstanceId);
assertPartialKey(parentInstanceId);

PartialProcessKey processKey = PartialProcessKey.from(UUID.randomUUID());
PartialProcessKey processKey = PartialProcessKey.from(UUID.randomUUID());

UUID orgId = OrganizationManager.DEFAULT_ORG_ID;
EntryPoint ep = payloadManager.parseEntryPoint(processKey, orgId, entryPoint);
UserPrincipal userPrincipal = UserPrincipal.assertCurrent();
UUID orgId = OrganizationManager.DEFAULT_ORG_ID;
EntryPoint ep = payloadManager.parseEntryPoint(processKey, orgId, entryPoint);
UserPrincipal userPrincipal = UserPrincipal.assertCurrent();

Payload payload;
try {
payload = payloadManager.createPayload(processKey, parentInstanceId, userPrincipal.getId(), userPrincipal.getUsername(), ep, input, out);
} catch (IOException e) {
log.error("start ['{}'] -> error creating a payload: {}", entryPoint, e);
throw new ConcordApplicationException("Error creating a payload", e);
}
Payload payload;
try {
payload = payloadManager.createPayload(processKey, parentInstanceId, userPrincipal.getId(), userPrincipal.getUsername(), ep, input, out);
} catch (IOException e) {
log.error("start ['{}'] -> error creating a payload: {}", entryPoint, e);
throw new ConcordApplicationException("Error creating a payload", e);
}

return toResponse(processManager.start(payload));
return toResponse(processManager.start(payload));
} finally {
input.close();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,25 +112,29 @@ public ResumeProcessResponse restore(@PathParam("id") UUID instanceId,
public void uploadCheckpoint(@PathParam("id") UUID instanceId,
@Parameter(schema = @Schema(type = "object", implementation = Object.class)) MultipartInput input) {

// TODO replace with ProcessKeyCache
ProcessEntry entry = processManager.assertProcess(instanceId);
ProcessKey processKey = new ProcessKey(entry.instanceId(), entry.createdAt());

UUID checkpointId = MultipartUtils.assertUuid(input, "id");
UUID correlationId = MultipartUtils.assertUuid(input, "correlationId");
String checkpointName = MultipartUtils.assertString(input, "name");
try (InputStream data = MultipartUtils.assertStream(input, "data");
TemporaryPath tmpIn = IOUtils.tempFile("checkpoint", ".zip")) {

Files.copy(data, tmpIn.path(), StandardCopyOption.REPLACE_EXISTING);
checkpointManager.importCheckpoint(processKey, checkpointId, correlationId, checkpointName, tmpIn.path());
} catch (ValidationErrorsException e) {
throw new ConcordApplicationException(e.getMessage(), Response.Status.BAD_REQUEST);
} catch (IOException e) {
log.error("uploadCheckpoint ['{}'] -> error", processKey, e);
throw new ConcordApplicationException("upload error: " + e.getMessage());
try {
// TODO replace with ProcessKeyCache
ProcessEntry entry = processManager.assertProcess(instanceId);
ProcessKey processKey = new ProcessKey(entry.instanceId(), entry.createdAt());

UUID checkpointId = MultipartUtils.assertUuid(input, "id");
UUID correlationId = MultipartUtils.assertUuid(input, "correlationId");
String checkpointName = MultipartUtils.assertString(input, "name");
try (InputStream data = MultipartUtils.assertStream(input, "data");
TemporaryPath tmpIn = IOUtils.tempFile("checkpoint", ".zip")) {

Files.copy(data, tmpIn.path(), StandardCopyOption.REPLACE_EXISTING);
checkpointManager.importCheckpoint(processKey, checkpointId, correlationId, checkpointName, tmpIn.path());
} catch (ValidationErrorsException e) {
throw new ConcordApplicationException(e.getMessage(), Response.Status.BAD_REQUEST);
} catch (IOException e) {
log.error("uploadCheckpoint ['{}'] -> error", processKey, e);
throw new ConcordApplicationException("upload error: " + e.getMessage());
}

log.info("uploadCheckpoint ['{}'] -> done", processKey);
} finally {
input.close();
}

log.info("uploadCheckpoint ['{}'] -> done", processKey);
}
}
Loading