You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by of...@apache.org on 2020/06/24 12:27:00 UTC

[incubator-dlab] 01/02: Merge branch 'audit' into develop

This is an automated email from the ASF dual-hosted git repository.

ofuks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git

commit 1f51bf71ebc7d0d7574f8525f23c4600e76c1529
Merge: 4e15862 cd374d8
Author: Oleh Fuks <ol...@gmail.com>
AuthorDate: Wed Jun 24 15:06:40 2020 +0300

    Merge branch 'audit' into develop
    
    # Conflicts:
    #	services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BucketResource.java
    #	services/self-service/src/main/java/com/epam/dlab/backendapi/service/BucketService.java
    #	services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BucketServiceImpl.java
    #	services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
    #	services/self-service/src/test/java/com/epam/dlab/backendapi/resources/ExploratoryResourceTest.java

 .../main/java/com/epam/dlab/model/StringList.java} |  34 +-
 .../java/com/epam/dlab/util/UsernameUtils.java     |   2 +-
 .../epam/dlab/rest/contracts/ComputationalAPI.java |   1 +
 .../azure/ComputationalResourceAzure.java          |   2 +-
 services/self-service/pom.xml                      |   6 +
 services/self-service/self-service.yml             |   4 +-
 .../dlab/backendapi/SelfServiceApplication.java    |  39 +-
 .../epam/dlab/backendapi/annotation/Audit.java}    |  24 +-
 .../UserGroupDao.java => annotation/Info.java}     |  18 +-
 .../ResourceName.java}                             |  18 +-
 .../conf/SelfServiceApplicationConfiguration.java  |   7 +
 .../dao/{UserGroupDao.java => AuditDAO.java}       |  15 +-
 .../com/epam/dlab/backendapi/dao/AuditDAOImpl.java | 162 ++++++
 .../java/com/epam/dlab/backendapi/dao/BaseDAO.java |   2 +
 .../epam/dlab/backendapi/dao/ExploratoryDAO.java   |  12 +-
 .../com/epam/dlab/backendapi/dao/UserGroupDao.java |   1 +
 .../epam/dlab/backendapi/dao/UserGroupDaoImpl.java |  28 +-
 .../dlab/backendapi/domain/AuditActionEnum.java}   |  10 +-
 .../dlab/backendapi/domain/AuditCreateDTO.java}    |  25 +-
 .../com/epam/dlab/backendapi/domain/AuditDTO.java} |  29 +-
 .../AuditPaginationDTO.java}                       |  40 +-
 .../AuditResourceTypeEnum.java}                    |  15 +-
 .../backendapi/interceptor/AuditInterceptor.java   | 122 +++++
 .../backendapi/modules/CloudProviderModule.java    |  11 +-
 .../epam/dlab/backendapi/modules/DevModule.java    |   6 +
 .../dlab/backendapi/modules/ProductionModule.java  |   6 +
 .../dlab/backendapi/resources/AuditResource.java   |  70 +++
 .../dlab/backendapi/resources/BucketResource.java  |   9 +-
 .../backendapi/resources/EndpointResource.java     |  16 +-
 .../backendapi/resources/ExploratoryResource.java  |   8 +-
 .../backendapi/resources/GitCredsResource.java     |  41 +-
 .../resources/ImageExploratoryResource.java        |   7 +-
 .../backendapi/resources/KeycloakResource.java     |  27 +-
 .../resources/LibExploratoryResource.java          |  22 +-
 .../dlab/backendapi/resources/ProjectResource.java |  11 +-
 .../backendapi/resources/SchedulerJobResource.java |   7 +-
 .../backendapi/resources/UserGroupResource.java    |   9 +-
 .../resources/aws/ComputationalResourceAws.java    |  83 ++--
 .../azure/ComputationalResourceAzure.java          |  73 +--
 .../resources/dto/HealthStatusPageDTO.java         |   2 +
 .../resources/dto/ProjectInfrastructureInfo.java   |   4 +-
 .../dto/UpdateGroupDTO.java}                       |  24 +-
 .../resources/gcp/ComputationalResourceGcp.java    | 103 ++--
 .../{UserGroupService.java => AuditService.java}   |  18 +-
 .../dlab/backendapi/service/BucketService.java     |   8 +-
 .../backendapi/service/ComputationalService.java   |  59 +--
 .../dlab/backendapi/service/EndpointService.java   |   6 +-
 .../backendapi/service/ExploratoryService.java     |   8 +-
 .../service/ImageExploratoryService.java           |   2 +-
 .../dlab/backendapi/service/LibraryService.java    |   4 +-
 .../dlab/backendapi/service/ProjectService.java    |  25 +-
 .../backendapi/service/SchedulerJobService.java    |   5 +-
 .../backendapi/service/SecurityServiceImpl.java    |  15 +-
 .../dlab/backendapi/service/UserGroupService.java  |   9 +-
 .../backendapi/service/impl/AuditServiceImpl.java  |  64 +++
 .../backendapi/service/impl/BucketServiceImpl.java |  17 +-
 .../service/impl/ComputationalServiceImpl.java     | 127 +++--
 .../service/impl/EndpointServiceImpl.java          |  83 ++--
 .../service/impl/EnvironmentServiceImpl.java       |  44 +-
 .../service/impl/ExploratoryServiceImpl.java       | 144 ++++--
 .../service/impl/GitCredentialServiceImpl.java     |  71 +--
 .../service/impl/ImageExploratoryServiceImpl.java  |  88 ++--
 .../impl/InfrastructureInfoServiceImpl.java        |  26 +-
 .../service/impl/LibraryServiceImpl.java           |  80 +--
 .../service/impl/ProjectServiceImpl.java           | 189 ++++---
 .../service/impl/SchedulerJobServiceImpl.java      | 207 ++++----
 .../service/impl/UserGroupServiceImpl.java         | 122 ++++-
 .../epam/dlab/backendapi/util/RequestBuilder.java  | 154 +++---
 .../management/endpoints/endpoints.component.ts    |   9 +-
 .../app/administration/roles/roles.component.ts    |  36 +-
 .../main/resources/webapp/src/app/app.module.ts    |  10 +-
 .../resources/webapp/src/app/app.routing.module.ts |  12 +-
 .../convert-action.pipe.ts}                        |  14 +-
 .../app/core/pipes/convert-action-pipe/index.ts}   |  20 +-
 .../resources/webapp/src/app/core/pipes/index.ts   |   1 +
 .../app/core/pipes/lib-sort-pipe/lib-sort.pipe.ts  |   6 +-
 .../services/applicationServiceFacade.service.ts   |  16 +
 .../webapp/src/app/core/services/audit.service.ts  |  47 ++
 .../audit/audit-grid/audit-grid.component.html     | 232 +++++++++
 .../audit/audit-grid/audit-grid.component.scss     | 276 +++++++++++
 .../audit/audit-grid/audit-grid.component.ts       | 208 ++++++++
 .../audit-toolbar/audit-toolbar.component.html}    |  14 +-
 .../audit-toolbar/audit-toolbar.component.scss}    |   0
 .../audit-toolbar/audit-toolbar.component.ts}      |  44 +-
 .../src/app/reports/audit/audit.component.ts       | 101 ++++
 .../audit/audit.module.ts}                         |  27 +-
 .../src/app/reports/audit/filter-audit.model.ts    |  27 +
 .../reporting-grid/reporting-grid.component.html   |   0
 .../reporting-grid/reporting-grid.component.scss   |   0
 .../reporting-grid/reporting-grid.component.ts     |   4 +-
 .../{ => reports}/reporting/reporting.component.ts |   8 +-
 .../{ => reports}/reporting/reporting.module.ts    |   6 +-
 .../reporting/toolbar/toolbar.component.html       |   4 +-
 .../reporting/toolbar/toolbar.component.scss       |   0
 .../reporting/toolbar/toolbar.component.ts         |   6 +-
 .../webapp/src/app/reports/reports.module.ts}      |  25 +-
 .../cluster-details/cluster-details.component.html |   2 +-
 .../cluster-details/cluster-details.component.ts   |   9 +-
 .../detail-dialog/detail-dialog.component.html     |   6 +-
 .../detail-dialog/detail-dialog.component.ts       |   6 +
 .../webapp/src/app/shared/form-controls/index.ts   |  17 +-
 .../multi-select-dropdown.component.html           |   6 +-
 .../notification-dialog.component.ts               |   7 +-
 .../src/app/shared/navbar/navbar.component.html    |  16 +-
 .../webapp/src/assets/styles/_dialogs.scss         |  10 +
 .../webapp/src/assets/styles/_general.scss         |   2 +
 .../resources/webapp/src/assets/styles/_theme.scss |  25 +-
 .../resources/ExploratoryResourceTest.java         | 229 ++++-----
 .../resources/ImageExploratoryResourceTest.java    |  14 +-
 .../resources/LibExploratoryResourceTest.java      |  46 +-
 .../resources/SchedulerJobResourceTest.java        |  25 +-
 .../resources/UserGroupResourceTest.java           |  39 +-
 .../service/impl/ComputationalServiceImplTest.java |  75 +--
 .../service/impl/EnvironmentServiceImplTest.java   | 110 ++--
 .../service/impl/ExploratoryServiceImplTest.java   | 132 ++---
 .../impl/ImageExploratoryServiceImplTest.java      |  10 +-
 .../service/impl/LibraryServiceImplTest.java       |  15 +-
 .../service/impl/SchedulerJobServiceImplTest.java  | 551 +++++++++++----------
 .../service/impl/UserGroupServiceImplTest.java     |  14 +-
 119 files changed, 3513 insertions(+), 1736 deletions(-)

