public async Task Handle(CreateLocalMembership command) { // does user already exist? var hasUserId = command.Principal != null && command.Principal.Identity.HasAppUserId(); var user = hasUserId ? await _entities.GetAsync <User>(command.Principal.Identity.GetUserId <int>()) : null; if (!hasUserId) { var createUser = new CreateUser { Name = command.UserName }; await _commands.Execute(createUser); user = createUser.CreatedEntity; // verify & associate email address await _commands.Execute(new RedeemEmailVerification(user) { Commit = false, Token = command.Token, Ticket = command.Ticket, }); } user.LocalMembership = new LocalMembership { User = user, PasswordHash = await _queries.Execute(new HashedPassword(command.Password)), }; user.SecurityStamp = Guid.NewGuid().ToString(); await _entities.SaveChangesAsync(); command.CreatedEntity = user.LocalMembership; }
public async Task Handle(UpdateEmailAddress command) { // load up the entity var entity = await _entities.Get <EmailAddress>() .EagerLoad(x => x.User.EmailAddresses) .ByIdAsync(command.EmailAddressId); var commit = false; // update the isprimary field when requested to if (command.IsPrimary.HasValue && entity.IsPrimary != command.IsPrimary.Value) { if (entity.IsPrimary && !command.IsPrimary.Value) { // todo: unit test validation to make sure this exception can never be thrown. throw new InvalidOperationException(string.Format( "Cannot set EmailAddress.IsPrimary to false for #{0}. This should have been caught in the validator.", entity.Id)); } // since the primary email address cannot be changed to non-primary, // at this point we must be changing a non-primary to primary. commit = true; var primaryEmail = entity.User.EmailAddresses.Single(x => x.IsPrimary); primaryEmail.IsPrimary = false; entity.IsPrimary = true; } if (commit) { await _entities.SaveChangesAsync(); } }
public async Task Handle(ResetPassword command) { var verification = await _entities.Get <EmailVerification>() .EagerLoad(x => x.EmailAddress) .ByTicketAsync(command.Ticket, false); verification.RedeemedOnUtc = DateTime.UtcNow; var user = verification.EmailAddress.User; var localMembership = await _queries.Execute(new LocalMembershipByVerifiedEmail(verification.EmailAddress.Value)); // if the user has a no local membership, create one if (localMembership == null) { localMembership = new LocalMembership { User = user, }; user.LocalMembership = localMembership; } // update the password var passwordHash = await _queries.Execute(new HashedPassword(command.Password)); user.LocalMembership.PasswordHash = passwordHash; user.SecurityStamp = Guid.NewGuid().ToString(); await _entities.SaveChangesAsync(); }
public async Task Handle(SendVerificationEmail command) { // create the email verification var createEmailVerification = new CreateEmailVerification { Commit = false, EmailAddress = command.EmailAddress, Purpose = command.Purpose, }; await _commands.Execute(createEmailVerification); var verification = createEmailVerification.CreatedEntity; // attach the email to a user when appropriate if (command.Purpose == EmailVerificationPurpose.AddEmail && command.Principal != null && command.Principal.Identity.IsAuthenticated) { verification.EmailAddress.UserId = command.Principal.Identity.GetUserId <int>(); } // load the templates var resourceFormat = string.Format("{0}.{1}.txt", verification.Purpose, "{0}"); var assembly = Assembly.GetExecutingAssembly(); var subjectFormat = assembly.GetManifestResourceText(assembly.GetManifestResourceName(string.Format(resourceFormat, "Subject"))); var bodyFormat = assembly.GetManifestResourceText(assembly.GetManifestResourceName(string.Format(resourceFormat, "Body"))); // format the message body var formatters = new Dictionary <string, string> { { "{EmailAddress}", verification.EmailAddress.Value }, { "{Secret}", verification.Secret }, // don't forget to encode the token, it contains illegal querystring characters { "{VerificationUrl}", string.Format(command.VerifyUrlFormat ?? "", Uri.EscapeDataString(verification.Token), Uri.EscapeDataString(verification.Ticket)) }, { "{SendFromUrl}", command.SendFromUrl } }; // create the message var message = new EmailMessage { EmailAddress = verification.EmailAddress, From = _appConfiguration.MailFromDefault.ToString(), Subject = formatters.Format(subjectFormat), Body = formatters.Format(bodyFormat), IsBodyHtml = false, SendOnUtc = DateTime.UtcNow, }; _entities.Create(message); // link the message to the verification verification.Message = message; await _entities.SaveChangesAsync(); _mail.Deliver(message.Id); command.CreatedTicket = verification.Ticket; }
public async Task Handle(CreateRemoteMembership command) { // does user already exist? var hasUserId = command.Principal.Identity.HasAppUserId(); var user = hasUserId ? await _entities.Get <User>() .EagerLoad(new Expression <Func <User, object> >[] { x => x.RemoteMemberships, }) .ByIdAsync(command.Principal.Identity.GetUserId <int>()) : command.User; if (user == null) { var createUser = new CreateUser { Name = command.UserName }; await _commands.Execute(createUser); user = createUser.CreatedEntity; // verify & associate email address await _commands.Execute(new RedeemEmailVerification(user) { Commit = false, Token = command.Token, Ticket = command.Ticket, }); } var ticket = await _queries.Execute(new PrincipalRemoteMembershipTicket(command.Principal)); // do not add this login if it already exists if (user.RemoteMemberships.ByUserLoginInfo(ticket.Login) != null) { return; } var entity = new RemoteMembership { User = user, UserId = user.Id, Id = { LoginProvider = ticket.Login.LoginProvider, ProviderKey = ticket.Login.ProviderKey }, }; user.RemoteMemberships.Add(entity); user.SecurityStamp = Guid.NewGuid().ToString(); if (command.Commit) { await _entities.SaveChangesAsync(); } command.CreatedEntity = entity; }
public async Task Handle(ChangeLocalPassword command) { var userId = command.Principal.Identity.GetUserId <int>(); var user = await _entities.Get <User>() .EagerLoad(new Expression <Func <User, object> >[] { x => x.LocalMembership, }) .ByIdAsync(userId); user.LocalMembership.PasswordHash = _userManager.PasswordHasher.HashPassword(command.NewPassword); user.SecurityStamp = Guid.NewGuid().ToString(); await _entities.SaveChangesAsync(); }
public async Task Handle(CreateEmailVerification command) { // find or create the email address var emailAddress = await _entities.Get <EmailAddress>().ByValueAsync(command.EmailAddress) ?? new EmailAddress { Value = command.EmailAddress.ToLower(), // TODO: allow users to change capitalization of email? HashedValue = await _queries.Execute(new HashedEmailValueBy(command.EmailAddress)), }; // create random secret and ticket // note that changing the length of the secret requires updating the // email messages sent to the address, since those mention secret length var secret = _queries.Execute(new RandomSecret(10, 12)); var ticket = _queries.Execute(new RandomSecret(20, 25)); // make sure ticket is unique while (_entities.Query <EmailVerification>().ByTicket(ticket) != null) { ticket = _queries.Execute(new RandomSecret(20, 25)); } // serialize a new user token to a string var token = await _userManager.UserTokenProvider.GenerateAsync(command.Purpose.ToString(), _userManager, new UserTicket { UserName = ticket, }); // create the verification var verification = new EmailVerification { EmailAddress = emailAddress, Purpose = command.Purpose, Secret = secret, Ticket = ticket, Token = token, // change this, and you have to change the content of the email messages to reflect new expiration ExpiresOnUtc = DateTime.UtcNow.AddMinutes(30), }; _entities.Create(verification); if (command.Commit) { await _entities.SaveChangesAsync(); } command.CreatedEntity = verification; }
public async Task Handle(ChangeUserName command) { var entity = await _entities.GetAsync <User>(command.UserId); entity.Name = command.UserName; entity.SecurityStamp = Guid.NewGuid().ToString(); await _entities.SaveChangesAsync(); await _authenticator.SignOut(); await _authenticator.SignOn(entity); command.SignedIn = entity; }
public async Task Handle(DeleteRemoteMembership command) { var userId = command.Principal.Identity.GetUserId <int>(); var userLoginInfo = new UserLoginInfo(command.LoginProvider, command.ProviderKey); var remoteMembership = await _entities.Get <RemoteMembership>() .EagerLoad(new Expression <Func <RemoteMembership, object> >[] { x => x.User, }) .ByUserIdAndLoginInfoAsync(userId, userLoginInfo); if (remoteMembership == null) { return; } _entities.Delete(remoteMembership); await _entities.SaveChangesAsync(); }
public async Task Handle(DeleteEmailAddress command) { // load up the entity var entity = await _entities.GetAsync <EmailAddress>(command.EmailAddressId); // delete if it is verified if (entity.IsVerified) { _entities.Delete(entity); } // when it is unverified, just detach from user else { entity.UserId = null; } await _entities.SaveChangesAsync(); }
public async Task Handle(RedeemEmailVerification command) { // verify & associate email address var verification = await _entities.Get <EmailVerification>() .EagerLoad(x => x.EmailAddress) .ByTicketAsync(command.Ticket, false); verification.RedeemedOnUtc = DateTime.UtcNow; var email = verification.EmailAddress; var user = command.User ?? await _entities.Get <User>() .EagerLoad(x => x.EmailAddresses) .ByIdAsync(command.Principal.Identity.GetUserId <int>()); email.User = user; email.IsVerified = true; // is this the user's primary email address? email.IsPrimary = !user.EmailAddresses.Any(x => x.IsPrimary); // expire unused verifications var unusedVerifications = await _entities.Get <EmailVerification>() .ByEmailAddressId(email.Id) .ToArrayAsync() ; foreach (var unusedVerification in unusedVerifications.Except(new[] { verification })) { unusedVerification.RedeemedOnUtc = unusedVerification.ExpiresOnUtc; } if (command.Commit) { await _entities.SaveChangesAsync(); } }
public async Task Handle(RejectEmailVerification command) { // reject this email verification var verification = await _entities.Get <EmailVerification>() .EagerLoad(x => x.EmailAddress) .ByTicketAsync(command.Ticket, false); verification.Token = "Rejected"; var email = verification.EmailAddress; email.UserId = null; verification.Secret = null; var ticket = _queries.Execute(new RandomSecret(20, 25)); // make sure ticket is unique while (_entities.Query <EmailVerification>().ByTicket(ticket) != null) { ticket = _queries.Execute(new RandomSecret(20, 25)); } verification.Ticket = ticket; await _entities.SaveChangesAsync(); }