public async Task <IActionResult> Post([FromBody] Credential request)
        {
            if (request == null)
            {
                ModelState.AddModelError("Save", "No data passed");
                return(BadRequest(ModelState));
            }

            try
            {
                applicationUser = userManager.GetUserAsync(httpContextAccessor.HttpContext.User).Result;

                if (request.PasswordSecret != null && applicationUser != null)
                {
                    request.PasswordHash = userManager.PasswordHasher.HashPassword(applicationUser, request.PasswordSecret);
                }

                var credential = repository.Find(null, d => d.Name.ToLower(null) == request.Name.ToLower(null))?.Items?.FirstOrDefault();
                if (credential != null)
                {
                    ModelState.AddModelError("Credential", "Credential Name Already Exists");
                    return(BadRequest(ModelState));
                }

                if (!credentialManager.ValidateStartAndEndDates(request))
                {
                    ModelState.AddModelError("Credential", "Start and End Date are not valid");
                    return(BadRequest(ModelState));
                }

                var result = await base.PostEntity(request);

                await webhookPublisher.PublishAsync("Credentials.NewCredentialCreated", request.Id.ToString(), request.Name).ConfigureAwait(false);

                return(result);
            }
            catch (Exception ex)
            {
                return(ex.GetActionResult());
            }
        }
        public async Task <IActionResult> Patch(string id,
                                                [FromBody] JsonPatchDocument <Credential> request)
        {
            try
            {
                Guid entityId           = new Guid(id);
                var  existingCredential = repository.GetOne(entityId);
                if (existingCredential == null)
                {
                    ModelState.AddModelError("Credential", "Credential cannot be found or does not exist.");
                    return(NotFound(ModelState));
                }

                for (int i = 0; i < request.Operations.Count; i++)
                {
                    //verify that credential name is not taken
                    if (request.Operations[i].op.ToString().ToLower() == "replace" && request.Operations[i].path.ToString().ToLower() == "/name")
                    {
                        existingCredential.Name = request.Operations[i].value.ToString();
                        _credentialManager.CredentialNameAvailability(existingCredential);
                    }

                    //generate new password hash
                    if (request.Operations[i].op.ToString().ToLower() == "replace" && request.Operations[i].path.ToString().ToLower() == "/passwordsecret")
                    {
                        var encryptionKey = _credentialManager.GetEncryptionKey();

                        if (!String.IsNullOrEmpty(request.Operations[i].value.ToString()))
                        {
                            //generate salt
                            existingCredential.HashSalt = CredentialHasher.CreateSalt(32); //create 32 byte salt

                            //generate hash
                            existingCredential.PasswordHash = CredentialHasher.GenerateSaltedHash(request.Operations[i].value.ToString(), existingCredential.HashSalt);

                            //encrypt the provided password
                            existingCredential.PasswordSecret = CredentialsEncrypter.Encrypt(request.Operations[i].value.ToString(), encryptionKey);
                        }
                        request.Replace(e => e.HashSalt, existingCredential.HashSalt);
                        request.Replace(e => e.PasswordHash, existingCredential.PasswordHash);
                        request.Replace(e => e.PasswordSecret, existingCredential.PasswordSecret);
                    }

                    //verify start-end date range
                    if (request.Operations[i].op.ToString().ToLower() == "replace" && request.Operations[i].path.ToString().ToLower() == "/startdate"
                        | request.Operations[i].path.ToString().ToLower() == "/enddate")
                    {
                        if (request.Operations[i].path.ToString().ToLower() == "/startdate")
                        {
                            existingCredential.StartDate = Convert.ToDateTime(request.Operations[i].value.ToString());
                        }
                        else
                        {
                            existingCredential.EndDate = Convert.ToDateTime(request.Operations[i].value.ToString());
                        }

                        if (!_credentialManager.ValidateStartAndEndDates(existingCredential))
                        {
                            ModelState.AddModelError("Credential", "Start and End Date are not valid. End Date must be after the Start Date");
                            return(BadRequest(ModelState));
                        }
                    }
                }

                await _webhookPublisher.PublishAsync("Credentials.CredentialUpdated", existingCredential.Id.ToString(), existingCredential.Name).ConfigureAwait(false);

                return(await base.PatchEntity(id, request));
            }
            catch (Exception ex)
            {
                return(ex.GetActionResult());
            }
        }