Beispiel #1
0
        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;
        }
Beispiel #2
0
        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();
            }
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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;
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
        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;
        }
Beispiel #8
0
        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;
        }
Beispiel #9
0
        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();
        }
Beispiel #10
0
        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();
        }
Beispiel #11
0
        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();
        }