/// <summary> /// Adds a user to the `sessions` collection /// </summary> /// <param name="user">The User to add.</param> /// <param name="cancellationToken">Allows the UI to cancel an asynchronous request. Optional.</param> /// <returns></returns> public async Task <UserResponse> LoginUserAsync(User user, CancellationToken cancellationToken = default) { try { var storedUser = await GetUserAsync(user.Email, cancellationToken); if (storedUser == null) { return(new UserResponse(false, "No user found. Please check the email address.")); } if (user.HashedPassword != null && user.HashedPassword != storedUser.HashedPassword) { return(new UserResponse(false, "The hashed password provided is not valid")); } if (user.HashedPassword == null && !PasswordHashOMatic.Verify(user.Password, storedUser.HashedPassword)) { return(new UserResponse(false, "The password provided is not valid")); } var filter = Builders <Session> .Filter.Eq(x => x.UserId, user.Email); await _sessionsCollection.UpdateOneAsync( filter, Builders <Session> .Update.Set(t => t.UserId, user.Email).Set(t => t.Jwt, user.AuthToken), new UpdateOptions { IsUpsert = true }); storedUser.AuthToken = user.AuthToken; return(new UserResponse(storedUser)); } catch (Exception ex) { return(new UserResponse(false, ex.Message)); } }
/// <summary> /// Adds a user to the `users` collection /// </summary> /// <param name="name">The name of the user.</param> /// <param name="email">The email of the user.</param> /// <param name="password">The clear-text password, which will be hashed before storing.</param> /// <param name="cancellationToken">Allows the UI to cancel an asynchronous request. Optional.</param> /// <returns></returns> public async Task <UserResponse> AddUserAsync(string name, string email, string password, CancellationToken cancellationToken = default) { try { // // var user = new User(); // TODO Ticket: User Management // Create a user with the "Name", "Email", and "HashedPassword" fields. // DO NOT STORE CLEAR-TEXT PASSWORDS! Instead, use the helper class // we have created for you: PasswordHashOMatic.Hash(password) // var user = new User(); user.Name = name; user.Email = email; user.HashedPassword = PasswordHashOMatic.Hash(password); await _usersCollection.InsertOneAsync(user); // // // TODO Ticket: Durable Writes // // To use a more durable Write Concern for this operation, add the // // .WithWriteConcern() method to your InsertOneAsync call. var newUser = await GetUserAsync(user.Email, cancellationToken); return(new UserResponse(newUser)); } catch (Exception ex) { return(ex.Message.StartsWith("MongoError: E11000 duplicate key error") ? new UserResponse(false, "A user with the given email already exists.") : new UserResponse(false, ex.Message)); } }
/// <summary> /// Adds a user to the `users` collection /// </summary> /// <param name="name">The name of the user.</param> /// <param name="email">The email of the user.</param> /// <param name="password">The clear-text password, which will be hashed before storing.</param> /// <param name="cancellationToken">Allows the UI to cancel an asynchronous request. Optional.</param> /// <returns></returns> public async Task <UserResponse> AddUserAsync(string name, string email, string password, CancellationToken cancellationToken = default) { try { var user = new User() { Name = name, Email = email, HashedPassword = PasswordHashOMatic.Hash(password), }; await _usersCollection.WithWriteConcern(WriteConcern.W1).InsertOneAsync(user); // // // TODO Ticket: Durable Writes // // To use a more durable Write Concern for this operation, add the // // .WithWriteConcern() method to your InsertOneAsync call. var newUser = await GetUserAsync(user.Email, cancellationToken); return(new UserResponse(newUser)); } catch (Exception ex) { return(ex.Message.StartsWith("MongoError: E11000 duplicate key error") ? new UserResponse(false, "A user with the given email already exists.") : new UserResponse(false, ex.Message)); } }
/// <summary> /// Adds a user to the `sessions` collection /// </summary> /// <param name="user">The User to add.</param> /// <param name="cancellationToken">Allows the UI to cancel an asynchronous request. Optional.</param> /// <returns></returns> public async Task <UserResponse> LoginUserAsync(User user, CancellationToken cancellationToken = default) { try { var storedUser = await GetUserAsync(user.Email, cancellationToken); if (storedUser == null) { return(new UserResponse(false, "No user found. Please check the email address.")); } if (user.HashedPassword != null && user.HashedPassword != storedUser.HashedPassword) { return(new UserResponse(false, "The hashed password provided is not valid")); } if (user.HashedPassword == null && !PasswordHashOMatic.Verify(user.Password, storedUser.HashedPassword)) { return(new UserResponse(false, "The password provided is not valid")); } // TODO Ticket: User Management // Locate the session object in the `sessions` collection by // matching the "user_id" field with the email passed to this function. // Then update the Session.UserId and Session.Jwt properties, // setting the former to the email and the latter to the // user.AuthToken that is passed in from the Controller. // // If the session doesn't exist, allow MongoDB to create a // new one by passing the IsUpsert update option. // await _sessionsCollection.UpdateOneAsync( // new BsonDocument(...), // Builders<Session>.Update.Set(...).Set(...), // new UpdateOptions(...)); var update = Builders <Session> .Update .Set(x => x.UserId, user.Email) .Set(x => x.Jwt, user.AuthToken); var options = new UpdateOptions { IsUpsert = true, }; await _sessionsCollection.UpdateOneAsync( x => x.UserId == user.Email, update, options, cancellationToken ); storedUser.AuthToken = user.AuthToken; return(new UserResponse(storedUser)); } catch (Exception ex) { return(new UserResponse(false, ex.Message)); } }
public async Task <ActionResult> Delete([FromBody] PasswordObject content) { var email = GetUserEmailFromToken(Request); if (email.StartsWith("Error")) { return(BadRequest(email)); } var user = await _userRepository.GetUserAsync(email); if (!PasswordHashOMatic.Verify(content.Password, user.HashedPassword)) { return(BadRequest("Provided password does not match user password.")); } return(Ok(await _userRepository.DeleteUserAsync(email))); }
/// <summary> /// Adds a user to the `users` collection /// </summary> /// <param name="name">The name of the user.</param> /// <param name="email">The email of the user.</param> /// <param name="password">The clear-text password, which will be hashed before storing.</param> /// <param name="cancellationToken">Allows the UI to cancel an asynchronous request. Optional.</param> /// <returns></returns> public async Task <UserResponse> AddUserAsync(string name, string email, string password, CancellationToken cancellationToken = default) { try { var user = new User { Name = name, Email = email, HashedPassword = PasswordHashOMatic.Hash(password) }; await _usersCollection.WithWriteConcern(new WriteConcern(1)).InsertOneAsync(user, cancellationToken); var newUser = await GetUserAsync(user.Email, cancellationToken); return(new UserResponse(newUser)); } catch (Exception ex) { return(ex.Message.StartsWith("MongoError: E11000 duplicate key error") ? new UserResponse(false, "A user with the given email already exists.") : new UserResponse(false, ex.Message)); } }
/// <summary> /// Adds a user to the `sessions` collection /// </summary> /// <param name="user">The User to add.</param> /// <param name="cancellationToken">Allows the UI to cancel an asynchronous request. Optional.</param> /// <returns></returns> public async Task <UserResponse> LoginUserAsync(User user, CancellationToken cancellationToken = default) { try { // Locate the session object in the `sessions` collection by // matching the "user_id" field with the email passed to this function. // Then update the Session.UserId and Session.Jwt properties, // setting the former to the email and the latter to the // user.AuthToken that is passed in from the Controller. // // If the session doesn't exist, allow MongoDB to create a // new one by passing the IsUpsert update option. // await _sessionsCollection.UpdateOneAsync( // new BsonDocument(...), // Builders<Session>.Update.Set(...).Set(...), // new UpdateOptions(...)); var storedUser = await GetUserAsync(user.Email, cancellationToken); if (storedUser == null) { return(new UserResponse(false, "No user found. Please check the email address.")); } if (user.HashedPassword != null && user.HashedPassword != storedUser.HashedPassword) { return(new UserResponse(false, "The hashed password provided is not valid")); } if (user.HashedPassword == null && !PasswordHashOMatic.Verify(user.Password, storedUser.HashedPassword)) { return(new UserResponse(false, "The password provided is not valid")); } var userSession = await GetUserSessionAsync(user.Email, cancellationToken); if (userSession is null) { var newSession = new Session(); newSession.Jwt = user.AuthToken; newSession.UserId = user.Id; await _sessionsCollection.InsertOneAsync(newSession); } else { var filter = Builders <Session> .Filter.Eq(t => t.UserId, userSession.UserId); await _sessionsCollection.UpdateOneAsync(filter, Builders <Session> .Update.Set(s => s.Jwt, user.AuthToken).Set(u => u.UserId, user.AuthToken), new UpdateOptions() { IsUpsert = true }); // IsUpsert = Gets or sets a value indicating whether to insert the document if it doesn't already exist. } storedUser.AuthToken = user.AuthToken; return(new UserResponse(storedUser)); } catch (Exception ex) { return(new UserResponse(false, ex.Message)); } }