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

Add Panoptes auth to app-root #5459

Merged
merged 10 commits into from
Oct 28, 2023
Merged

Add Panoptes auth to app-root #5459

merged 10 commits into from
Oct 28, 2023

Conversation

eatyourgreens
Copy link
Contributor

@eatyourgreens eatyourgreens commented Oct 12, 2023

  • configure ESLint.
  • add the Panoptes auth client, from panoptes-client.
  • add the useSWR hook, from 'swr'.
  • add usePanoptesUser for SWR-style user fetching.
  • add an express server to handle HTTPS in local development.
  • add a page context component to provide global styling, the Grommet theme, and Panoptes auth context.
  • add the panoptes user to both page header and footer.
  • fetch your unread message count (useUnreadMessages) and unread notifications count (useUnreadNotifications), once you've signed in.
  • add an admin toggle to the page footer, and an admin border to the page body.

Please request review from @zooniverse/frontend team or an individual member of that team.

Package

  • app-root

How to Review

Either yarn dev or yarn start should run a local HTTPS server on https://local.zooniverse.org:3000.

If you have a Panoptes session cookie for local.zooniverse.org:3000, you should be logged in when the page loads, and see your username top right.

Screenshot of the app home page, with a logged-in user top right.

There's no sign-in form yet. If you aren't logged in, you'll need to log in to local.zooniverse.org:3000 in another tab (eg. with the content pages app), in order to set the session cookie.

Admin mode should toggle the top-level admin menu and page border, and persist across page loads.

Once you are logged in, the user object is persisted in local storage for faster sign-in across tabs.

Screen.Recording.2023-10-14.at.12.00.53.mov

Checklist

PR Creator - Please cater the checklist to fit the review needed for your code changes.
PR Reviewer - Use the checklist during your review. Each point should be checkmarked or discussed before PR approval.

General

  • Tests are passing locally and on Github
  • Documentation is up to date and changelog has been updated if appropriate
  • You can yarn panic && yarn bootstrap or docker-compose up --build and FEM works as expected
  • FEM works in all major desktop browsers: Firefox, Chrome, Edge, Safari (Use Browserstack account as needed)
  • FEM works in a mobile browser

General UX

Example Staging Project: i-fancy-cats

  • All pages of a FEM project load: Home Page, Classify Page, and About Pages
  • Can submit a classification
  • Can sign-in and sign-out
  • The component is accessible

New Feature

  • The PR creator has listed user actions to use when testing the new feature
  • Unit tests are included for the new feature
  • A storybook story has been created or updated
    • Example of SlideTutorial component with docgen comments, and its story

@coveralls
Copy link

coveralls commented Oct 12, 2023

Coverage Status

coverage: 82.227%. remained the same when pulling b90779c on root-auth into 8a48d12 on master.

@eatyourgreens eatyourgreens force-pushed the root-auth branch 6 times, most recently from 00d42df to b8f46f0 Compare October 13, 2023 14:21
@eatyourgreens
Copy link
Contributor Author

@mcbouslog might be a good person to review the code for notifications and messages. I copied it more-or-less straight from the project app.

@eatyourgreens eatyourgreens force-pushed the root-auth branch 2 times, most recently from aeee0f3 to c37ea0b Compare October 13, 2023 16:45
@eatyourgreens
Copy link
Contributor Author

I think this is ready for review now.

@eatyourgreens eatyourgreens force-pushed the root-auth branch 3 times, most recently from 6bd43bf to feb3d61 Compare October 13, 2023 20:36
@eatyourgreens
Copy link
Contributor Author

Here's a short recording when I have notifications.

Screen.Recording.2023-10-18.at.09.38.28.mov

@eatyourgreens eatyourgreens force-pushed the root-auth branch 2 times, most recently from fad9dbe to 60748c2 Compare October 18, 2023 09:29
@goplayoutside3 goplayoutside3 self-assigned this Oct 18, 2023
Copy link
Contributor

@goplayoutside3 goplayoutside3 left a comment

Choose a reason for hiding this comment

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

