public bool DenyInviteToKitchen(long kitchenId, PantryPlannerUser user) { if (user == null) { throw new ArgumentNullException(nameof(user)); } if (Context.KitchenExists(kitchenId) == false) { throw new KitchenNotFoundException(kitchenId); } if (Context.UserExists(user.Id) == false) { throw new UserNotFoundException(user.UserName); } KitchenUser inviteToDeny = user.KitchenUser.Where(k => k.KitchenId == kitchenId && k.UserId == user.Id && k.HasAcceptedInvite.Value == false).FirstOrDefault(); if (inviteToDeny == null) { throw new InviteNotFoundException("No invite found for kitchen."); } Context.KitchenUser.Remove(inviteToDeny); Context.SaveChangesAsync(); return(true); }
public async Task DenyKitchenInvite_ValidKitchen_ReturnsOKAndInviteDenied() { List <long> myKitchenIds = _userManager.TestUser.KitchenUser.Select(u => u.KitchenId).ToList(); Kitchen notMyKitchen = _context.KitchenUser.Where(u => myKitchenIds.Contains(u.KitchenId) == false).FirstOrDefault()?.Kitchen; PantryPlannerUser userSendingInvite = notMyKitchen.KitchenUser .Where(k => k.UserId != _userManager.TestUser.Id) .FirstOrDefault()? .User; if (userSendingInvite == null || notMyKitchen == null) { throw new Exception("user or kitchen is not setup for testing"); } // send invite to test user KitchenUserService service = new KitchenUserService(_context); service.InviteUserToKitchenByUsername(_userManager.TestUser.UserName, notMyKitchen.KitchenId, userSendingInvite); // have test user accept invite ActionResult inviteResult = await _controller.DenyKitchenInvite(notMyKitchen.KitchenId); Assert.IsType <OkResult>(inviteResult); Assert.False(_context.KitchenUser.Any(k => k.KitchenId == notMyKitchen.KitchenId && k.UserId == _userManager.TestUser.Id)); }
/// <summary> /// Creates users and adds them to already existing kitchens. /// </summary> /// <param name="context"> create users using this DbContext and adds them Kitchens in it </param> /// <param name="numOfUsersToAddPerKitchen"> amount of users to add per Kitchen </param> internal static void AddNewRandomUsersToKitchens(PantryPlannerContext context, int numOfUsersToAddPerKitchen) { if (context.Kitchen.Count() == 0) { throw new Exception("Cannot add users because Kitchen is not populated"); } Random randGenerator = new Random(); foreach (Kitchen kitchen in context.Kitchen) { bool hasAccepted = true; // this will guarantee that atleast one new user has accepted the Invite (i.e. HasAcceptedInvite = true) for (int i = 0; i < numOfUsersToAddPerKitchen; i++) { PantryPlannerUser newUser = AddNewRandomUser(context); KitchenUser newKitchenUser = new KitchenUser() { KitchenId = kitchen.KitchenId, UserId = newUser.Id, DateAdded = DateTime.Now, IsOwner = false, HasAcceptedInvite = hasAccepted }; context.KitchenUser.Add(newKitchenUser); context.SaveChanges(); hasAccepted = (randGenerator.Next(0, 2) == 0); } } }
/// <summary> /// Returns the PantryPlannerUser associated with the <paramref name="userClaimsPrincipal"/>. /// Determines user based on Cookies or checking the Claims that are set by Jwt for authorization. /// </summary> /// <exception cref="PermissionsException"> Thrown when user can not be found and is null </exception> /// <param name="userManager"> </param> /// <param name="userClaimsPrincipal"></param> /// <returns> A valid <see cref="PantryPlannerUser"/> </returns> public static async Task <PantryPlannerUser> GetUserFromCookieOrJwtAsync(this UserManager <PantryPlannerUser> userManager, ClaimsPrincipal userClaimsPrincipal) { // first attempt to get the user based on Cookies PantryPlannerUser user = await userManager.GetUserAsync(userClaimsPrincipal); if (user != null) { return(user); } // Second attempt to get the user based on Jwt claims (User Id is stored in Jwt)... reference: https://stackoverflow.com/questions/46112258/how-do-i-get-current-user-in-net-core-web-api-from-jwt-token IEnumerable <Claim> nameIdentifiers = userClaimsPrincipal.FindAll(ClaimTypes.NameIdentifier); foreach (var claim in nameIdentifiers) // looping over nameidentifier claims because it could be the email or Id in the token { user = await userManager.FindByIdAsync(claim.Value); if (user != null) { break; } } if (user == null) { // no user could be determined from Cookies passed in or from the Jwt token so throw a unauthorized result throw new PermissionsException("Could not authenticate user."); } return(user); }
public KitchenUser OwnerDeleteKitchenUserByKitchenUserId(long kitchenUserId, PantryPlannerUser user) { if (user == null) { throw new ArgumentNullException(nameof(user)); } var kitchenUser = Context.KitchenUser.Find(kitchenUserId); if (kitchenUser == null) { throw new KitchenUserNotFoundException(); } // validate user has rights and owns the kitchen if (!Permissions.UserOwnsKitchen(user, kitchenUser.KitchenId)) { throw new PermissionsException($"you must be kitchen owner to remove the user '{kitchenUser.User.UserName}'"); } // validate user is not removing themselves since they own the kitchen if (kitchenUser.UserId == user.Id) { throw new InvalidOperationException("You can not remove yourself from the Kitchen because you own it. Transfer ownership or delete the kitchen instead."); } Context.KitchenUser.Remove(kitchenUser); Context.SaveChanges(); return(kitchenUser); }
public Kitchen GetKitchenById(long id, PantryPlannerUser user) { if (user == null) { throw new ArgumentNullException(nameof(user)); } if (Context.KitchenExists(id) == false) { throw new KitchenNotFoundException(id); } if (Context.UserExists(user.Id) == false) { throw new UserNotFoundException(user.UserName); } Kitchen kitchen = Context.Kitchen.Find(id); if (!Permissions.UserHasRightsToKitchen(user, kitchen)) { throw new PermissionsException(); } return(kitchen); }
public KitchenUserServiceUnitTest() { _testUser = InMemoryDataGenerator.TestUser; _context = InMemoryDataGenerator.CreateAndInitializeInMemoryDatabaseContext(Guid.NewGuid().ToString(), _testUser, insertIngredientData: false); _kitchenUserService = new KitchenUserService(_context); }
/// <summary> /// Validate <paramref name="idToken"/> is Google Id Token and then Login the user. An account will be auto-created if the google user does not have an account yet. /// Returns a Jwt Token for authorizing later requests. /// </summary> /// <param name="idToken"> Google Id Token provided by google when signing in with OAuth (e.g. from mobile app) </param> /// <returns> Jwt Token for authorizing later requests to API. </returns> /// <exception cref="AccountException"> Thrown when <paramref name="idToken"/> is not valid or user can not be created or login </exception> public async Task <string> LoginUsingGoogleIdToken(string idToken) { bool isValid = await IsGoogleTokenValidAsync(idToken).ConfigureAwait(false); if (!isValid) { throw new AccountException("Google Id token is invalid"); } GoogleJsonWebSignature.Payload validPayload = await GoogleJsonWebSignature.ValidateAsync(idToken).ConfigureAwait(false); PantryPlannerUser appUser = _userManager.Users.SingleOrDefault(u => u.Email == validPayload.Email); if (appUser == null) { // user doesn't exist so we'll auto create them appUser = await AutoCreateAccountFromGoogleAsync(validPayload).ConfigureAwait(false); } if (appUser != null) { // sign the user in and return a Jwt Token await _signInManager.SignInAsync(appUser, false).ConfigureAwait(false); string token = GenerateJwtToken(appUser, _configuration); return(token); } // reached here then the user could not be created/found throw new AccountException($"Could not login with google user for email {validPayload.Email}"); }
/// <summary> /// Login to API with username and password. Jwt Token returned on success that can be used to authorize later requests. /// </summary> /// <param name="model"> DTO with email and password to login with </param> /// <returns> Jwt Token for logged in user </returns> /// <exception cref="AccountException"> Thrown when failed to login (cant find user, user is locked out, or invalid username/password) </exception> internal async Task <string> LoginWithEmailAndPasswordAsync(LoginDto model) { SignInResult result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, false, false); if (result.Succeeded) { PantryPlannerUser appUser = _userManager.Users.SingleOrDefault(r => r.Email == model.Email); if (appUser == null) { throw new AccountException("Could not look up user."); } string token = GenerateJwtToken(appUser, _configuration); return(token); } else if (result.IsLockedOut) { throw new AccountException("The user is locked out"); } else if (result.IsNotAllowed) { throw new AccountException("The user is not allowed to login"); } throw new AccountException("Failed to login."); }
/// <summary> /// Adds an ingredient to the <see cref="Context"/> that was added by the <paramref name="user"/>. /// </summary> /// <param name="newIngredient"> ingredient to add </param> /// <param name="user"> user who is adding ingredient </param> public void AddIngredient(Ingredient newIngredient, PantryPlannerUser user) { if (user == null) { throw new ArgumentNullException(nameof(user)); } if (newIngredient == null) { throw new ArgumentNullException(nameof(newIngredient)); } if (Context.UserExists(user.Id) == false) { throw new UserNotFoundException(user.UserName); } // validate name passed in if (String.IsNullOrWhiteSpace(newIngredient.Name)) { throw new InvalidOperationException("Ingredient Name is required"); } // validate an ingredient with same name in the same category doesn't already exist if (Context.IngredientExistsForUser(newIngredient, user)) { throw new InvalidOperationException($"An ingredient with the name {newIngredient.Name} already exists"); } newIngredient.AddedByUserId = user.Id; newIngredient.DateAdded = DateTime.Now; Context.Ingredient.Add(newIngredient); Context.SaveChanges(); }
public async Task<IActionResult> OnPostConfirmationAsync(string returnUrl = null) { returnUrl = returnUrl ?? Url.Content("~/"); // Get the information about the user from the external login provider var info = await _signInManager.GetExternalLoginInfoAsync(); if (info == null) { ErrorMessage = "Error loading external login information during confirmation."; return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); } if (ModelState.IsValid) { var user = new PantryPlannerUser { UserName = Input.Email, Email = Input.Email }; var result = await _userManager.CreateAsync(user); if (result.Succeeded) { result = await _userManager.AddLoginAsync(user, info); if (result.Succeeded) { await _signInManager.SignInAsync(user, isPersistent: false); _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); return LocalRedirect(returnUrl); } } foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } } LoginProvider = info.LoginProvider; ReturnUrl = returnUrl; return Page(); }
/// <summary> /// Adds test data to <paramref name="context"/> and initializes <paramref name="testUser"/> with relationships to the test data. /// </summary> public static void InitializeUsersAndKitchens(PantryPlannerContext context, PantryPlannerUser testUser) { InitializeUser(context, testUser); InitializeKitchen(context); InitializeKitchenAndKitchenUserForUser(context, testUser); InitializeRandomKitchenAndKitchenUser(context); AddNewRandomUsersToKitchens(context, numOfUsersToAddPerKitchen: 3); }
public List <KitchenUser> GetAcceptedUsersForKitchen(Kitchen kitchen, PantryPlannerUser userAccessing) { if (kitchen == null) { throw new ArgumentNullException("kitchen is null"); } return(GetAcceptedUsersForKitchenById(kitchen.KitchenId, userAccessing)); }
internal bool UserAddedIngredient(Ingredient ingredient, PantryPlannerUser user) { if (ingredient == null) { return(false); } return(UserAddedIngredient(ingredient.IngredientId, user)); }
internal bool UserHasRightsToKitchen(PantryPlannerUser user, Kitchen kitchen) { if (Context == null || user == null || kitchen == null || Context.KitchenUser == null) { return(false); } return(Context.KitchenUser.Any(x => x.KitchenId == kitchen.KitchenId && x.UserId == user.Id)); }
public bool DenyInviteToKitchen(Kitchen kitchen, PantryPlannerUser user) { if (kitchen == null) { throw new ArgumentNullException(nameof(kitchen)); } return(DenyInviteToKitchen(kitchen.KitchenId, user)); }
public bool AcceptInviteToKitchen(Kitchen kitchenToJoin, PantryPlannerUser userAccepting) { if (kitchenToJoin == null) { throw new ArgumentNullException("kitchen is null"); } return(AcceptInviteToKitchenByKitchenId(kitchenToJoin.KitchenId, userAccepting)); }
public List <KitchenUser> GetMyInvites(PantryPlannerUser user) { if (user == null) { throw new ArgumentNullException("user"); } return(GetMyInvites(user.Id)); }
public List <KitchenUser> GetUsersThatHaveNotAcceptedInvite(Kitchen kitchen, PantryPlannerUser userAccessing) { if (kitchen == null) { throw new ArgumentNullException("kitchen is null"); } return(GetUsersThatHaveNotAcceptedInviteByKitchenId(kitchen.KitchenId, userAccessing)); }
internal bool UserAddedIngredient(long ingredientId, PantryPlannerUser user) { if (user == null) { return(false); } return(UserAddedIngredient(ingredientId, user.Id)); }
internal bool UserOwnsKitchen(PantryPlannerUser user, Kitchen kitchen) { if (user == null || kitchen == null) { return(false); } return(Context.KitchenUser.Any(x => x.KitchenId == kitchen.KitchenId && x.UserId == user.Id && x.IsOwner)); }
/// <summary> /// Deletes ingredient if user has rights to it (i.e. added the ingredient) /// </summary> public Ingredient DeleteIngredient(Ingredient ingredient, PantryPlannerUser userDeleting) { if (ingredient == null) { throw new ArgumentNullException(nameof(ingredient)); } return(DeleteIngredient(ingredient.IngredientId, userDeleting)); }
public void AcceptInviteToKitchen_InvalidKitchen_ThrowsKitchenNotFoundException() { // add random user to test against PantryPlannerUser newUser = InMemoryDataGenerator.AddNewRandomUser(_context); Assert.Throws <KitchenNotFoundException>(() => { _kitchenUserService.AcceptInviteToKitchenByKitchenId(-5, newUser); }); }
public void InviteUserToKitchenByUsername_InvalidKitchenId_ThrowsKitchenNotFoundException() { // add random user to test against PantryPlannerUser newUser = InMemoryDataGenerator.AddNewRandomUser(_context); Assert.Throws <KitchenNotFoundException>(() => { _kitchenUserService.InviteUserToKitchenByUsername(newUser.UserName, -5, _testUser); }); }
public void InviteUserToKitchenByUsername_NullKitchen_ThrowsArgumentNullException() { // add random user to test against PantryPlannerUser newUser = InMemoryDataGenerator.AddNewRandomUser(_context); Assert.Throws <ArgumentNullException>(() => { _kitchenUserService.InviteUserToKitchenByUsername(newUser.UserName, null, _testUser); }); }
public KitchenUser DeleteKitchenUserFromKitchenByUsername(Kitchen kitchen, string usernameToDelete, PantryPlannerUser userDeleting) { if (Context.UserExists(usernameToDelete) == false) { throw new UserNotFoundException(usernameToDelete); } PantryPlannerUser userToDelete = Context.Users.Where(u => u.UserName == usernameToDelete).FirstOrDefault(); return(DeleteKitchenUserFromKitchen(kitchen.KitchenId, userToDelete.Id, userDeleting)); }
public KitchenServiceUnitTest() { _testUser = new PantryPlannerUser() { Id = "Constructor123", UserName = "******", Email = "*****@*****.**" }; _context = InMemoryDataGenerator.CreateAndInitializeInMemoryDatabaseContext(Guid.NewGuid().ToString(), _testUser, insertIngredientData: false); _kitchenService = new KitchenService(_context); }
public KitchenUser DeleteMyselfFromKitchen(long kitchenId, PantryPlannerUser user) { if (Context.KitchenExists(kitchenId) == false) { throw new KitchenNotFoundException(kitchenId); } Kitchen kitchen = Context.Kitchen.Find(kitchenId); return(DeleteMyselfFromKitchen(kitchen, user)); }
public async Task AutoCreateAccountFromGoogleAsync_Valid_UserReturnedAsync() { GoogleJsonWebSignature.Payload payload = new GoogleJsonWebSignature.Payload() { Email = "*****@*****.**" }; PantryPlannerUser newUser = await _service.AutoCreateAccountFromGoogleAsync(payload); Assert.NotNull(newUser); Assert.Equal(payload.Email, newUser.Email); }
public void AcceptInviteToKitchen_NoKitchenInvite_ThrowsInviteNotFoundException() { // add random user to test against PantryPlannerUser newUser = InMemoryDataGenerator.AddNewRandomUser(_context); // get valid kitchen from test user Kitchen kitchen = _testUser.KitchenUser.FirstOrDefault()?.Kitchen; Assert.Throws <InviteNotFoundException>(() => { _kitchenUserService.AcceptInviteToKitchen(kitchen, newUser); }); }