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

Themes: redirect logged-in-only routes to login page in logged-out sessions #30543

Merged
merged 3 commits into from
Feb 6, 2019

Conversation

jsnajdr
Copy link
Member

@jsnajdr jsnajdr commented Feb 1, 2019

For theme uploads, there can be only one route definition for both logged-in and logged-out sessions. When logged out, the redirectLoggedOut handler will kick in and will redirect to login page.

For other /themes routes, we redirect the logged-in-only ones (i.e., with :site_id suffix) to login page when hit in logged-out session.

Spinoff from #30537, fixes the issue with Themes deep links not correctly redirecting to login page described in p1HpG7-6eg-p2.

How to test:
Verify that all /themes routes are still correctly rendered, both in server- and client-rendered versions, both logged in and logged out. Verify that the logged-in-only (with /:site_id suffix) routes redirect to login when accessed in logged-out session.

@jsnajdr jsnajdr added [Feature Group] Appearance & Themes Features related to the appearance of sites. [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Feb 1, 2019
@jsnajdr jsnajdr self-assigned this Feb 1, 2019
@matticbot
Copy link
Contributor

@jsnajdr jsnajdr requested review from ockham, jessefriedman and a team February 1, 2019 14:59
@blowery
Copy link
Contributor

blowery commented Feb 1, 2019

@blowery
Copy link
Contributor

blowery commented Feb 1, 2019

/themes/upload gets me to the login screen, but the styles are a bit odd:

screen shot 2019-02-01 at 12 43 45 pm

…ssions

For theme uploads, there can be only one route definition for both logged-in and logged-out
sessions. When logged out, the `redirectLoggedOut` handler will kick in and will redirect to
login page.

For other `/themes` routes, we redirect the logged-in-only ones (i.e., with `:site_id` suffix)
to login page when hit in logged-out session.
@jsnajdr jsnajdr force-pushed the update/themes-logged-out-redirects branch from a3c158b to 7ebcd60 Compare February 5, 2019 08:46
@jsnajdr
Copy link
Member Author

jsnajdr commented Feb 5, 2019

/theme/modern-business/example.blog redirects to /theme/modern-business

That makes much more sense than showing a blank page, but I changed it anyway in 749b434. Previously, the siteSelection handler wouldn't find the example.blog site and would redirect to "all sites". Now there is the same redirectToLoginIfSiteRequested handler there as in /themes.

/themes/example.blog just shows a white screen, but didn't pop up the login dialog.

Oops, that's a bug in my patch. I implemented a flawed logic where the following series of routes was tried to match:

  • /themes/:tier(free|premium)? (legit logged out)
  • /themes/:vertical?/:tier(free|premium)? (legit logged out)
  • /themes/:tier(free|premium)?/:site_id (redirect to login if logged out)
  • /themes/:vertical?/:tier(free|premium)?/:site_id (redirect to login if logged out)

I expected /themes/example.blog to match the one with site_id, but it matched /themes/:vertical instead!

Fixed by having only one set of routes for both logged in and logged out:

  • /themes/:tier(free|premium)?/:site_id(site_id_pattern)?
  • /themes/:vertical?/:tier(free|premium)?/:site_id(site_id_pattern)?

There is always and optional :site_id suffix at the end and it must match a site_id_pattern, i.e., numeric ID or slug with dots.

If the optional site_id is detected and the session is logged out, we'll redirect to login.

Then /themes/example.blog matches the first route (with no vertical) and site_id is present. Because example.blog is a valid site ID.

But /themes/wedding doesn't contain a valid site ID, and wedding is correctly detected as vertical in the second route, correctly rendering wedding themes even in logged-out session.

@ockham can you please review this PR for more gotchas like this? Themes are complicated 😄

@jsnajdr jsnajdr force-pushed the update/themes-logged-out-redirects branch from d2ef315 to 6398811 Compare February 5, 2019 10:51
@jsnajdr
Copy link
Member Author

jsnajdr commented Feb 5, 2019

/themes/upload gets me to the login screen, but the styles are a bit odd:

🤦‍♂️ Another SSR bug, similar to #26944 (comment)

Server rendered a placeholder markup for /themes/upload, where the body has is-section-themes CSS class. The the client-side router redirects to login and the login page is the first thing ever rendered by React. React expects the SSR markup to be identical, but it seems something completely different and fails to update DOM attributes. The CSS class is still is-section-themes instead of is-section-login and the page styling is broken.

Fixed in 6398811 by forcing a full page reload after login redirect.


next();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit of a style nit, but I kind of prefer to make route information as explicit as possible in route defs (i.e. router() statements, in this case) -- rather than having a check if there really is a site_id param by this middleware.

How about:

  1. Renaming loggedOutRoutes to routesWithoutSiteFragments
  2. Renaming loggedInRoutes to routesWithSiteFragments, and removing the ? after the :site_id(${ siteId })
  3. In if ( isLoggedIn ) { /*...*/ }: Changing router( routesWithSiteFragments, /*...*/ ) to router( [ ...routesWithoutSiteFragments, ...routesWithSiteFragments ], /*...*/ )
  4. In the else branch: Add router( routesWithSiteFragments, redirectLoggedOut );

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ockham! This suggestion is very similar to my original implementation (visible here, I force-pushed over that commit since then), but there is one gotcha:

if ( loggedIn ) {
  router( [ ...routesWithoutSiteFragments, ...routesWithSiteFragments ] );
}

This doesn't work, because /themes/site.blog is matched by the /themes/:vertical? pattern rather than the /themes/:site_id one. Because of their order. Putting routesWithSiteFragments first should fix that. /themes/site.blog and /themes/1234 will match the more restrictive site_id pattern, while /themes/wedding will fall through to the one with vertical.

It's solvable, but I'd rather land this PR first, as it works correctly, and then improve in a followup PR. There are folks blocked by this bug and waiting for a fix. And there is a risk that the improvements won't be so straightforward and will require a few review/testing cycles to make them right.

Copy link
Contributor

@ockham ockham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works fine in my testing (I tried different permutations of logged-in/out, /themes with and without site fragments and/or filters, and /theme with and without site fragments).

I left one suggestion which I think would allow us to keep route defs a bit more declarative, but feel free to disregard.

@jsnajdr jsnajdr merged commit ea1c259 into master Feb 6, 2019
@matticbot matticbot removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Feb 6, 2019
@jsnajdr jsnajdr deleted the update/themes-logged-out-redirects branch February 6, 2019 09:58
jsnajdr added a commit that referenced this pull request Feb 9, 2019
Fixes regression introduced in #30543 where (because of a missing `return`) the
page.js handler chain is not terminated when a redirect to login happens.
I.e., `next` is called and the following handlers are executed.

That can lead to a "flash of silly content" before the redirect or even crash.
jsnajdr added a commit that referenced this pull request Feb 13, 2019
…30686)

Fixes regression introduced in #30543 where (because of a missing `return`) the
page.js handler chain is not terminated when a redirect to login happens.
I.e., `next` is called and the following handlers are executed.

That can lead to a "flash of silly content" before the redirect or even crash.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature Group] Appearance & Themes Features related to the appearance of sites.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants