public void Get_admin_url_should_return_valid_admin_url()
        {
            var shop = "test.myshopify.com";
            var ret  = ShopifyUrlHelper.GetAdminUrl(shop);

            Assert.Equal($"https://{shop}/admin", ret);
        }
Ejemplo n.º 2
0
        public virtual IActionResult RedirectAfterNewUserCancelledPayment(AppUser user)
        {
            var url = ShopifyUrlHelper.GetAdminUrl(user.MyShopifyDomain);

            Logger.LogInformation($"Redirecting to {url}.");
            return(Redirect(url));
        }
        public void make_store_friendly_app_name_should_return_valid_name()
        {
            var unfriendlyName = "my app version 2.0";
            var ret            = ShopifyUrlHelper.MakeStoreFriendlyAppName(unfriendlyName, null);

            Assert.Equal("my-app-version-2.0", ret);
        }
        public void Get_App_Uninstall_Web_Hook_Url_Should_Returl_Valid_Url()
        {
            var data = ShopifyUrlHelper.GetAppUninstallWebHookUrl(settings, "123456");

            Assert.NotNull(data);
            Assert.Equal($"{APP_BASE_URL}/appuninstaller/{UNINSTALL_ACTIONS.AppUninstalled}?userId=123456", data);
        }
        public void Get_Charge_Result_Handler_Url_Should_Returl_Valid_Url()
        {
            var data = ShopifyUrlHelper.GetChargeResultHandlerUrl(settings);

            Assert.NotNull(data);
            Assert.Equal($"{APP_BASE_URL}/shopify/{SHOPIFY_ACTIONS.ChargeResult}", data);
        }
        public void make_store_friendly_app_name_should_dashify_supplied_char_array()
        {
            var unfriendlyName = "my app version 2.0";
            var ret            = ShopifyUrlHelper.MakeStoreFriendlyAppName(unfriendlyName, new char[] { '.' });

            Assert.Equal("my-app-version-2-0", ret);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// This is the method that is called first when user tries to access or install your app.
 /// This method starts the installation process (by sending to authrization url) if user is not subscribed already otherwise
 /// tries to auto login the user and sends to the landing page(dashboard).
 /// </summary>
 /// <param name="shop">The store (URL) that is trying to access app.</param>
 /// <returns></returns>
 public virtual async Task <IActionResult> Handshake(string shop)
 {
     using (Logger.BeginScope(new { Shop = shop }))
     {
         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 already authrorized.Calling _ProceedWithShopExists.");
                     return(await _ProceedWithShopExists(shop));
                 }
                 else
                 {
                     Logger.LogWarning("Shop is NOT authrorized.Either new shop or imcomplete installation from previous attempt.So let's install it.");
                     var handlerUrl = ShopifyUrlHelper.GetAuthResultHandlerUrl(Settings);
                     Logger.LogInformation("Getting permission list.");
                     var permissions = ListPermissions();
                     Logger.LogInformation("Permission list acquiring is done. {@list}.", permissions);
                     Logger.LogInformation("Getting authorization url.");
                     var authUrl = ShopifyAPI.GetAuthorizationUrl(shop, permissions, handlerUrl);
                     Logger.LogInformation($"Redirecting to authrization url '{authUrl}'.");
                     return(Redirect(authUrl.ToString()));
                 }
             }
             else
             {
                 Logger.LogWarning("Request is NOT authentic.Throwing Exception.");
                 throw new Exception("Request is not authentic.");
             }
         }
         catch (Exception ex)
         {
             Logger.LogWarning("Error occurred while handshaking.");
             throw ex;
         }
     }
 }
Ejemplo n.º 8
0
        public virtual async Task <ActionResult> LogOff()
        {
            Logger.LogInformation("Getting the current logged on user object first.");
            var me = await AppUserCache.GetLoggedOnUser();

            Logger.LogInformation("Current user is {@me}.", me);
            Logger.LogInformation("Now calling ClearLoggedOnUser() to clear the cache.");
            AppUserCache.ClearLoggedOnUser();
            Logger.LogInformation("Done calling ClearLoggedOnUser().");
            Logger.LogInformation("Now calling SignOutAsync() to do identity framework signout.");
            await _signInManager.SignOutAsync();

            Logger.LogInformation("Done calling SignOutAsync().");
            Logger.LogInformation("Now calling LogOffHappened() event.");
            await LogOffHappened(me);

            Logger.LogInformation("Done handling LogOffHappened() event.");
            var redirectTo = ShopifyUrlHelper.GetAdminUrl(me.MyShopifyDomain);

            Logger.LogInformation($"Now redirecting to '{redirectTo}'.");
            return(Redirect(ShopifyUrlHelper.GetAdminUrl(me.MyShopifyDomain)));
        }
