/// <summary>Default constructor for configuring the worker classes for this controller.</summary>
 /// <param name="trinity">The instance required for undertaking data management/verification purposes on the business ontology.</param>
 public CredentialsController(DbContextTrinity trinity)
 {
     repo    = new ModelRepository <Credential>(trinity.DefaultModel);
     shaper  = new ModelFormatter <Credential>(trinity.DefaultModel.Uri.AbsoluteUri);
     checker = new ModelValidator <Credential>(trinity.DefaultModel);
     crypto  = new CredentialHasher();
 }
        public Credential CreateGlobalCredential(GlobalCredentialViewModel request)
        {
            if (!String.IsNullOrEmpty(request.PasswordSecret))
            {
                //get encryption key
                var orgId = _organizationManager.GetDefaultOrganization().Id;
                _organizationSettingRepository.ForceIgnoreSecurity();

                var organizationKey = _organizationSettingRepository.Find(null, o => o.OrganizationId == orgId).Items.FirstOrDefault().EncryptionKey;
                var applicationKey  = _configuration.GetSection("ApplicationEncryption:Key").Value;
                var encryptionKey   = applicationKey + organizationKey;

                //generate salt
                request.HashSalt = CredentialHasher.CreateSalt(32); //create 32 byte salt

                //generate hash
                request.PasswordHash = CredentialHasher.GenerateSaltedHash(request.PasswordSecret, request.HashSalt);

                // Encrypt and decrypt the sample text via the Aes256CbcEncrypter class.
                request.PasswordSecret = CredentialsEncrypter.Encrypt(request.PasswordSecret, encryptionKey);
            }

            Credential credential = new Credential();

            credential = request.Map(request);

            CredentialNameAvailability(credential);

            if (!ValidateStartAndEndDates(credential))
            {
                throw new EntityOperationException("Start and End Date are not valid");
            }

            return(credential);
        }
        public string GetPassword(Credential request)
        {
            var    encryptionKey  = GetEncryptionKey();
            string stringPassword = request.PasswordSecret;

            if (String.IsNullOrEmpty(stringPassword))
            {
                return("");
            }

            if (!CredentialsEncrypter.IsBase64(request.PasswordSecret))//if encryption is not in base64
            {
                //encrypt existing password
                request.HashSalt = CredentialHasher.CreateSalt(32); //create 32 byte salt

                //generate hash
                request.PasswordHash = CredentialHasher.GenerateSaltedHash(request.PasswordSecret, request.HashSalt);

                //encrypt the provided password
                request.PasswordSecret = CredentialsEncrypter.Encrypt(request.PasswordSecret, encryptionKey);

                _repo.Update(request);

                return(stringPassword);
            }
            return(CredentialsEncrypter.Decrypt(request.PasswordSecret, encryptionKey));
        }
        public Credential CreateAgentCredential(AgentCredentialViewModel request)
        {
            if (!String.IsNullOrEmpty(request.PasswordSecret))
            {
                var encryptionKey = GetEncryptionKey();

                //generate salt
                request.HashSalt = CredentialHasher.CreateSalt(32); //create 32 byte salt

                //generate hash
                request.PasswordHash = CredentialHasher.GenerateSaltedHash(request.PasswordSecret, request.HashSalt);

                // Encrypt and decrypt the sample text via the Aes256CbcEncrypter class.
                request.PasswordSecret = CredentialsEncrypter.Encrypt(request.PasswordSecret, encryptionKey);
            }

            Credential globalCredential = _repo.Find(null, a => a.Name == request.Name && a.AgentId == null).Items?.FirstOrDefault();
            Credential agentCredential  = request.Map(request);

            if (globalCredential == null)
            {
                throw new EntityDoesNotExistException("No global credential exists with the given name");
            }

            CredentialNameAvailability(agentCredential);

            if (!ValidateStartAndEndDates(agentCredential))
            {
                throw new EntityOperationException("Start and End Date are not valid");
            }

            agentCredential.Provider = globalCredential.Provider;
            return(agentCredential);
        }
        public Credential UpdateCredential(string id, Credential request)
        {
            Guid entityId = new Guid(id);

            var existingCredential = _repo.GetOne(entityId);

            if (existingCredential == null)
            {
                throw new EntityDoesNotExistException("Credential could not be found or does not exist");
            }

            request.Id = entityId;
            CredentialNameAvailability(request);

            if (!ValidateStartAndEndDates(request))
            {
                throw new InvalidOperationException("");
            }

            existingCredential.StartDate   = request.StartDate;
            existingCredential.EndDate     = request.EndDate;
            existingCredential.Domain      = request.Domain;
            existingCredential.UserName    = request.UserName;
            existingCredential.Certificate = request.Certificate;

            if (!String.IsNullOrEmpty(request.PasswordSecret))//password is not null or empty, then set a new password
            {
                var encryptionKey = GetEncryptionKey();

                if (CredentialsEncrypter.IsBase64(existingCredential.PasswordSecret))//if encryption is in base64
                {
                    existingCredential.PasswordSecret = CredentialsEncrypter.Decrypt(existingCredential.PasswordSecret, encryptionKey);
                }

                if (existingCredential.PasswordSecret != request.PasswordSecret)
                {
                    //generate salt
                    existingCredential.HashSalt = CredentialHasher.CreateSalt(32); //create 32 byte salt

                    //generate hash
                    existingCredential.PasswordHash = CredentialHasher.GenerateSaltedHash(request.PasswordSecret, existingCredential.HashSalt);

                    //encrypt the provided password
                    existingCredential.PasswordSecret = CredentialsEncrypter.Encrypt(request.PasswordSecret, encryptionKey);
                }
            }

            if (request.PasswordSecret == "")//if password is an empty string, then remove password fields
            {
                existingCredential.HashSalt       = null;
                existingCredential.PasswordHash   = null;
                existingCredential.PasswordSecret = null;
            }

            return(existingCredential);
        }
        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());
            }
        }