Ejemplo n.º 1
0
        public virtual async Task <UserLoginResult> TryLogin(LoginViewModel model)
        {
            var          template        = new LoginResultTemplate();
            IUserContext userContext     = null;
            LdapUser     ldapUser        = null;
            var          isFakeLdapEmail = false;

            if (UserManager.Site.UseEmailForLogin && !string.IsNullOrWhiteSpace(model.UserName) && model.UserName.IndexOf("@") > -1)
            {
                template.User = await UserManager.FindByEmailAsync(model.UserName);
            }

            if (template.User == null)
            {
                template.User = await UserManager.FindByNameAsync(model.UserName);
            }

            if (template.User == null || string.IsNullOrWhiteSpace(template.User.PasswordHash)) //no password on cloudscribe user so could be ldap
            {
                if (LdapHelper.IsImplemented && !string.IsNullOrWhiteSpace(UserManager.Site.LdapServer) && !string.IsNullOrWhiteSpace(UserManager.Site.LdapDomain))
                {
                    ldapUser = await LdapHelper.TryLdapLogin(UserManager.Site as ILdapSettings, model.UserName, model.Password);
                }
            }

            if (ldapUser != null) //ldap auth success
            {
                if (template.User == null)
                {
                    //ldap auth success but no siteuser exists so create one and sign in
                    var cloudscribeUser = new SiteUser()
                    {
                        SiteId          = UserManager.Site.Id,
                        UserName        = model.UserName,
                        Email           = ldapUser.Email,
                        DisplayName     = ldapUser.CommonName,
                        FirstName       = ldapUser.FirstName,
                        LastName        = ldapUser.LastName,
                        LastLoginUtc    = DateTime.UtcNow,
                        AccountApproved = true
                    };

                    if (string.IsNullOrWhiteSpace(cloudscribeUser.DisplayName))
                    {
                        cloudscribeUser.DisplayName = model.UserName;
                    }

                    if (string.IsNullOrWhiteSpace(cloudscribeUser.Email))
                    {
                        // identity doesn't allow create user with no email so fake it here then null it out below after sign in.
                        // the cloudscribe site rules middleware will then force the user to provide an email
                        cloudscribeUser.Email = model.UserName + "@fake-email.com";
                        isFakeLdapEmail       = true;
                    }

                    var createdResult = await UserManager.CreateAsync(cloudscribeUser);

                    if (createdResult.Succeeded)
                    {
                        template.User = cloudscribeUser;
                        await SignInManager.SignInAsync(cloudscribeUser, model.RememberMe);

                        template.SignInResult = SignInResult.Success;
                        if (isFakeLdapEmail)
                        {
                            // clear the fake email, the user should then be forced to provide an email by site rules middleware
                            cloudscribeUser.Email           = null;
                            cloudscribeUser.NormalizedEmail = null;
                            await UserCommands.Update(cloudscribeUser);
                        }
                    }
                }
                else
                {
                    //siteuser already created for ldap user so just sign in
                    await SignInManager.SignInAsync(template.User, model.RememberMe);

                    template.SignInResult = SignInResult.Success;
                }
            }

            if (template.User != null && ldapUser == null) //these rules don't apply for ldap users
            {
                await LoginRulesProcessor.ProcessAccountLoginRules(template);
            }

            if (template.User != null)
            {
                //this will get persisted if login succeeds
                template.User.BrowserKey = Guid.NewGuid().ToString();

                userContext = new UserContext(template.User);
            }

            if (userContext != null &&
                template.SignInResult == SignInResult.Failed &&
                template.RejectReasons.Count == 0)
            {
                var persistent = false;
                if (UserManager.Site.AllowPersistentLogin)
                {
                    persistent = model.RememberMe;
                }

                //template.SignInResult = await SignInManager.PasswordSignInAsync(
                //    model.UserName,
                //    model.Password,
                //    persistent,
                //    lockoutOnFailure: false);

                template.SignInResult = await SignInManager.PasswordSignInAsync(
                    template.User,
                    model.Password,
                    persistent,
                    lockoutOnFailure : false);


                if (template.SignInResult.Succeeded)
                {
                    //update last login time
                    template.User.LastLoginUtc = DateTime.UtcNow;

                    if (string.IsNullOrEmpty(template.User.SecurityStamp))
                    {
                        // if security stamp is empty then the securitystamp validation
                        // fails when it checks after 30 minutes
                        // users created via usermanager this gets populated but not
                        // populated for the admin user created by seeding data
                        // changes to the user such as password change also will populate it
                        // but we can go ahead and check here and populate it if it is empty
                        await UserManager.UpdateSecurityStampAsync(template.User);

                        if (template.User.PasswordHash == "admin||0")
                        {
                            // initial admin user has not updated the password, need to hash it
                            await UserManager.ChangeUserPassword(template.User, "admin", validatePassword : false);

                            await SignInManager.SignOutAsync();

                            // security stamp needs to be there before authentication to avoid the problem

                            template.SignInResult = await SignInManager.PasswordSignInAsync(
                                model.UserName,
                                model.Password,
                                persistent,
                                lockoutOnFailure : false);
                        }
                    }
                    else
                    {
                        await UserManager.UpdateAsync(template.User);
                    }
                }
            }

            return(new UserLoginResult(
                       template.SignInResult,
                       template.RejectReasons,
                       userContext,
                       template.IsNewUserRegistration,
                       template.MustAcceptTerms,
                       template.NeedsAccountApproval,
                       template.NeedsEmailConfirmation,
                       template.EmailConfirmationToken,
                       template.NeedsPhoneConfirmation
                       ));
        }