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

Refactor ValidateLogin #11457

Merged
merged 11 commits into from
Oct 10, 2022
Merged

Refactor ValidateLogin #11457

merged 11 commits into from
Oct 10, 2022

Conversation

marcochavezf
Copy link
Contributor

@marcochavezf marcochavezf commented Sep 29, 2022

cc @Beamanator since you noticed the original refactor was reverted 😄

Details

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/218822

Tests

(steps taken from #10026)

Four use cases can occur with this flow:

  1. A user is already logged into NewDot, and the secondary login is NOT validated
  2. A user is already logged into NewDot, and their secondary login is already validated and/or the link is invalid
  3. A user is NOT logged into NewDot, and their secondary login is NOT validated
  4. A user is NOT logged into NewDot, and their secondary login is already validated and/or the link is invalid

Resulting Conditions

  • In the first two cases, the user is simply redirected to their last open report/conversation home with no error message displayed. Additionally, in Case 1, the account is silently validated behind the scenes.

  • In the latter two cases, the user is redirected to the login page. In Case 4, an error message would displayed below the password field stating: "This set password link is invalid or has expired...", while in Case 3, the user would encounter a password prompt.

To test the cases described above:

  1. Log into OldDot and add a Secondary Login from Account Settings e.g. [email protected]
  2. Open the sent email Verify secondary email for Expensify and copy the link address of click on this link to validate your login (we just want the last part of the URL, i.e. /v/16/WSSWMNNMH)
  3. Log into NewDot, or not, depending on the test cases above.
  4. Formulate the URL (by using the path obtained from step 2) to emulate clicking a verification link (see video here as example):
  • http://localhost:8080/v/<accountID>/<validationCode> on local dev
  • http://staging.new.expensify.com/v/<accountID>/<validationCode> on staging
  • http://staging.new.expensify.com/v/<accountID>/<validationCode> on production
  1. Verify that the resulting conditions described hold true for all 4 cases

Additionally, test the steps for this regression that reverted the original PR.

  1. Create a workspace if you don't have one
  2. Navigate to the workspace > Reimburse expenses > Connect bank account
  3. Complete at least steps 1 and 2 for Connect bank account
  4. Close the Connect bank account modal and open it again (it should show the page with the title Almost done!)
  5. Click the back button, and verify that you're taken back to the Workspace Initial Settings page:
Screen.Recording.2022-10-04.at.17.36.31.mov
  • Verify that no errors appear in the JS console

PR Review Checklist

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • Any functional components have the displayName property
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

PR Reviewer Checklist

The reviewer will copy/paste it into a new comment and complete it after the author checklist is completed

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • Any functional components have the displayName property
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

QA Steps

Follow same steps from Test section.

  • Verify that no errors appear in the JS console

Screenshots

Web

User is logged into NewDot:

Screen.Recording.2022-10-04.at.17.15.05.mov

User is NOT logged into NewDot, and their secondary login is NOT validated:

Screen.Recording.2022-10-04.at.17.20.19.mov

User is NOT logged into NewDot, and their secondary login is already validated and/or the link is invalid:

Screen.Recording.2022-10-04.at.17.21.16.mov

Mobile Web - Chrome

Screen Shot 2022-10-04 at 17 31 59

Mobile Web - Safari

Screen Shot 2022-10-04 at 17 35 07

Desktop

Not applicable, validation link opens browser

iOS

Not applicable, validation link opens browser

Android

Not applicable, validation link opens browser

@marcochavezf marcochavezf self-assigned this Sep 29, 2022
@marcochavezf marcochavezf changed the title [WIP] Refactor ValidateLogin Refactor ValidateLogin Oct 4, 2022
@marcochavezf marcochavezf marked this pull request as ready for review October 4, 2022 22:46
@marcochavezf marcochavezf requested a review from a team as a code owner October 4, 2022 22:46
@melvin-bot melvin-bot bot requested review from dangrous and removed request for a team October 4, 2022 22:46
@marcochavezf marcochavezf requested a review from a team October 4, 2022 22:47
@melvin-bot melvin-bot bot removed the request for review from a team October 4, 2022 22:48
@marcochavezf marcochavezf requested a review from a team October 4, 2022 22:48
@melvin-bot melvin-bot bot removed the request for review from a team October 4, 2022 22:49
@dangrous
Copy link
Contributor

dangrous commented Oct 5, 2022

Hey! So the code looks great, and I got both this flow and the bank account thing to work great on desktop/web and android/chrome. However, scenario 1 wasn't working for me on ios/safari - it would just be a blank screen. I was having some other ios issues so it might just be me, but it might be good to get someone else to quickly test - maybe @Beamanator since you're cced already? Sorry! I can approve and do the checklist and everything if that's working for you.

@Beamanator Beamanator self-requested a review October 5, 2022 12:57
Copy link
Contributor

@Beamanator Beamanator left a comment

Choose a reason for hiding this comment

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

Hmm so for the first case, what I think I'm supposed to test is:

  1. Log in to NewDot & OldDot with the same account
  2. In OldDot, add a secondary login (like [email protected])
  3. Use script/clitools.sh generator:validateLink to create a validation URL, take just the validation code
  4. Open http://localhost:8080/v/<accountID>/<validationCode> and see that the page now shows the last report you were on (this works)
  5. Go back to OldDot, you should see that the secondary login is now validated

I'm not seeing step 5 happen - is that a problem? I don't see that the secondary login is now validated 🤔 Even after rebuilding Auth & retesting I still don't see this happening, am I doing something wrong or am I reading the test steps incorrectly?

@dangrous
Copy link
Contributor

dangrous commented Oct 5, 2022

Oops @Beamanator I hadn't checked that part either - I'm also not seeing the validation go through on OldDot. It seems like that's unrelated to this code, but good to confirm (I wonder if using clitools it's validating as a separate account, rather than a secondary login?)

