Studio: Refactor AuthProvider into Redux slice#2778
Studio: Refactor AuthProvider into Redux slice#2778katinthehatsite wants to merge 6 commits intotrunkfrom
Conversation
| @@ -1,4 +1,4 @@ | |||
| import { createSlice, PayloadAction } from '@reduxjs/toolkit'; | |||
There was a problem hiding this comment.
This is not related directly to changes in this PR. This is something that my linter flagged that needed to be fixed and was present on trunk
fredrikekelund
left a comment
There was a problem hiding this comment.
Thanks for tackling this, @katinthehatsite.
The end goal with this refactor should be to remove AuthProvider altogether. That, and doing something about setWpcomClient from src/stores/wpcom-api are the two big changes needed here, IMO.
There was a problem hiding this comment.
We should remove this context provider altogether. Components can easily consume Redux state and dispatch actions. There's no point in keeping this provider as a thin wrapper around the Redux slice.
| export const selectIsAuthenticated = ( state: RootState ) => state.auth.isAuthenticated; | ||
| export const selectUser = ( state: RootState ) => state.auth.user ?? undefined; |
There was a problem hiding this comment.
| export const selectIsAuthenticated = ( state: RootState ) => state.auth.isAuthenticated; | |
| export const selectUser = ( state: RootState ) => state.auth.user ?? undefined; | |
| export const authThunks = { | |
| handleInvalidToken, | |
| initializeAuth, | |
| authTokenReceived, | |
| authLogout, | |
| }; | |
| export const authSelectors = { | |
| selectIsAuthenticated: ( state: RootState ) => state.auth.isAuthenticated, | |
| selectUser: ( state: RootState ) => state.auth.user ?? undefined, | |
| }; |
We've followed this pattern in some other Redux slices. I think it's helpful to namespace selectors, actions, and thunks this way.
| import { getIpcApi } from 'src/lib/get-ipc-api'; | ||
| import { isInvalidTokenError } from 'src/lib/is-invalid-oauth-token-error'; | ||
| import { store, RootState } from 'src/stores'; | ||
| import { getWpcomClient, setWpcomClient } from 'src/stores/wpcom-api'; |
There was a problem hiding this comment.
Now that the auth details live in the Redux state tree, I'd argue that src/stores/wpcom-api should either retrieve the client state prop from this slice or subscribe to state updates from it. We should remove the getWpcomClient and setWpcomClient from src/stores/wpcom-api
| onInvalidToken(); | ||
| await getIpcApi().showMessageBox( { | ||
| type: 'error', | ||
| message: 'Session Expired', | ||
| detail: 'Your session has expired. Please log in again.', | ||
| } ); |
There was a problem hiding this comment.
If the idea is to always dispatch handleInvalidToken here, then I think it's better to pass the store as an argument to this function and call store.dispatch( handleInvalidToken() ).
We could also consider moving the getIpcApi().showMessageBox() call to handleInvalidToken
| void dispatch( initializeAuth( { locale } ) ); | ||
| }, [ dispatch, locale ] ); | ||
|
|
||
| useIpcListener( 'auth-updated', ( _event, payload ) => { |
There was a problem hiding this comment.
This can be moved to apps/studio/src/stores/auth-slice.ts like so:
window.ipcListener.subscribe( 'auth-updated', ( _event, payload ) => {
if ( 'error' in payload ) {
let title: string = __( 'Authentication error' );
let message: string = __( 'Please try again.' );
if ( payload.error instanceof Error && payload.error.message.includes( 'access_denied' ) ) {
title = __( 'Authorization denied' );
message = __(
'It looks like you denied the authorization request. To proceed, please click "Approve"'
);
}
void getIpcApi().showErrorMessageBox( { title, message } );
return;
}
void store.dispatch( authTokenReceived( { token: payload.token, locale } ) );
} );| useEffect( () => { | ||
| void dispatch( initializeAuth( { locale } ) ); | ||
| }, [ dispatch, locale ] ); |
There was a problem hiding this comment.
This can be dispatched in apps/studio/src/stores/index.ts instead.
Related issues
Fixes https://linear.app/a8c/issue/STU-1379/studio-refactor-authprovider-into-redux-slice
How AI was used in this PR
I used it in the plan mode to plan the refactor, then gave feedback on the plan and used it for implementation, making further manual corrections.
Proposed Changes
This PR refactors
AuthProviderinto Redux slice.Testing Instructions
npm start~/Library/Application Support/Studio/appdata-v1.jsonauthTokenPre-merge Checklist