-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Fix 51888 cors errors are displayed for attachments #53407
base: main
Are you sure you want to change the base?
Fix 51888 cors errors are displayed for attachments #53407
Conversation
@hungvu193 should we ask for Design team's help for a better spinner now ? |
Not yet, please address the linting. After the codes look good then I will request a review from Design team. |
Here's the flow:
|
@hungvu193 we need Design to make the choice of the type of image (SVG, GIF, ...) and certainly provide us the image to use based on this video https://github.com/user-attachments/assets/ccd73db5-d00a-49cd-83b2-0b3fb7388577 and the GIF file. Their help will change the code (call to updateAspectRatio, sizing, style...). After all the changes made based on their advice, they review. Thats the work experience i have with them. But as you said we can also go this way #53407 (comment) |
@hungvu193 run lint was hanging on my pc. Now we are done with the lint errors, the remaining error is related to the legacy use of withOnyx not our changes. I guess that step should be skipped when deploying on staging. |
Ah no. Once you changed a file that includes |
@hungvu193 sorry but that's a whole different issue with its testing and debugging. been there done, done that. We can not take that extra load as we are not even close to be done here. I had the same experience from a previous ticket and the ticket created to make such replacement was a whole issue in itself as it was necessary to avoid regressions. Let's not go that road, i will advise. |
We don't create a separate ticket if the changes to the Onyx migration are small. For example, in my previous PR, I also migrated |
@hungvu193 i propose we reconsider that possibility once we are done with the main issue |
What's the main issue? The |
@hungvu193 dont forget that Image is a central component highly used in every screen of the code, so this "simple" change will require a lot of testing for possible regressions. Why not deal with issues one after the other ? |
@hungvu193 Many have made changes and PRs on this file before us and faced that Lint error/warning. This "simple" component could be at high risks of regressions. I will advise in this case to not do anything instead of breaking something |
src/CONST.ts
Outdated
@@ -1445,6 +1445,8 @@ const CONST = { | |||
UNKNOWN: 'unknown', | |||
}, | |||
}, | |||
// the number of hours for an idle session to expire | |||
SESSIONS_MAXIDLE_NB_HOURS: 2, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use milliseconds instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes good idea
src/components/Image/index.tsx
Outdated
} | ||
return previousSessionAge.current; | ||
} | ||
if (Math.abs(new Date().getTime() - session.creationDate) >= CONST.SESSIONS_MAXIDLE_NB_HOURS * 3600000) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we used milliseconds for CONST.SESSIONS_MAXIDLE_NB_HOURS
we can do this instead:
if (Math.abs(new Date().getTime() - session.creationDate) >= CONST.SESSIONS_MAXIDLE_NB_HOURS * 3600000) { | |
if (Math.abs(new Date().getTime() - session.creationDate) >= CONST.SESSIONS_MAXIDLE_NB_HOURS) { |
/** | ||
* trying to figure out if the current session is expired or fresh from a necessary reauthentication | ||
*/ | ||
const previousSessionAge = useRef<number | undefined>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a hook called usePrevious
, let use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok i'll check that
src/components/Image/index.tsx
Outdated
useEffect(() => { | ||
previousSessionAge.current = validSessionAge; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After using usePrevious
we can remove this block:
useEffect(() => { | |
previousSessionAge.current = validSessionAge; | |
}); |
src/components/Image/index.tsx
Outdated
[CONST.CHAT_ATTACHMENT_TOKEN_KEY]: authToken, | ||
}, | ||
}; | ||
if (!!session?.creationDate && new Date().getTime() - session.creationDate < CONST.SESSIONS_MAXIDLE_NB_HOURS * 3600000) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we create a function called isValidSessionCreationDate
to reuse this logic?
ie:
function isValidSessionCreationDate() {
return !!session?.creationDate && (new Date().getTime() - session.creationDate) > CONST.SESSIONS_MAXIDLE_NB_HOURS
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'll see how can isolate that logic in a function with a relevant name, good idea
src/components/Image/index.tsx
Outdated
if (Math.abs(previousSessionAge.current - session.creationDate) < 60000) { | ||
return session.creationDate; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why we have this condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we expect a reauthenticate to happen in less than 60s if the current session was expired. I have made the tests. so the new valid session will be newer than 60s after
} | ||
} | ||
return propsSource; | ||
// The session prop is not required, as it causes the image to reload whenever the session changes. For more information, please refer to issue #26034. | ||
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps | ||
}, [propsSource, isAuthTokenRequired]); | ||
}, [propsSource, isAuthTokenRequired, validSessionAge]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the comment right above to explain why we should add validSessionAge
in dependencies array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
@@ -72,6 +102,7 @@ function Image({source: propsSource, isAuthTokenRequired = false, session, onLoa | |||
{...forwardedProps} | |||
onLoad={handleLoad} | |||
style={[style, shouldSetAspectRatioInStyle && aspectRatio ? {aspectRatio, height: 'auto'} : {}, shouldOpacityBeZero && {opacity: 0}]} | |||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment to explain why we disable eslint here
We still need to do it anyway. PR can't be merged if all the tests aren't passed. That's mandatory. |
How did previous PRs end up in main then ? I really think we should avoid this as we can never do enough testing for regressions imho |
Changes from previous PRs were added when we didn't deprecate |
@hungvu193 lets change it after we are done with the main issue, if you insist on it. I can't put my focus on that right now as i must start testing for regressions right away once we change it. |
@hungvu193 i will upload the web test video as you can see the sizing of the image cause the attachments not to render properly (we cant just use any gif from the web). So the code will be adjusted once we have the definitive image from Design. I think we can have Design team's help based on the web test and the other envs are not necessary as they will be reviewed anyway once we have the definitive image demo_with_2H_expired_token.mp4 |
The fact that we display image based on its size. I'm thinking about the way we should keep image loading until it has valid session. Wdyt? |
So There's no image/gif placeholder needed. Instead we improve the loading conditions of image |
the problem is the final source of the image is not known yet at that step, it will be recalculated once we have a valid session, so we cannot anticipate the loading unless you're thinking of some other way for it |
@hungvu193 i did some updates based on your review but it didnt use the useprevious hook yet (i will test it some more). |
I think for now that's fine to keep image resize like that. Let's complete the author checklist and mark this PR as ready for review. I took a few tests, everything seems working fine. Let's finish the PR phrase so I'll request a review from Design team 😄 |
So I abandoned my tab for hours and when I'm back I got this issue. Screen.Recording.2024-12-05.at.15.40.06.mov |
As I checked the log, ReAuthenticate seems to never get called during that time, so session was invalid and the loading was showed forever |
yes we need to fix it in the caroussel also. I'll work on it. |
@hungvu193 we will be using a reauthenticator which will be a singleton object called when the spinner is returned as source for the image. The current session will be send as parameter. It will listen to network and session onyx keys so it wont do anything if offline and will deactivate once it receive a session from Onyx. Once activated (only once) it will expect a session from Onyx in the next 10s (preferred) or 15s and if it doesnt receive a new session it will ask for reauthentication (only once with no retry). Wdyt ? i'll implement it |
@hungvu193 but normally the notification pusher triggers reauthentifications (if necessary every 5 seconds) and we shouldnt need a reauthenticator triggers edit* |
I will do some testings about the caroussel display |
@hungvu193 i have implemented the reauthenticator (still i dont know what you think of the idea) https://github.com/Kalydosos/App/blob/fix-51888-cors-errors-are-displayed-for-attachments/src/libs/actions/Session/Reauthenticator.ts . I let the comments in the code to help you test it out. I set the session expiration time to 5mn for testing. You can then see how it works for the image in the chat reauthenticate_for_thread_images.mp4and then for the carousel reauthenticator_demo.mp4the point is now to make sure it is used when it is really necessary and maybe we could shorten the wait time to 7s or 8s |
Yes |
ok. So their tests will not be based on or copy my tests then, right ? |
#I'm not sure what you mean by |
they were supposed to follow our tests steps on every platform. If we use a trick that they cannot use, how can they validate the test steps for sure ? I really thnik we should ask |
Checkout |
@hungvu193 that's the tool i was talking about here #53407 (comment). The problem is 1. we curently do not setted creationDate for the function used by that tool and 2.even if we do, the troubleshooting panel covers the chat and the images could not be seen reloading (i tried that earlier). I will think of a way also. |
But we still can test the case when user press on that image right? |
No we will still need to interact with Onyx after clicking on the image (you are speaking of the carousel test right ?) A possible solution will be to set interval (a form of useEffect in the function of the test tool) that will give the time to go back in the chat or the carousel to observe the effect of expiring the session. But that will be a definitive change in the code not a temporary modification. Thus we need to know what was the usage and the intention by those who use the tool to make sure we are still consistent with the prior usage. |
but i still think we should do all these efforts when it worth it, meaning when we agree with the tests team that this will do as a solution |
Why not? I can still use it to record the video. Screen.Recording.2024-12-21.at.22.57.55.mov |
@hungvu193 videos of all platforms are up. I think we should deliver the version with modified testool now, right ? |
Yeah |
@@ -765,7 +777,7 @@ function invalidateCredentials() { | |||
|
|||
function invalidateAuthToken() { | |||
NetworkStore.setAuthToken('pizza'); | |||
Onyx.merge(ONYXKEYS.SESSION, {authToken: 'pizza'}); | |||
Onyx.merge(ONYXKEYS.SESSION, {authToken: 'pizza', encryptedAuthToken: 'pizza'}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's include the creationTime as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes i pushed the version now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a 50s lapse of time before the session is expired when clicked on the test tool. That will be enough for every tester to do the tests on native platforms comfortably. I think you should redo your tests videos with the current version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait, why don't you add creationTime
here? If so, if we use this tool, the session won't invalid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as i mentionned here #53407 (comment) the point of this tool is to invalidate the session token (thus the name of the function invalidateAuthToken) in the BE and see how interactions go. No putting any creationDate maintains the same experience with this tool before and after our changes, we are not impacting that tool
Reviewer Checklist
Screenshots/VideosAndroid: NativeAndroid: mWeb ChromeScreen.Recording.2024-12-23.at.11.21.29.moviOS: NativeScreen.Recording.2024-12-24.at.16.23.34.moviOS: mWeb SafariScreen.Recording.2024-12-23.at.10.58.30.movMacOS: Chrome / SafariScreen.Recording.2024-12-23.at.10.44.45.movMacOS: DesktopScreen.Recording.2024-12-23.at.10.45.05.mov |
NetworkStore.setAuthToken('pizza'); | ||
Onyx.merge(ONYXKEYS.SESSION, {authToken: 'pizza'}); | ||
// expires the session after 50s | ||
setTimeout(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why timeout here? I dont think we need it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes it's necessary, otherwise we barely can observe the reload of images in the tests (like in your own Android:mweb video btw). Not everybody is as quick in clicking as you are 😄 I mentionned it in the checklist tests steps and in some previous comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove timeout, I can still test without timeout, it doesn't make sense when you need to wait for 30s to invalid the session
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i cannot do the tests without setting the timeout and i'm sure many couldnt. You are doing test2 only in your android mweb video, you cannot do test3 if there is no timeout. Please include all 3 tests in your videos and you could see that timeout is necessary. We could maybe reduce the lapse time from 50s to 30s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. We don't need timeout, we have a shortcut to open TestTool menu (command + D on web and 4 finger gesture on native).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by Send expired session
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rlinoz we litteraly send an expired session to the FE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We create a new tool called Invalidate session delayed
not Send expired session
. Can you update please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hungvu193 "Invalidate session delayed" is a suggession by @rlinoz but "send expired session" is a more accurate title for what we do in fact. We dont really "invalidate" the session we expires it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hungvu193 should we ask for the translations ?
src/libs/actions/Session/index.ts
Outdated
setTimeout(() => { | ||
NetworkStore.setAuthToken('pizza'); | ||
Onyx.merge(ONYXKEYS.SESSION, {authToken: 'pizza', encryptedAuthToken: 'pizza', creationDate: new Date().getTime() - CONST.SESSION_EXPIRATION_TIME_MS}); | ||
}, 50000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setTimeout(() => { | |
NetworkStore.setAuthToken('pizza'); | |
Onyx.merge(ONYXKEYS.SESSION, {authToken: 'pizza', encryptedAuthToken: 'pizza', creationDate: new Date().getTime() - CONST.SESSION_EXPIRATION_TIME_MS}); | |
}, 50000); | |
NetworkStore.setAuthToken('pizza'); | |
Onyx.merge(ONYXKEYS.SESSION, {authToken: 'pizza', encryptedAuthToken: 'pizza', creationDate: 1}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you have suggested that we use the testool "invalidate session" to do the test of expiring the session on native platforms because we could not use the devtools console in those platforms to do so. The test in the devtools console is to set the session creation date to 2hours before. If we do otherwise it's inconsistent with our web test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the creationDate only need to be an invalid (expired) value, what's the matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it need to be a realistic test. In the real life situation that this PR is fixing the session expires when its creation time is more than 2h ago. Please let's do things the way it should reflect the real usage of the app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QA can access that test tool menu on "real life" app. No need to worry about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm speaking of what expiring a session means in real life usage of the app. It means its creation time is 2h ago. Any other value of that creation date is not a test of our PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is test tool, who cares about real life usage? A Testtool should do what it should. We need invalid session, that's all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no @hungvu193 we need to expire the session. We can invalidate just by only sending "pizza" as token but expiring the session has to do with the value of its creation date.
…ttps://github.com/Kalydosos/App into fix-51888-cors-errors-are-displayed-for-attachments
…d-for-attachments
…ttps://github.com/Kalydosos/App into fix-51888-cors-errors-are-displayed-for-attachments
…d-for-attachments
@hungvu193 it's all good now except the translations #53407 (comment) . I redo all the videos (for the nth time 😃 ), hope it's all setted ! |
Let's wait for confirmation from Internal Engineer in our ongoing discussion |
Explanation of Change
Fixed Issues
$ 51888
PROPOSAL: #51888 (comment)
Tests
Test 1 steps
Test 2 steps
Note : on native platforms, the troubleshooting test tool "Send expired session" can be used to send an expired session in the next 15 seconds when clicked.
Test 3 steps
Note : on native platforms, the troubleshooting test tool "Send expired session" can be used to send an expired session in the next 15 seconds when clicked.
Offline tests
QA Steps
Same as tests
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)src/languages/*
files and using the translation methodSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Design
label and/or tagged@Expensify/design
so the design team can review the changes.ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Android: Native
android_native.mp4
Android: mWeb Chrome
android_mweb.mp4
iOS: Native
ios_native.mp4
iOS: mWeb Safari
ios_mweb_safari.mp4
MacOS: Chrome / Safari
ios_web_safari.mp4
MacOS: Desktop
macos_desktop.mp4