/// <summary> /// NOTE: This method will be deleted when RSIS Goal 925 is completed. But continue using it when necessary since there is no good alternative. /// </summary> public static ActionButtonSetup CreateWithUrl( string text, ResourceInfo resourceInfo, ActionControlIcon icon = null ) { return new ActionButtonSetup( text, new EwfLink( resourceInfo ), icon: icon ); }
protected override bool isIdenticalTo( ResourceInfo infoAsBaseType ) { var info = infoAsBaseType as StaticFileInfo; return info != null && info.appRelativeFilePath == appRelativeFilePath; }
private string getTransferPath( ResourceInfo resource ) { var url = resource.GetUrl( true, true, false ); if( resource.ShouldBeSecureGivenCurrentRequest != RequestIsSecure( Request ) ) throw new ApplicationException( url + " has a connection security setting that is incompatible with the current request." ); return url; }
private void navigate( ResourceInfo destination, FullResponse secondaryResponse ) { var requestState = AppRequestState.Instance.EwfPageRequestState; string destinationUrl; try { // Determine the final redirect destination. If a destination is already specified and it is the current page or a page with the same entity setup, // replace any default optional parameter values it may have with new values from this post back. If a destination isn't specified, make it the current // page with new parameter values from this post back. At the end of this block, redirectInfo is always newly created with fresh data that reflects any // changes that may have occurred in EH methods. It's important that every case below *actually creates* a new page info object to guard against this // scenario: // 1. A page modifies data such that a previously created redirect destination page info object that is then used here is no longer valid because it // would throw an exception from init if it were re-created. // 2. The page redirects, or transfers, to this destination, leading the user to an error page without developers being notified. This is bad behavior. if( requestState.ModificationErrorsExist || ( requestState.DmIdAndSecondaryOp != null && requestState.DmIdAndSecondaryOp.Item2 == SecondaryPostBackOperation.NoOperation ) ) destination = InfoAsBaseType.CloneAndReplaceDefaultsIfPossible( true ); else if( destination != null ) destination = destination.CloneAndReplaceDefaultsIfPossible( false ); else destination = createInfoFromNewParameterValues(); // This GetUrl call is important even for the transfer case below for the same reason that we *actually create* a new page info object in every case // above. We want to force developers to get an error email if a page modifies data to make itself unauthorized/disabled without specifying a different // page as the redirect destination. The resulting transfer would lead the user to an error page. destinationUrl = destination.GetUrl(); } catch( Exception e ) { throw getPossibleDeveloperMistakeException( "The post-modification destination page became invalid.", innerException: e ); } // Put the secondary response into session state right before navigation so that it doesn't get sent if there is an error before this point. if( secondaryResponse != null ) { // It's important that we put the response in session state first since it's used by the Info.init method of the pre-built-response page. StandardLibrarySessionState.Instance.ResponseToSend = secondaryResponse; StandardLibrarySessionState.Instance.SetClientSideNavigation( EwfApp.MetaLogicFactory.CreatePreBuiltResponsePageInfo().GetUrl(), !secondaryResponse.FileName.Any(), null ); } // If the redirect destination is identical to the current page, do a transfer instead of a redirect. if( destination.IsIdenticalToCurrent() ) { AppRequestState.Instance.ClearUserAndImpersonator(); resetPage(); } // If the redirect destination is the current page, but with different query parameters, save request state in session state until the next request. if( destination.GetType() == InfoAsBaseType.GetType() ) StandardLibrarySessionState.Instance.EwfPageRequestState = requestState; NetTools.Redirect( destinationUrl ); }
/// <summary> /// Returns true if this resource info object is identical to the specified resource info object. /// </summary> protected abstract bool isIdenticalTo( ResourceInfo infoAsBaseType );
/// <summary> /// NOTE: This method will be deleted when RSIS Goal 925 is completed. But continue using it when necessary since there is no good alternative. /// </summary> public static ActionButtonSetup CreateWithUrl(string text, ResourceInfo resourceInfo, ActionControlIcon icon = null) { return(new ActionButtonSetup(text, new EwfLink(resourceInfo), icon: icon)); }
/// <summary> /// MVC and internal use only. /// </summary> public AccessDeniedException(bool causedByIntermediateUser, ResourceInfo logInPage) { this.causedByIntermediateUser = causedByIntermediateUser; this.logInPage = logInPage; }
/// <summary> /// NOTE: This method will be deleted when RSIS Goal 925 is completed. But continue using it when necessary since there is no good alternative. /// </summary> public static ActionButtonSetup CreateWithUrl( string text, ResourceInfo resourceInfo ) { return new ActionButtonSetup( text, new EwfLink( resourceInfo ) ); }
/// <summary> /// Returns credit-card-collection hidden fields and a JavaScript function call getter that opens a Stripe Checkout modal window. If the window's submit /// button is clicked, the credit card is charged or otherwise used. Do not execute the getter until after the page tree has been built. /// </summary> /// <param name="testPublishableKey">Your test publishable API key. Will be used in non-live installations. Do not pass null.</param> /// <param name="livePublishableKey">Your live publishable API key. Will be used in live installations. Do not pass null.</param> /// <param name="name">See https://stripe.com/docs/checkout. Do not pass null.</param> /// <param name="description">See https://stripe.com/docs/checkout. Do not pass null.</param> /// <param name="amountInDollars">See https://stripe.com/docs/checkout, but note that this parameter is in dollars, not cents</param> /// <param name="testSecretKey">Your test secret API key. Will be used in non-live installations. Do not pass null.</param> /// <param name="liveSecretKey">Your live secret API key. Will be used in live installations. Do not pass null.</param> /// <param name="successHandler">A method that executes if the credit-card submission is successful. The first parameter is the charge ID and the second /// parameter is the amount of the charge, in dollars.</param> /// <param name="prefilledEmailAddressOverride">By default, the email will be prefilled with AppTools.User.Email if AppTools.User is not null. You can /// override this with either a specified email address (if user is paying on behalf of someone else) or the empty string (to force the user to type in the /// email address).</param> public static Tuple <IReadOnlyCollection <EtherealComponentOrElement>, Func <string> > GetCreditCardCollectionHiddenFieldsAndJsFunctionCall( string testPublishableKey, string livePublishableKey, string name, string description, decimal?amountInDollars, string testSecretKey, string liveSecretKey, Func <string, decimal, StatusMessageAndDestination> successHandler, string prefilledEmailAddressOverride = null) { if (!EwfApp.Instance.RequestIsSecure(HttpContext.Current.Request)) { throw new ApplicationException("Credit-card collection can only be done from secure pages."); } EwfPage.Instance.ClientScript.RegisterClientScriptInclude(typeof(PaymentProcessingStatics), "Stripe Checkout", "https://checkout.stripe.com/checkout.js"); if (amountInDollars.HasValue && amountInDollars.Value.DollarValueHasFractionalCents()) { throw new ApplicationException("Amount must not include fractional cents."); } ResourceInfo successDestination = null; var postBack = PostBack.CreateFull( id: PostBack.GetCompositeId("ewfCreditCardCollection", description), actionGetter: () => new PostBackAction(successDestination)); var token = new DataValue <string>(); var hiddenFieldId = new HiddenFieldId(); List <EtherealComponentOrElement> hiddenFields = new List <EtherealComponentOrElement>(); FormState.ExecuteWithDataModificationsAndDefaultAction( postBack.ToCollection(), () => hiddenFields.Add(new EwfHiddenField("", (postBackValue, validator) => token.Value = postBackValue.Value, id: hiddenFieldId).PageComponent)); postBack.AddModificationMethod( () => { // We can add support later for customer creation, subscriptions, etc. as needs arise. if (!amountInDollars.HasValue) { throw new ApplicationException("Only simple charges are supported at this time."); } StripeCharge response; try { response = new StripeGateway(ConfigurationStatics.IsLiveInstallation ? liveSecretKey : testSecretKey).Post( new ChargeStripeCustomer { Amount = (int)(amountInDollars.Value * 100), Currency = "usd", Description = description.Any() ? description : null, Card = token.Value }); } catch (StripeException e) { if (e.Type == "card_error") { throw new DataModificationException(e.Message); } throw new ApplicationException("A credit-card charge failed.", e); } try { var messageAndDestination = successHandler(response.Id, amountInDollars.Value); if (messageAndDestination.Message.Any()) { EwfPage.AddStatusMessage(StatusMessageType.Info, messageAndDestination.Message); } successDestination = messageAndDestination.Destination; } catch (Exception e) { throw new ApplicationException("An exception occurred after a credit card was charged.", e); } }); FormAction action = new PostBackFormAction(postBack); action.AddToPageIfNecessary(); return(Tuple.Create <IReadOnlyCollection <EtherealComponentOrElement>, Func <string> >( hiddenFields, () => { var jsTokenHandler = "function( token, args ) { " + hiddenFieldId.GetJsValueModificationStatements("token.id") + " " + action.GetJsStatements() + " }"; return "StripeCheckout.open( { key: '" + (ConfigurationStatics.IsLiveInstallation ? livePublishableKey : testPublishableKey) + "', token: " + jsTokenHandler + ", name: '" + name + "', description: '" + description + "', " + (amountInDollars.HasValue ? "amount: " + amountInDollars.Value * 100 + ", " : "") + "email: '" + (prefilledEmailAddressOverride ?? (AppTools.User == null ? "" : AppTools.User.Email)) + "' } )"; })); }
/// <summary> /// Creates a image style object. /// </summary> /// <param name="imageInfo">The image. Do not pass null.</param> /// <param name="alternativeText">The alternative text for the image; see https://html.spec.whatwg.org/multipage/embedded-content.html#alt. Pass null (which /// omits the alt attribute) or the empty string only when the specification allows.</param> /// <param name="sizesToAvailableWidth">Whether the image sizes itself to fit all available width.</param> /// <param name="rolloverImageInfo"></param> public ImageHyperlinkStyle(ResourceInfo imageInfo, string alternativeText, bool sizesToAvailableWidth = false, ResourceInfo rolloverImageInfo = null) { this.sizesToAvailableWidth = sizesToAvailableWidth; this.imageInfo = imageInfo; this.alternativeText = alternativeText; this.rolloverImageInfo = rolloverImageInfo; }