diff --cc services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BucketResource.java
index 1cca27c,c4f7b6e..4ceb55e
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BucketResource.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BucketResource.java
@@@ -143,7 -138,7 +146,7 @@@ public class BucketResource 
                              fileSize = Long.parseLong(Streams.asString(stream));
                          }
                      } else {
-                         bucketService.uploadObject(userInfo, bucket, object, endpoint, stream, item.getContentType(), fileSize);
 -                        bucketService.uploadObjects(userInfo, bucket, object, endpoint, stream, fileSize, String.format(AUDIT_UPLOAD_MESSAGE, object, fileSize));
++                        bucketService.uploadObject(userInfo, bucket, object, endpoint, stream, item.getContentType(), fileSize, String.format(AUDIT_UPLOAD_MESSAGE, object, fileSize));
                      }
                  } catch (Exception e) {
                      log.error("Cannot upload object {} to bucket {}. {}", object, bucket, e.getMessage(), e);
diff --cc services/self-service/src/main/java/com/epam/dlab/backendapi/service/BucketService.java
index cd22ddc,1cb0769..8cf09dd
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BucketService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BucketService.java
@@@ -29,11 -29,9 +29,9 @@@ import java.util.List
  public interface BucketService {
      List<BucketDTO> getObjects(UserInfo userInfo, String bucket, String endpoint);
  
-     void uploadObject(UserInfo userInfo, String bucket, String object, String endpoint, InputStream inputStream, String contentType, long fileSize);
 -    void uploadObjects(UserInfo userInfo, String bucket, String object, String endpoint, InputStream inputStream, long fileSize, String auditInfo);
++    void uploadObject(UserInfo userInfo, String bucket, String object, String endpoint, InputStream inputStream, String contentType, long fileSize, String auditInfo);
  
-     void uploadFolder(UserInfo userInfo, String bucket, String folder, String endpoint);
+     void downloadObject(UserInfo userInfo, String bucket, String object, String endpoint, HttpServletResponse resp, String auditInfo);
  
-     void downloadObject(UserInfo userInfo, String bucket, String object, String endpoint, HttpServletResponse resp);
- 
-     void deleteObjects(UserInfo userInfo, String bucket, List<String> objects, String endpoint);
+     void deleteObjects(UserInfo userInfo, String bucket, List<String> objects, String endpoint, String auditInfo);
  }
diff --cc services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BucketServiceImpl.java
index 489c3e0,93fc12b..c2f9617
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BucketServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BucketServiceImpl.java
@@@ -80,8 -86,9 +88,9 @@@ public class BucketServiceImpl implemen
          }
      }
  
