What are "actions" in Vaadin 14? - user-interface

In Vaadin 14, while looking at the Login component, specifically the source code for AbstractLogin.java, I noticed:
An "action" can be saved on a login widget via getElement.setProperty.
The Javadoc for AbstractLogin::setAction says: “Once action is defined a {#link AbstractLogin.LoginEvent} is not fired anymore.”
I understand making an object of mine a listener for LoginEvent by registering with the login widget via AbstractLogin::addLoginListener.
But this “action” seems to be an alternative way to work instead of event listeners.
Can someone tell me more about actions and how they work in Vaadin Flow?
I searched the Vaadin Docs for the word action but found nothing there.

The HTML API of the LoginForm specifies the following
action: string | null | undefined= null notify
If set, a synchronous POST call will be fired to the path defined. The
login event is also dispatched, so event.preventDefault() can be
called to prevent the POST call.
I understand that, with this option you can configure the login form to post the data login processing or e.g. to external authentication service. Useful use case is to set it "login" when using Vaadin with Spring security. This case is shown in Bakery App Starter.

Related

Where to check if an User is logged in in a Laravel Application?

I've been using your advice and View::sharing all of my important data to all views. However, there is one issue I have encountered.
This code:
if(!Auth::guest()){
$user=Auth::user()->id;
}
else $user=0;
$temp=DB::select('query');
View::share('cartnumber', count($temp));
View::share('cartitems', $temp);
doesn't work when put in AppServiceProvider. Or better, it always sets $user=0, even if I am logged in. I thought it is because AppServiceProvider's boot function executes before the site checks if someone is logged in.
I then tried to use a BaseController with a construct function but that doesn't work either. The only solution that seems to work correctly is putting the code in every single Controller for every view! That actually works, which kind of confirms my theory.
But is there anywhere I can put this code without having to copy/paste it in every single Controller? Thanks in advance!
You'd likely want to put this code later in the request life cycle to guarantee an auth user because as others have mentioned middleware/session code has not occured during this part of the framework booting up. You could use a service class to call in all your controllers to avoid the copy pasting. Or If you'd like to achieve this using code in your service provider you could use a View Composer instead of a share this allows you to define a callback/or class that will be called right before the view is returned
view()->composer(['/uri-that-needs-data'], function ($view) {
if (Auth::check()) {
$cart = DB::query(...)->get();
$view->with('cartitems', $cart);
}
});
Check out https://laravel.com/docs/5.7/views#view-composers for more details.
Auth::user() will be empty until the session middleware has run.
The reason you can't access the user inside your service provider is because that code is run during the "bootstrapping" phase of the application lifecycle, when it's doing things like loading filesystem or cache drivers, long before the request is sent through response handlers (including middleware).
Once the application has been bootstrapped and all service providers
have been registered, the Request will be handed off to the router
for dispatching. The router will dispatch the request to a route or
controller, as well as run any route specific middleware.
Source: https://laravel.com/docs/5.7/lifecycle
If you don't want to copy/paste that code everywhere, then one place to put it is in custom route middleware. You can list it after the auth middleware to guarantee a logged-in user.
Edit: View composers are another really good option, as suggested by #surgiie. The reason these can be set up inside a service provider (unlike your example) is because the view composer registers a callback, but doesn't execute it until a much later stage in the application lifecycle.

General handling of AJAX call error on client side

We have a JSF 2.2 application using PrimeFaces.
Now, when an error occurs, I check for an AJAX request and deliver a partial response (as shown in BalusC's anwer to this question).
But what is, if there's no server anymore to handle the error, e.g. due to connection loss? At the moment, just nothing happens, leaving the user puzzled.
I found a hint in that question, which works, but I'd like to solve this in a general way, so that all AJAX calls which fail try to redirect to the start page - and then may receive the browser connection error message.
For standard JSF ajax, use jsf.ajax.addOnError() to set the default error handler. E.g.
jsf.ajax.addOnError(function(data) {
alert(data.responseText);
});
See also chapter 13.3.6.2 of the JSF 2.2 spec. You can find all properties of data object in table 14-4 of the JSF spec.
For PrimeFaces 4+, hook pfAjaxError event in jQuery (before 4, just use ajaxError). E.g.
$(document).on("pfAjaxError", function(event, xhr, options) {
alert(xhr.responseText);
});
Just customize it accordingly to show some div in top.

Grails Spring Security only responds with ajax/JSON on login fail

I'm using spring security in a grails app and when a login fails it always redirects to "login/authfail?ajax=true" and a json is rendered.
I even tried to redefine the 'ajaxAuthFailUrl' to be the same as 'defaultFailureUrl', but even though it redirects to '/login/authfail?login_error=1' I still getting the same json.
I dig the spring plugin to see why it 'thinks' it's an ajax request. Then on 'SpringSecurityService.java' I put some debug messages on 'isAjax' method. The result was, first of all, it calls 'isAjax' 2 times in a row. And the request is considered an ajax for different reasons:
there is a header 'ajaxHeader'
there is an ajax parameter on the request
and finally when it checks the SavedRequest's headers, it also finds it to be an ajax call.
I confess I'm lost, I don't have a clue about how to try to fix it...
I'm using:
Grails 2.3.8
spring-security-core:2.0-RC4
runtime ':spring-security-acl:2.0-RC1'
and I have a custom authentication handler that is set on BootStrap:
authenticationProcessingFilter.authenticationSuccessHandler = new MyUrlAuthenticationSuccessHandler()

After Wicket session timeout - pageParameters are null

I'm using wicket 6.
My application is based on WebPages created with pageParameters in the constructor. I'm using also a pageParameter country that is a path-parameter defined with:
mountPage("/${country}/pagepath", MyPage.class);
I have many statefull forms in every page.
I'm now trying to handle the case when the session expires (to reproduce this scenario I delete or modify the jsessionid cookie).
After that I click a submit button in a page and I'd expect wicket to understand that the session has expired.
But the behaviour that I have is this:
the current page is reloaded but the pageparameters are 'null'
the url is rewritten using the package notation like:
localhost:8080/wicket/bookmarkable/com.test.pages.MyPage
So it looks like the url mapping is somehow lost.
I need to reload the same page with pageParameters information or show an info page that says something like click here to reload.
I've already tried to use:
getApplicationSettings().setPageExpiredErrorPage(HomePage.class);
but that didn't help.
Any help is appreciated. Thanks.
Looks like there is a bug in Wicket 6 which causes this issue: https://issues.apache.org/jira/browse/WICKET-5068
It is fixed in Wicket 7. For Wicket 6, there is a workaround: disable WICKET-4594 fix.
First add the following mapper:
public class BookmarkableMapperThatSavesPageParametersForListener extends BookmarkableMapper {
#Override
protected PageParameters getPageParametersForListener(PageInfo pageInfo, PageParameters pageParameters) {
return pageParameters;
}
}
Then use it to replace a built-in BookmarkableMapper in your Application#init() (this has to be added before any manipulations with the root mapper):
mount(new BookmarkableMapperThatSavesPageParametersForListener());
This approach works in our application and it does not seem to break anything.
More info: Wicket 6: empty PageParameters when recreating a page after expiration
You could ask your question in the wicket mailing list. What you are observing might be a bug. Please check PageParameters missing from re-created Page
Conceptually, it should be possible to submit the form normally even if you need an authenticated user session.
If the session is expired then you may be able to re-create a user session with a remember-me cookie. Wicket should re-construct the page with parameters, apply the form values and process the submit. In case where the page is stateful, there could be some complications that are possibly resolvable. If you find that your use case is not supported with stateful pages then you could file an issue and meanwhile use StatelessForm.

Grails Ajax Login

I want to take use of the ajax login feature of the spring security plugin.
I am completely stuck getting a JSON success response from the loginController into my GWT client.
As I understood from the documentation I need to post my params to the url /j_spring_security_check and spring security is redirecting me to the right action.
If I look into my LoginController I see nothing of the actual login logic and its a bit magic for me where all the login/db stuff is done. Further spring security always redirects to action auth instead of using AjaxAuth even if I add the header "X-Requested-With" to post. If I do my post to the url /login/ajaxAuth I am getting a 401 which is OK because its written down in the controller(even if i dont know why we need to return a 401 here). Maybe I am doing something completely wrong :-)
My basic questions are:
Where can I find the login logic?
What parameter do I have to provide?
Which URL do I have to use?
What do I have to do if I dont want to use the username but instead and email field?
Thanks for all your help!
Looks like you're correctly implemented it, maybe there some small bug, like a typo.
Btw:
It's implemented at filter, that process your request before actual controllers. At your case it will be UsernamePasswordAuthenticationFilter (or RequestHolderAuthenticationFilter). Controller is used there only to render an additional data. As for ajax auth, it uses /login/ajaxSuccess, that renders a JSON response
By default it uses j_username & j_password. And you can use ajax=true parameter, instead of X-Request-With header
/j_spring_security_check by default
You can implement your own GrailsUserDetailsService (or extend GormUserDetailsService), and setup it as a spring bean, with name userDetailsService, at resources.xml
You can also turn on logging for Spring Security by:
log4j {
debug 'org.codehaus.groovy.grails.plugins.springsecurity',
'org.springframework.security'
}
maybe it will be helpful
I am using Grails 2.1.1 and ran into this same issue. Tried all the above things but still couldnt get my AJAX login to call the ajaxSuccess method.
However when it failed it was calling authFail?ajax=true.
After digging in more, here is what I did:
Added grails.plugins.springsecurity.successHandler.targetUrlParameter = 'ajaxUrl' in my Config.groovy
Added <input type="hidden" name="ajaxUrl" value="/login/ajaxSuccess" /> in my AJAX login form
Not sure why it fixed, but it seemed to work for me.
Just posting this solution for users who get stuck and come to this ticket for solution.

Resources