[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)); } }
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 } }
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)); }