public void ExtractCalibrationFileDetails_NoConfiguration_Failed() { var projectConfigurations = new List <ProjectConfigurationModel>(); var extractedCalibrationFileOk = ProjectRequestHelper.ExtractCalibrationFileDetails(projectConfigurations, out string fileName, out DateTime? fileDateUtc); Assert.False(extractedCalibrationFileOk); }
/// <summary> /// Processes the CreateProjectEvent /// </summary> protected override async Task <ContractExecutionResult> ProcessAsyncEx <T>(T item) { var projectValidation = CastRequestObjectTo <ProjectValidation>(item, errorCode: 68); // Write to WM first to obtain their ProjectTRN to use as ProjectUid for our DB etc var response = new CreateProjectResponseModel(); try { // don't send our timezone, we only need it for WorksOS. WM has their own, calculated from the boundary, for their own uses. var createProjectRequestModel = AutoMapperUtility.Automapper.Map <CreateProjectRequestModel>(projectValidation); response = await cwsProjectClient.CreateProject(createProjectRequestModel, customHeaders); if (response == null || string.IsNullOrEmpty(response.Id)) { serviceExceptionHandler.ThrowServiceException(HttpStatusCode.BadRequest, 7); } } catch (Exception e) { serviceExceptionHandler.ThrowServiceException(HttpStatusCode.InternalServerError, 61, "worksManager.CreateProject", e.Message); } log.LogDebug($"{nameof(CreateProjectTBCExecutor)}: Created project {response.Id}"); return(new ProjectV6DescriptorsSingleResult( AutoMapperUtility.Automapper.Map <ProjectV6Descriptor>(await ProjectRequestHelper.GetProject(new Guid(response.Id), new Guid(customerUid), new Guid(userId), log, serviceExceptionHandler, cwsProjectClient, customHeaders) .ConfigureAwait(false)))); }
public void GetProjectListForCustomer_NoUserUid_HappyPath() { // todo once intersection utility is complete, this may be able to return projects var projectName = "the project name"; var lastUpdate = DateTime.UtcNow.AddDays(-1); var projectConfigurations = new List <ProjectConfigurationModel>(); var fullName = "trn::profilex:us-west-2:project:5d2ab210-5fb4-4e77-90f9-b0b41c9e6e3f||2020-03-25 23:03:45.314||BootCamp 2012.dc"; projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.CALIBRATION.ToString(), FileName = fullName }); var projectDetailResponseModel = CreateProjectDetailModel(_customerTrn, _projectTrn, projectName, lastUpdate, projectConfigurations: projectConfigurations); var projectDetailListResponseModel = new ProjectDetailListResponseModel() { Projects = new List <ProjectDetailResponseModel>() { projectDetailResponseModel } }; var mockCwsProjectClient = new Mock <ICwsProjectClient>(); mockCwsProjectClient.Setup(pr => pr.GetProjectsForCustomer(It.IsAny <Guid>(), It.IsAny <Guid?>(), It.IsAny <bool>(), It.IsAny <CwsProjectType?>(), It.IsAny <ProjectStatus?>(), It.IsAny <bool>(), It.IsAny <HeaderDictionary>())).ReturnsAsync(projectDetailListResponseModel); var projectDatabaseModelList = ProjectRequestHelper.GetIntersectingProjects(_customerUid.ToString(), 89, 179, _projectUid.ToString(), _logger, _serviceExceptionHandler, mockCwsProjectClient.Object, _customHeaders); var result = projectDatabaseModelList.Result; Assert.NotNull(result); Assert.Empty(result); }
public async Task <ProjectV6DescriptorsSingleResult> GetProjectV6(string projectUid) { Logger.LogInformation($"{nameof(GetProjectV6)}"); var project = await ProjectRequestHelper.GetProject(new Guid(projectUid), new Guid(CustomerUid), new Guid(UserId), Logger, ServiceExceptionHandler, CwsProjectClient, customHeaders).ConfigureAwait(false); return(new ProjectV6DescriptorsSingleResult(AutoMapperUtility.Automapper.Map <ProjectV6Descriptor>(project))); }
public async Task <ReturnLongV5Result> UpsertImportedFileV5TBC( [FromRoute] long projectId, [FromBody] ImportedFileTbc importedFileTbc, [FromServices] ISchedulerProxy schedulerProxy) { // MobileLinework .kml/.kmz files are sent along with linework files // we need to suppress any error and return as if all ok. // however we won't have a LegacyFileId to return - hmmm hope Business centre ignores this if (importedFileTbc.ImportedFileTypeId == ImportedFileType.MobileLinework) { Logger.LogInformation( $"{nameof(UpsertImportedFileV5TBC)}: Ignore MobileLinework from BusinessCentre. projectId {projectId} importedFile: {JsonConvert.SerializeObject(importedFileTbc)}"); return(ReturnLongV5Result.CreateLongV5Result(HttpStatusCode.OK, -1)); } // this also validates that this customer has access to the projectUid var project = await ProjectRequestHelper.GetProjectForCustomer(new Guid(CustomerUid), new Guid(UserId), projectId, Logger, ServiceExceptionHandler, CwsProjectClient, customHeaders); var projectUid = project.ProjectId; importedFileTbc = FileImportV5TBCDataValidator.ValidateUpsertImportedFileRequest(new Guid(projectUid), importedFileTbc); Logger.LogInformation( $"{nameof(UpsertImportedFileV5TBC)}: projectId {projectId} projectUid {projectUid} importedFile: {JsonConvert.SerializeObject(importedFileTbc)}"); var fileEntry = await TccHelper.GetFileInfoFromTccRepository(importedFileTbc, Logger, ServiceExceptionHandler, FileRepo); await TccHelper.CopyFileWithinTccRepository(importedFileTbc, CustomerUid, projectUid, FileSpaceId, Logger, ServiceExceptionHandler, FileRepo).ConfigureAwait(false); ImportedFileDescriptorSingleResult importedFileResult; using (var ms = await TccHelper.GetFileStreamFromTcc(importedFileTbc, Logger, ServiceExceptionHandler, FileRepo)) { importedFileResult = await UpsertFileInternal(importedFileTbc.Name, ms, new Guid(projectUid), importedFileTbc.ImportedFileTypeId, importedFileTbc.ImportedFileTypeId == ImportedFileType.Linework ?importedFileTbc.LineworkFile.DxfUnitsTypeId : DxfUnitsType.Meters, fileEntry.createTime, fileEntry.modifyTime, importedFileTbc.ImportedFileTypeId == ImportedFileType.SurveyedSurface ?importedFileTbc.SurfaceFile.SurveyedUtc : (DateTime?)null, schedulerProxy); } // Automapper maps src.ImportedFileId to LegacyFileId, so this IS the one sent to TRex and used to ref via TCC var response = importedFileResult != null ? ReturnLongV5Result.CreateLongV5Result(HttpStatusCode.OK, importedFileResult.ImportedFileDescriptor.LegacyFileId) : ReturnLongV5Result.CreateLongV5Result(HttpStatusCode.InternalServerError, -1); Logger.LogInformation( $"{nameof(UpsertImportedFileV5TBC)}: Completed successfully. Response: {response} importedFile: {JsonConvert.SerializeObject(importedFileResult)}"); return(response); }
/// <summary> /// Validates that project belongs to the customer. /// </summary> public async Task ValidateProjectWithCustomer(string customerUid, string projectUid) { var project = (await ProjectRequestHelper.GetProjectListForCustomer(new Guid(customerUid), new Guid(userId), log, serviceExceptionHandler, cwsProjectClient, null, null, false, false, customHeaders).ConfigureAwait(false)) .FirstOrDefault(prj => string.Equals(prj.ProjectUID, projectUid, StringComparison.OrdinalIgnoreCase)); if (project == null) { serviceExceptionHandler.ThrowServiceException(HttpStatusCode.BadRequest, 1); } log.LogInformation($"projectUid {projectUid} validated"); }
public void ExtractCalibrationFileDetails_NoCalibrationCnfiguration_Failed() { var projectConfigurations = new List <ProjectConfigurationModel>(); projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.AVOIDANCE_ZONE.ToString() }); var extractedCalibrationFileOk = ProjectRequestHelper.ExtractCalibrationFileDetails(projectConfigurations, out string fileName, out DateTime? fileDateUtc); Assert.False(extractedCalibrationFileOk); }
public async Task <ProjectV6DescriptorsListResult> GetProjectsV6([FromQuery] CwsProjectType?projectType, [FromQuery] ProjectStatus projectStatus = ProjectStatus.Active, [FromQuery] bool onlyAdmin = true, [FromQuery] bool includeBoundaries = false) { Logger.LogInformation($"{nameof(GetProjectsV6)}"); var projects = await ProjectRequestHelper.GetProjectListForCustomer(new Guid(CustomerUid), new Guid(UserId), Logger, ServiceExceptionHandler, CwsProjectClient, projectType, projectStatus, onlyAdmin, includeBoundaries, customHeaders); return(new ProjectV6DescriptorsListResult { ProjectDescriptors = projects.Select(project => AutoMapperUtility.Automapper.Map <ProjectV6Descriptor>(project)) .ToImmutableList() }); }
public async Task GetProject_CustomerMismatch() { var projectDetailResponseModel = CreateProjectDetailModel(TRNHelper.MakeTRN(Guid.NewGuid(), TRNHelper.TRN_ACCOUNT), _projectTrn); var mockCwsProjectClient = new Mock <ICwsProjectClient>(); mockCwsProjectClient.Setup(pr => pr.GetMyProject(It.IsAny <Guid>(), It.IsAny <Guid>(), It.IsAny <HeaderDictionary>())).ReturnsAsync(projectDetailResponseModel); var ex = await Assert.ThrowsAsync <ServiceException>(() => ProjectRequestHelper.GetProject(_projectUid, _customerUid, Guid.NewGuid(), _logger, _serviceExceptionHandler, mockCwsProjectClient.Object, _customHeaders)); Assert.Equal(HttpStatusCode.Forbidden, ex.Code); Assert.Equal(2001, ex.GetResult.Code); }
/// <summary> /// Validates a project identifier. /// </summary> protected async Task ValidateProjectId(string projectUid) { LogCustomerDetails("GetProject", projectUid); var project = (await ProjectRequestHelper.GetProjectListForCustomer(new Guid(CustomerUid), new Guid(UserId), Logger, ServiceExceptionHandler, CwsProjectClient, null, null, true, false, customHeaders)) .FirstOrDefault(p => string.Equals(p.ProjectUID, projectUid, StringComparison.OrdinalIgnoreCase)); if (project == null) { ServiceExceptionHandler.ThrowServiceException(HttpStatusCode.BadRequest, 1); } Logger.LogInformation($"Project {JsonConvert.SerializeObject(project)} retrieved"); }
public async Task <ProjectV6DescriptorsListResult> GetIntersectingProjects(string customerUid, double latitude, double longitude, string projectUid) { Logger.LogInformation($"{nameof(GetIntersectingProjects)}"); var projects = await ProjectRequestHelper.GetIntersectingProjects( customerUid, latitude, longitude, projectUid, Logger, ServiceExceptionHandler, CwsProjectClient, customHeaders).ConfigureAwait(false); return(new ProjectV6DescriptorsListResult { ProjectDescriptors = projects.Select(project => AutoMapperUtility.Automapper.Map <ProjectV6Descriptor>(project)) .ToImmutableList() }); }
/// <summary> /// Validates a project name. Must be unique amongst active projects for the Customer. /// </summary> private async Task <int> ValidateProjectName(Guid customerUid, Guid userUid, string projectName, Guid?projectUid) { log.LogInformation($"{nameof(ValidateProjectName)} projectName: {projectName} projectUid: {projectUid}"); var duplicateProjectNames = (await ProjectRequestHelper.GetProjectListForCustomer(customerUid, userUid, log, serviceExceptionHandler, cwsProjectClient, null, ProjectStatus.Active, false, false, customHeaders)) .Where( p => !p.IsArchived && string.Equals(p.Name, projectName, StringComparison.OrdinalIgnoreCase) && (!projectUid.HasValue || !string.Equals(p.ProjectUID, projectUid.ToString(), StringComparison.OrdinalIgnoreCase))) .ToList(); log.LogInformation($"{nameof(ValidateProjectName)} Any duplicateProjectNames? {JsonConvert.SerializeObject(duplicateProjectNames)} retrieved"); return(duplicateProjectNames.Count); }
public void GetProject_UserProjectDefaultAdmin_HappyPath() { var projectDetailResponseModel = CreateProjectDetailModel(_customerTrn, _projectTrn); var mockCwsProjectClient = new Mock <ICwsProjectClient>(); mockCwsProjectClient.Setup(pr => pr.GetMyProject(It.IsAny <Guid>(), It.IsAny <Guid>(), It.IsAny <HeaderDictionary>())).ReturnsAsync(projectDetailResponseModel); var projectDatabaseModelResult = ProjectRequestHelper.GetProject(_projectUid, _customerUid, _userUid, _logger, _serviceExceptionHandler, mockCwsProjectClient.Object, _customHeaders); var result = projectDatabaseModelResult.Result; Assert.NotNull(result); Assert.Equal(_projectUid.ToString(), result.ProjectUID); Assert.Equal(UserProjectRoleEnum.Admin, result.UserProjectRole); }
public async Task <Dictionary <long, ProjectDataTBCSingleResult> > GetProjects() { Logger.LogInformation($"{nameof(GetProjects)} "); var projects = await ProjectRequestHelper.GetProjectListForCustomer(new Guid(CustomerUid), new Guid(UserId), Logger, ServiceExceptionHandler, CwsProjectClient, projectType : CwsProjectType.AcceptsTagFiles, status : null, onlyAdmin : false, includeBoundaries : true, customHeaders : customHeaders); var result = new Dictionary <long, ProjectDataTBCSingleResult>(); foreach (var project in projects) { var projectTbc = AutoMapperUtility.Automapper.Map <ProjectDataTBCSingleResult>(project); result[projectTbc.LegacyProjectId] = projectTbc; } Logger.LogDebug($"{nameof(GetProjects)}: completed successfully. projects {JsonConvert.SerializeObject(result)}"); return(result); }
public async Task <ImmutableList <DesignDetailV5Result> > GetImportedFilesV5TBC([FromRoute] long projectId, [FromRoute] long?id = null) { Logger.LogInformation($"{nameof(GetImportedFilesV5TBC)}: projectId {projectId} id {id}"); // this also validates that this customer has access to the projectUid var project = await ProjectRequestHelper.GetProjectForCustomer(new Guid(CustomerUid), new Guid(UserId), projectId, Logger, ServiceExceptionHandler, CwsProjectClient, customHeaders); var projectUid = project.ProjectId; var files = await ImportedFileRequestDatabaseHelper.GetImportedFileList(projectUid, Logger, UserId, ProjectRepo) .ConfigureAwait(false); var selected = id.HasValue ? files.Where(x => x.LegacyFileId == id.Value) : files; return(selected.Select(x => new DesignDetailV5Result { id = x.LegacyFileId, name = x.Name, fileType = (int)x.ImportedFileType, insertUTC = x.ImportedUtc }).ToImmutableList()); }
public void GetProjectListForCustomer_HappyPath() { var projectName = "the project name"; var lastUpdate = DateTime.UtcNow.AddDays(-1); var projectConfigurations = new List <ProjectConfigurationModel>(); var fullName = "trn::profilex:us-west-2:project:5d2ab210-5fb4-4e77-90f9-b0b41c9e6e3f||2020-03-25 23:03:45.314||BootCamp 2012.dc"; projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.CALIBRATION.ToString(), FileName = fullName }); var projectDetailResponseModel = CreateProjectDetailModel(_customerTrn, _projectTrn, projectName, lastUpdate, projectConfigurations: projectConfigurations); var projectDetailListResponseModel = new ProjectDetailListResponseModel() { Projects = new List <ProjectDetailResponseModel>() { projectDetailResponseModel } }; var mockCwsProjectClient = new Mock <ICwsProjectClient>(); mockCwsProjectClient.Setup(pr => pr.GetProjectsForCustomer(It.IsAny <Guid>(), It.IsAny <Guid>(), It.IsAny <bool>(), It.IsAny <CwsProjectType?>(), It.IsAny <ProjectStatus?>(), It.IsAny <bool>(), It.IsAny <HeaderDictionary>())).ReturnsAsync(projectDetailListResponseModel); var projectDatabaseModelList = ProjectRequestHelper.GetProjectListForCustomer(_customerUid, _userUid, _logger, _serviceExceptionHandler, mockCwsProjectClient.Object, null, null, false, true, _customHeaders); var result = projectDatabaseModelList.Result; Assert.NotNull(result); Assert.Single(result); Assert.Equal(_projectUid.ToString(), result[0].ProjectUID); Assert.Equal(_customerUid.ToString(), result[0].CustomerUID); Assert.Equal(projectName, result[0].Name); Assert.Equal(CwsProjectType.AcceptsTagFiles, result[0].ProjectType); Assert.Equal("New Zealand Standard Time", result[0].ProjectTimeZone); Assert.Equal("Pacific/Auckland", result[0].ProjectTimeZoneIana); Assert.Equal("POLYGON((150.3 1.2,150.4 1.2,150.4 1.3,150.4 1.4,150.3 1.2))", result[0].Boundary); Assert.Equal("BootCamp 2012.dc", result[0].CoordinateSystemFileName); Assert.Equal(new DateTime(2020, 03, 25, 23, 03, 45, 314), result[0].CoordinateSystemLastActionedUTC); Assert.False(result[0].IsArchived); Assert.Equal(lastUpdate, result[0].LastActionedUTC); }
public void ExtractCalibrationFileDetails_InvalidFullName_Failed() { var projectConfigurations = new List <ProjectConfigurationModel>(); projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.AVOIDANCE_ZONE.ToString() }); var invalidFullName = "2020-03-25 23:03:45.314||BootCamp 2012.dc"; projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.CALIBRATION.ToString(), FileName = invalidFullName }); var extractedCalibrationFileOk = ProjectRequestHelper.ExtractCalibrationFileDetails(projectConfigurations, out var fileName, out var fileDateUtc); Assert.False(extractedCalibrationFileOk); }
public void ExtractCalibrationFileDetails_InvalidFileExtension_Failed() { var projectConfigurations = new List <ProjectConfigurationModel>(); projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.AVOIDANCE_ZONE.ToString() }); var invalidFullName = "trn::profilex:us-west-2:project:5d2ab210-5fb4-4e77-90f9-b0b41c9e6e3f||2020-03-25 23:03:45.314||BootCamp 2012.aa"; projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.CALIBRATION.ToString(), FileName = invalidFullName }); var extractedCalibrationFileOk = ProjectRequestHelper.ExtractCalibrationFileDetails(projectConfigurations, out var fileName, out var fileDateUtc); Assert.False(extractedCalibrationFileOk); }
public void ExtractCalibrationFileDetails_HappyPath() { var projectConfigurations = new List <ProjectConfigurationModel>(); projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.AVOIDANCE_ZONE.ToString() }); var fullName = "trn::profilex:us-west-2:project:5d2ab210-5fb4-4e77-90f9-b0b41c9e6e3f||2020-03-25 23:03:45.314||BootCamp 2012.dc"; projectConfigurations.Add(new ProjectConfigurationModel() { FileType = ProjectConfigurationFileType.CALIBRATION.ToString(), FileName = fullName }); var extractedCalibrationFileOk = ProjectRequestHelper.ExtractCalibrationFileDetails(projectConfigurations, out var fileName, out var fileDateUtc); Assert.True(extractedCalibrationFileOk); Assert.Equal("BootCamp 2012.dc", fileName); Assert.Equal(new DateTime(2020, 03, 25, 23, 03, 45, 314), fileDateUtc); }
/// <summary> /// Adds file via Trex /// </summary> protected override async Task <ContractExecutionResult> ProcessAsyncEx <T>(T item) { var importedFile = CastRequestObjectTo <CreateImportedFile>(item, errorCode: 68); await ImportedFileRequestDatabaseHelper.CheckIfParentSurfaceExistsAsync(importedFile.ImportedFileType, importedFile.ParentUid, serviceExceptionHandler, projectRepo); // need to write to Db prior to // notifying TRex as Trex needs the ImportedFileUid var createImportedFileEvent = await ImportedFileRequestDatabaseHelper.CreateImportedFileinDb( Guid.Parse(customerUid), importedFile.ProjectUid, importedFile.ImportedFileType, importedFile.DxfUnitsType, importedFile.FileName, importedFile.SurveyedUtc, JsonConvert.SerializeObject(importedFile.FileDescriptor), importedFile.FileCreatedUtc, importedFile.FileUpdatedUtc, userEmailAddress, log, serviceExceptionHandler, projectRepo, importedFile.ParentUid, importedFile.Offset, importedFile.ImportedFileUid); if (importedFile.IsTRexDesignFileType) { await ImportedFileRequestHelper.NotifyTRexAddFile(importedFile.ProjectUid, importedFile.ImportedFileType, importedFile.FileName, createImportedFileEvent.ImportedFileUID, importedFile.SurveyedUtc, log, customHeaders, serviceExceptionHandler, tRexImportFileProxy, projectRepo); } if (importedFile.ImportedFileType == ImportedFileType.Linework || importedFile.ImportedFileType == ImportedFileType.GeoTiff) { var project = ProjectRequestHelper.GetProject(importedFile.ProjectUid, new Guid(customerUid), new Guid(userId), log, serviceExceptionHandler, cwsProjectClient, customHeaders); var existing = projectRepo.GetImportedFile(createImportedFileEvent.ImportedFileUID.ToString()); await Task.WhenAll(project, existing); var dcFileName = importedFile.ImportedFileType == ImportedFileType.GeoTiff ? null : DataOceanFileUtil.DataOceanFileName(project.Result.CoordinateSystemFileName, false, importedFile.ProjectUid, null); //Generate raster tiles var jobRequest = TileGenerationRequestHelper.CreateRequest( importedFile.ImportedFileType, customerUid, importedFile.ProjectUid.ToString(), existing.Result.ImportedFileUid, importedFile.DataOceanRootFolder, importedFile.DataOceanFileName, dcFileName, importedFile.DxfUnitsType, importedFile.SurveyedUtc); await schedulerProxy.ScheduleVSSJob(jobRequest, customHeaders); } var fileDescriptor = new ImportedFileDescriptorSingleResult( (await ImportedFileRequestDatabaseHelper .GetImportedFileList(importedFile.ProjectUid.ToString(), log, userId, projectRepo)) .ToImmutableList() .First(f => f.ImportedFileUid == createImportedFileEvent.ImportedFileUID.ToString()) ); log.LogInformation( $"CreateImportedFileV4. completed successfully. Response: {JsonConvert.SerializeObject(fileDescriptor)}"); return(fileDescriptor); }
protected override async Task <ContractExecutionResult> ProcessAsyncEx <T>(T item) { var data = CastRequestObjectTo <ProjectValidation>(item, errorCode: 68); //Check customerUid in request matches header since some of the API calls use the data and some the header if (!string.Equals(data.CustomerUid.ToString(), customHeaders["X-VisionLink-CustomerUID"], StringComparison.OrdinalIgnoreCase)) { return(new ContractExecutionResult(135, "Mismatched customerUid.")); } var userUid = new Guid(userId); if (data.UpdateType == ProjectUpdateType.None) { log.LogWarning("Unknown CWS update type in project validation"); return(new ContractExecutionResult(136, "Unknown update type in project validation.")); } else if (data.UpdateType == ProjectUpdateType.Created) { //Validate required fields are present if (!data.ProjectType.HasValue) { return(new ContractExecutionResult(130, "Missing project type.")); } if (string.IsNullOrEmpty(data.ProjectName)) { return(new ContractExecutionResult(11, "Missing Project Name.")); } if (string.IsNullOrEmpty(data.ProjectBoundaryWKT)) { return(new ContractExecutionResult(8, "Missing Project Boundary.")); } if (string.IsNullOrEmpty(data.CoordinateSystemFileName)) { return(new ContractExecutionResult(132, "Missing coordinate system file name.")); } if (data.CoordinateSystemFileContent == null || data.CoordinateSystemFileContent.Length == 0) { return(new ContractExecutionResult(133, "Missing coordinate system file contents.")); } //Validate project name not duplicate // ProjectUID won't be filled yet var duplicates = await ValidateProjectName(data.CustomerUid, userUid, data.ProjectName, data.ProjectUid); if (duplicates > 0) { return(new ContractExecutionResult(109, $"Project Name must be unique. {duplicates} active project duplicates found.")); } //Validate project boundary dynamic boundaryResult = ValidateProjectBoundary(data.ProjectBoundaryWKT); if (boundaryResult.code != ContractExecutionStatesEnum.ExecutedSuccessfully) { return(new ContractExecutionResult(boundaryResult.code, boundaryResult.message)); } //Validate project boundary doesn't overlap existing projects log.LogDebug($"Testing if there are overlapping projects for project {data.ProjectName}"); var overlaps = await ProjectRequestHelper.DoesProjectOverlap(data.CustomerUid, null, userUid, data.ProjectBoundaryWKT, log, serviceExceptionHandler, cwsProjectClient, customHeaders); if (overlaps) { return(new ContractExecutionResult(43, "Project boundary overlaps another project.")); } //Validate coordinate system file dynamic coordSysResult = await ValidateCoordinateSystemFile(data.ProjectUid, data.CoordinateSystemFileName, data.CoordinateSystemFileContent); if (coordSysResult.code != ContractExecutionStatesEnum.ExecutedSuccessfully) { return(new ContractExecutionResult(coordSysResult.code, coordSysResult.message)); } } else if (data.UpdateType == ProjectUpdateType.Updated) { //Validate projectUID if (!data.ProjectUid.HasValue) { return(new ContractExecutionResult(5, "Missing ProjectUID.")); } if (data.ProjectType.HasValue) { //Changing from non 3d-enabled to 3d-enabled. if (string.IsNullOrEmpty(data.CoordinateSystemFileName)) { return(new ContractExecutionResult(132, "Missing coordinate system file name.")); } if (data.CoordinateSystemFileContent == null || data.CoordinateSystemFileContent.Length == 0) { return(new ContractExecutionResult(133, "Missing coordinate system file contents.")); } // Get the existing project to validate name and boundary var project = await cwsProjectClient.GetMyProject(data.ProjectUid.Value, userUid, customHeaders : customHeaders); if (project == null) { return(new ContractExecutionResult(7, "Project does not exist.")); } if (string.IsNullOrEmpty(data.ProjectName)) { data.ProjectName = project.ProjectName; } if (string.IsNullOrEmpty(data.ProjectBoundaryWKT)) { data.ProjectBoundaryWKT = GeometryConversion.ProjectBoundaryToWKT(project.ProjectSettings.Boundary); } } //Validate project name if changed if (!string.IsNullOrEmpty(data.ProjectName)) { var duplicates = await ValidateProjectName(data.CustomerUid, userUid, data.ProjectName, data.ProjectUid); if (duplicates > 0) { return(new ContractExecutionResult(109, $"Project Name must be unique. {duplicates} active project duplicates found.")); } } //Validate project boundary if changed if (!string.IsNullOrEmpty(data.ProjectBoundaryWKT)) { dynamic boundaryResult = ValidateProjectBoundary(data.ProjectBoundaryWKT); if (boundaryResult.code != ContractExecutionStatesEnum.ExecutedSuccessfully) { return(new ContractExecutionResult(boundaryResult.code, boundaryResult.message)); } var overlaps = await ProjectRequestHelper.DoesProjectOverlap(data.CustomerUid, data.ProjectUid, userUid, data.ProjectBoundaryWKT, log, serviceExceptionHandler, cwsProjectClient, customHeaders); if (overlaps) { return(new ContractExecutionResult(43, "Project boundary overlaps another project.")); } } //Validate coordinate system file if changed if (!string.IsNullOrEmpty(data.CoordinateSystemFileName) || (data.CoordinateSystemFileContent?.Length > 0)) { if (string.IsNullOrEmpty(data.CoordinateSystemFileName) || data.CoordinateSystemFileContent == null || data.CoordinateSystemFileContent.Length == 0) { return(new ContractExecutionResult(134, "Both coordinate system file name and contents must be provided.")); } dynamic coordSysResult = await ValidateCoordinateSystemFile(data.ProjectUid, data.CoordinateSystemFileName, data.CoordinateSystemFileContent); if (coordSysResult.code != ContractExecutionStatesEnum.ExecutedSuccessfully) { return(new ContractExecutionResult(coordSysResult.code, coordSysResult.message)); } } } else if (data.UpdateType == ProjectUpdateType.Archived) { if (!data.ProjectUid.HasValue) { return(new ContractExecutionResult(5, "Missing ProjectUID.")); } //no other validation for ProjectUpdateType.Archived } else if (data.UpdateType == ProjectUpdateType.Deleted) { if (!data.ProjectUid.HasValue) { return(new ContractExecutionResult(5, "Missing ProjectUID.")); } try { //If the project, regardless of type, has any tag file data, it cannot be deleted. var result = await productivity3dV2ProxyCompaction.GetProjectStatistics(data.ProjectUid.Value, customHeaders); if (result.extents?.ValidExtents == true && result.extents?.EmptyExtents == false) { log.LogInformation($"ValidateProjectExecutor: Project {data.ProjectUid.Value} has tag file data. NOT ok to delete."); return(new ContractExecutionResult(141, "Cannot delete a project that has 3D production (tag file) data")); } log.LogInformation($"ValidateProjectExecutor: Project {data.ProjectUid.Value} has NO tag file data. Ok to delete."); } catch (Exception e) { if (!e.Message.Contains($"GetStatistics: SiteModel: {data.ProjectUid.Value} not found")) { return(new ContractExecutionResult(57, $"A problem occurred at the validate project deletion endpoint in 3dpm. Exception: {e.Message}")); } log.LogInformation($"ValidateProjectExecutor: Project {data.ProjectUid.Value} not found in TRex. Ok to delete."); } } return(new ContractExecutionResult()); }
/// <summary> /// Deletes file via Trex /// </summary> protected override async Task <ContractExecutionResult> ProcessAsyncEx <T>(T item) { var deleteImportedFile = CastRequestObjectTo <DeleteImportedFile>(item, errorCode: 68); await CheckIfUsedInFilter(deleteImportedFile); await CheckIfHasReferenceSurfacesAsync(deleteImportedFile); // DB change must be made before productivity3dV2ProxyNotification.DeleteFile is called as it calls back here to get list of Active files //Don't think the above comment applies any more ! var deleteImportedFileEvent = await ImportedFileRequestDatabaseHelper.DeleteImportedFileInDb (deleteImportedFile.ProjectUid, deleteImportedFile.ImportedFileUid, serviceExceptionHandler, projectRepo); ImportedFileInternalResult importedFileInternalResult = null; if (deleteImportedFile.IsTRexDesignFileType) { //Now delete in TRex await ImportedFileRequestHelper.NotifyTRexDeleteFile(deleteImportedFile.ProjectUid, deleteImportedFile.ImportedFileType, deleteImportedFile.FileDescriptor.FileName, deleteImportedFile.ImportedFileUid, deleteImportedFile.SurveyedUtc, log, customHeaders, serviceExceptionHandler, tRexImportFileProxy); //and from s3 bucket ProjectRequestHelper.DeleteFileFromS3Repository( deleteImportedFile.ProjectUid.ToString(), deleteImportedFile.FileDescriptor.FileName, deleteImportedFile.ImportedFileType == ImportedFileType.SurveyedSurface, deleteImportedFile.SurveyedUtc, log, serviceExceptionHandler, persistantTransferProxyFactory.NewProxy(TransferProxyType.DesignImport)); } if (deleteImportedFile.ImportedFileType == ImportedFileType.Linework || deleteImportedFile.ImportedFileType == ImportedFileType.GeoTiff) { var dataOceanFileName = DataOceanFileUtil.DataOceanFileName(deleteImportedFile.FileDescriptor.FileName, deleteImportedFile.ImportedFileType == ImportedFileType.SurveyedSurface || deleteImportedFile.ImportedFileType == ImportedFileType.GeoTiff, deleteImportedFile.ImportedFileUid, deleteImportedFile.SurveyedUtc); importedFileInternalResult = await DataOceanHelper.DeleteFileFromDataOcean( dataOceanFileName, deleteImportedFile.DataOceanRootFolder, customerUid, deleteImportedFile.ProjectUid, deleteImportedFile.ImportedFileUid, log, dataOceanClient, authn, configStore); var tasks = new List <Task>(); //delete generated DXF tiles var dxfFileName = DataOceanFileUtil.GeneratedFileName(dataOceanFileName, deleteImportedFile.ImportedFileType); var dataOceanPath = DataOceanFileUtil.DataOceanPath(deleteImportedFile.DataOceanRootFolder, customerUid, deleteImportedFile.ProjectUid.ToString()); var fullFileName = $"{dataOceanPath}{Path.DirectorySeparatorChar}{dxfFileName}"; tasks.Add(pegasusClient.DeleteTiles(fullFileName, DataOceanHelper.CustomHeaders(authn))); await Task.WhenAll(tasks); } if (importedFileInternalResult != null) { await ImportedFileRequestDatabaseHelper.UndeleteImportedFile (deleteImportedFile.ProjectUid, deleteImportedFile.ImportedFileUid, serviceExceptionHandler, projectRepo); serviceExceptionHandler.ThrowServiceException(importedFileInternalResult.StatusCode, importedFileInternalResult.ErrorNumber, importedFileInternalResult.ResultCode, importedFileInternalResult.ErrorMessage1); } return(new ContractExecutionResult()); }
/// <summary> /// Processes the Upsert /// </summary> protected override async Task <ContractExecutionResult> ProcessAsyncEx <T>(T item) { var importedFile = CastRequestObjectTo <UpdateImportedFile>(item, errorCode: 68); var existingImportedFile = await projectRepo.GetImportedFile(importedFile.ImportedFileUid.ToString()); if (existingImportedFile == null) { throw new ServiceException(HttpStatusCode.BadRequest, new ContractExecutionResult(ProjectErrorCodesProvider.GetErrorNumberwithOffset(122), ProjectErrorCodesProvider.FirstNameWithOffset(122))); } if (importedFile.IsTRexDesignFileType) { await ImportedFileRequestHelper.NotifyTRexUpdateFile(importedFile.ProjectUid, importedFile.ImportedFileType, importedFile.FileDescriptor.FileName, importedFile.ImportedFileUid, importedFile.SurveyedUtc, log, customHeaders, serviceExceptionHandler, tRexImportFileProxy); } if (importedFile.ImportedFileType == ImportedFileType.Linework || importedFile.ImportedFileType == ImportedFileType.GeoTiff) { string dcFileName = null; if (importedFile.ImportedFileType == ImportedFileType.Linework) { var project = await ProjectRequestHelper.GetProject(importedFile.ProjectUid, new Guid(customerUid), new Guid(userId), log, serviceExceptionHandler, cwsProjectClient, customHeaders); dcFileName = DataOceanFileUtil.DataOceanFileName(project.CoordinateSystemFileName, false, importedFile.ProjectUid, null); } var jobRequest = TileGenerationRequestHelper.CreateRequest( importedFile.ImportedFileType, customerUid, importedFile.ProjectUid.ToString(), existingImportedFile.ImportedFileUid, importedFile.DataOceanRootFolder, importedFile.DataOceanFileName, dcFileName, importedFile.DxfUnitsTypeId, importedFile.SurveyedUtc); await schedulerProxy.ScheduleVSSJob(jobRequest, customHeaders); } // if all succeeds, update Db and put update to kafka que var updateImportedFileEvent = await ImportedFileRequestDatabaseHelper.UpdateImportedFileInDb(existingImportedFile, existingImportedFile.FileDescriptor, importedFile.SurveyedUtc, existingImportedFile.MinZoomLevel, existingImportedFile.MaxZoomLevel, importedFile.FileCreatedUtc, importedFile.FileUpdatedUtc, userEmailAddress, log, serviceExceptionHandler, projectRepo); var fileDescriptor = new ImportedFileDescriptorSingleResult( (await ImportedFileRequestDatabaseHelper.GetImportedFileList(importedFile.ProjectUid.ToString(), log, userId, projectRepo)) .ToImmutableList() .FirstOrDefault(f => f.ImportedFileUid == importedFile.ImportedFileUid.ToString()) ); log.LogInformation( $"UpdateImportedFileExecutor. entry {(fileDescriptor.ImportedFileDescriptor == null ? "not " : "")}retrieved from DB : {JsonConvert.SerializeObject(fileDescriptor)}"); return(fileDescriptor); }
/// <summary> /// Common file processing method used by all importedFile endpoints. /// </summary> protected async Task <ImportedFileDescriptorSingleResult> UpsertFileInternal( string filename, Stream fileStream, Guid projectUid, ImportedFileType importedFileType, DxfUnitsType dxfUnitsType, DateTime fileCreatedUtc, DateTime fileUpdatedUtc, DateTime?surveyedUtc, ISchedulerProxy schedulerProxy, Guid?parentUid = null, double?offset = null) { ImportedFileDescriptorSingleResult importedFile = null; var existing = await ImportedFileRequestDatabaseHelper .GetImportedFileForProject (projectUid.ToString(), filename, importedFileType, surveyedUtc, Logger, ProjectRepo, offset, parentUid) .ConfigureAwait(false); var creating = existing == null; Logger.LogInformation( creating ? $"{nameof(UpsertFileInternal)}. file doesn't exist already in DB: {filename} projectUid {projectUid} ImportedFileType: {importedFileType} surveyedUtc {(surveyedUtc == null ? "N/A" : surveyedUtc.ToString())} parentUid {parentUid} offset: {offset}" : $"{nameof(UpsertFileInternal)}. file exists already in DB. Will be updated: {JsonConvert.SerializeObject(existing)}"); FileDescriptor fileDescriptor = null; var importedFileUid = creating ? Guid.NewGuid() : Guid.Parse(existing.ImportedFileUid); var dataOceanFileName = DataOceanFileUtil.DataOceanFileName(filename, importedFileType == ImportedFileType.SurveyedSurface || importedFileType == ImportedFileType.GeoTiff, importedFileUid, surveyedUtc); if (importedFileType == ImportedFileType.ReferenceSurface) { //FileDescriptor not used for reference surface but validation requires values fileDescriptor = FileDescriptor.CreateFileDescriptor("Not applicable", "Not applicable", filename); } else { if (IsTRexDesignFileType(importedFileType)) { fileDescriptor = ProjectRequestHelper.WriteFileToS3Repository( fileStream, projectUid.ToString(), filename, importedFileType == ImportedFileType.SurveyedSurface, surveyedUtc, Logger, ServiceExceptionHandler, persistantTransferProxyFactory.NewProxy(TransferProxyType.DesignImport)); } //This is needed for ATs. fileDescriptor = FileDescriptor.CreateFileDescriptor( FileSpaceId, $"/{CustomerUid}/{projectUid}", filename); if (importedFileType == ImportedFileType.Linework || importedFileType == ImportedFileType.GeoTiff) { //save copy to DataOcean await DataOceanHelper.WriteFileToDataOcean( fileStream, DataOceanRootFolderId, CustomerUid, projectUid.ToString(), dataOceanFileName, Logger, ServiceExceptionHandler, DataOceanClient, Authorization, importedFileUid, ConfigStore); } } if (creating) { var createImportedFile = new CreateImportedFile( projectUid, filename, fileDescriptor, importedFileType, surveyedUtc, dxfUnitsType, fileCreatedUtc, fileUpdatedUtc, DataOceanRootFolderId, parentUid, offset, importedFileUid, dataOceanFileName); importedFile = await WithServiceExceptionTryExecuteAsync(() => RequestExecutorContainerFactory .Build <CreateImportedFileExecutor>( LoggerFactory, ConfigStore, ServiceExceptionHandler, CustomerUid, UserId, UserEmailAddress, customHeaders, productivity3dV2ProxyCompaction : Productivity3dV2ProxyCompaction, persistantTransferProxyFactory : persistantTransferProxyFactory, tRexImportFileProxy : tRexImportFileProxy, projectRepo : ProjectRepo, dataOceanClient : DataOceanClient, authn : Authorization, schedulerProxy : schedulerProxy, cwsProjectClient : CwsProjectClient) .ProcessAsync(createImportedFile) ) as ImportedFileDescriptorSingleResult; Logger.LogInformation( $"{nameof(UpsertFileInternal)}: Create completed successfully. Response: {JsonConvert.SerializeObject(importedFile)}"); } else { // this also validates that this customer has access to the projectUid var project = await ProjectRequestHelper.GetProject(projectUid, new Guid(CustomerUid), new Guid(UserId), Logger, ServiceExceptionHandler, CwsProjectClient, customHeaders); var importedFileUpsertEvent = new UpdateImportedFile( projectUid, project.ShortRaptorProjectId, importedFileType, (importedFileType == ImportedFileType.SurveyedSurface || importedFileType == ImportedFileType.GeoTiff) ? surveyedUtc : null, dxfUnitsType, fileCreatedUtc, fileUpdatedUtc, fileDescriptor, Guid.Parse(existing?.ImportedFileUid), existing.ImportedFileId, DataOceanRootFolderId, offset, dataOceanFileName); importedFile = await WithServiceExceptionTryExecuteAsync(() => RequestExecutorContainerFactory .Build <UpdateImportedFileExecutor>( LoggerFactory, ConfigStore, ServiceExceptionHandler, CustomerUid, UserId, UserEmailAddress, customHeaders, productivity3dV2ProxyCompaction : Productivity3dV2ProxyCompaction, tRexImportFileProxy : tRexImportFileProxy, projectRepo : ProjectRepo, dataOceanClient : DataOceanClient, authn : Authorization, schedulerProxy : schedulerProxy, cwsProjectClient : CwsProjectClient) .ProcessAsync(importedFileUpsertEvent) ) as ImportedFileDescriptorSingleResult; Logger.LogInformation( $"{nameof(UpsertFileInternal)}: Update completed successfully. Response: {JsonConvert.SerializeObject(importedFile)}"); } await NotificationHubClient.Notify(new ProjectChangedNotification(projectUid)); return(importedFile); }