Esempio n. 1
0
        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));
        }
Esempio n. 2
0
        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));
        }
Esempio n. 3
0
        /// <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);
        }
Esempio n. 4
0
        /// <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));
        }
Esempio n. 5
0
        /// <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));
        }