@marcochavezf
Copy link
Contributor Author

Oh good catch related to the script/clitools.sh generator:validateLink. For the local testing, I did it with the email links (as shown in the video), and I just left the same instructions from the other PR thinking that the behavior will be the same, but seems there's a different result when we use script/clitools.sh generator:validateLink 🤔

Could you test with the link code sent to your email? I'm going to update the instructions to do it in that way since QA will be able to only test it with the email link.

@marcochavezf
Copy link
Contributor Author

marcochavezf commented Oct 5, 2022

Yup, it works only by copying the validation code from the validation link from the email. I recorded a test with iOS/Safari validating a secondary login (the tricky part was "copy-pasta" of the validation code because I couldn't paste it into the iOS simulator 😄).

Screen.Recording.2022-10-05.at.15.56.35.mov

@Beamanator
Copy link
Contributor

Noice noice I'll try it with emailed links (not sure why that would be different though, maybe there's some weird bug in the generator script?)

Also there's conflicts 😅 sorry

@Beamanator
Copy link
Contributor

Ugg still not working for me with email links 🙃 Can you try, @dangrous ? I wonder if I'm holding something wrong, like in PHP or Auth? Very confused :(

@dangrous
Copy link
Contributor

dangrous commented Oct 6, 2022

All 4 tests cases DO work for me (at least on desktop) when I actually have the emails sent (expected behavior on the NewDot side, and the email addresses are marked as verified on OldDot.

I'm going to try mobile web ios/android again and if that works I'll go ahead and checklist/merge [EDIT: once conflicts are resolved]. If not, we should discuss how to move ahead if we can't fully test...

@dangrous
Copy link
Contributor

dangrous commented Oct 6, 2022

Okay, confirmed! This works on all web platforms!

@marcochavezf
Copy link
Contributor Author

All 4 tests cases DO work for me (at least on desktop) when I actually have the emails sent (expected behavior on the NewDot side, and the email addresses are marked as verified on OldDot.

I'm going to try mobile web ios/android again and if that works I'll go ahead and checklist/merge [EDIT: once conflicts are resolved]. If not, we should discuss how to move ahead if we can't fully test...

Hey @dangrous! Thanks for testing, before you test on mobile again, I noticed the change that introduced the conflict changed the flow slightly. Since currentlyViewedReportID was removed here, now we're going to navigate to the home instead of the previous report when the user is logged in.

And since we can't add secondary logins in NewDot atm (afaik that's part of the Account Settings project, @Beamanator correct me if I'm wrong), I think it's OK to navigate always to home instead of the previous report for this refactor cc @marcaaron @tgolen

I'm going to update the test steps and test again on mobile in a bit.

@marcochavezf
Copy link
Contributor Author

Updated video for web desktop, also tested on mobile web (Chrome and Safari) and worked fine 👍🏽

Screen.Recording.2022-10-06.at.13.45.43.mov

@marcochavezf marcochavezf dismissed Beamanator’s stale review October 6, 2022 18:55

updated testing steps

@dangrous
Copy link
Contributor

dangrous commented Oct 6, 2022

Yeah I think that nav update makes sense, the existing path was kind of annoying in my case because the last opened report was a chat with a user i deleted so it would just never load haha. Not an issue for someone who would be using the app frequently, but home seems like the best destination. Will test through now!

@dangrous
Copy link
Contributor

dangrous commented Oct 6, 2022

Okay tested again and everything works as expected on ios safari, android chrome, and desktop chrome.

HOWEVER I happened to try being logged into a different account on NewDot, and the same flow happens. Meaning - if I'm logged into an account that isn't the account being validated, I will just be auto returned to where I was in the app AND the secondary login for the other account will still be validated in OldDot. This seems... bad, right? I don't think it's related to this particular PR, so I think we can still merge this, but we should probably make a separate issue. Thoughts?

@Beamanator
Copy link
Contributor

Beamanator commented Oct 7, 2022

Ugg I'm glad it's working for both of y'all, maybe there's something wrong with my env 🙃

HOWEVER I happened to try being logged into a different account on NewDot, and the same flow happens. Meaning - if I'm logged into an account that isn't the account being validated, I will just be auto returned to where I was in the app AND the secondary login for the other account will still be validated in OldDot. This seems... bad, right?

Ooh thanks for testing this @dangrous ! I thinkkk yes that's bad... I'm not exactly sure how this could be used maliciously but still it doesn't seem good.

I don't think it's related to this particular PR, so I think we can still merge this, but we should probably make a separate issue. Thoughts?

Hmm true it's not related to this PR, buttt it's probably related to the Web-E version of this PR (the one where ValidateLogin was added in the backend) so I would vote we hold this on fixing that in Web-E - since this PR isn't "critical" (it's not "fixing" anything, I think) - it's just refactoring stuff, and possibly helping introduce the bug you caught

Note: If that bug already exists on production we can probably go ahead and merge this one, but I am guessing it doesn't? Wanna try?

@dangrous
Copy link
Contributor

dangrous commented Oct 7, 2022

It actually does exist on production - just tried it.

I mean, I can't really think of a way that it could be used for evil? But seems insecure nonetheless. Like I guess if you typed in the wrong email and someone else happened to verify it then they would have access to your account, but I think it could only be an accident not intentional.

@marcochavezf
Copy link
Contributor Author

Yeah I think this scenario can only happens if the malicious person has access to the validation email, but in that case I think we can do nothing because by design the account can be validated with or without the authtoken (whether a user is logged in or not in NewDot).

@dangrous
Copy link
Contributor

dangrous commented Oct 7, 2022

I'm gonna go ahead and checklist, and @Beamanator you can have the final word! I think we can go ahead and merge this since the (potential) flaw exists on production anyway.

PR Reviewer Checklist

The reviewer will copy/paste it into a new comment and complete it after the author checklist is completed

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • Any functional components have the displayName property
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

@JmillsExpensify
Copy link

@Beamanator it'd be awesome to make sure you put this PR on your list for Monday! We technically already closed our this refactor, so I like to re-close it out and focus on the few remaining APIs as soon as we can. 😄

Copy link
Contributor

@Beamanator Beamanator left a comment

Choose a reason for hiding this comment

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

Thanks for testing in production @dangrous and I agree with y'all's assessment that this weird flow reeeeally can't be taken advantage of. Code looks good so let's :shipit: !

@Beamanator Beamanator merged commit d5c61fe into main Oct 10, 2022
@Beamanator Beamanator deleted the marco-validateLoginRefactor branch October 10, 2022 08:38
@melvin-bot melvin-bot bot added the Emergency label Oct 10, 2022
@melvin-bot
Copy link

melvin-bot bot commented Oct 10, 2022

@Beamanator looks like this was merged without passing tests. Please add a note explaining why this was done and remove the Emergency label if this is not an emergency.

@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@Beamanator
Copy link
Contributor

Tests were passing Melvin 🙃

@dangrous
Copy link
Contributor

Do we want to still create an issue to require an authToken for that validation action? or are we confident it doesn't need one? My opinion would be to update it because better safe than sorry, but I'm open!

@Beamanator
Copy link
Contributor

Good call @dangrous - If it were me, I'd bring this discussion to #engineering-chat b/c maaybe this is a known thing & is very difficult to work around, or maybe it's "fine" & expected ORR maybe nobody has tested this flow and it's actually something we should fix! Do you mind bringing the convo there to see what others think?

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by @Beamanator in version: 1.2.13-0 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@yuwenmemon
Copy link
Contributor

Tested, works well! ✅

@OSBotify
Copy link
Contributor

🚀 Deployed to production by @yuwenmemon in version: 1.2.13-5 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

smrutiparida pushed a commit to autosave-app/App that referenced this pull request Oct 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants