コード例 #1
0
 public async Task <LoginUserTxnPayload> LoginUser(
     LoginUserTxnInput input,
     [Service] IConfiguration configuration,
     [Service] UserManager <IdentityUser> userManager,
     [Service] SignInManager <IdentityUser> signInManager,
     [Service] ApplicationDbContext contextMVC)
 {
     return(await new LoginUserTxn().Execute(
                input: input,
                configuration: configuration,
                userManager: userManager,
                signInManager: signInManager,
                contextMVC: contextMVC,
                autoCommit: true
                ));
 }
コード例 #2
0
        public async Task <LoginUserTxnPayload> Execute(
            LoginUserTxnInput input,
            IConfiguration configuration,
            UserManager <IdentityUser> userManager,
            SignInManager <IdentityUser> signInManager,
            ApplicationDbContext contextMVC,
            bool autoCommit)
        {
            LoginUserTxnPayload _payload = new LoginUserTxnPayload();

            //***** Declare variables and messages
            string errorMessage = "LoginUserTxn***LOGIN_FAIL";
            string okMessage    = "LoginUserTxn***LOGIN_PASS";
            string errorMessageExceptionCode = "LoginUserTxn***TXN_EXCEPTION";
            string errorMessageException     = "TXN_EXCEPTION";

            // Error handling
            bool error = false; // To Handle Only One Error

            try
            {
                // DBContext by convention is a UnitOfWork, track changes and commits when SaveChanges is called
                // Multithreading issue: so if we use only one DBContext, it will track all entities (_context.Customer.Add) and commit them when SaveChanges is called,
                // No Matter what transactions or client calls SaveChanges.
                // Note: Rollback will not remove the entities from the tracker in the context. so better dispose it.

                //***** Make The Validations - Be careful : Concurrency. Same name can be saved multiple times if called at the exact same time. Better have an alternate database constraint
                if (!error)
                {
                    // To check later - RefreshToken
                    // https://stackoverflow.com/questions/53659247/using-aspnetusertokens-table-to-store-refresh-token-in-asp-net-core-web-api

                    var result = await signInManager.PasswordSignInAsync(userName : input.Email, password : input.Password, isPersistent : false, lockoutOnFailure : false);

                    if (!result.Succeeded)
                    {
                        _payload.PayloadResult = PayloadResult.ResultBad(Messages: new List <MessageItem>()
                        {
                            new MessageItem {
                                Code = errorMessage, Message = errorMessage, Detail = ""
                            }
                        });
                        return(_payload);
                    }

                    var user = await signInManager.UserManager.FindByEmailAsync(input.Email);

                    if (user == null)
                    {
                        _payload.PayloadResult = PayloadResult.ResultBad(Messages: new List <MessageItem>()
                        {
                            new MessageItem {
                                Code = errorMessage, Message = errorMessage, Detail = ""
                            }
                        });
                        return(_payload);
                    }

                    // Get the UserApp
                    var userApp = await contextMVC.UserApp.Where(x => x.IdentityId == user.Id).FirstOrDefaultAsync();

                    if (userApp == null)
                    {
                        _payload.PayloadResult = PayloadResult.ResultBad(Messages: new List <MessageItem>()
                        {
                            new MessageItem {
                                Code = errorMessage, Message = errorMessage, Detail = ""
                            }
                        });
                        return(_payload);
                    }

                    //***** Save and Commit to the Database (Atomic because is same Context DB)
                    if (!error && autoCommit)
                    {
                        await contextMVC.SaveChangesAsync(); // Call it only once so do all other operations first
                    }

                    //***** Confirm the Result (Pass | Fail) If gets to here there are not errors then return the new data from database
                    _payload.PayloadResult = PayloadResult.ResultGood(Messages: new List <MessageItem> {
                        new MessageItem {
                            Code = okMessage, Message = okMessage, Detail = ""
                        }
                    });
                    _payload.JWTInfo = await this.CreateTokenAsync(user, userApp, configuration, userManager);
                }// if (!error)
            }
            catch (Exception ex) // Main try
            {
                System.Diagnostics.Debug.WriteLine("Error: " + ex.Message);
                string innerError = (ex.InnerException != null) ? ex.InnerException.Message : "";
                System.Diagnostics.Debug.WriteLine("Error Inner: " + innerError);
                _payload = new LoginUserTxnPayload
                {
                    PayloadResult = PayloadResult.ResultBad(Messages: new List <MessageItem> {
                        new MessageItem {
                            Code = errorMessageExceptionCode, Message = errorMessageException, Detail = ex.Message
                        }
                    })
                }; // Restart variable to avoid returning any already saved data
            }
            finally
            {
                // Save Logs if needed
            }

            return(_payload);
        }