Access widget stop processing - sitefinity

I have three widgets on a page one widget checks the access to page and I wanted the other widget's not to process if the access widget returns false. Is there anyway I can do that? Almost need something like stopPropagation. The access widget returns a just a div when access is true but when access is false it will return a restriction message.

That access-checker widget should redirect to a Login page or something (e.g. throw a 403 unauthorized exception) if the user does not have access.
Alternatively you can set something in TempData, e.g.
TempData["UserRestricted"] = true;
and then read that value in the other widgets and act appropriately, but this makes them a bit tight-coupled.
You can also combine these widgets into one?

Related

How to prevent the flashing of content in a prerendered Blazor WebAssembly app?

The following code snippet can illustrate the issue present in Blazor applications which are rendered on the server side:
App.Client/Pages/Test.razor
#page "/test"
<p>#text</p>
#code
{
private string text;
protected override async Task OnInitializedAsync()
{
await Task.Delay(1000); // wait 1000 milliseconds
text = "foo";
}
}
When the component is first initailized on the server, the text variable is set to foo and a HTML document containing the string is sent over to the client. However, the client Blazor app isn't aware of the value that the server has assigned to the variable, which becomes null again. OnInitializedAsync is called again on the client and text is set back to foo, but only after a one second period during which there's nothing on the screen - a situation server-side rendering aims to avoid in the first place.
Do you know of any way to send components already populated with data?
Ok -- just being a bit picky -- this is a Blazor page....it isn't a component.
Yes, the pre-render they use isn't great, but assuming you're using Blazor for a SPA it should only happen once. Be careful to avoid a hard reload if you use the Microsoft.AspNetCore.Components.NavigationManager NavigateTo method. A hard re-load triggers pre-rendering because you refresh the SPA.
To avoid the whiplash, you want to avoid needing 1 second to load the text value. So you could use a singleton controller and inject it into the page. On the pre-render pass the value isn't yet known so we need 1 second to load it. Then on the client side pass the data could be accessed via the controller immediately.
Granted this isn't perfect if there is a ton of data to display. But in cases like that I generally show a 'loading' spinner and it gives the customer a feeling of controlled motion.

Calling a controller method (from an external email link) that does not return a View, but simply exits

I have an MVC 4 Razor intranet app using Windows credentials where a new user must register (existing users are automatically redirected to the main user page). This generates an approval request email to the admin and returns a view with an Exit button simply saying your application has been submitted. The user then closes the app.
The email is in HTML and presents the user's entered data and has Approved or Declined selections. It then has a button to invoke code to insert the user into the Members table (if accepted) and return an email to the user with the decision.
Since some time may transpire between the app mailing the admin and the admin making the decision, the session will originally terminate. I need to have the email invoke a method to persist the new user, email the decision, and then simply exit. It will not involve the browser in any way, so no Views are involved. I could write this as a background console app, but that would involve duplicating a lot of code in the MVC app - with referential integrity issues on bug fixes or updates.
How can I write a method in the Controller that can be invoked by a link in the email as if from a browser that does the work and then exits without returning anything to a browser?
If I make the method an ActionResult method and return new EmptyResult() or return(null) I assume it will try to return an empty page to nowhere.
Can I alternatively construct a method in my Controller, where it has access to all of the support code, like?
public void EnrollMember(Member member, bool decision)
{
if (decision == true)
{
// insert new user into Members table
// generate accepted email
}
else
{
// generate declined email
}
}
and then just link to it the same way I link to Index(), /MyController/EnrollMember(...)?
There is no main() in the app since it is an ASP.NET MVC app, and I don't know how to terminate the app from within a Controller method without trying to return something, instead of from a View in the browser.
I'm a long-time programmer, but a .NET newbie so this probably has a simple answer.
The "view" is just the response. You don't necessarily have to return a view, but you must return a response. There's no way around that. If the link opens in a browser, then something will be displayed, regardless. Even if you were to just return an empty ContentResult, at least a blank page will be displayed in the browser.
To achieve something akin to what you're looking for, your best bet would be to return an HTML document with just a simple bit of JavaScript that will act to close the window:
<html>
<body>
<script>
window.close();
</script>
</body>
</html>

