public async Task <ActionResult> SetupExternalAccount()
        {
            // get the registration module for some defaults
            LoginConfigData config = await LoginConfigDataProvider.GetConfigAsync();

            bool allowNewUser = config.AllowUserRegistration;

            ExtUserInfo extInfo = await GetUserInfo(config);

            if (!allowNewUser && extInfo.ExistingUser == null)
            {
                throw new Error(this.__ResStr("noInvite", "This site allows new accounts by invitation only - According to our records there is no account on this site for your {0} credentials", extInfo.LoginProviderDisplay));
            }

            SetupExternalAccountModel model = new SetupExternalAccountModel {
                AllowNewUser         = allowNewUser,
                ExistingUser         = extInfo.ExistingUser != null,
                UserName             = extInfo.Name,
                Email                = extInfo.Email,
                RegistrationType     = config.RegistrationType,
                LoginProviderDisplay = extInfo.LoginProviderDisplay,
            };

            return(View(model));
        }
        private async Task <ExtUserInfo> GetUserInfo(LoginConfigData config)
        {
            ExtUserInfo info = new ExtUserInfo();

            SignInManager <UserDefinition> _signinManager = (SignInManager <UserDefinition>)YetaWFManager.ServiceProvider.GetService(typeof(SignInManager <UserDefinition>));
            ExternalLoginInfo loginInfo = await _signinManager.GetExternalLoginInfoAsync();

            if (loginInfo == null)
            {
                Logging.AddErrorLog("AuthenticationManager.GetExternalLoginInfoAsync() returned null");
                throw new Error(this.__ResStr("noExtLogin", "No external login has been processed"));
            }
            info.LoginInfo            = loginInfo;
            info.Email                = loginInfo.Principal.FindFirstValue(ClaimTypes.Email);
            info.Name                 = loginInfo.Principal.FindFirstValue(ClaimTypes.Name);
            info.LoginProvider        = loginInfo.LoginProvider;
            info.LoginProviderDisplay = loginInfo.ProviderDisplayName;

            // Check whether this is an invited user
            using (UserDefinitionDataProvider dataProvider = new UserDefinitionDataProvider()) {
                List <DataProviderFilterInfo> filters = null;
                switch (config.RegistrationType)
                {
                default:
                case RegistrationTypeEnum.NameAndEmail:
                    filters = DataProviderFilterInfo.Join(filters, new DataProviderFilterInfo {
                        Field = nameof(UserDefinition.UserName), Operator = "==", Value = info.Name,
                    });
                    filters = DataProviderFilterInfo.Join(filters, new DataProviderFilterInfo {
                        Field = nameof(UserDefinition.Email), Operator = "==", Value = info.Email,
                    });
                    break;

                case RegistrationTypeEnum.EmailOnly:
                    filters = DataProviderFilterInfo.Join(filters, new DataProviderFilterInfo {
                        Field = nameof(UserDefinition.Email), Operator = "==", Value = info.Email,
                    });
                    break;

                case RegistrationTypeEnum.NameOnly:
                    filters = DataProviderFilterInfo.Join(filters, new DataProviderFilterInfo {
                        Field = nameof(UserDefinition.UserName), Operator = "==", Value = info.Name,
                    });
                    break;
                }
                info.ExistingUser = await dataProvider.GetItemAsync(filters);
            }
            return(info);
        }
        public async Task <ActionResult> SetupExternalAccount_Partial(SetupExternalAccountModel model)
        {
            LoginConfigData config = await LoginConfigDataProvider.GetConfigAsync();

            bool allowNewUser = config.AllowUserRegistration;

            ExtUserInfo extInfo = await GetUserInfo(config);

            model.AllowNewUser         = allowNewUser;
            model.ExistingUser         = extInfo.ExistingUser != null;
            model.LoginProviderDisplay = extInfo.LoginProviderDisplay;
            model.RegistrationType     = config.RegistrationType;
            if (extInfo.ExistingUser != null)
            {
                model.UserName = extInfo.Name;
                model.Email    = extInfo.Email;
            }

            if (!ModelState.IsValid)
            {
                return(PartialView(model));
            }

            UserDefinition user;

            if (allowNewUser && extInfo.ExistingUser == null)
            {
                // set new user info

                user = new UserDefinition();
                switch (config.RegistrationType)
                {
                default:
                case RegistrationTypeEnum.NameAndEmail:
                    user.UserName = model.UserName;
                    user.Email    = model.Email;
                    break;

                case RegistrationTypeEnum.EmailOnly:
                    user.UserName = user.Email = model.Email;
                    break;

                case RegistrationTypeEnum.NameOnly:
                    user.UserName = user.Email = model.UserName;
                    break;
                }
                if (config.VerifyNewUsers)
                {
                    user.UserStatus = UserStatusEnum.NeedValidation;
                }
                else if (config.ApproveNewUsers)
                {
                    user.UserStatus = UserStatusEnum.NeedApproval;
                }
                else
                {
                    user.UserStatus = UserStatusEnum.Approved;
                }
                user.RegistrationIP = Manager.UserHostAddress;

                // create new local account
                var createResult = await Managers.GetUserManager().CreateAsync(user);

                if (!createResult.Succeeded)
                {
                    throw new Error(string.Join(" - ", (from e in createResult.Errors select e.Description)));
                }
            }
            else
            {
                // invited user

                // verify invitation
                if (extInfo.ExistingUser.VerificationCode != model.InvitationCode)
                {
                    ModelState.AddModelError(nameof(model.InvitationCode), this.__ResStr("badInvite", "The invitation code is invalid"));
                    return(PartialView(model));
                }
                user            = extInfo.ExistingUser;
                user.UserStatus = UserStatusEnum.Approved;
            }

            // add login provider info
            IdentityResult result = await Managers.GetUserManager().AddLoginAsync(user, extInfo.LoginInfo);

            if (!result.Succeeded)
            {
                throw new Error(string.Join(" - ", (from e in result.Errors select e.Description)));
            }

            // send appropriate email based on account status
            Emails emails = new Emails();

            if (user.UserStatus == UserStatusEnum.NeedValidation)
            {
                await emails.SendVerificationAsync(user, config.BccVerification?Manager.CurrentSite.AdminEmail : null);

                string nextPage = string.IsNullOrWhiteSpace(config.VerificationPendingUrl) ? Manager.CurrentSite.HomePageUrl : config.VerificationPendingUrl;
                return(FormProcessed(model, this.__ResStr("okAwaitRegistration", "An email has just been sent to your email address \"{0}\" to complete the registration. Allow a few minutes for delivery. Once received, please use the information in the email to complete the registration.", model.Email),
                                     this.__ResStr("okRegTitle", "Welcome!"),
                                     NextPage: nextPage));
            }
            else if (user.UserStatus == UserStatusEnum.NeedApproval)
            {
                await emails.SendApprovalNeededAsync(user);

                string nextPage = string.IsNullOrWhiteSpace(config.ApprovalPendingUrl) ? Manager.CurrentSite.HomePageUrl : config.ApprovalPendingUrl;
                return(FormProcessed(model, this.__ResStr("okAwaitApproval", "An email has just been sent to the site administrator for approval of your new account. Once processed and approved, you will receive an email confirming your approval."),
                                     this.__ResStr("okRegTitle", "Welcome!"),
                                     NextPage: nextPage));
            }
            else if (user.UserStatus == UserStatusEnum.Approved)
            {
                if (config.NotifyAdminNewUsers)
                {
                    await emails.SendNewUserCreatedAsync(user);
                }
                await LoginModuleController.UserLoginAsync(user, config.PersistentLogin);

                return(FormProcessed(model, this.__ResStr("okRegText", "Your new account has been successfully registered."), this.__ResStr("okRegTitle", "Welcome!"),
                                     NextPage: Manager.ReturnToUrl, ForceRedirect: true));
            }
            else
            {
                throw new InternalError("badUserStatus", "Unexpected account status {0}", user.UserStatus);
            }
        }