+     @Audit(action = UPLOAD, type = BUCKET)
      @Override
-     public void uploadObject(UserInfo userInfo, String bucket, String object, String endpoint, InputStream inputStream, String contentType, long fileSize) {
 -    public void uploadObjects(@User UserInfo userInfo, @ResourceName String bucket, String object, String endpoint, InputStream inputStream, long fileSize, @Info String auditInfo) {
++    public void uploadObject(@User UserInfo userInfo, @ResourceName String bucket, String object, String endpoint, InputStream inputStream,String contentType, long fileSize, @Info String auditInfo) {
          log.info("Uploading file {} for user {} to bucket {}", object, userInfo.getName(), bucket);
          try {
              EndpointDTO endpointDTO = endpointService.get(endpoint);
@@@ -97,28 -104,9 +106,29 @@@
          log.info("Finished uploading file {} for user {} to bucket {}", object, userInfo.getName(), bucket);
      }
  
 +    @Override
 +    public void uploadFolder(UserInfo userInfo, String bucket, String folder, String endpoint) {
 +        log.info("Uploading folder {} for user {} to bucket {}", folder, userInfo.getName(), bucket);
 +        try {
 +            if (!folder.endsWith("/")) {
 +                throw new DlabException("Folder doesn't end with '/'");
 +            }
 +            EndpointDTO endpointDTO = endpointService.get(endpoint);
 +            FolderUploadDTO dto = new FolderUploadDTO(bucket, folder);
 +            Response response = provisioningService.post(String.format(BUCKET_UPLOAD_FOLDER, endpointDTO.getUrl()), userInfo.getAccessToken(), dto, Response.class);
 +            if (response.getStatus() != HttpStatus.SC_OK) {
 +                throw new DlabException(String.format("Something went wrong. Response status is %s ", response.getStatus()));
 +            }
 +        } catch (Exception e) {
 +            log.error("Cannot upload folder {} to bucket {} for user {}, endpoint {}. Reason {}", folder, bucket, userInfo.getName(), endpoint, e.getMessage());
 +            throw new DlabException(String.format("Cannot upload object %s to bucket %s for user %s, endpoint %s. Reason %s", folder, bucket, userInfo.getName(), endpoint, e.getMessage()));
 +        }
 +        log.info("Finished uploading folder {} for user {} to bucket {}", folder, userInfo.getName(), bucket);
 +    }
 +
+     @Audit(action = DOWNLOAD, type = BUCKET)
      @Override
-     public void downloadObject(UserInfo userInfo, String bucket, String object, String endpoint, HttpServletResponse resp) {
+     public void downloadObject(@User UserInfo userInfo, @ResourceName String bucket, String object, String endpoint, HttpServletResponse resp, @Info String auditInfo) {
          log.info("Downloading file {} for user {} from bucket {}", object, userInfo.getName(), bucket);
          EndpointDTO endpointDTO = endpointService.get(endpoint);
          try (InputStream inputStream = provisioningService.getWithMediaTypes(String.format(BUCKET_DOWNLOAD_OBJECT, endpointDTO.getUrl(), bucket, encodeObject(object)), userInfo.getAccessToken(),
diff --cc services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
index 34f2424,282106a..2c6154e
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
@@@ -99,172 -116,212 +116,222 @@@ public class ProjectServiceImpl impleme
  	}
  
  	@BudgetLimited
 -    @Override
 -    public void create(UserInfo user, ProjectDTO projectDTO, @Project String resourceName) {
 -        if (!projectDAO.get(projectDTO.getName()).isPresent()) {
 -            projectDAO.create(projectDTO);
 -            createProjectOnCloud(user, projectDTO);
 -        } else {
 -            throw new ResourceConflictException("Project with passed name already exist in system");
 -        }
 -    }
 +	@Override
 +	public void create(UserInfo user, ProjectDTO projectDTO) {
 +		if (!projectDAO.get(projectDTO.getName()).isPresent()) {
 +			projectDAO.create(projectDTO);
 +			createProjectOnCloud(user, projectDTO);
 +		} else {
 +			throw new ResourceConflictException("Project with passed name already exist in system");
 +		}
 +	}
  
 -    @Override
 -    public ProjectDTO get(String name) {
 -        return projectDAO.get(name)
 -                .orElseThrow(projectNotFound());
 -    }
 +	@Override
 +	public ProjectDTO get(String name) {
 +		return projectDAO.get(name)
 +				.orElseThrow(projectNotFound());
 +	}
  
- 	@Override
- 	public void terminateEndpoint(UserInfo userInfo, String endpoint, String name) {
- 		projectActionOnCloud(userInfo, name, TERMINATE_PRJ_API, endpoint);
- 		projectDAO.updateEdgeStatus(name, endpoint, UserInstanceStatus.TERMINATING);
- 		exploratoryService.updateProjectExploratoryStatuses(name, endpoint, UserInstanceStatus.TERMINATING);
- 	}
+     @Audit(action = TERMINATE, type = EDGE_NODE)
+     @Override
+     public void terminateEndpoint(@User UserInfo userInfo, @ResourceName String endpoint, @Project String name) {
+         projectActionOnCloud(userInfo, name, TERMINATE_PRJ_API, endpoint);
+         projectDAO.updateEdgeStatus(name, endpoint, UserInstanceStatus.TERMINATING);
+         exploratoryService.updateProjectExploratoryStatuses(name, endpoint, UserInstanceStatus.TERMINATING);
+     }
  
 -    @ProjectAdmin
 -    @Override
 -    public void terminateEndpoint(@User UserInfo userInfo, List<String> endpoints, @ResourceName @Project String name) {
 -        endpoints.forEach(endpoint -> terminateEndpoint(userInfo, endpoint, name));
 -    }
 +	@ProjectAdmin
 +	@Override
 +	public void terminateEndpoint(@User UserInfo userInfo, List<String> endpoints, @Project String name) {
 +		List<ProjectEndpointDTO> endpointDTOs = getProjectEndpointDTOS(endpoints, name);
 +		checkProjectRelatedResourcesInProgress(name, endpointDTOs, TERMINATE_ACTION);
 +		endpoints.forEach(endpoint -> terminateEndpoint(userInfo, endpoint, name));
 +	}
  
 -    @BudgetLimited
 -    @Audit(action = START, type = EDGE_NODE)
 -    @Override
 -    public void start(@User UserInfo userInfo, @ResourceName String endpoint, @Project String name) {
 -        projectActionOnCloud(userInfo, name, START_PRJ_API, endpoint);
 -        projectDAO.updateEdgeStatus(name, endpoint, UserInstanceStatus.STARTING);
 -    }
 +	@BudgetLimited
++	@Audit(action = START, type = EDGE_NODE)
 +	@Override
- 	public void start(UserInfo userInfo, String endpoint, @Project String name) {
++	public void start(@User UserInfo userInfo,@ResourceName String endpoint, @Project String name) {
 +		projectActionOnCloud(userInfo, name, START_PRJ_API, endpoint);
 +		projectDAO.updateEdgeStatus(name, endpoint, UserInstanceStatus.STARTING);
 +	}
  
 -    @ProjectAdmin
 -    @Override
 -    public void start(@User UserInfo userInfo, List<String> endpoints, @Project String name) {
 -        endpoints.forEach(endpoint -> start(userInfo, endpoint, name));
 -    }
 +	@ProjectAdmin
 +	@Override
 +	public void start(@User UserInfo userInfo, List<String> endpoints, @Project String name) {
 +		endpoints.forEach(endpoint -> start(userInfo, endpoint, name));
 +	}
  
 -    @Audit(action = STOP, type = EDGE_NODE)
 -    @Override
 -    public void stop(@User UserInfo userInfo, @ResourceName String endpoint, @Project String name, @Info String auditInfo) {
 -        projectActionOnCloud(userInfo, name, STOP_PRJ_API, endpoint);
 -        projectDAO.updateEdgeStatus(name, endpoint, UserInstanceStatus.STOPPING);
 -    }
++	@Audit(action = STOP, type = EDGE_NODE)
 +	@Override
- 	public void stop(UserInfo userInfo, String endpoint, String name) {
++	public void stop(@User UserInfo userInfo, @ResourceName String endpoint,@Project String name, @Info String auditInfo) {
 +		projectActionOnCloud(userInfo, name, STOP_PRJ_API, endpoint);
 +		projectDAO.updateEdgeStatus(name, endpoint, UserInstanceStatus.STOPPING);
 +	}
  
 -    @ProjectAdmin
 -    @Override
 -    public void stopWithResources(@User UserInfo userInfo, List<String> endpoints, @ResourceName @Project String projectName) {
 -        List<ProjectEndpointDTO> endpointDTOs = get(projectName)
 -                .getEndpoints()
 -                .stream()
 -                .filter(projectEndpointDTO -> endpoints.contains(projectEndpointDTO.getName()))
 -                .collect(Collectors.toList());
 -        checkProjectRelatedResourcesInProgress(projectName, endpointDTOs, STOP_ACTION);
 +	@ProjectAdmin
 +	@Override
- 	public void stopWithResources(@User UserInfo userInfo, List<String> endpoints, @Project String projectName) {
++	public void stopWithResources(@User UserInfo userInfo, List<String> endpoints, @ResourceName @Project String projectName) {
 +		List<ProjectEndpointDTO> endpointDTOs = getProjectEndpointDTOS(endpoints, projectName);
 +		checkProjectRelatedResourcesInProgress(projectName, endpointDTOs, STOP_ACTION);
  
- 		exploratoryDAO.fetchRunningExploratoryFieldsForProject(projectName,
- 				endpointDTOs
- 						.stream()
+         endpointDTOs
+                 .stream()
+                 .filter(e -> !Arrays.asList(UserInstanceStatus.TERMINATED, UserInstanceStatus.TERMINATING, UserInstanceStatus.STOPPED,
+                         UserInstanceStatus.FAILED).contains(e.getStatus()))
+                 .forEach(e -> stop(userInfo, e.getName(), projectName, null));
+ 
+         exploratoryDAO.fetchRunningExploratoryFieldsForProject(projectName,
+                 endpointDTOs
+                         .stream()
  						.map(ProjectEndpointDTO::getName)
  						.collect(Collectors.toList()))
- 				.forEach(e -> exploratoryService.stop(new UserInfo(e.getUser(), userInfo.getAccessToken()), projectName, e.getExploratoryName()));
- 
- 		endpointDTOs.stream().filter(e -> !Arrays.asList(UserInstanceStatus.TERMINATED,
- 				UserInstanceStatus.TERMINATING, UserInstanceStatus.STOPPED, UserInstanceStatus.FAILED).contains(e.getStatus()))
- 				.forEach(e -> stop(userInfo, e.getName(), projectName));
+ 				.forEach(e -> exploratoryService.stop(userInfo, e.getUser(), projectName, e.getExploratoryName(), null));
  	}
  
  	@ProjectAdmin
  	@Override
  	public void update(@User UserInfo userInfo, UpdateProjectDTO projectDTO, @Project String projectName) {
- 		final ProjectDTO project = projectDAO.get(projectDTO.getName()).orElseThrow(projectNotFound());
- 		final Set<String> endpoints = project.getEndpoints()
- 				.stream()
- 				.map(ProjectEndpointDTO::getName)
- 				.collect(toSet());
- 		final HashSet<String> newEndpoints = new HashSet<>(projectDTO.getEndpoints());
- 		newEndpoints.removeAll(endpoints);
- 		final List<ProjectEndpointDTO> endpointsToBeCreated = newEndpoints.stream()
- 				.map(e -> new ProjectEndpointDTO(e, UserInstanceStatus.CREATING, null))
- 				.collect(Collectors.toList());
- 		project.getEndpoints().addAll(endpointsToBeCreated);
- 		projectDAO.update(new ProjectDTO(project.getName(), projectDTO.getGroups(), project.getKey(),
- 				project.getTag(), project.getBudget(), project.getEndpoints(), projectDTO.isSharedImageEnabled()));
- 		endpointsToBeCreated.forEach(e -> createEndpoint(userInfo, project, e.getName()));
- 	}
- 
- 	@Override
- 	public void updateBudget(List<ProjectDTO> projects) {
- 		projects.forEach(p -> projectDAO.updateBudget(p.getName(), p.getBudget()));
- 	}
+         final ProjectDTO project = projectDAO.get(projectDTO.getName()).orElseThrow(projectNotFound());
+         final Set<String> endpoints = project.getEndpoints()
+                 .stream()
+                 .map(ProjectEndpointDTO::getName)
+                 .collect(toSet());
+         final Set<String> newEndpoints = new HashSet<>(projectDTO.getEndpoints());
+         newEndpoints.removeAll(endpoints);
+         final String projectUpdateAudit = updateProjectAudit(projectDTO, project, newEndpoints);
+         updateProject(userInfo, projectName, projectDTO, project, newEndpoints, projectUpdateAudit);
+     }
+ 
+     @Audit(action = UPDATE, type = PROJECT)
+     public void updateProject(@User UserInfo userInfo, @Project @ResourceName String projectName, UpdateProjectDTO projectDTO, ProjectDTO project, Set<String> newEndpoints,
+                               @Info String projectAudit) {
+         final List<ProjectEndpointDTO> endpointsToBeCreated = newEndpoints
+                 .stream()
+                 .map(e -> new ProjectEndpointDTO(e, UserInstanceStatus.CREATING, null))
+                 .collect(Collectors.toList());
+         project.getEndpoints().addAll(endpointsToBeCreated);
+         projectDAO.update(new ProjectDTO(project.getName(), projectDTO.getGroups(), project.getKey(),
+                 project.getTag(), project.getBudget(), project.getEndpoints(), projectDTO.isSharedImageEnabled()));
+         endpointsToBeCreated.forEach(e -> createEndpoint(userInfo, projectName, project, e.getName()));
+     }
+ 
+     @Override
+     public void updateBudget(UserInfo userInfo, List<UpdateProjectBudgetDTO> dtos) {
+         final List<ProjectDTO> projects = dtos
+                 .stream()
+                 .filter(dto -> Objects.nonNull(dto.getBudget()))
+                 .map(dto -> ProjectDTO.builder().name(dto.getProject()).budget(dto.getBudget()).build())
+                 .collect(Collectors.toList());
+ 
+         projects.forEach(p -> updateBudget(userInfo, p.getName(), p.getBudget(), getUpdateBudgetAudit(p)));
+     }
+ 
+     @Audit(action = UPDATE, type = PROJECT)
+     public void updateBudget(@User UserInfo userInfo, @Project @ResourceName String name, Integer budget, @Info String updateBudgetAudit) {
+         projectDAO.updateBudget(name, budget);
+     }
  
 -    @Override
 -    public boolean isAnyProjectAssigned(UserInfo userInfo) {
 -        final Set<String> userGroups = concat(userInfo.getRoles().stream(),
 -                userGroupDao.getUserGroups(userInfo.getName()).stream())
 -                .collect(toSet());
 -        return projectDAO.isAnyProjectAssigned(userGroups);
 -    }
 +	@Override
 +	public boolean isAnyProjectAssigned(UserInfo userInfo) {
 +		final Set<String> userGroups = concat(userInfo.getRoles().stream(),
 +				userGroupDao.getUserGroups(userInfo.getName()).stream())
 +				.collect(toSet());
 +		return projectDAO.isAnyProjectAssigned(userGroups);
 +	}
  
 -    @Override
 -    public boolean checkExploratoriesAndComputationalProgress(String projectName, List<String> endpoints) {
 -        return exploratoryDAO.fetchProjectEndpointExploratoriesWhereStatusIn(projectName, endpoints, Arrays.asList(
 -                UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE,
 -                UserInstanceStatus.CONFIGURING, UserInstanceStatus.RECONFIGURING, UserInstanceStatus.STOPPING,
 -                UserInstanceStatus.TERMINATING),
 -                UserInstanceStatus.CREATING, UserInstanceStatus.CONFIGURING, UserInstanceStatus.STARTING,
 -                UserInstanceStatus.RECONFIGURING, UserInstanceStatus.CREATING_IMAGE, UserInstanceStatus.STOPPING,
 -                UserInstanceStatus.TERMINATING).isEmpty();
 -    }
 +	@Override
 +	public boolean checkExploratoriesAndComputationalProgress(String projectName, List<String> endpoints) {
 +		return exploratoryDAO.fetchProjectEndpointExploratoriesWhereStatusIn(projectName, endpoints, Arrays.asList(
 +				UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE,
 +				UserInstanceStatus.CONFIGURING, UserInstanceStatus.RECONFIGURING, UserInstanceStatus.STOPPING,
 +				UserInstanceStatus.TERMINATING),
 +				UserInstanceStatus.CREATING, UserInstanceStatus.CONFIGURING, UserInstanceStatus.STARTING,
 +				UserInstanceStatus.RECONFIGURING, UserInstanceStatus.CREATING_IMAGE, UserInstanceStatus.STOPPING,
 +				UserInstanceStatus.TERMINATING).isEmpty();
 +	}
  
- 	private void createProjectOnCloud(UserInfo user, ProjectDTO projectDTO) {
- 		try {
- 			projectDTO.getEndpoints().forEach(endpoint -> createEndpoint(user, projectDTO,
- 					endpoint.getName()));
- 		} catch (Exception e) {
- 			log.error("Can not create project due to: {}", e.getMessage());
- 			projectDAO.updateStatus(projectDTO.getName(), ProjectDTO.Status.FAILED);
- 		}
- 	}
- 
- 	private void createEndpoint(UserInfo user, ProjectDTO projectDTO, String endpointName) {
- 		EndpointDTO endpointDTO = endpointService.get(endpointName);
- 		String uuid = provisioningService.post(endpointDTO.getUrl() + CREATE_PRJ_API, user.getAccessToken(),
- 						requestBuilder.newProjectCreate(user, projectDTO, endpointDTO), String.class);
- 		requestId.put(user.getName(), uuid);
- 	}
+     private void createProjectOnCloud(UserInfo user, ProjectDTO projectDTO) {
+         try {
+             projectDTO.getEndpoints().forEach(endpoint -> createEndpoint(user, projectDTO.getName(), projectDTO, endpoint.getName()));
+         } catch (Exception e) {
+             log.error("Can not create project due to: {}", e.getMessage());
+             projectDAO.updateStatus(projectDTO.getName(), ProjectDTO.Status.FAILED);
+         }
+     }
+ 
+     @Audit(action = CREATE, type = EDGE_NODE)
+     public void createEndpoint(@User UserInfo user, @Project String projectName, ProjectDTO projectDTO, @ResourceName String endpointName) {
+         EndpointDTO endpointDTO = endpointService.get(endpointName);
+         String uuid = provisioningService.post(endpointDTO.getUrl() + CREATE_PRJ_API, user.getAccessToken(),
+                 requestBuilder.newProjectCreate(user, projectDTO, endpointDTO), String.class);
+         requestId.put(user.getName(), uuid);
+     }
  
 -    private void projectActionOnCloud(UserInfo user, String projectName, String provisioningApiUri, String endpoint) {
 -        try {
 -            EndpointDTO endpointDTO = endpointService.get(endpoint);
 -            String uuid = provisioningService.post(endpointDTO.getUrl() + provisioningApiUri, user.getAccessToken(),
 -                    requestBuilder.newProjectAction(user, projectName, endpointDTO), String.class);
 -            requestId.put(user.getName(), uuid);
 -        } catch (Exception e) {
 -            log.error("Can not terminate project due to: {}", e.getMessage());
 -            projectDAO.updateStatus(projectName, ProjectDTO.Status.FAILED);
 -        }
 -    }
 +	private void projectActionOnCloud(UserInfo user, String projectName, String provisioningApiUri, String endpoint) {
 +		try {
 +			EndpointDTO endpointDTO = endpointService.get(endpoint);
 +			String uuid = provisioningService.post(endpointDTO.getUrl() + provisioningApiUri, user.getAccessToken(),
 +					requestBuilder.newProjectAction(user, projectName, endpointDTO), String.class);
 +			requestId.put(user.getName(), uuid);
 +		} catch (Exception e) {
 +			log.error("Can not terminate project due to: {}", e.getMessage());
 +			projectDAO.updateStatus(projectName, ProjectDTO.Status.FAILED);
 +		}
 +	}
  
 -    private void checkProjectRelatedResourcesInProgress(String projectName, List<ProjectEndpointDTO> endpoints, String action) {
 -		boolean edgeProgress = endpoints
 -				.stream().anyMatch(e ->
 -                        Arrays.asList(UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.STOPPING,
 -                                UserInstanceStatus.TERMINATING).contains(e.getStatus()));
 +	private void checkProjectRelatedResourcesInProgress(String projectName, List<ProjectEndpointDTO> endpoints, String action) {
- 		boolean edgeProgress = endpoints
++        boolean edgeProgress = endpoints
 +				.stream()
 +				.anyMatch(e ->
- 						Arrays.asList(UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.STOPPING,
- 								UserInstanceStatus.TERMINATING).contains(e.getStatus()));
++                Arrays.asList(UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.STOPPING,
++                        UserInstanceStatus.TERMINATING).contains(e.getStatus()));
  
 -        List<String> endpointsName = endpoints.stream().map(ProjectEndpointDTO::getName).collect(Collectors.toList());
 -        if (edgeProgress || !checkExploratoriesAndComputationalProgress(projectName, endpointsName)) {
 -            throw new ResourceConflictException((String.format("Can not %s environment because one of project " +
 -                    "resource is in processing stage", action)));
 -        }
 -    }
 +		List<String> endpointNames = endpoints
 +				.stream()
 +				.map(ProjectEndpointDTO::getName)
 +				.collect(Collectors.toList());
 +		if (edgeProgress || !checkExploratoriesAndComputationalProgress(projectName, endpointNames)) {
 +			throw new ResourceConflictException((String.format("Can not %s environment because one of project " +
 +					"resource is in processing stage", action)));
 +		}
 +	}
  
 -    private String updateProjectAudit(UpdateProjectDTO projectDTO, ProjectDTO project, Set<String> newEndpoints) {
 -        if (configuration.isAuditEnabled()) {
 -            return null;
 -        }
 -        StringBuilder audit = new StringBuilder();
 -        final Set<String> newGroups = new HashSet<>(projectDTO.getGroups());
 -        newGroups.removeAll(project.getGroups());
 -        final Set<String> removedGroups = new HashSet<>(project.getGroups());
 -        removedGroups.removeAll(projectDTO.getGroups());
 -
 -        if (!newEndpoints.isEmpty()) {
 -            audit.append(String.format(AUDIT_ADD_ENDPOINT, String.join(", ", newEndpoints)));
 -        }
 -        if (!newGroups.isEmpty()) {
 -            audit.append(String.format(AUDIT_ADD_GROUP, String.join(", ", newGroups)));
 -        }
 -        if (!removedGroups.isEmpty()) {
 -            audit.append(String.format(AUDIT_REMOVE_GROUP, String.join(", ", removedGroups)));
 -        }
 -        return audit.toString();
 -    }
++	private String updateProjectAudit(UpdateProjectDTO projectDTO, ProjectDTO project, Set<String> newEndpoints) {
++		if (configuration.isAuditEnabled()) {
++			return null;
++		}
++		StringBuilder audit = new StringBuilder();
++		final Set<String> newGroups = new HashSet<>(projectDTO.getGroups());
++		newGroups.removeAll(project.getGroups());
++		final Set<String> removedGroups = new HashSet<>(project.getGroups());
++		removedGroups.removeAll(projectDTO.getGroups());
++
++		if (!newEndpoints.isEmpty()) {
++			audit.append(String.format(AUDIT_ADD_ENDPOINT, String.join(", ", newEndpoints)));
++		}
++		if (!newGroups.isEmpty()) {
++			audit.append(String.format(AUDIT_ADD_GROUP, String.join(", ", newGroups)));
++		}
++		if (!removedGroups.isEmpty()) {
++			audit.append(String.format(AUDIT_REMOVE_GROUP, String.join(", ", removedGroups)));
++		}
++		return audit.toString();
++	}
+ 
 -    private String getUpdateBudgetAudit(ProjectDTO p) {
 -        return String.format(AUDIT_UPDATE_BUDGET, get(p.getName()).getBudget(), p.getBudget());
 -    }
++	private String getUpdateBudgetAudit(ProjectDTO p) {
++		return String.format(AUDIT_UPDATE_BUDGET, get(p.getName()).getBudget(), p.getBudget());
++	}
+ 
 -    private Supplier<ResourceNotFoundException> projectNotFound() {
 -        return () -> new ResourceNotFoundException("Project with passed name not found");
 -    }
 +	private List<ProjectEndpointDTO> getProjectEndpointDTOS(List<String> endpoints, @Project String name) {
 +		return get(name)
 +				.getEndpoints()
 +				.stream()
 +				.filter(projectEndpointDTO -> endpoints.contains(projectEndpointDTO.getName()))
 +				.collect(Collectors.toList());
 +	}
 +
 +	private Supplier<ResourceNotFoundException> projectNotFound() {
 +		return () -> new ResourceNotFoundException("Project with passed name not found");
 +	}
  }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org