I think this is looking good! I'm able to load https://local.zooniverse.org:3000 and see my username signed-in in the ZooHeader. I added a note to the app-root project board to revisit unit tests for notifications, too.

I have a couple of "big picture" question for understanding:

  1. This setup uses useContext rather than mobx like the older apps in FEM. All app-root components that have useContext will re-render anytime PanoptesAuthContext changes (anything in adminMode, user, etc). I don't think that's a bad thing, but is this the same or different re-rendering behavior than using mobx?

  2. The user fetching functions usePanoptesUser and fetchPanoptesUser look quite a bit different than the same-name functions in app-project. Is the decision to not use swr directly in the hooks a more robust solution than how it's implemented in app-project?

packages/app-root/next.config.mjs Outdated Show resolved Hide resolved
@@ -0,0 +1,53 @@
if (process.env.NEWRELIC_LICENSE_KEY) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Because this express server is only used for local development, do we need new relic? Just want to think through this server while we have the chance and consider the build bug from app-content-pages too: #5428

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The express server runs on yarn start too, but we need to test that on Kubernetes.

Your comment reminds me that the live content pages app isn't logging to New Relic either.

Copy link
Contributor

@goplayoutside3 goplayoutside3 Oct 23, 2023

Choose a reason for hiding this comment

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

Right! I think that's what I'm getting at. The content pages app will probably never use a custom express server in deployment again, so New Relic should not be setup for app-root either. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How do we debug slow pages and Postgres queries without New Relic?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I mean, content pages should be using New Relic in production too. It should be imported when the Next app loads and starts, at the top of next.config.js.

Copy link
Contributor

Choose a reason for hiding this comment

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

Does the debugging via New Relic happen via logging from a production deploy, a local build, or both?

Copy link
Contributor

@goplayoutside3 goplayoutside3 Oct 23, 2023

Choose a reason for hiding this comment

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

🤔 app-project does have New Relic imported into next.config.js but app-content-pages does not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any environment that has NEWRELIC_LICENSE_KEY set, according to the code. That’s production and staging deploys.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like they only have examples for the pages router.
https://github.com/newrelic-experimental/newrelic-nextjs-integration

Copy link
Contributor

Choose a reason for hiding this comment

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

In addition to lack of New Relic + App Router documentation, I strongly suggest that New Relic isn't included in app-root (for now). We don't really know what deployment of this app will look like yet, and I'd prefer to setup logging tools that are used in staging + production envs when we get to that step. I've added it as a to-do in the project board.

Otherwise everything here is looking good!


