public async Task <IHttpActionResult> GetConfig([FromUri] Guid?tenantId, [FromUri] Guid?operationId = null) { var errors = new List <FFErrorCode>(); if (!tenantId.HasValue) { errors.Add(ValidationErrorCode.PropertyRequired(nameof(tenantId))); } if (errors.Any()) { return(Request.CreateApiResponse(NoDtoHelpers.CreateCommandResult(errors))); } var authHeader = Request.Headers.Authorization.ToString(); var result = await _facade.Get((Guid)tenantId, operationId, authHeader); return(Request.CreateApiResponse(result)); }
public async Task <IHttpActionResult> Post() { var errors = new List <FFErrorCode>(); // Parse Request Content var provider = new MultipartFormDataStreamProvider(Path.GetTempPath()); var parts = await Request.Content.ReadAsMultipartAsync(provider).ConfigureAwait(false); // Validate the request body if (string.IsNullOrEmpty(parts.FormData["uploadTransactionType"])) { errors.Add(GeneralErrorCodes.FormDataFieldMissing("uploadTransactionType")); } var tenantIdString = parts.FormData["tenantId"]; if (string.IsNullOrEmpty(tenantIdString)) { errors.Add(GeneralErrorCodes.FormDataFieldMissing("tenantId")); } var tenantIdGuid = Guid.Empty; if (!Guid.TryParse(tenantIdString, out tenantIdGuid) || tenantIdGuid == Guid.Empty) { errors.Add(GeneralErrorCodes.FormDataFieldInvalid("tenantId")); } // Get files var files = parts.FileData.Select(x => x.LocalFileName); var enumeratedFiles = files as IList <string> ?? files.ToList(); if (!enumeratedFiles.Any()) { errors.Add(GeneralErrorCodes.FormDataFilesMissing()); } if (errors.Any()) { return(Request.CreateApiResponse(NoDtoHelpers.CreateCommandResult(errors))); } var fileToUpload = enumeratedFiles.First(); var originalFileName = parts.FileData[0].Headers.ContentDisposition.FileName.Replace("\"", string.Empty); var fileUploadMetadata = new FileUploadMetadataDto { SavedFileName = fileToUpload, OriginalFileName = originalFileName, TransactionType = parts.FormData["uploadTransactionType"].Replace("\"", string.Empty) }; var authHeader = Request.Headers.Authorization.ToString(); var result = await _facade.Upload(fileUploadMetadata, authHeader, tenantIdGuid); foreach (var file in enumeratedFiles) { File.Delete(file); } return(Request.CreateApiResponse(result)); }
/// <summary> /// Deletes the requested operation if the operation has no measurements associated to it's locations. /// </summary> /// <param name="operationId">Guid identitifer of the operation to delete</param> /// <returns>Task that returns the request result.</returns> public async Task <CommandResultNoDto> Delete(Guid?operationId) { var errors = new List <FFErrorCode>(); var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal(); if (string.IsNullOrEmpty(userId)) { errors.Add(GeneralErrorCodes.TokenInvalid("UserId")); } if (!operationId.HasValue || operationId == Guid.Empty) { errors.Add(ValidationErrorCode.PropertyRequired("OperationId")); } if (errors.Count > 0) { return(NoDtoHelpers.CreateCommandResult(errors)); } var userIdGuid = Guid.Parse(userId); List <Location> locations = new List <Location>(); List <LocationParameterLimit> locationParameterLimits = new List <LocationParameterLimit>(); List <LocationParameter> locationParameters = new List <LocationParameter>(); List <LocationLogEntry> locationLocationLogEntries = new List <LocationLogEntry>(); // Check that the Location exists and if it's an operation if (!_context.Locations.Any(x => x.Id == operationId.Value && x.LocationType.LocationTypeGroup.Id == Data.Constants.LocationTypeGroups.Operation.Id)) { errors.Add(EntityErrorCode.EntityNotFound); } else { // Check if user is in the proper tenant. if (!_context.Locations.Single(x => x.Id == operationId.Value) .ProductOfferingTenantLocations.Any(x => x.Tenant.Users.Any(u => u.Id == userIdGuid))) { errors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId")); } // Check that the operation has no measurements or notes and can be deleted // NOTE : This method will not scale beyond more than 4 or 5 levels max var operation = _context.Locations.Include("Locations").Single(x => x.Id == operationId.Value); locations.Add(operation); var systems = operation.Locations; locations.AddRange(systems); foreach (var system in systems) { locations.AddRange(_context.Locations.Where(x => x.ParentId == system.Id).ToList()); } var locationIds = locations.Select(l => l.Id); locationParameters = _context.LocationParameters.Where(x => locationIds.Contains(x.LocationId)).ToList(); var locationParamIds = locationParameters.Select(lp => lp.Id); locationParameterLimits = _context.LocationParameterLimits.Where( x => locationParamIds.Contains(x.LocationParameterId)).ToList(); var hasLocationLocationLogEntries = _context.LocationLogEntries.Any(x => locationIds.Contains(x.LocationId)); var hasMeasurements = _context.Measurements.Any(x => locationParamIds.Contains(x.LocationParameterId)); var hasParameterNotes = _context.LocationParameterNotes.Any( x => locationParamIds.Contains(x.LocationParameterId)); var hasMeasurementTransactions = _context.MeasurementTransactions.Any(x => locationIds.Contains(x.LocationId)); if (hasParameterNotes || hasMeasurements || hasLocationLocationLogEntries || hasMeasurementTransactions) { errors.Add(EntityErrorCode.EntityCouldNotBeDeleted); } } if (errors.Count > 0) { return(NoDtoHelpers.CreateCommandResult(errors)); } _context.LocationParameterLimits.RemoveRange(locationParameterLimits); _context.LocationParameters.RemoveRange(locationParameters); _context.Locations.RemoveRange(locations); _context.LocationLogEntries.RemoveRange(locationLocationLogEntries); await _context.SaveChangesAsync().ConfigureAwait(false); var commandResult = NoDtoHelpers.CreateCommandResult(errors); // CreateCommandResult will either return BadRequest(400) or Ok(200) // Overriding the Status code to return a 204 on a successful delete commandResult.StatusCode = FacadeStatusCode.NoContent; return(commandResult); }
/// <summary> /// Accepts a single xls file that contains operation configuration. /// </summary> /// <param name="fileMetadata">Metadata associated with the file upload request.</param> /// <param name="authenticationHeader">Authentication header for the request.</param> /// <param name="requestTenantId">The selected Tenant Id from the request import the Operation Config to</param> /// <returns>A task that returns the result of the upload option.</returns> public async Task <CommandResultNoDto> Upload(FileUploadMetadataDto fileMetadata, string authenticationHeader, Guid requestTenantId) { var errors = new List <FFErrorCode>(); var odataHelper = new Core.Api.OData.ODataHelper(); var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal(); if (userId == null) { errors.Add(GeneralErrorCodes.TokenInvalid("UserId")); } if (errors.Count > 0) { return(NoDtoHelpers.CreateCommandResult(errors)); } // ReSharper disable once AssignNullToNotNullAttribute var userIdGuid = Guid.Parse(userId); // Check that the Tenant Id in the request body is in the user's claim tenants var tenants = odataHelper.GetTenantIds(Thread.CurrentPrincipal) as List <Guid>; // Check user has no tenants in their claim or if the tenantid in the request body is not in the claim if (tenants == null || tenants.All(x => x != requestTenantId)) { errors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId")); } if (errors.Count > 0) { return(NoDtoHelpers.CreateCommandResult(errors)); } // Store file in blob storage. var result = await _blobManager.StoreAsync(_blobStorageConnectionString, _blobStorageContainerName, fileMetadata.SavedFileName); // Add file metadata to documentDB to later be retrieved by request // An Id property is created by documentDB and in populated in the result object await _documentDb.CreateItemAsync( new UploadTransaction { OriginalFileName = fileMetadata.OriginalFileName, TenantIds = tenants, UploadTransactionType = fileMetadata.TransactionType, UserId = userIdGuid, UtcTimestamp = DateTime.UtcNow }); var queueMessage = new BlobQueueMessage { BlobName = result.BlobName, BlobSize = result.BlobSize, BlobUrl = result.BlobUrl, BlobTransactionType = fileMetadata.TransactionType, UserId = userIdGuid, AuthenticationHeader = authenticationHeader, // TenantId should be checked by the blob processor that it matches the tenant in the Operation Config to be processed TenantId = requestTenantId }; var msg = JsonConvert.SerializeObject(queueMessage); // Add message to queue. await _queueManager.AddAsync(_blobStorageConnectionString, _queueStorageContainerName, msg); return(NoDtoHelpers.CreateCommandResult(errors)); }
/// <summary> /// Creates an operation configuration file and saves it to blob storage. When /// the file is ready to be downloaded, a signalr notification is sent to the user who made the /// requst. /// </summary> /// <param name="tenantId">Identifies the tenant that the operation belongs to.</param> /// <param name="operationId">Identifies the operation to create the configuration for or /// null to create a configuration file template with no operation related data.</param> /// <param name="authenticationHeader">Authentication header for the request.</param> /// <returns>A task that returns the result of the request.</returns> public async Task <CommandResultNoDto> Get(Guid tenantId, Guid?operationId, string authenticationHeader) { var errors = new List <FFErrorCode>(); var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal(); if (userId == null) { errors.Add(GeneralErrorCodes.TokenInvalid("UserId")); } if (errors.Count > 0) { return(NoDtoHelpers.CreateCommandResult(errors)); } // ReSharper disable once AssignNullToNotNullAttribute var userIdGuid = Guid.Parse(userId); // Check that the user has access to the requested tenant. var odataHelper = new Core.Api.OData.ODataHelper(); var tenants = odataHelper.GetTenantIds(Thread.CurrentPrincipal) as List <Guid>; if (tenants == null || tenants.All(x => x != tenantId)) { errors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId")); } if (operationId != null) { var operation = await _context.Locations.FirstOrDefaultAsync(x => x.Id == operationId).ConfigureAwait(false); if (operation == null) { errors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("OperationId")); } else if (operation.ProductOfferingTenantLocations.All(x => x.TenantId != tenantId)) { errors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId")); } } if (errors.Count > 0) { return(NoDtoHelpers.CreateCommandResult(errors)); } var transactionType = operationId == null ? UploadTransactionTypes.ExportOperationTemplate : UploadTransactionTypes.ExportOperationConfig; var queueMessage = new BlobQueueMessage { BlobTransactionType = transactionType, UserId = userIdGuid, TenantId = tenantId, OperationId = operationId, AuthenticationHeader = authenticationHeader }; // Add message to queue. await _queueManager.AddAsync(_blobStorageConnectionString, _queueStorageContainerName, JsonConvert.SerializeObject(queueMessage)); return(NoDtoHelpers.CreateCommandResult(errors)); }