Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router throws exception when navigating between PermitAll and AnonymousAllowed views #20939

Open
abdullahtellioglu opened this issue Feb 3, 2025 · 13 comments · May be fixed by #20990
Open

Router throws exception when navigating between PermitAll and AnonymousAllowed views #20939

abdullahtellioglu opened this issue Feb 3, 2025 · 13 comments · May be fixed by #20990

Comments

@abdullahtellioglu
Copy link
Collaborator

Description of the bug

I have two views one is anonymous allowed, the other one requires login. When I try to navigate from anonymous to another one, a console errors are logged

Screen.Recording.2025-02-03.at.14.32.58.mov

.

Expected behavior

There should not be any console errors.

Minimal reproducible example

Create two views as below. Activate Copilot and click the links in Views & Routes panel

LoggedInOnly.java

@Route(value = "loggedin")
@PermitAll
public class LoggedInOnly extends VerticalLayout {

    public LoggedInOnly(AuthenticatedUser authenticatedUser) {
    }
}

LoginView.java

@AnonymousAllowed
@PageTitle("Login")
@Route(value = "login")
public class LoginView extends LoginOverlay implements BeforeEnterObserver {

    private final AuthenticatedUser authenticatedUser;

    public LoginView(AuthenticatedUser authenticatedUser) {
        this.authenticatedUser = authenticatedUser;
        setAction(RouteUtil.getRoutePath(VaadinService.getCurrent().getContext(), getClass()));
    }

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        if (authenticatedUser.get().isPresent()) {
            // Already logged in
            setOpened(false);
            event.forwardTo("");
        }

        setError(event.getLocation().getQueryParameters().getParameters().containsKey("error"));
    }
}

Versions

Hilla: 24.7.0.alpha9
Flow: 24.7.0.alpha9
Vaadin: 24.7.0.alpha6
Spring Boot: 3.4.2
Spring: 6.2.2
Spring Security: Enabled
Copilot: 24.7-SNAPSHOT
Frontend Hotswap: Enabled, using Vite
OS: aarch64 Mac OS X 14.7.1
Java: JetBrains s.r.o. 21.0.5
Browser: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Java Hotswap: Java Hotswap is enabled
IDE Plugin: 1.4.6 IntelliJ

@abdullahtellioglu abdullahtellioglu changed the title Router throws exception when navigating Router throws exception when navigating between PermitAll and AnonymousAllowed views Feb 3, 2025
@Artur-
Copy link
Member

Artur- commented Feb 3, 2025

Looks like a Flow issue

@caalador
Copy link
Contributor

caalador commented Feb 4, 2025

@Artur- What does copilot do/call when the route in the Views & Routes panel is clicked?

@Artur-
Copy link
Member

Artur- commented Feb 4, 2025

It should be a standard link, nothing special

@mshabarov mshabarov moved this from 🪵Product backlog to 🟢Ready to Go in Vaadin Flow ongoing work (Vaadin 10+) Feb 5, 2025
@mcollovati
Copy link
Collaborator

If I add a public view with a standard like (router-ignore) or a RouterLink, the browser is redirected to the login view and I don't get any error on the browser console.

However, when clicking the link on the Copilot panel, I can see several navigation requests from the client.
The first one is for the protected view (route="" in my example) and the int the server response there's a vaadin-navigate to login event fire instruction.
But the client instead immediately sends a navigation to the blank route, and the server again requests for a navigation to login.
This time, the client tries to navigate to login, but after getting the server response, it again sends a navigation request to blank path, and when processing the response the client-side error happens.

Image

@mcollovati
Copy link
Collaborator

@Artur- did I get it right that the link on the Copilot panel is not a "normal" link, but it emits an event on the event bus that is handled with window.history.pushState and window.dispatchEvent(new PopStateEvent('popstate'));?

@Artur-
Copy link
Member

Artur- commented Feb 10, 2025

It certainly seems so. I wonder why

@mcollovati
Copy link
Collaborator

I did a test replacing the code in the event bus navigate handler to fire a vaadin-router-go event and with this change the navigation from the side panel seems to work correctly.
However, I don't know if this can be considered a proper fix.
If you agree, I'd transfer the issue to the Copilot repository.

@Artur-
Copy link
Member

Artur- commented Feb 11, 2025

Yes, the Copilot code as it is currently looks like some workaround for earlier React router integration issues in Flow. I don't know if

  window.history.pushState(state, '', data.detail.path);
  window.dispatchEvent(new PopStateEvent('popstate'));

is supposed to be a valid way to navigate, but it should not be needed for Copilot either

@Artur-
Copy link
Member

Artur- commented Feb 11, 2025

Dispatching a vaadin-router-go event seems quite.. internal and does not work in a Hilla app, it seems

@mshabarov mshabarov moved this from 🟢Ready to Go to 📥Inbox - needs triage in Vaadin Flow ongoing work (Vaadin 10+) Feb 12, 2025
@mshabarov mshabarov moved this from 📥Inbox - needs triage to 🪵Product backlog in Vaadin Flow ongoing work (Vaadin 10+) Feb 12, 2025
@mcollovati
Copy link
Collaborator

A normal anchor should work, but it looks like that currently the listener that intercept clicks on anchors is registered only when Flow is initialized.
So, for a Hilla/Hybrid app, it will not be initialized until you navigate to a Flow view.
I wonder if the listener can be registered somehow in index.tsx / index.ts and work with both React and Vaadin routers

@Artur-
Copy link
Member

Artur- commented Feb 12, 2025

Would https://github.com/vaadin/flow/blob/main/flow-server/src/main/resources/com/vaadin/flow/server/frontend/vaadin-react.tsx be the correct place?

@mcollovati
Copy link
Collaborator

mcollovati commented Feb 12, 2025

Is Vaadin router affected by the same issue?

EDIT: Looks like vaadin-router registers the listener in the constructor (https://github.com/vaadin/router/blob/main/src/router.ts#L157), so it probably works out-of-the-box (to be tested).

https://github.com/vaadin/router/blob/main/src/triggers/click.ts

@Artur-
Copy link
Member

Artur- commented Feb 12, 2025

From Copilot point of view it is irrelevant as Vaadin router is not supported

mcollovati added a commit that referenced this issue Feb 12, 2025
When using React router, clicks on anchors are intercepted only if Flow client
has been initialized. In Hilla or hybrid application, if a Flow view is never
navigated, clicking on such links cause the browser to reload the page instead
of navigating to the expected view.
This change registers a global click handler that intercepts click events and
triggers a router navigation if necessary.
The new behavior is aligned with vaadin-router.

Fixes #20939
@mcollovati mcollovati linked a pull request Feb 12, 2025 that will close this issue
mcollovati added a commit that referenced this issue Feb 13, 2025
When using React router, clicks on anchors are intercepted only if Flow client
has been initialized. In Hilla or hybrid application, if a Flow view is never
navigated, clicking on such links cause the browser to reload the page instead
of navigating to the expected view.
This change registers a global click handler that intercepts click events and
triggers a router navigation if necessary.
The new behavior is aligned with vaadin-router.

Fixes #20939
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🔖 Normal Priority (P2)
Status: 🪵Product backlog
Development

Successfully merging a pull request may close this issue.

5 participants