public async Task <IActionResult> AuthorizeConfirm(AuthorizeConfirmAddressModel model)
        {
            var app = (await ApiService.AppInfoAsync(model.AppId)).App;

            if (app == null)
            {
                return(NotFound());
            }
            if (!ModelState.IsValid)
            {
                return(View("AuthError"));
            }
            var user = await GetCurrentUserAsync();

            var viewModel = new AuthorizeConfirmViewModel
            {
                AppName      = app.AppName,
                UserNickName = user.NickName,
                AppId        = model.AppId,
                ToRedirect   = model.ToRedirect,
                State        = model.State,
                Scope        = model.Scope,
                ResponseType = model.ResponseType,
                UserIcon     = user.HeadImgUrl,
                // Permissions
                ViewOpenId        = app.ViewOpenId,
                ViewPhoneNumber   = app.ViewPhoneNumber,
                ChangePhoneNumber = app.ChangePhoneNumber,
                ConfirmEmail      = app.ConfirmEmail,
                ChangeBasicInfo   = app.ChangeBasicInfo,
                ChangePassword    = app.ChangePassword
            };

            return(View(viewModel));
        }
        public async Task <IActionResult> ViewAllEmails(ViewAllEmailsAddressModel model)
        {
            var accessToken = await _dbContext
                              .AccessToken
                              .SingleOrDefaultAsync(t => t.Value == model.AccessToken);

            var app = await ApiService.AppInfoAsync(accessToken.ApplyAppId);

            var targetUser = await _dbContext.Users.Include(t => t.Emails).SingleOrDefaultAsync(t => t.Id == model.OpenId);

            if (targetUser == null)
            {
                return(this.Protocal(ErrorType.NotFound, "Could not find target user."));
            }
            if (!_dbContext.LocalAppGrant.Exists(t => t.AppID == accessToken.ApplyAppId && t.APIUserId == targetUser.Id))
            {
                return(Json(new AiurProtocal {
                    Code = ErrorType.Unauthorized, Message = "This user did not grant your app!"
                }));
            }
            return(Json(new AiurCollection <IUserEmail>(targetUser.Emails)
            {
                Code = ErrorType.Success,
                Message = "Successfully get the target user's emails."
            }));
        }
        public async Task <IActionResult> ViewPhoneNumber(ViewPhoneNumberAddressModel model)
        {
            var accessToken = await _dbContext
                              .AccessToken
                              .SingleOrDefaultAsync(t => t.Value == model.AccessToken);

            var app = await ApiService.AppInfoAsync(accessToken.ApplyAppId);

            var targetUser = await _dbContext.Users.FindAsync(model.OpenId);

            if (targetUser == null)
            {
                return(this.Protocal(ErrorType.NotFound, "Could not find target user."));
            }
            if (!_dbContext.LocalAppGrant.Exists(t => t.AppID == accessToken.ApplyAppId && t.APIUserId == targetUser.Id))
            {
                return(Json(new AiurProtocal {
                    Code = ErrorType.Unauthorized, Message = "This user did not grant your app!"
                }));
            }
            if (!app.App.ViewPhoneNumber)
            {
                return(this.Protocal(ErrorType.Unauthorized, "You app is not allowed to view users' phone number."));
            }
            return(Json(new AiurValue <string>(targetUser.PhoneNumber)
            {
                Code = ErrorType.Success,
                Message = "Successfully get the target user's phone number."
            }));
        }
        public async Task <IActionResult> PasswordAuth(PasswordAuthAddressModel model)
        {
            var app = (await ApiService.AppInfoAsync(model.AppId)).App;

            if (app == null)
            {
                return(NotFound());
            }
            var mail = await _dbContext
                       .UserEmails
                       .Include(t => t.Owner)
                       .SingleOrDefaultAsync(t => t.EmailAddress == model.Email);

            if (mail == null)
            {
                ModelState.AddModelError(string.Empty, "Unknown user email.");
                return(ResultGenerator.GetInvalidModelStateErrorResponse(ModelState));
            }
            var user   = mail.Owner;
            var result = await _signInManager.PasswordSignInAsync(user, model.Password, isPersistent : false, lockoutOnFailure : true);

            if (result.Succeeded)
            {
                OAuthPack pack = null;
                if (await user.HasAuthorizedApp(_dbContext, model.AppId))
                {
                    pack = await user.GeneratePack(_dbContext, model.AppId);
                }
                else
                {
                    await user.GrantTargetApp(_dbContext, model.AppId);

                    pack = await user.GeneratePack(_dbContext, model.AppId);
                }
                return(Json(new AiurValue <int>(pack.Code)
                {
                    Code = ErrorType.Success,
                    Message = "Auth success."
                }));
            }
            else if (result.RequiresTwoFactor)
            {
                throw new NotImplementedException();
            }
            else if (result.IsLockedOut)
            {
                throw new NotImplementedException();
            }
            else
            {
                return(this.Protocal(ErrorType.Unauthorized, "Wrong password!"));
            }
        }
        public async Task <IActionResult> Register(RegisterViewModel model)
        {
            var capp = (await ApiService.AppInfoAsync(model.AppId)).App;

            if (capp == null)
            {
                return(NotFound());
            }
            if (!ModelState.IsValid)
            {
                model.Recover(capp.AppName, capp.AppIconAddress);
                return(View(model));
            }
            bool exists = _dbContext.UserEmails.Exists(t => t.EmailAddress == model.Email.ToLower());

            if (exists)
            {
                ModelState.AddModelError(string.Empty, $"A user with email '{model.Email}' already exists!");
                model.Recover(capp.AppName, capp.AppIconAddress);
                return(View(model));
            }
            var user = new APIUser
            {
                UserName         = model.Email,
                Email            = model.Email,
                NickName         = model.Email.Split('@')[0],
                PreferedLanguage = model.PreferedLanguage
            };
            var result = await _userManager.CreateAsync(user, model.Password);

            if (result.Succeeded)
            {
                var primaryMail = new UserEmail
                {
                    EmailAddress = model.Email.ToLower(),
                    OwnerId      = user.Id
                };
                _dbContext.UserEmails.Add(primaryMail);
                await _dbContext.SaveChangesAsync();

                await _signInManager.SignInAsync(user, isPersistent : true);

                return(await FinishAuth(model));
            }
            AddErrors(result);
            model.Recover(capp.AppName, capp.AppIconAddress);
            return(View(model));
        }
        public async Task <IActionResult> Register(AuthorizeAddressModel model)
        {
            var app = (await ApiService.AppInfoAsync(model.appid)).App;

            if (app == null)
            {
                return(NotFound());
            }
            if (!ModelState.IsValid)
            {
                return(View("AuthError"));
            }
            var viewModel = new RegisterViewModel(model.redirect_uri, model.state, model.appid, model.scope, model.response_type, app.AppName, app.AppIconAddress);

            return(View(viewModel));
        }
        public async Task <IActionResult> Authorize(AuthorizeViewModel model)
        {
            var app = (await ApiService.AppInfoAsync(model.AppId)).App;

            if (app == null)
            {
                return(NotFound());
            }
            if (!ModelState.IsValid)
            {
                return(View(model));
            }
            var mail = await _dbContext
                       .UserEmails
                       .Include(t => t.Owner)
                       .SingleOrDefaultAsync(t => t.EmailAddress == model.Email.ToLower());

            if (mail == null)
            {
                ModelState.AddModelError(string.Empty, "Unknown user email.");
                model.Recover(app.AppName, app.AppIconAddress);
                return(View(model));
            }
            var user   = mail.Owner;
            var result = await _signInManager.PasswordSignInAsync(user, model.Password, isPersistent : true, lockoutOnFailure : true);

            if (result.Succeeded)
            {
                return(await FinishAuth(model, app.ForceConfirmation));
            }
            else if (result.RequiresTwoFactor)
            {
                throw new NotImplementedException();
            }
            else if (result.IsLockedOut)
            {
                ModelState.AddModelError(string.Empty, "The account is locked for too many attempts.");
            }
            else
            {
                ModelState.AddModelError(string.Empty, "The password does not match our records.");
            }
            model.Recover(app.AppName, app.AppIconAddress);
            return(View(model));
        }
        public async Task <IActionResult> CodeToOpenId(CodeToOpenIdAddressModel model)
        {
            var AccessToken = await _dbContext.AccessToken.SingleOrDefaultAsync(t => t.Value == model.AccessToken);

            if (AccessToken == null)
            {
                return(this.Protocal(ErrorType.WrongKey, "Not a valid access token!"));
            }
            var targetPack = await _dbContext
                             .OAuthPack
                             .Where(t => t.IsUsed == false)
                             .SingleOrDefaultAsync(t => t.Code == model.Code);

            if (targetPack == null)
            {
                return(this.Protocal(ErrorType.WrongKey, "Invalid Code."));
            }
            if (targetPack.ApplyAppId != AccessToken.ApplyAppId)
            {
                return(this.Protocal(ErrorType.Unauthorized, "The app granted code is not the app granting access token!"));
            }
            var capp = (await ApiService.AppInfoAsync(targetPack.ApplyAppId)).App;

            if (capp == null)
            {
                return(this.Protocal(ErrorType.NotFound, "App not found."));
            }
            if (!capp.ViewOpenId)
            {
                return(this.Protocal(ErrorType.Unauthorized, "The app doesn't have view open id permission."));
            }
            targetPack.IsUsed = true;
            await _dbContext.SaveChangesAsync();

            var viewModel = new CodeToOpenIdViewModel
            {
                openid  = targetPack.UserId,
                scope   = "scope",
                Message = "Successfully get user openid",
                Code    = ErrorType.Success
            };

            return(Json(viewModel));
        }
        public async Task <JsonResult> ChangeProfile(ChangeProfileAddressModel model)
        {
            var accessToken = await _dbContext
                              .AccessToken
                              .SingleOrDefaultAsync(t => t.Value == model.AccessToken);

            var targetUser = await _dbContext.Users.FindAsync(model.OpenId);

            var app = await ApiService.AppInfoAsync(accessToken.ApplyAppId);

            if (!_dbContext.LocalAppGrant.Exists(t => t.AppID == accessToken.ApplyAppId && t.APIUserId == targetUser.Id))
            {
                return(Json(new AiurProtocal {
                    Code = ErrorType.Unauthorized, Message = "This user did not grant your app!"
                }));
            }
            if (!app.App.ChangeBasicInfo)
            {
                return(this.Protocal(ErrorType.Unauthorized, "You app is not allowed to change users' basic info."));
            }
            if (!string.IsNullOrEmpty(model.NewNickName))
            {
                targetUser.NickName = model.NewNickName;
            }
            if (!string.IsNullOrEmpty(model.NewIconAddress))
            {
                targetUser.HeadImgUrl = model.NewIconAddress;
            }
            if (!string.IsNullOrEmpty(model.NewBio))
            {
                targetUser.Bio = model.NewBio;
            }
            await _dbContext.SaveChangesAsync();

            return(Json(new AiurProtocal {
                Code = ErrorType.Success, Message = "Successfully changed this user's nickname!"
            }));
        }
        public async Task <JsonResult> ChangePassword(ChangePasswordAddressModel model)
        {
            var accessToken = await _dbContext
                              .AccessToken
                              .SingleOrDefaultAsync(t => t.Value == model.AccessToken);

            var targetUser = await _dbContext.Users.FindAsync(model.OpenId);

            var app = await ApiService.AppInfoAsync(accessToken.ApplyAppId);

            if (!_dbContext.LocalAppGrant.Exists(t => t.AppID == accessToken.ApplyAppId && t.APIUserId == targetUser.Id))
            {
                return(Json(new AiurProtocal {
                    Code = ErrorType.Unauthorized, Message = "This user did not grant your app!"
                }));
            }
            if (!app.App.ChangePassword)
            {
                return(this.Protocal(ErrorType.Unauthorized, "You app is not allowed to change users' password."));
            }
            var result = await _userManager.ChangePasswordAsync(targetUser, model.OldPassword, model.NewPassword);

            await _userManager.UpdateAsync(targetUser);

            if (result.Succeeded)
            {
                return(Json(new AiurProtocal {
                    Code = ErrorType.Success, Message = "Successfully changed this user's password!"
                }));
            }
            else
            {
                return(Json(new AiurProtocal {
                    Code = ErrorType.WrongKey, Message = result.Errors.First().Description
                }));
            }
        }
        public async Task <JsonResult> SetPhoneNumber(SetPhoneNumberAddressModel model)
        {
            var accessToken = await _dbContext
                              .AccessToken
                              .SingleOrDefaultAsync(t => t.Value == model.AccessToken);

            var app = await ApiService.AppInfoAsync(accessToken.ApplyAppId);

            var targetUser = await _dbContext.Users.FindAsync(model.OpenId);

            if (targetUser == null)
            {
                return(this.Protocal(ErrorType.NotFound, "Could not find target user."));
            }
            if (!_dbContext.LocalAppGrant.Exists(t => t.AppID == accessToken.ApplyAppId && t.APIUserId == targetUser.Id))
            {
                return(Json(new AiurProtocal {
                    Code = ErrorType.Unauthorized, Message = "This user did not grant your app!"
                }));
            }
            if (!app.App.ChangePhoneNumber)
            {
                return(this.Protocal(ErrorType.Unauthorized, "You app is not allowed to set users' phone number."));
            }
            if (string.IsNullOrWhiteSpace(model.Phone))
            {
                targetUser.PhoneNumber = string.Empty;
            }
            else
            {
                targetUser.PhoneNumber = model.Phone;
            }
            await _userManager.UpdateAsync(targetUser);

            return(this.Protocal(ErrorType.Success, "Successfully set the user's PhoneNumber!"));
        }
        public async Task <IActionResult> Authorize(AuthorizeAddressModel model)
        {
            var app = (await ApiService.AppInfoAsync(model.appid)).App;

            if (app == null)
            {
                return(NotFound());
            }
            if (!ModelState.IsValid)
            {
                return(View("AuthError"));
            }
            var url  = new Uri(model.redirect_uri);
            var user = await GetCurrentUserAsync();

            // Wrong domain
            if (url.Host != app.AppDomain && app.DebugMode == false)
            {
                ModelState.AddModelError(string.Empty, "Redirect uri did not work in the valid domain!");
                _logger.LogInformation($"A request with appId {model.appid} is access wrong domian.");
                return(View("AuthError"));
            }
            // Signed in but have to input info.
            else if (user != null && app.ForceInputPassword == false && model.forceConfirm != true)
            {
                return(await FinishAuth(model.Convert(user.Email), app.ForceConfirmation));
            }
            // Not signed in but we don't want his info
            else if (model.tryAutho == true)
            {
                return(Redirect($"{url.Scheme}://{url.Host}:{url.Port}/?{Values.DirectShowString.Key}={Values.DirectShowString.Value}"));
            }
            var viewModel = new AuthorizeViewModel(model.redirect_uri, model.state, model.appid, model.scope, model.response_type, app.AppName, app.AppIconAddress);

            return(View(viewModel));
        }