public async Task <IActionResult> NotifyAllUsers([FromBody] NotifyRequest notification)
        {
            if (notification == null)
            {
                ModelState.AddModelError(ErrorResponses.MissingBody, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var requestedNotification = new Notification()
            {
                Status         = notification.Status,
                Type           = notification.Type,
                Priority       = notification.Priority,
                StartDate      = notification.StartDate,
                EndDate        = notification.EndDate,
                Subject        = notification.Subject,
                Message        = notification.Message,
                AllowDismissal = notification.AllowDismissal
            };
            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var notifyCommand = new Jibberwock.Persistence.DataAccess.Commands.Notifications.Notify(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null,
                                                                                                    requestedNotification, notification.SendAsEmail, _queueDataSource, WebApiConfiguration.ServiceBus.Queues.Notifications);
            var resultantCommand = await notifyCommand.Execute(SqlServerDataSource);

            return(Ok(resultantCommand.Result));
        }
        public async Task <IActionResult> CreateCharacteristic([FromBody] ProductCharacteristicChangeSetting characteristic)
        {
            if (characteristic == null)
            {
                ModelState.AddModelError(ErrorResponses.MissingBody, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var charModel = new ProductCharacteristic()
            {
                Name        = characteristic.Name,
                Description = characteristic.Description,
                Enabled     = characteristic.Enabled,
                Visible     = characteristic.Visible,
                ValueType   = characteristic.ValueType
            };
            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var createCharacteristicCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.CreateCharacteristic(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, charModel);

            var creationSuccessful = await createCharacteristicCommand.Execute(SqlServerDataSource);

            return(Created(string.Empty, creationSuccessful.Result));
        }
        public async Task <IActionResult> ControlUserAccess([FromRoute] long id, [FromBody, Bind(nameof(UserAccessChangeSetting.Enabled))] UserAccessChangeSetting accessChangeSetting)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }
            if (accessChangeSetting == null)
            {
                ModelState.AddModelError(ErrorResponses.MissingBody, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var requestedState = new User()
            {
                Id = id, Enabled = accessChangeSetting.Enabled
            };
            var controlUserAccessCommand = new Jibberwock.Persistence.DataAccess.Commands.Security.ControlUserAccess(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, requestedState);

            var controlSuccessful = await controlUserAccessCommand.Execute(SqlServerDataSource);

            if (controlSuccessful.Result)
            {
                return(Ok(requestedState));
            }
            else
            {
                return(NotFound());
            }
        }
        public async Task <IActionResult> GetCurrentUserNotifications()
        {
            var currUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var listNotificationsCommand = new Jibberwock.Persistence.DataAccess.Commands.Notifications.ListClientNotifications(Logger, currUser);
            var allNotifications         = await listNotificationsCommand.Execute(SqlServerDataSource);

            return(Ok(allNotifications));
        }
        public async Task <IActionResult> GetProducts([FromQuery] bool includeHiddenProducts)
        {
            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var listProductsCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.ListProducts(Logger, currentUser, includeHiddenProducts);

            var products = await listProductsCommand.Execute(SqlServerDataSource);

            return(Ok(products));
        }
        public async Task <IActionResult> CreateProductTier([FromRoute, ResourcePermissions(SecurableResourceType.Product, Permission.Change)] long id, [FromBody] TierCreationOptions productTier)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }
            if (productTier == null)
            {
                ModelState.AddModelError(ErrorResponses.MissingBody, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            // This is a three-step operation (because the tier characteristic values need to be interpreted)
            // First, get the list of characteristics (and their associated data types)
            // Second, perform the conversion from a string/object into a usable form
            // Third, perform the upload
            var suppliedCharacteristicValues = await parseProductCharacteristicsAsync(id, productTier.CharacteristicValues);

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var tierModel = new Tier()
            {
                Name       = productTier.Name,
                ExternalId = productTier.ExternalId,
                StartDate  = productTier.StartDate,
                EndDate    = productTier.EndDate,
                Product    = new Product()
                {
                    Id = id
                },
                Visible         = productTier.Visible,
                Characteristics = suppliedCharacteristicValues
            };

            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            // Create the tier, then pass the details along to a GetTierById command to populate the full details
            var createTierCommand   = new Jibberwock.Persistence.DataAccess.Commands.Products.CreateTier(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, tierModel);
            var auditedTierCreation = await createTierCommand.Execute(SqlServerDataSource);

            var getCreatedTierCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.GetTier(Logger, currentUser, auditedTierCreation.Result);
            var resultantTier         = await getCreatedTierCommand.Execute(SqlServerDataSource);

            return(Created(string.Empty, resultantTier));
        }
        public async Task <IActionResult> UpdateProductTier([FromRoute, ResourcePermissions(SecurableResourceType.Product, Permission.Change)] long id, [FromRoute] long tierId, [FromBody] TierCreationOptions updatedTier)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }
            if (tierId == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var suppliedCharacteristicValues = await parseProductCharacteristicsAsync(id, updatedTier.CharacteristicValues);

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var tierModel = new Tier()
            {
                Id        = tierId,
                Name      = updatedTier.Name,
                StartDate = updatedTier.StartDate,
                EndDate   = updatedTier.EndDate,
                Product   = new Product()
                {
                    Id = id
                },
                Visible         = updatedTier.Visible,
                Characteristics = suppliedCharacteristicValues
            };

            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            // Update the tier, then return it to the clients
            var updateTierCommand   = new Jibberwock.Persistence.DataAccess.Commands.Products.UpdateTier(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, tierModel);
            var auditedTierCreation = await updateTierCommand.Execute(SqlServerDataSource);

            if (auditedTierCreation.Result != null)
            {
                return(Ok(auditedTierCreation.Result));
            }
            else
            {
                return(NotFound());
            }
        }
        public async Task <IActionResult> DismissNotification([FromRoute] long notificationId)
        {
            var currUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var dismissNotificationCommand = new Jibberwock.Persistence.DataAccess.Commands.Notifications.Dismiss(Logger, currUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null,
                                                                                                                  new Notification()
            {
                Id = notificationId
            });

            await dismissNotificationCommand.Execute(SqlServerDataSource);

            return(NoContent());
        }
        public async Task <IActionResult> DeleteProductCharacteristic([FromRoute] int id)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var charModel = new ProductCharacteristic()
            {
                Id = id
            };
            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var deleteCharacteristicCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.DeleteCharacteristic(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, charModel);

            var deleteSuccessful = await deleteCharacteristicCommand.Execute(SqlServerDataSource);

            switch (deleteSuccessful.Result)
            {
            case Persistence.DataAccess.Commands.Products.DeleteCharacteristicStatusCode.Success:
                return(StatusCode(StatusCodes.Status204NoContent));

            case Persistence.DataAccess.Commands.Products.DeleteCharacteristicStatusCode.AssociatedTier:
                ModelState.AddModelError(ErrorResponses.AssociatedWithTier, string.Empty);
                break;

            case Persistence.DataAccess.Commands.Products.DeleteCharacteristicStatusCode.AssociatedProduct:
                ModelState.AddModelError(ErrorResponses.AssociatedWithProduct, string.Empty);
                break;

            case Persistence.DataAccess.Commands.Products.DeleteCharacteristicStatusCode.Missing:
                return(NotFound());

            default:
                throw new ArgumentOutOfRangeException("This operation's return value was unexpected.");
            }

            // We've only reached this point if there's been an error in the model state
            return(BadRequest(ModelState));
        }
        public async Task <IActionResult> UpdateProduct([FromRoute, ResourcePermissions(SecurableResourceType.Product, Permission.Change)] long id, [FromBody] ProductCreationOptions updatedProduct)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }
            if (updatedProduct == null)
            {
                ModelState.AddModelError(ErrorResponses.MissingBody, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var prodModel = new Product()
            {
                Id                          = id,
                Name                        = updatedProduct.Name,
                Description                 = updatedProduct.Description,
                MoreInformationUrl          = updatedProduct.MoreInformationUrl,
                Visible                     = updatedProduct.Visible,
                ConfigurationControlName    = updatedProduct.ConfigurationControlName,
                DefaultProductConfiguration = new Jibberwock.DataModels.Products.Configuration.RawProductConfiguration(updatedProduct.DefaultProductConfiguration),
                ApplicableCharacteristics   = updatedProduct.ApplicableCharacteristicIDs.Select(x => new ProductCharacteristic()
                {
                    Id = x
                })
            };
            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var updateProductCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.UpdateProduct(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, prodModel);

            var updateSuccessful = await updateProductCommand.Execute(SqlServerDataSource);

            if (updateSuccessful.Result != null)
            {
                return(Ok(updateSuccessful.Result));
            }
            else
            {
                return(NotFound());
            }
        }
        public async Task <IActionResult> GetProductTiers([FromRoute, ResourcePermissions(SecurableResourceType.Product, Permission.Read)] long id, [FromQuery] bool includeHiddenTiers)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var productModel = new Product()
            {
                Id = id
            };
            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var listTiersCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.ListTiers(Logger, currentUser, includeHiddenTiers, productModel);
            var tiers            = await listTiersCommand.Execute(SqlServerDataSource);

            return(Ok(tiers));
        }
        public async Task <IActionResult> UpdateProductCharacteristic([FromRoute] int id, [FromBody] ProductCharacteristicChangeSetting updatedCharacteristic)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }
            if (updatedCharacteristic == null)
            {
                ModelState.AddModelError(ErrorResponses.MissingBody, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var charModel = new ProductCharacteristic()
            {
                Id      = id, Name = updatedCharacteristic.Name, Description = updatedCharacteristic.Description,
                Enabled = updatedCharacteristic.Enabled, Visible = updatedCharacteristic.Visible
            };
            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var updateCharacteristicCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.UpdateCharacteristic(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, charModel);

            var updateSuccessful = await updateCharacteristicCommand.Execute(SqlServerDataSource);

            if (updateSuccessful.Result != null)
            {
                return(Ok(updateSuccessful.Result));
            }
            else
            {
                return(NotFound());
            }
        }
        public async Task <IActionResult> GetSingleProductTier([FromRoute, ResourcePermissions(SecurableResourceType.Product, Permission.Read)] long id, [FromRoute] long tierId)
        {
            if (id == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }
            if (tierId == 0)
            {
                ModelState.AddModelError(ErrorResponses.InvalidId, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var getTierCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.GetTier(Logger, currentUser, new Tier()
            {
                Id = tierId, Product = new Product()
                {
                    Id = id
                }
            });
            var tier = await getTierCommand.Execute(SqlServerDataSource);

            if (tier == null)
            {
                return(NotFound());
            }
            else
            {
                return(Ok(tier));
            }
        }
        public async Task <IActionResult> CreateProduct([FromBody] ProductCreationOptions product)
        {
            if (product == null)
            {
                ModelState.AddModelError(ErrorResponses.MissingBody, string.Empty);
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            product.ApplicableCharacteristicIDs ??= Enumerable.Empty <int>();

            var productModel = new Jibberwock.DataModels.Products.Product()
            {
                Name                        = product.Name,
                Description                 = product.Description,
                MoreInformationUrl          = product.MoreInformationUrl,
                Visible                     = product.Visible,
                ConfigurationControlName    = product.ConfigurationControlName,
                DefaultProductConfiguration = new Jibberwock.DataModels.Products.Configuration.RawProductConfiguration(product.DefaultProductConfiguration),
                ApplicableCharacteristics   = product.ApplicableCharacteristicIDs?.Select(i => new Jibberwock.DataModels.Products.ProductCharacteristic()
                {
                    Id = i
                }).ToArray()
            };

            var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

            var createProductCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.CreateProduct(Logger, currentUser, HttpContext.TraceIdentifier, WebApiConfiguration.Authorization.DefaultServiceId, null, productModel);

            var creationSuccessful = await createProductCommand.Execute(SqlServerDataSource);

            return(Created(string.Empty, creationSuccessful.Result));
        }
        private async Task <IEnumerable <TierProductCharacteristic> > parseProductCharacteristicsAsync(long productId, IEnumerable <TierCharacteristicValue> characteristicValues)
        {
            var suppliedCharacteristicValues = new List <TierProductCharacteristic>();

            if (characteristicValues != null && characteristicValues.Any())
            {
                // Get the characteristics, filtering to Enabled ones for sanity's sake.
                // Focus on the global characteristics list, then the product's applicable characteristics
                var listCharacteristicsCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.ListAllCharacteristics(Logger);
                var globalCharacteristicsList  = await listCharacteristicsCommand.Execute(SqlServerDataSource);

                var globalCharacteristics = globalCharacteristicsList.Where(c => c.Enabled).ToDictionary(ch => ch.Id);

                var currentUser = await CurrentUserRetriever.GetCurrentUserAsync();

                var getProductCommand = new Jibberwock.Persistence.DataAccess.Commands.Products.GetById(Logger, currentUser, new Product()
                {
                    Id = productId
                });
                var productDetails = await getProductCommand.Execute(SqlServerDataSource);

                var productCharacteristics = productDetails.ApplicableCharacteristics.Where(c => c.Enabled).ToDictionary(ch => ch.Id);

                foreach (var charValue in characteristicValues)
                {
                    // Discard any supplied characteristics which don't exist in the lists
                    if (!globalCharacteristics.ContainsKey(charValue.CharacteristicId) | !productCharacteristics.ContainsKey(charValue.CharacteristicId))
                    {
                        ModelState.AddModelError(ErrorResponses.InvalidCharacteristic, $"{{ \"id\": {charValue.CharacteristicId} }}");
                        continue;
                    }

                    var prodChar     = productCharacteristics[charValue.CharacteristicId];
                    var resultantTpc = new TierProductCharacteristic()
                    {
                        ProductCharacteristic = prodChar
                    };

                    // Handle the translation, converting from strings to booleans, longs or strings
                    switch (prodChar.ValueType)
                    {
                    case ProductCharacteristicValueType.Boolean:
                        if (!bool.TryParse(charValue.Value, out var parsedBool))
                        {
                            ModelState.AddModelError(ErrorResponses.InvalidCharacteristicValue, $"{{ \"id\": {charValue.CharacteristicId}, \"type\": {(int)prodChar.ValueType} }}");
                            continue;
                        }

                        resultantTpc.CharacteristicValue = parsedBool;
                        break;

                    case ProductCharacteristicValueType.Numeric:
                        if (!long.TryParse(charValue.Value, out var parsedLong))
                        {
                            ModelState.AddModelError(ErrorResponses.InvalidCharacteristicValue, $"{{ \"id\": {charValue.CharacteristicId}, \"type\": {(int)prodChar.ValueType} }}");
                            continue;
                        }

                        resultantTpc.CharacteristicValue = parsedLong;
                        break;

                    case ProductCharacteristicValueType.String:
                        resultantTpc.CharacteristicValue = charValue.Value;
                        break;
                    }

                    suppliedCharacteristicValues.Add(resultantTpc);
                }
            }

            return(suppliedCharacteristicValues);
        }
        public async Task <IActionResult> GetCurrentUser()
        {
            var currUser = await CurrentUserRetriever.GetCurrentUserAsync();

            return(Ok(currUser));
        }