Ejemplo n.º 9
0
        public virtual async Task <IActionResult> SelectedPlan(int planId)
        {
            using (Logger.BeginScope(new { PlanId = planId }))
            {
                try
                {
                    Logger.LogInformation("Getting user");
                    var user = await UserDbServiceHelper.GetAppUserByIdAsync(UserDbService, UserInContextHelper.GetCurrentUserId(HttpContext));

                    string domain = user.MyShopifyDomain;
                    string token  = user.ShopifyAccessToken;
                    /*user plan id = 0  means that customer is new*/
                    int userPlanId = user.GetPlanId();
                    Logger.LogInformation($"Got user.User ID '{user.Id}', domain '{user.MyShopifyDomain}', token '{user.ShopifyAccessToken}' and Plan Id '{user.PlanId}'.");
                    //privileged ip holders can downgrade or upgrade plan, others are upgrade only
                    var validUpgrade    = planId >= userPlanId;
                    var priviledgedUser = IPAddressHelper.IsCurrentUserIpPrivileged(HttpContext, Settings);

                    Logger.LogInformation($"Selected is a valid upgrade : {validUpgrade}");
                    Logger.LogInformation($"Selector's IP is priviledged: {priviledgedUser}");

                    if (validUpgrade || priviledgedUser)
                    {
                        Logger.LogInformation("Plan selection is approved.");
                        var plan = PlanReader[planId];
                        if (plan != null && plan.Id > 0)
                        {
                            Logger.LogInformation($"Found plan for the selected ID. Plan Name '{plan.Name}'.");
                            var charge = new ShopifyRecurringChargeObject()
                            {
                                Name      = plan.Name,
                                Price     = plan.Price,
                                TrialDays = plan.TrialDays,
                                Test      = plan.IsTest,
                                ReturnUrl = ShopifyUrlHelper.GetChargeResultHandlerUrl(Settings),
                            };
                            try
                            {
                                Logger.LogInformation("Creating recurring charge via api for selected plan.");
                                charge = await ShopifyAPI.CreateRecurringChargeAsync(domain, token, charge);

                                Logger.LogInformation($"Successfully created recurring charge. Redirecting to confirmation URL '{charge.ConfirmationUrl}'.");
                                return(Redirect(charge.ConfirmationUrl));
                            }
                            catch (Exception ex)
                            {
                                Logger.LogError(ex, $"Failed creating recurring charge for the selected plan.Redirecting to '{SHOPIFY_ACTIONS.ChoosePlan.ToString()}' action.");
                                WebMsg.AddTempDanger(this, "Could not create a recurring charge record/confirmation url via shopify api. Please try again.", false, false);
                                return(RedirectToAction(SHOPIFY_ACTIONS.ChoosePlan.ToString(), Settings.GetShopifyControllerName()));
                            }
                        }
                    }

                    //if we are here then it is an invalid plan
                    Logger.LogWarning($"Selection is not approved.Redirecting to '{SHOPIFY_ACTIONS.ChoosePlan.ToString()}' adction");
                    WebMsg.AddTempDanger(this, "Invalid Plan Selected", false, false);
                    return(RedirectToAction(SHOPIFY_ACTIONS.ChoosePlan.ToString(), Settings.GetShopifyControllerName()));
                }
                catch (Exception ex)
                {
                    Logger.LogWarning("Error occurred while executing SelectedPlan())");
                    LogGenericError(ex);
                    throw ex;
                }
            }
        }
Ejemplo n.º 10
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;
                }
            }
        }
        public void Get_Rate_My_App_Url_Should_Return_Valid_Url()
        {
            var ret = ShopifyUrlHelper.GetRateMyAppUrl(settings, "myapp");

            Assert.Equal("https://apps.shopify.com/myapp", ret);
        }
        public void Get_Liquid_File_Link_Should_Return_Valid_Link()
        {
            var ret = ShopifyUrlHelper.GetLiquidFileLink(THEME_FOLDER_NAMES.layout, "store.myshopify.com", "product", ".myext");

            Assert.Equal($"https://store.myshopify.com/admin/themes/current/?key={THEME_FOLDER_NAMES.layout}/product.myext", ret);
        }
        public void Get_plan_chosing_url_should_return_a_valid_url()
        {
            var ret = ShopifyUrlHelper.GetPlanChoosingUrl(settings);

            Assert.Equal($"{APP_BASE_URL}/shopify/{SHOPIFY_ACTIONS.ChoosePlan}", ret);
        }
        public void Get_selected_plan_handler_url_should_return_a_valid_url()
        {
            var ret = ShopifyUrlHelper.GetSelectedPlanHandlerUrl(settings, 2);

            Assert.Equal($"{APP_BASE_URL}/shopify/{SHOPIFY_ACTIONS.SelectedPlan}?planId={2}", ret);
        }