/// <summary> /// Gets the user by the id, either from the cache or the database. /// </summary> /// <param name="userId">The id of the user to get.</param> /// <returns>Returns the user info, either from the cache or the database if found, otherwise null.</returns> public async Task <User> GetByIdAsync(int userId) { // Gets the user from cache: User user = _userCache.Get(userId); if (user == null) { // User not found in cache - so gets from the database: user = await GetUserByIdFromDatabase(userId); if (user == null) { throw new Exception("The user id was not found in the database."); } _userCache.Set(user); } return(user); }
/// <summary> /// Sets (adds or updates) the specified product and quantity in the cart. /// </summary> /// <param name="productId">The id of the product to set.</param> /// <param name="quantity">The quantity to set.</param> public async Task SetProductAsync(int productId, int quantity) { if (quantity < 1) { throw new ArgumentException($"{nameof(quantity)} cannot be less than 1.", nameof(quantity)); } // First, checks the product exists and valid in the database: if (!await _dbContext.Products.AnyAsync(p => p.Id == productId && p.IsAvailable)) { return; } // Creates/Updates the cart: // Now, checks if it's the first item in the cart: if (this.IsEmpty()) { // So creates a new cart: this.Cart = new ClientCart(); this.Cart.Products = new List <ClientCartProduct>(); ClientCartProduct cartProduct = new ClientCartProduct() { ClientCart = Cart, ProductId = productId, Quantity = quantity }; this.Cart.Products.Add(cartProduct); _dbContext.ClientCarts.Add(this.Cart); } // Otherwise, it's not the first item: else { // Checks if the product already exists in the cart: ClientCartProduct cartProduct = this.Cart.Products.FirstOrDefault(p => p.ProductId == productId); if (cartProduct != null) { // Updates the item: cartProduct.Quantity = quantity; _dbContext.ClientCartProducts.Update(cartProduct); } else { // Adds the item: cartProduct = new ClientCartProduct() { ClientCartId = this.Cart.Id, ProductId = productId, Quantity = quantity }; _dbContext.ClientCartProducts.Add(cartProduct); } } // If the user is authenticated - connects the cart to him: User user = await _userIdentity.GetCurrentAsync(); if (user != null && user.ClientCartId == null) { user.ClientCart = this.Cart; _dbContext.Users.Update(user); } await _dbContext.SaveChangesAsync(); // Gets the cart back from the database: ClientCart clientCartBack = null; if (user != null) { clientCartBack = Task.Run(() => GetAuthUserCartByDatabase()).Result; user.ClientCartId = clientCartBack.Id; _userCache.Set(user); this.CacheAuthUserCart(user.Id, clientCartBack); } else { clientCartBack = Task.Run(() => GetClientCartByDatabase(this.Cart.Id)).Result; this.CacheClientCart(clientCartBack); } // If user is anonymous - sets his cart id to the cookie: if (_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated == false) { this.SetUserCartIdToCookie(this.Cart.Id); } }
/// <summary> /// Registers a new user by the specified user info parameters. /// </summary> /// <remarks>Handles: password encryption, cookie authentication, client's preferences (like currency and theme), and also user cache memory.</remarks> /// <param name="firstName">The first name of the user.</param> /// <param name="lastName">The last name of the user.</param> /// <param name="emailAddress">The email address of the user.</param> /// <param name="password">The password of the user.</param> /// <param name="subscribeNewsletter">Indicates whether to subscribe the user to the newsletter or not.</param> /// <returns>Returns the user info from the database.</returns> public async Task <User> RegisterAsync(string firstName, string lastName, string emailAddress, string password, bool subscribeNewsletter) { if (string.IsNullOrEmpty(firstName)) { throw new ArgumentNullException(nameof(firstName), $"{nameof(firstName)} cannot be null or empty."); } if (string.IsNullOrEmpty(lastName)) { throw new ArgumentNullException(nameof(lastName), $"{nameof(lastName)} cannot be null or empty."); } if (string.IsNullOrEmpty(emailAddress)) { throw new ArgumentNullException(nameof(emailAddress), $"{nameof(emailAddress)} cannot be null or empty."); } if (string.IsNullOrEmpty(password)) { throw new ArgumentNullException(nameof(password), $"{nameof(password)} cannot be null or empty."); } // Creates a user object by the specified user info parameters: string passwordSalt = EncryptionHelper.GenerateSalt(); string passwordHash = EncryptionHelper.HashSHA256(password + passwordSalt); User newUser = new User() { FirstName = firstName, LastName = lastName, EmailAddress = emailAddress, PasswordHash = passwordHash, PasswordSalt = passwordSalt, Currency = _clientCurrency.Currency.Code, Theme = _clientTheme.Theme.ID, Role = UserRole.Customer }; _dbContext.Users.Add(newUser); // Adds to newsletter subscription: if (subscribeNewsletter) { // Checks the email is not already subscribed: if (await _dbContext.NewsletterSubscribers.AnyAsync(s => s.EmailAddress.Equals(emailAddress)) == false) { NewsletterSubscriber subscriber = new NewsletterSubscriber() { EmailAddress = emailAddress }; _dbContext.NewsletterSubscribers.Add(subscriber); } } await _dbContext.SaveChangesAsync(); User userFromDB = await _users.GetUserByEmailAsync(emailAddress); if (userFromDB == null) { throw new NullReferenceException($"Error getting the user info after insertion to the database, {nameof(userFromDB)} cannot be null."); } this.SetClientAuthentication(userFromDB, false); _userCache.Set(userFromDB); return(userFromDB); }