How do I simply set the ModelStateError from the HandleUnauthorizedRequest method?

So what is happening is that I have a condition within my override of the HandleUnauthorizedRequest method in my custom authorize attribute. Up to this point, I've been throwing a 403 which gets picked up and redirects to a custom error page. Well now, that's not really what I want. What I actually want is to show the same login page but add a message to the validation summary "You do not have access to this resource.", that way it's a bit more user friendly. It'll indicate that your creds were good, but you don't belong here.
I thought something like this would work:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// passed authentication, failed authorization
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Controller.ViewData.ModelState.AddModelError("", "Not Authorized");
return;
}
base.HandleUnauthorizedRequest(filterContext);
}
But this isn't working. What's happening is that the login page simply reloads. So this makes me feel like I'm close, but I need that model error to show up.
Any ideas?
UPDATE:
It would seem that the Controller that I'm adding an error to here is actually controller of whichever action had the attribute that led to here. I need to somehow add the error to the login controller. Not sure if that's even possible.
You are calling the base method here:
base.HandleUnauthorizedRequest(filterContext);
If you are using Forms Authentication this base method simply redirects you to the login page. And a redirect means a new HTTP request from the client. The current context and whatever you stored in it is lost. Well, to be more precise, the base method is returning a 401 HTTP status code which is then intercepted by the FormsAuthenticationModule which redirects to the login page defined in your web.config. But this implementation details is not important.
What you could do is perform the redirect yourself to the login page instead of leaving it to the base method. You could do this by setting the filterContext.Result property to a RedirectToRouteResult instance. In this case you could pass the error message as a query string parameter.
UPDATE:
According to your updated question it seems that you are calling return; after setting the ModelState value and not calling the base method and thus no redirect will happen to the login url. You could in this case return some error view by setting the filterContext.Result to an instance of a ViewResult in which view you could use the value you stored in the ModelState.

Best Practice for "Evaluate Now, Respond Later"?

Suppose I'm building a login system. The user enters a username and password into a field and it is sent via HTTPS to the server, which validates the login before the page loads. If a bad password is sent, the login obviously fails immediately, but one would want the error message to be displayed later in the page, near the login box.
The obvious solution is to set a global flag and have the login box check it and add the error message if necessary, but my understanding is that global variables are best avoided. Is there another straightforward method of achieving this functionality?
For a non-AJAX login page, it is common practice to redirect the user browser to the login page with an extra query parameter in the url, In pseudo-code, here is the login validation controller code segment:
success = checkLogin(username,password)
if (success == false)
redirect('http://example.com/login?failedlogin=true')
The login page controller would be responsible for detecting this query param and telling the view code to display a failure message. I don't believe the term 'global flag' applies to this practice so it should meet your requirements.
If the login page uses Ajax, the Javascript on the login page takes the results of the AJAX call and updates the appropriate DOM elements with the failure message.

How can I block based on URL (from address bar) in a safari extension

I'm trying to write an extension that will block access to (configurable) list of URLs if they are accessed more than N times per hour. From what I understand, I need to have a start script pass a "should I load this" message to a global HTML page (who can access the settings object to get the list of URLs), who will give a thumbs up/thumbs down message back to the start script to deny/allow loading.
That works out fine for me, but when I use the usual beforeLoad/canLoad handlers, I get messages for all the sub-items that need to be loaded (images/etc..), which screws up the #accesses/hour limit I'm trying to make.
Is there a way to synchronously pass messages back and forth between the two sandboxes so I can tell the global HTML page, "this is the URL in the window bar and the timestamp for when this request came in", so I can limit duplicate requests?
Thanks!
You could use a different message for the function that checks whether to allow the page to load, rather than using the same message as for your beforeLoad handler. For example, in the injected script (which must be a "start" script), put:
safari.self.tab.dispatchMessage('pageIsLoading');
And in the global script:
function handleMessage(event) {
if (event.name == 'pageIsLoading') {
if (event.target.url.indexOf('forbidden.site.com') > -1) {
console.log(event.timeStamp);
event.target.url = 'about:blank';
}
}
}