2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.openecomp.sdc.be.servlets;
22 import com.jcabi.aspects.Loggable;
23 import fj.data.Either;
24 import io.swagger.v3.oas.annotations.Operation;
25 import io.swagger.v3.oas.annotations.Parameter;
26 import io.swagger.v3.oas.annotations.media.ArraySchema;
27 import io.swagger.v3.oas.annotations.media.Content;
28 import io.swagger.v3.oas.annotations.media.Schema;
29 import io.swagger.v3.oas.annotations.responses.ApiResponse;
30 import io.swagger.v3.oas.annotations.servers.Server;
31 import io.swagger.v3.oas.annotations.servers.Servers;
32 import io.swagger.v3.oas.annotations.tags.Tag;
33 import io.swagger.v3.oas.annotations.tags.Tags;
35 import java.io.IOException;
36 import java.util.List;
39 import javax.inject.Inject;
40 import javax.servlet.ServletContext;
41 import javax.servlet.http.HttpServletRequest;
42 import javax.ws.rs.Consumes;
43 import javax.ws.rs.DELETE;
44 import javax.ws.rs.GET;
45 import javax.ws.rs.HeaderParam;
46 import javax.ws.rs.POST;
47 import javax.ws.rs.PUT;
48 import javax.ws.rs.Path;
49 import javax.ws.rs.PathParam;
50 import javax.ws.rs.Produces;
51 import javax.ws.rs.QueryParam;
52 import javax.ws.rs.core.Context;
53 import javax.ws.rs.core.MediaType;
54 import javax.ws.rs.core.Response;
55 import org.apache.http.HttpStatus;
56 import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
57 import org.glassfish.jersey.media.multipart.FormDataParam;
58 import org.json.JSONException;
59 import org.json.JSONObject;
60 import org.keycloak.representations.AccessToken;
61 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
62 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
63 import org.openecomp.sdc.be.components.impl.ImportUtils;
64 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
65 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
66 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
67 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
68 import org.openecomp.sdc.be.config.BeEcompErrorManager;
69 import org.openecomp.sdc.be.dao.api.ActionStatus;
70 import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
71 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
72 import org.openecomp.sdc.be.datatypes.enums.DeleteActionEnum;
73 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
74 import org.openecomp.sdc.be.impl.ComponentsUtils;
75 import org.openecomp.sdc.be.impl.ServletUtils;
76 import org.openecomp.sdc.be.model.Resource;
77 import org.openecomp.sdc.be.model.UploadResourceInfo;
78 import org.openecomp.sdc.be.model.User;
79 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
80 import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData;
81 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
82 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
83 import org.openecomp.sdc.common.api.Constants;
84 import org.openecomp.sdc.common.datastructure.Wrapper;
85 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
86 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
87 import org.openecomp.sdc.common.log.enums.StatusCode;
88 import org.openecomp.sdc.common.log.wrappers.Logger;
89 import org.openecomp.sdc.common.util.ValidationUtils;
90 import org.openecomp.sdc.common.zip.exception.ZipException;
91 import org.openecomp.sdc.exception.ResponseFormat;
92 import org.openecomp.sdc.common.util.Multitenancy;
93 import org.springframework.stereotype.Controller;
95 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
97 @Tags({@Tag(name = "SDCE-2 APIs")})
98 @Servers({@Server(url = "/sdc2/rest")})
100 public class ResourcesServlet extends AbstractValidationsServlet {
102 private static final Logger log = Logger.getLogger(ResourcesServlet.class);
103 private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ResourcesServlet.class.getName());
104 private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
105 private static final String MODIFIER_ID_IS = "modifier id is {}";
106 private final ResourceBusinessLogic resourceBusinessLogic;
109 public ResourcesServlet(ComponentInstanceBusinessLogic componentInstanceBL,
110 ResourceBusinessLogic resourceBusinessLogic, ComponentsUtils componentsUtils, ServletUtils servletUtils,
111 ResourceImportManager resourceImportManager) {
112 super(componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
113 this.resourceBusinessLogic = resourceBusinessLogic;
118 @Consumes(MediaType.APPLICATION_JSON)
119 @Produces(MediaType.APPLICATION_JSON)
120 @Operation(description = "Create Resource", method = "POST", summary = "Returns created resource", responses = {
121 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
122 @ApiResponse(responseCode = "201", description = "Resource created"),
123 @ApiResponse(responseCode = "403", description = "Restricted operation"),
124 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
125 @ApiResponse(responseCode = "409", description = "Resource already exist"),
126 @ApiResponse(responseCode = "401", description = "Unauthorized Tenant")})
127 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
128 public Response createResource(@Parameter(description = "Resource object to be created", required = true) String data,
129 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId)
130 throws IOException, ZipException {
131 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
133 String url = request.getMethod() + " " + request.getRequestURI();
134 log.debug(START_HANDLE_REQUEST_OF, url);
136 User modifier = new User();
137 modifier.setUserId(userId);
138 log.debug(MODIFIER_ID_IS, userId);
139 loggerSupportability.log(LoggerSupportabilityActions.CREATE_RESOURCE, StatusCode.STARTED, "Starting to create Resource by user {}", userId);
142 Wrapper<Response> responseWrapper = new Wrapper<>();
144 if (isUIImport(data)) {
145 performUIImport(responseWrapper, data, request, userId, null);
149 Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier);
150 if (convertResponse.isRight()) {
151 log.debug("failed to parse resource");
152 response = buildErrorResponse(convertResponse.right().value());
155 Multitenancy keyaccess = new Multitenancy();
156 Resource resource = convertResponse.left().value();
157 if (keyaccess.multiTenancyCheck())
159 AccessToken.Access realmAccess = keyaccess.getAccessToken(request).getRealmAccess();
160 Set<String> realmroles = realmAccess.getRoles();
161 boolean match = realmroles.contains(resource.getTenant());
163 Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
164 Object representation = RepresentationUtils.toRepresentation(createdResource);
165 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
166 responseWrapper.setInnerElement(response);
168 .log(LoggerSupportabilityActions.CREATE_RESOURCE, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
169 "Resource successfully created user {}", userId);
171 return Response.status(401, "Unauthorized Tenant").build();
174 Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
175 Object representation = RepresentationUtils.toRepresentation(createdResource);
176 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
177 responseWrapper.setInnerElement(response);
179 .log(LoggerSupportabilityActions.CREATE_RESOURCE, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
180 "Resource successfully created user {}", userId);
183 return responseWrapper.getInnerElement();
184 } catch (final IOException | ZipException e) {
185 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource");
186 log.debug("create resource failed with exception", e);
191 private boolean isUIImport(String data) {
194 JSONObject json = new JSONObject(data);
195 String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME);
196 isUIImport = payloadName != null && !payloadName.isEmpty();
197 } catch (JSONException e) {
198 log.debug("failed to parse json sent from client, json:{}", data, e);
204 private void performUIImport(final Wrapper<Response> responseWrapper, final String data, final HttpServletRequest request, final String userId,
205 final String resourceUniqueId) throws ZipException {
206 Wrapper<User> userWrapper = new Wrapper<>();
207 Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
208 Wrapper<String> yamlStringWrapper = new Wrapper<>();
209 ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI;
210 commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data);
211 if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
212 fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum,
214 // PayLoad Validations
215 commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
217 specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request,
218 data, resourceAuthorityEnum);
219 if (responseWrapper.isEmpty()) {
220 handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(),
221 yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId);
225 private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) {
226 return getComponentsUtils()
227 .convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE);
230 private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) {
231 Either<Resource, ResponseFormat> ret = getComponentsUtils()
232 .convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA,
233 ComponentTypeEnum.RESOURCE);
234 if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow)
235 ret.left().value().setRequirements(null);
236 ret.left().value().setCapabilities(null);
242 @Path("/resources/{resourceId}")
243 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
244 public Response deleteResource(@PathParam("resourceId") final String resourceId,
245 @Parameter(description = "Optional parameter to determine the delete action: " +
246 "DELETE, which will permanently delete the Resource from the system or " +
247 "MARK_AS_DELETE, which will logically mark the Resource as deleted. Default action is to MARK_AS_DELETE")
248 @QueryParam("deleteAction") final DeleteActionEnum deleteAction,
249 @Context final HttpServletRequest request) {
250 String url = request.getMethod() + " " + request.getRequestURI();
251 log.debug(START_HANDLE_REQUEST_OF, url);
253 String userId = request.getHeader(Constants.USER_ID_HEADER);
254 User modifier = new User();
255 modifier.setUserId(userId);
256 log.debug(MODIFIER_ID_IS, userId);
257 loggerSupportability.log(LoggerSupportabilityActions.DELETE_RESOURCE, StatusCode.STARTED, "Starting to delete Resource by user {}", userId);
259 String resourceIdLower = resourceId.toLowerCase();
260 ResponseFormat actionResponse;
261 if (DeleteActionEnum.DELETE.equals(deleteAction)) {
262 resourceBusinessLogic.deleteResourceAllVersions(resourceId, modifier);
263 actionResponse = componentsUtils.getResponseFormat(ActionStatus.NO_CONTENT);
265 actionResponse = resourceBusinessLogic.deleteResource(resourceIdLower, modifier);
267 if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
268 log.debug("failed to delete resource");
269 return buildErrorResponse(actionResponse);
272 loggerSupportability.log(LoggerSupportabilityActions.DELETE_RESOURCE, StatusCode.COMPLETE, "Ended delete Resource by user {}", userId);
273 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
274 } catch (Exception e) {
275 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource");
276 log.debug("delete resource failed with exception ", e);
282 @Path("/resources/{resourceName}/{version}")
283 @Operation(description = "Delete Resource By Name And Version", method = "DELETE", summary = "Returns no content", responses = {
284 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
285 @ApiResponse(responseCode = "204", description = "Resource deleted"),
286 @ApiResponse(responseCode = "403", description = "Restricted operation"),
287 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
288 @ApiResponse(responseCode = "404", description = "Resource not found")})
289 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
290 public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version,
291 @Context final HttpServletRequest request) {
292 ServletContext context = request.getSession().getServletContext();
293 String url = request.getMethod() + " " + request.getRequestURI();
294 log.debug(START_HANDLE_REQUEST_OF, url);
296 String userId = request.getHeader(Constants.USER_ID_HEADER);
297 User modifier = new User();
298 modifier.setUserId(userId);
299 log.debug(MODIFIER_ID_IS, userId);
301 ResourceBusinessLogic businessLogic = getResourceBL(context);
302 ResponseFormat actionResponse = businessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier);
303 if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
304 log.debug("failed to delete resource");
305 response = buildErrorResponse(actionResponse);
308 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
313 @Path("/resources/{resourceId}")
314 @Consumes(MediaType.APPLICATION_JSON)
315 @Produces(MediaType.APPLICATION_JSON)
316 @Operation(description = "Retrieve Resource", method = "GET", summary = "Returns resource according to resourceId", responses = {
317 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
318 @ApiResponse(responseCode = "200", description = "Resource found"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
319 @ApiResponse(responseCode = "404", description = "Resource not found")})
320 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
321 public Response getResourceById(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request,
322 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
323 ServletContext context = request.getSession().getServletContext();
324 String url = request.getMethod() + " " + request.getRequestURI();
325 log.debug(START_HANDLE_REQUEST_OF, url);
327 User modifier = new User();
328 modifier.setUserId(userId);
329 log.debug(MODIFIER_ID_IS, userId);
332 String resourceIdLower = resourceId.toLowerCase();
333 log.trace("get resource with id {}", resourceId);
334 Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResource(resourceIdLower, modifier);
335 if (actionResponse.isRight()) {
336 log.debug("failed to get resource");
337 response = buildErrorResponse(actionResponse.right().value());
340 Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
341 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
342 } catch (IOException e) {
343 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource");
344 log.debug("get resource failed with exception", e);
350 @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}")
351 @Consumes(MediaType.APPLICATION_JSON)
352 @Produces(MediaType.APPLICATION_JSON)
353 @Operation(description = "Retrieve Resource by name and version", method = "GET", summary = "Returns resource according to resourceId", responses = {
354 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
355 @ApiResponse(responseCode = "200", description = "Resource found"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
356 @ApiResponse(responseCode = "404", description = "Resource not found")})
357 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
358 public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName,
359 @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request,
360 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
362 User modifier = new User();
363 modifier.setUserId(userId);
364 log.debug(MODIFIER_ID_IS, userId);
367 Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic
368 .getResourceByNameAndVersion(resourceName, resourceVersion, userId);
369 if (actionResponse.isRight()) {
370 response = buildErrorResponse(actionResponse.right().value());
373 Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
374 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
375 } catch (IOException e) {
376 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version");
377 log.debug("get resource failed with exception", e);
383 @Path("/resources/validate-name/{resourceName}")
384 @Consumes(MediaType.APPLICATION_JSON)
385 @Produces(MediaType.APPLICATION_JSON)
386 @Operation(description = "validate resource name", method = "GET", summary = "checks if the chosen resource name is available ", responses = {
387 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
388 @ApiResponse(responseCode = "200", description = "Resource found"), @ApiResponse(responseCode = "403", description = "Restricted operation")})
389 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
390 public Response validateResourceName(@PathParam("resourceName") final String resourceName, @QueryParam("subtype") String resourceType,
391 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
392 String url = request.getMethod() + " " + request.getRequestURI();
393 log.debug(START_HANDLE_REQUEST_OF, url);
395 User modifier = new User();
396 modifier.setUserId(userId);
397 log.debug(MODIFIER_ID_IS, userId);
399 if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) {
400 log.debug("invalid resource type received");
401 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
404 ResourceTypeEnum typeEnum = null;
405 if (resourceType != null) {
406 typeEnum = ResourceTypeEnum.valueOf(resourceType);
408 Either<Map<String, Boolean>, ResponseFormat> actionResponse = resourceBusinessLogic
409 .validateResourceNameExists(resourceName, typeEnum, userId);
410 if (actionResponse.isRight()) {
411 log.debug("failed to validate resource name");
412 response = buildErrorResponse(actionResponse.right().value());
415 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
419 @Path("/resources/certified/abstract")
420 @Consumes(MediaType.APPLICATION_JSON)
421 @Produces(MediaType.APPLICATION_JSON)
422 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
423 public Response getCertifiedAbstractResources(@Context final HttpServletRequest request,
424 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
425 String url = request.getMethod() + " " + request.getRequestURI();
426 log.debug("(get) Start handle request of {}", url);
428 List<Resource> resources = resourceBusinessLogic.getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId);
429 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources));
430 } catch (IOException e) {
431 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources");
432 log.debug("getCertifiedAbstractResources failed with exception", e);
438 @Path("/resources/certified/notabstract")
439 @Consumes(MediaType.APPLICATION_JSON)
440 @Produces(MediaType.APPLICATION_JSON)
441 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
442 public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request,
443 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
444 String url = request.getMethod() + " " + request.getRequestURI();
445 log.debug("(get) Start handle request of {}", url);
447 List<Resource> resouces = resourceBusinessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId);
448 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces));
449 } catch (IOException e) {
450 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources");
451 log.debug("getCertifiedNotAbstractResources failed with exception", e);
457 @Path("/resources/{resourceId}/metadata")
458 @Consumes(MediaType.APPLICATION_JSON)
459 @Produces(MediaType.APPLICATION_JSON)
460 @Operation(description = "Update Resource Metadata", method = "PUT", summary = "Returns updated resource metadata", responses = {
461 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
462 @ApiResponse(responseCode = "200", description = "Resource metadata updated"),
463 @ApiResponse(responseCode = "403", description = "Restricted operation"),
464 @ApiResponse(responseCode = "400", description = "Invalid content")})
465 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
466 public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId,
467 @Parameter(description = "Resource metadata to be updated", required = true) String data,
468 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId)
470 String url = request.getMethod() + " " + request.getRequestURI();
471 log.debug(START_HANDLE_REQUEST_OF, url);
473 User modifier = new User();
474 modifier.setUserId(userId);
475 log.debug(MODIFIER_ID_IS, userId);
478 String resourceIdLower = resourceId.toLowerCase();
479 Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils()
480 .convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA,
481 ComponentTypeEnum.RESOURCE);
482 if (updateInfoResource.isRight()) {
483 log.debug("failed to parse resource metadata");
484 response = buildErrorResponse(updateInfoResource.right().value());
487 Resource updatedResource = resourceBusinessLogic
488 .updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false);
489 Object resource = RepresentationUtils.toRepresentation(updatedResource);
490 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
491 } catch (IOException e) {
492 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata");
493 log.debug("Update Resource Metadata failed with exception", e);
499 @Path("/resources/{resourceId}")
500 @Consumes(MediaType.APPLICATION_JSON)
501 @Produces(MediaType.APPLICATION_JSON)
502 @Operation(description = "Update Resource", method = "PUT", summary = "Returns updated resource", responses = {
503 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
504 @ApiResponse(responseCode = "200", description = "Resource updated"),
505 @ApiResponse(responseCode = "403", description = "Restricted operation"),
506 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
507 @ApiResponse(responseCode = "409", description = "Resource already exist")})
508 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
509 public Response updateResource(@Parameter(description = "Resource object to be updated", required = true) String data,
510 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
511 @PathParam(value = "resourceId") String resourceId) throws IOException, ZipException {
512 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
514 String url = request.getMethod() + " " + request.getRequestURI();
515 log.debug(START_HANDLE_REQUEST_OF, url);
517 User modifier = new User();
518 modifier.setUserId(userId);
519 log.debug(MODIFIER_ID_IS, userId);
520 loggerSupportability.log(LoggerSupportabilityActions.UPDATE_RESOURCE, StatusCode.STARTED, "Starting to update a resource by user {}", userId);
523 Wrapper<Response> responseWrapper = new Wrapper<>();
525 if (isUIImport(data)) {
526 performUIImport(responseWrapper, data, request, userId, resourceId);
528 Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier);
529 if (convertResponse.isRight()) {
530 log.debug("failed to parse resource");
531 response = buildErrorResponse(convertResponse.right().value());
534 Resource updatedResource = resourceBusinessLogic
535 .validateAndUpdateResourceFromCsar(convertResponse.left().value(), modifier, null, null, resourceId);
536 Object representation = RepresentationUtils.toRepresentation(updatedResource);
537 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
538 responseWrapper.setInnerElement(response);
540 .log(LoggerSupportabilityActions.UPDATE_RESOURCE, updatedResource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
541 "Ended update a resource by user {}", userId);
543 return responseWrapper.getInnerElement();
544 } catch (final IOException | ZipException e) {
545 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource");
546 log.debug("update resource failed with exception", e);
552 @Path("/resources/csar/{csaruuid}")
553 @Consumes(MediaType.APPLICATION_JSON)
554 @Produces(MediaType.APPLICATION_JSON)
555 @Operation(description = "Create Resource", method = "POST", summary = "Returns resource created from csar uuid", responses = {
556 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
557 @ApiResponse(responseCode = "201", description = "Resource retrieced"),
558 @ApiResponse(responseCode = "403", description = "Restricted operation"),
559 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
560 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
561 public Response getResourceFromCsar(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
562 @PathParam(value = "csaruuid") String csarUUID) throws IOException {
564 String url = request.getMethod() + " " + request.getRequestURI();
565 log.debug(START_HANDLE_REQUEST_OF, url);
566 // retrieve user details
567 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
568 User user = new User();
569 user.setUserId(userId);
570 log.debug("user id is {}", userId);
573 Either<Resource, ResponseFormat> eitherResource = resourceBusinessLogic
574 .getLatestResourceFromCsarUuid(ValidationUtils.sanitizeInputString(csarUUID), user);
576 if (eitherResource.isRight()) {
577 log.debug("failed to get resource from csarUuid : {}", csarUUID);
578 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT), eitherResource.right().value());
580 Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value());
581 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
584 } catch (IOException e) {
585 log.debug("get resource by csar failed with exception", e);
591 @Path("/resources/importReplaceResource")
592 @Produces(MediaType.APPLICATION_JSON)
593 @Operation(description = "Import Resource", method = "POST", summary = "Returns imported resource", responses = {
594 @ApiResponse(responseCode = "201", description = "Resource created"),
595 @ApiResponse(responseCode = "403", description = "Restricted operation"),
596 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
597 @ApiResponse(responseCode = "409", description = "Resource already exist")})
598 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
599 public Response importReplaceResource(
600 @Parameter(description = "The user id", required = true) @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
601 @Parameter(description = "X-ECOMP-RequestID header", required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
602 @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
603 @Parameter(description = "Determines the format of the body of the response", required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
604 @Parameter(description = "The username and password", required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
605 @Context final HttpServletRequest request, @Parameter(description = "FileInputStream") @FormDataParam("resourceZip") File file,
606 @Parameter(description = "ContentDisposition") @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader,
607 @Parameter(description = "resourceMetadata") @FormDataParam("resourceZipMetadata") String resourceInfoJsonString) {
609 String requestURI = request.getRequestURI();
610 String url = request.getMethod() + " " + requestURI;
611 log.debug("importReplaceResource,Start handle request of {}", url);
613 User modifier = new User();
614 modifier.setUserId(userId);
615 log.debug("importReplaceResource,modifier id is {}", userId);
616 log.debug("importReplaceResource,get file:{},fileName:{}", file, file.getName());
618 ResponseFormat responseFormat = null;
619 AuditingActionEnum auditingActionEnum = AuditingActionEnum.Import_Replace_Resource;
620 String assetType = "resources";
621 ComponentTypeEnum componentType = ComponentTypeEnum.findByParamName(assetType);
622 ResourceCommonInfo resourceCommonInfo = new ResourceCommonInfo(componentType.getValue());
623 DistributionData distributionData = new DistributionData(instanceIdHeader, requestURI);
625 if (instanceIdHeader == null || instanceIdHeader.isEmpty()) {
626 log.debug("importReplaceResource: Missing X-ECOMP-InstanceID header");
627 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
628 getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, resourceCommonInfo, requestId, null);
629 return buildErrorResponse(responseFormat);
632 Wrapper<Response> responseWrapper = new Wrapper<>();
634 Wrapper<User> userWrapper = new Wrapper<>();
635 Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
636 Wrapper<String> yamlStringWrapper = new Wrapper<>();
637 ResourceAuthorityTypeEnum serviceAuthorityEnum = ResourceAuthorityTypeEnum.CSAR_TYPE_BE;
638 // PayLoad Validations
639 commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, serviceAuthorityEnum, userId, resourceInfoJsonString);
640 fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, modifier, resourceInfoJsonString, serviceAuthorityEnum, file);
641 specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(),
642 request, resourceInfoJsonString, serviceAuthorityEnum);
643 log.debug("importReplaceResource:get payload:{}", uploadResourceInfoWrapper.getInnerElement().getPayloadData());
644 log.debug("importReplaceResource:get ResourceType:{}", uploadResourceInfoWrapper.getInnerElement().getResourceType());
645 if (responseWrapper.isEmpty()) {
646 log.debug("importReplaceService:start handleImport");
647 handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(),
648 yamlStringWrapper.getInnerElement(), serviceAuthorityEnum, true, null);
650 return responseWrapper.getInnerElement();
651 } catch (ZipException e) {
652 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Import Resource");
653 log.debug("import resource failed with exception", e);
654 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));