const hostnames = {
development: 'local.zooniverse.org',
branch: 'fe-project-branch.preview.zooniverse.org',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
branch: 'fe-project-branch.preview.zooniverse.org',

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change will crash when APP_ENV is set to 'branch' but I'm not sure if that's a big deal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is branch included here in anticipation of doing a branch deploy with app-root?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it’s just in all the server setups by default. The content pages app defines it too.

branch: 'fe-project-branch.preview.zooniverse.org',

Comment on lines +15 to +27
/*
Null users crash the ZooHeader component.
Set them to undefined for now.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion to create a Github Issue for this so we can bug-fix in ZooHeader.

Copy link
Contributor Author

@eatyourgreens eatyourgreens Oct 22, 2023

Choose a reason for hiding this comment

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

I’m not sure that it’s a bug in the header. The header has a default set for user. However, default values are applied to undefined props in React, not null props, and undefined isn’t an allowed value in JSON.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the default here should be null, not an empty object. Probably depends on what we expect user to be when no one is logged in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With Server Components, it might even be better to pass a promise that resolves to a user.

https://react.dev/reference/react/use#streaming-data-from-server-to-client

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah okay, I understand the need to set to undefined now - thanks!

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Oct 20, 2023

A couple of quick answers:

  1. The global store object in the project app (and the classifier) is also injected into components with useContext.

  2. You might find it useful, for your own understanding, to take a look at the usePanoptesUser hook in the classifier too. Off the top of my head, I don't know how it's been implemented in the project app, but I'll take a look when I'm back next week.

@eatyourgreens eatyourgreens force-pushed the root-auth branch 2 times, most recently from 76f8e6c to 3bf2629 Compare October 23, 2023 13:22
@eatyourgreens
Copy link
Contributor Author

I've rewritten usePanoptesuser to use the SWR hook for data fetching, and a couple of effect hooks for local data storage and subscribing to auth change events.

Note that useSWR will always return the same, stale user object until this issue is fixed: zooniverse/panoptes-javascript-client#207

@goplayoutside3
Copy link
Contributor

I initially said let's remove New Relic here, but following #5522, do you think New Relic should be required in next.config.js instead?

In this PR I want to be clear about why New Relic is in server.js.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Oct 26, 2023

New Relic should be loaded in before the app starts running, so at the top of server.js for a custom server or at the top of next.config.js otherwise.

If you look at the project app, you should see that newrelic is loaded at the top of both files.

Looking at the original PR (#926), there's a config file that needs to be added too.

@eatyourgreens
Copy link
Contributor Author

#1812 has some useful context for why we use custom servers, including links to the original issues.

@goplayoutside3
Copy link
Contributor

#1812 has some useful context for why we use custom servers, including links to the original issues.

This is super helpful thank you!

@eatyourgreens
Copy link
Contributor Author

I also looked up the latest advice for using New Relic with Next, and it looks like it has changed since we originally set everything up. There's now @newrelic/next middleware that can be run at startup with NODE_OPTIONS.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Oct 26, 2023

You're right, though, that this won't be needed until we're running the new user pages on Kubernetes. It will be useful, then, to trace how long page builds take and to tune our JS code on the server.

Copy link
Contributor

@goplayoutside3 goplayoutside3 left a comment

Choose a reason for hiding this comment

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

I think this PR is fine to merge, but wanted to check-in if any discussion on New Relic needs resolving? It looks like if merged as is, New Relic is setup in server.js but not used until this app is deployed. At deploy, we'll need to revisit New Relic config if, for example, server.js can't be used in a deployed version due to issues recently seen in app-content-pages.

@github-actions github-actions bot added the approved This PR is approved for merging label Oct 27, 2023
@eatyourgreens
Copy link
Contributor Author

None of our Next.js apps are using @newrelic/next so I'll follow up next week with a PR to redo New Relic across the whole monorepo.

@eatyourgreens eatyourgreens enabled auto-merge (squash) October 28, 2023 06:03
- add the Panoptes auth client, from `panoptes-client`.
- add `usePanoptesUser` for SWR-style user fetching.
- add an express server to handle HTTPS in local development.
- add the panoptes user to both page header and footer.
- add `swr`.
- `useUnreadMessages` fetches your unread message count with `useSWR`.
- `useUnreadNotifications` fetchs your unread notifications count with `useSWR`.
- persist the current user in local storage.
- check admin mode with `useAdminMode`.
- add the admin mode toggle to the footer, and the admin mode border to the page.
Add `PageContextProvider`, responsible for:
- global page styles.
- providing the Zooniverse Grommet theme.
- providing Panoptes auth context (user and admin mode.)
- move `fetchPanoptesUser` into a helper.
- add explanatory comments.
- restore the missing `avatar_src` when getting the user object from a JWT.
- use `useSWR` to fetch the user object from Panoptes.
- persist the returned data in local storage.
- reset the current Panoptes session when auth changes.
@eatyourgreens eatyourgreens merged commit 5a9a09f into master Oct 28, 2023
7 checks passed
@eatyourgreens eatyourgreens deleted the root-auth branch October 28, 2023 06:10
Copy link
Contributor

@goplayoutside3 goplayoutside3 left a comment

Choose a reason for hiding this comment

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

This was somehow missed in review, but this commit "Add named page headers" added header elements to /about/page.js and /projects/page.js without a parent element. These two pages now throw an error during the app-root build process locally.

@goplayoutside3
Copy link
Contributor

These two pages now throw an error during the app-root build process locally.

Fixed in #5551

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved This PR is approved for merging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants