Exemplo n.º 1
0
        /// <summary>
        /// This method mainly tries to generate access token, creates user record, creates uninstall web hook and finally
        /// sends to the page where user can choose plan.
        /// </summary>
        /// <param name="shop">The store (URL) that is trying to access app.</param>
        /// <param name="code">Authrization code generated and send from shopify that will be used to gnerate access code</param>
        /// <returns></returns>
        public virtual async Task <IActionResult> AuthResult(string shop, string code)
        {
            using (Logger.BeginScope(new { Shop = shop, Code = code }))
            {
                try
                {
                    Logger.LogInformation("Checking request authenticity.");
                    if (ShopifyAPI.IsAuthenticRequest(Request))
                    {
                        Logger.LogInformation("Request is authentic.");
                        Logger.LogInformation("Checking if shop is authorized.");
                        if (UserDbServiceHelper.ShopIsAuthorized(UserDbService, shop))
                        {
                            Logger.LogInformation("Shop is authrorized.Calling _ProceedWithShopExists.");
                            return(await _ProceedWithShopExists(shop));
                        }
                        else
                        {
                            string accessToken = "";
                            try
                            {
                                Logger.LogWarning("Shop is NOT authrorized.Requesting authentication (access) token via api.");
                                accessToken = await ShopifyAPI.Authorize(shop, code);
                            }
                            catch (Exception ex)
                            {
                                Logger.LogCritical("Shopify did not authorize.No access code received.Throwing exception.");
                                throw new Exception("Shopify did not authorize.No access code received.", ex);
                            }
                            Logger.LogInformation($"Rceived access token '{accessToken}'");
                            Thread.Sleep(500);
                            /*Get shop object cause we need the shop email address*/
                            ShopifyShopObject shopObj = null;
                            try
                            {
                                Logger.LogInformation("Request shopify shop obj using access token.");
                                shopObj = await ShopifyAPI.GetShopAsync(shop, accessToken);
                            }
                            catch (Exception ex)
                            {
                                Logger.LogCritical("Could not retrive shop info obj.");
                                throw new Exception("Could not retrive shop info obj.", ex);
                            }

                            Logger.LogInformation($"Received shop info obj. Shop '{shopObj.Domain}' and email '{shopObj.Email}'");

                            #region User Creation
                            //Generate password
                            Logger.LogInformation("Generating password using shop info obj.");
                            string password = PassGenerator.GetPassword(new PasswordGeneratorInfo(shopObj.MyShopifyDomain, shopObj.Email));
                            Logger.LogInformation($"Successfully generated a password '{password}'.");
                            /*Now create an account */
                            Logger.LogInformation("Creating user account using shop info and password.");
                            var userCreation = await UserManager.CreateAppUser(shopObj.MyShopifyDomain, shopObj.Email, accessToken, password);

                            #endregion

                            if (userCreation.Succeeded)
                            {
                                AppUser user = await UserDbServiceHelper.GetUserByShopDomain(UserDbService, shopObj.MyShopifyDomain);

                                Logger.LogInformation($"Successfully created user for the shop.User id '{user.Id}'");

                                #region Uninstall hook creation
                                //As soon as user is created , create the uninstall hook
                                string uninstallCallback = "";
                                try
                                {
                                    Logger.LogInformation("Trying to find app/uninstalled topic in the web hook definition list in the appsettings.json file.");
                                    List <WebHookDefinition> whDefList = AppSettings.BindObject <List <WebHookDefinition> >("WebHooks", Config);

                                    if (whDefList.Count > 0)
                                    {
                                        var def = whDefList.Where(x => x.Topic.ToLower() == "app/uninstalled").FirstOrDefault();
                                        if (def.Topic == string.Empty)
                                        {
                                            Logger.LogWarning("List of webhooks found in the appsettings file but no app/uninstalled topic found.");
                                            uninstallCallback = ShopifyUrlHelper.GetAppUninstallWebHookUrl(Settings, user.Id);
                                            Logger.LogInformation($"Using system default uninstall callback url {uninstallCallback}.");
                                        }
                                        else
                                        {
                                            Logger.LogInformation($"Found app/uninstalled topic call in the appsettings file.The callback url is {def.Callback}.");
                                            uninstallCallback = ShopifyUrlHelper.GetAppUninstallWebHookUrl(def.Callback, user.Id);
                                        }
                                    }
                                    else
                                    {
                                        Logger.LogInformation("No weebhooks are defined in the appsettings file.");
                                        uninstallCallback = ShopifyUrlHelper.GetAppUninstallWebHookUrl(Settings, user.Id);
                                        Logger.LogInformation($"Using system default uninstall callback url {uninstallCallback}.");
                                    }

                                    Logger.LogInformation($"Trying to create uninstall web hook with call back url {uninstallCallback}.");
                                    var hook = await ShopifyAPI.CreateWebhookAsync(user.MyShopifyDomain, accessToken, new ShopifyWebhookObject()
                                    {
                                        Address = uninstallCallback,
                                        Topic   = "app/uninstalled"
                                    });

                                    Logger.LogInformation($"Successfully created uninstall web hook. Hook id '{hook.Id.Value}'.");
                                }
                                catch (Exception ex)
                                {
                                    LogGenericError(ex);
                                    Logger.LogCritical($"Failed creating uninstall webhook for user id '{user.Id}.The call back url is {uninstallCallback}'.");
                                    Logger.LogInformation("Sending UninstallHookCreationFailedAsync email.");
                                    var response = await Emailer.UninstallHookCreationFailedAsync(user, shopObj.MyShopifyDomain);

                                    if (response)
                                    {
                                        Logger.LogInformation("Successfully sent UninstallHookCreationFailedAsync email.");
                                    }
                                    else
                                    {
                                        Logger.LogInformation("Could not send UninstallHookCreationFailedAsync email.");
                                    }
                                    //we dont thorw error here...just gracefully ignore it
                                }
                                #endregion

                                #region Sign in
                                //Now sign in
                                Logger.LogInformation($"Trying to sign in using username '{user.UserName}' and password '{password}'. User id '{user.Id}'");
                                var signInStatus = await SignInManager.PasswordSignInAsync(user.UserName, password, false, lockoutOnFailure : false);

                                if (signInStatus.Succeeded)
                                {
                                    Logger.LogInformation($"Successfully signed in. User id '{user.Id}'");
                                    UserCache.ClearLoggedOnUser();
                                    return(RedirectToAction(SHOPIFY_ACTIONS.ChoosePlan.ToString(), Settings.GetShopifyControllerName()));
                                }
                                else
                                {
                                    Logger.LogCritical($"Signing in for  User id '{user.Id}' failed.");
                                    throw new Exception("Could not sign you in using app account.Sign in failed!");
                                }
                                #endregion
                            }
                            else
                            {
                                var reasons = $"Reasons: { string.Join(", ", userCreation.Errors) }";
                                Logger.LogCritical($"User creation failed.{reasons}");
                                throw new Exception($"Could not create app user.{reasons}.");
                            }
                        }
                    }
                    else
                    {
                        Logger.LogCritical("Request is not authentic. Throwing error.");
                        throw new Exception("Request is not authentic.");
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogWarning("Error occurred while executing AuthResult().");
                    LogGenericError(ex);
                    throw ex;
                }
            }
        }
Exemplo n.º 2
0
        public void OnAuthorization(AuthorizationFilterContext filterContext)
        {
            //already logged in by Identity now check subscription
            if (filterContext.Result == null)
            {
                _Logger.LogInformation("Starting subscription check.");
                var context = filterContext.HttpContext;

                _Logger.LogInformation("Getting current user.");
                AppUser currentUser = _UserCache.GetLoggedOnUser().Result;
                if (currentUser == null)
                {
                    _Logger.LogError("User must be logged on before checking subscription.Redirecting to login page.");
                    //throw new Exception("Subscription check must be done on logged on user. But current user is found null.");
                    filterContext.Result = new RedirectToActionResult(ACCOUNT_ACTIONS.Login.ToString(), _Settings.GetAccountControllerName(), new { });
                }
                else
                {
                    _Logger.LogInformation($"Current user is '{currentUser.MyShopifyDomain}'");

                    //admin must have access token atleast
                    if (currentUser.ShopIsConnected == false /*&& !currentUser.IsAdmin*/)
                    {
                        _Logger.LogWarning($"User '{currentUser.MyShopifyDomain}' has no shopify access token. Charge status check cannot be done on diconnected shop.Redirecting to '{_Settings.GetShopifyControllerName()}/{SHOPIFY_ACTIONS.HandShake.ToString()}'.");
                        filterContext.Result = _CreateRedirectResult(_Settings.GetShopifyControllerName(), SHOPIFY_ACTIONS.HandShake.ToString());
                    }
                    //billing connected or disconnected, for admin it is never checked
                    else if (currentUser.BillingIsConnected == false && !currentUser.IsAdmin)
                    {
                        _Logger.LogWarning($"User '{currentUser.MyShopifyDomain}' billing charge id is null.Charge status check cannot be done on null charge id.Redirecting to '{_Settings.GetShopifyControllerName()}/{SHOPIFY_ACTIONS.ChoosePlan.ToString()}'.");
                        filterContext.Result = _CreateRedirectResult(_Settings.GetShopifyControllerName(), SHOPIFY_ACTIONS.ChoosePlan.ToString());
                    }
                    else
                    {
                        ShopifyRecurringChargeObject chargeStatus = null;
                        //for admin user if no billing charge id all good, but if theres one then we will look into it
                        if (currentUser.IsAdmin)
                        {
                            _Logger.LogInformation($"Skipping charge status check because user '{currentUser.MyShopifyDomain}' is admin.");
                            chargeStatus = new ShopifyRecurringChargeObject()
                            {
                                Status = SHOPIFY_CHARGE_STATUS.active.ToString()
                            };
                        }
                        else
                        {
                            _Logger.LogInformation($"Checking charge status for user '{currentUser.MyShopifyDomain}'.");
                            try
                            {
                                chargeStatus = Task.Run(() => _ShopifyApi.GetRecurringChargeAsync(currentUser.MyShopifyDomain, currentUser.ShopifyAccessToken, currentUser.ShopifyChargeId.Value)).Result;
                            }
                            catch (Exception ex)
                            {
                                _Logger.LogError($"Error occurred duing GetRecurringChargeAsync() call.{ex.Message}.{ex.StackTrace}");
                                throw ex;
                            }
                        }

                        if (chargeStatus.Status == SHOPIFY_CHARGE_STATUS.accepted.ToString() || chargeStatus.Status == SHOPIFY_CHARGE_STATUS.active.ToString())
                        {
                            _Logger.LogInformation($"Require subscription passed for user '{currentUser.MyShopifyDomain}'");
                        }
                        else
                        {
                            _Emailer.InActiveChargeIdDetectedAsync(currentUser, chargeStatus.Status);

                            if (chargeStatus.Status == SHOPIFY_CHARGE_STATUS.declined.ToString() ||
                                chargeStatus.Status == SHOPIFY_CHARGE_STATUS.expired.ToString() ||
                                chargeStatus.Status == SHOPIFY_CHARGE_STATUS.pending.ToString())
                            {
                                _Logger.LogWarning($"Require subscription did not pass for user '{currentUser.MyShopifyDomain}'");
                                _Logger.LogWarning($"User '{currentUser.MyShopifyDomain}' has declined/expired/pending charge status.");
                                _Logger.LogWarning($"Unsetting charge info for user '{currentUser.MyShopifyDomain}'.");
                                UserDbServiceHelper.UnSetUserChargeInfo(_UserDbService, currentUser.Id);
                                _Logger.LogWarning($"Removing user '{currentUser.MyShopifyDomain}' from cache.");
                                _UserCache.ClearLoggedOnUser();//resset cache so that next try makes BillingIsConnected = false
                                var handShakeAction = SHOPIFY_ACTIONS.HandShake.ToString();
                                _Logger.LogWarning($"Redirecting user '{currentUser.MyShopifyDomain}' to '{_Settings.GetShopifyControllerName()}/{handShakeAction}'.");
                                filterContext.Result = _CreateRedirectResult(_Settings.GetShopifyControllerName(), handShakeAction);
                            }
                            else if (chargeStatus.Status == SHOPIFY_CHARGE_STATUS.frozen.ToString())
                            {
                                _Logger.LogError($"User '{currentUser.MyShopifyDomain}' has frozen shopify store account. Throwing error.");
                                throw new UnauthorizedAccessException("Your shopify account is frozen.Once shopify unfreezes your store account you will be able to use this app again.");
                            }
                        }
                    }
                }
            }
        }