[HttpGet("{id:int}/accounts")] // working
        public IActionResult User_GetAccounts(int id)
        {
            try
            {
                // verify that the user is either admin or is requesting their own data
                if (!HelperMethods.ValidateIsUserOrAdmin(_httpContextAccessor, _context, id))
                {
                    ErrorMessage error = new ErrorMessage("Invalid User", "Caller can only access their information.");
                    return(new UnauthorizedObjectResult(error));
                }

                // get and return all this user's accounts
                List <ReturnableAccount> accs = new List <ReturnableAccount>();
                foreach (Account acc in _context.Users.Single(a => a.ID == id).Accounts.ToArray())
                {
                    ReturnableAccount retAcc = new ReturnableAccount(acc);
                    accs.Add(retAcc);
                }

                return(new OkObjectResult(accs));
            }
            catch (Exception ex)
            {
                ErrorMessage error = new ErrorMessage("Error retrieving accounts.", ex.Message);
                return(new InternalServerErrorResult(error));
            }
        }
Example #2
0
        public async Task POST_AddNewAccount()
        {
            /*
             * HttpPost("users/{id}/accounts")
             * Add a new saved password account to the users data collection.
             */

            using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, _client.BaseAddress + "users/" + _testUser.ID.ToString() + "/accounts"))
            {
                // construct body with a new account to add.. using same techniques as client side encryption
                // so we send an encrypted account and receive an encrypted account
                NewAccount accToAdd = new NewAccount
                {
                    Title       = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("Discord", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Login       = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("username", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Password    = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("useless", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Url         = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("https://discord.com", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Description = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("description...", _uniqueUserEncryptionKeyAndIv)).Replace("-", "")
                };
                requestMessage.Content = new StringContent(JsonConvert.SerializeObject(accToAdd), Encoding.UTF8, "application/json");

                // Add cookie, make request and validate status code
                requestMessage.Headers.Add("AccessToken", _accessToken);
                HttpResponseMessage response = await _client.SendAsync(requestMessage);

                Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                // parse account from response, and also request the data from the database directly for comparison
                ReturnableAccount returnedAcc   = JsonConvert.DeserializeObject <ReturnableAccount>(response.Content.ReadAsStringAsync().Result);
                ReturnableAccount accInDatabase = new ReturnableAccount(_context.Accounts.SingleOrDefault(acc => acc.ID == returnedAcc.ID));
                TestingHelpingMethods.IntegrationTest_CompareAccounts(accToAdd, returnedAcc, accInDatabase); // make sure all are equal
                Assert.Null(returnedAcc.FolderID);                                                           // check for null folderid indicating no parent
            }
        }
Example #3
0
        public async Task PUT_EditAccount()
        {
            /*
             * HttpPut("users/{id}/accounts/{acc_id}")
             * Edits one of the users saved accounts in the database
             */

            int accId = 4; // user John Doe always has an account with id of 4 from the db initializer

            using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Put, _client.BaseAddress + "users/" + _testUser.ID.ToString() + "/accounts/" + accId.ToString()))
            {
                // construct body with an encrypted account edit..
                // so we send an encrypted account and receive an encrypted account
                NewAccount accToEdit = new NewAccount
                {
                    Title       = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("changed", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Login       = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("changed", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Password    = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("changed", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Url         = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("https://changed.com", _uniqueUserEncryptionKeyAndIv)).Replace("-", ""),
                    Description = BitConverter.ToString(HelperMethods.EncryptStringToBytes_Aes("changed...", _uniqueUserEncryptionKeyAndIv)).Replace("-", "")
                };
                requestMessage.Content = new StringContent(JsonConvert.SerializeObject(accToEdit), Encoding.UTF8, "application/json");

                // Add cookie, make request and validate status code
                requestMessage.Headers.Add("AccessToken", _accessToken);
                HttpResponseMessage response = await _client.SendAsync(requestMessage);

                Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                // parse account from response, and also request the data from the database directly for comparison
                ReturnableAccount returnedAcc   = JsonConvert.DeserializeObject <ReturnableAccount>(response.Content.ReadAsStringAsync().Result);
                ReturnableAccount accInDatabase = new ReturnableAccount(_context.Accounts.SingleOrDefault(acc => acc.ID == returnedAcc.ID));
                TestingHelpingMethods.IntegrationTest_CompareAccounts(accToEdit, returnedAcc, accInDatabase); // make sure all are equal
            }
        }
 // validate that the database editted the account and that the data is equal to what was returned, and what we sent
 public static void IntegrationTest_CompareAccounts(NewAccount sentData, ReturnableAccount retData, ReturnableAccount dataInDB)
 {
     Assert.NotNull(dataInDB);
     Assert.True(retData.Title == dataInDB.Title && retData.Title == sentData.Title);
     Assert.True(retData.Login == dataInDB.Login && retData.Login == sentData.Login);
     Assert.True(retData.Password == dataInDB.Password && retData.Password == sentData.Password);
     Assert.True(retData.Url == dataInDB.Url && retData.Url == sentData.Url);
     Assert.True(retData.Description == dataInDB.Description && retData.Description == sentData.Description);
     Assert.Equal(retData.LastModified, dataInDB.LastModified);
     Assert.Equal(retData.IsFavorite, dataInDB.IsFavorite);
     Assert.Equal(retData.FolderID, dataInDB.FolderID);
 }
        public IActionResult User_DeleteFolder(int id, int folder_id)
        {
            // verify that the user is either admin or is requesting their own data
            if (!HelperMethods.ValidateIsUserOrAdmin(_httpContextAccessor, _context, id, _keyAndIV))
            {
                ErrorMessage error = new ErrorMessage("Invalid User", "Caller can only access their information.");
                return(new UnauthorizedObjectResult(error));
            }

            // validate ownership of said folder
            if (!_context.Users.Single(a => a.ID == id).Folders.Exists(b => b.ID == folder_id))
            {
                ErrorMessage error = new ErrorMessage("Invalid folder", "User does not have a folder matching that ID.");
                return(new BadRequestObjectResult(error));
            }

            Folder folderToDelete = _context.Users.Single(a => a.ID == id).Folders.Single(b => b.ID == folder_id);

            // if this folder has children, then we need to call DeleteFolder on all children
            if (folderToDelete.HasChild)
            {
                List <Folder> folders = _context.Users.Single(a => a.ID == id).Folders.ToList <Folder>();
                foreach (Folder folder in folders)
                {
                    if (folder.ParentID == folderToDelete.ID)
                    {
                        User_DeleteFolder(id, folder.ID); // recursive call to go down the tree and delete children
                    }
                }
            }

            // delete the accounts in the folder
            List <Account> accounts = _context.Users.Single(a => a.ID == id).Accounts.ToList <Account>();

            foreach (Account account in accounts)
            {
                if (account.FolderID == folderToDelete.ID)
                {
                    _context.Accounts.Remove(account); // no need to call User_DeleteAccount because identity and access token have already been verifies
                }
            }
            _context.SaveChanges();                  // save the accounts being deleted
            _context.Folders.Remove(folderToDelete); // remove the folder
            _context.SaveChanges();                  // save the folder being deleted.. must be done seperate because of foreign keys

            // if parent isnt root, then check if parent still has children
            if (folderToDelete.ParentID != null)
            {
                bool          parent_has_children = false;
                List <Folder> folders             = _context.Users.Single(a => a.ID == id).Folders.ToList <Folder>();
                foreach (Folder fold in folders)
                {
                    // if this folders parent is the same as the one we were just deleting than the original parent still has kids
                    if (fold.ParentID == folderToDelete.ParentID)
                    {
                        parent_has_children = true;
                    }
                }

                // update parent if needed
                if (!parent_has_children)
                {
                    _context.Users.Single(a => a.ID == id).Folders.Single(b => b.ID == folderToDelete.ParentID).HasChild = false;
                    _context.SaveChanges();
                }
            }

            // get and return all this user's folders...
            // this is helpful to have here because deleting one folder could affect others and we dont
            // want to redo the parsing logic UI side or make more api calls
            List <ReturnableFolder> updatedFolders = new List <ReturnableFolder>();

            foreach (Folder fold in _context.Users.Single(a => a.ID == id).Folders.ToArray())
            {
                ReturnableFolder retFold = new ReturnableFolder(fold);
                updatedFolders.Add(retFold);
            }

            // get and return all this user's accounts
            List <ReturnableAccount> safe = new List <ReturnableAccount>();

            foreach (Account acc in _context.Users.Single(a => a.ID == id).Accounts.ToArray())
            {
                ReturnableAccount retAcc = new ReturnableAccount(acc);
                safe.Add(retAcc);
            }

            // return both as an anonomous type
            var test = new { safe, updatedFolders };

            return(new OkObjectResult(test));
        }