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

Backup Optic Tokens to a file to allow importing from another device #590

Merged
merged 13 commits into from
Jul 13, 2022

Conversation

D-Pagey
Copy link
Contributor

@D-Pagey D-Pagey commented Jul 8, 2022

Closes #537

Outstanding Design Questions:

  1. if the user has secrets and imports, should that overwrite existing secrets? Merge secrets? (the current behaviour will first clean the existing secrets and then will import the backup)
  2. if the user has secrets and imports, how do we inform them about the answer to 1.? (with the current behaviour an alert is shown when trying to import notifying the user that importing a backup will reset the existing tokens)

PR update 2022-07-12

  • Settings screen layout updated
  • Added toast messages for import and export operations
  • Added alert box when importing tokens: 'This will permanently remove the existing tokens, replacing them with the ones you are importing. Are you sure you want to continue?'
  • Added reset method in secretsManager
  • The export feature is now using two methods, one for Android (StorageAccessFramework) and one for iOS (expo-sharing)
  • Backup file name will contain the timestamp in the name, so that multiple files are created without any issues
  • If there are no secrets and you try to export, a toast will appear: 'There are no secrets to export'

@D-Pagey D-Pagey self-assigned this Jul 8, 2022
@D-Pagey D-Pagey force-pushed the feature/backup-import-tokens branch from dbced36 to 1fe478f Compare July 8, 2022 15:49
@D-Pagey D-Pagey force-pushed the feature/backup-import-tokens branch from 1fe478f to 26349af Compare July 8, 2022 15:51
D-Pagey and others added 5 commits July 8, 2022 17:42
Added working import export feature for both Android and iOS devices
Updated tests snapshots because of the UI changes in the SettingsScreen and added the reset function in the TokenScreen test
Added missing reset function in HomeScreen test
@davideroffo davideroffo self-assigned this Jul 12, 2022
@github-actions
Copy link

This pull request was automatically deployed using Expo GitHub Actions!

  • Project: @nearform/optic-expo
  • Channel: pr-590

@davideroffo davideroffo marked this pull request as ready for review July 12, 2022 08:37
@davideroffo davideroffo requested a review from simoneb July 12, 2022 08:37
@D-Pagey D-Pagey removed their assignment Jul 12, 2022
@simoneb
Copy link
Member

simoneb commented Jul 12, 2022

@davideroffo on the outstanding design question. If there are secrets when trying to import, we should warn the user that they will be wiped away and replaced. An alert would do.

@davideroffo
Copy link
Contributor

davideroffo commented Jul 12, 2022

@simoneb I already added that alert, you can see it described in one of the bullet points in the PR description:

  • Added alert box when importing tokens: 'This will permanently remove the existing tokens, replacing them with the ones you are importing. Are you sure you want to continue?'

@simoneb
Copy link
Member

simoneb commented Jul 12, 2022

@simoneb I already added that alert, you can see it described in one of the bullet points in the PR description:

  • Added alert box when importing tokens: 'This will permanently remove the existing tokens, replacing them with the ones you are importing. Are you sure you want to continue?'

Then we're good 🆗

@davideroffo davideroffo mentioned this pull request Jul 12, 2022
3 tasks
Copy link
Member

@simoneb simoneb left a comment

Choose a reason for hiding this comment

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

Overall LGTM, please see inline comments

src/screens/SettingsScreen.tsx Outdated Show resolved Hide resolved
src/screens/SettingsScreen.tsx Outdated Show resolved Hide resolved
src/screens/SettingsScreen.tsx Outdated Show resolved Hide resolved
src/screens/SettingsScreen.tsx Outdated Show resolved Hide resolved
Changes due to the PR comments
@davideroffo davideroffo requested a review from simoneb July 12, 2022 10:53
Added .txt file extension to optic-backup
const parsedSecrets = JSON.parse(result) as Secret[]
return parsedSecrets
} catch (err) {
console.log(err)
Copy link
Member

Choose a reason for hiding this comment

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

we're not handling the error. if there is an error, the user won't know

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

Comment on lines 63 to 67
if (Platform.OS === 'android') {
androidExport(fileName, fileContent)
} else {
iosExport(fileName, fileContent)
}
Copy link
Member

Choose a reason for hiding this comment

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

why don't we move this logic inside the export utils?

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

try {
const documentMeta = await DocumentPicker.getDocumentAsync()

if (documentMeta.type === 'success') {
Copy link
Member

Choose a reason for hiding this comment

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

why don't we invert this logic so we reduce the nesting and early return in case un error/cancel?

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

}
}

const showImportConfirmAlert = (onConfirm: () => void) => {
Copy link
Member

Choose a reason for hiding this comment

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

this function doesn't need to live inside the component body

Copy link
Contributor

Choose a reason for hiding this comment

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

moved in the settings.ts file


await reset()
for (const secret of parsedSecrets) {
await add(secret)
Copy link
Member

Choose a reason for hiding this comment

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

isn't there a quicker way to bulk insert secrets?

Copy link
Contributor

Choose a reason for hiding this comment

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

I've added a new addAll() method in the Secrets Context for adding all the secrets in one shot

Improving the pull request addressing some of the PR comments
Removed commented code and unuseful check on the document type different from success. Document type can be only success or cancel.
@davideroffo davideroffo requested a review from simoneb July 12, 2022 12:50
Comment on lines 85 to 86
await reset()
await addAll(parsedSecrets)
Copy link
Member

Choose a reason for hiding this comment

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

do we need to call these two functions? isn't addAll actually replacing the secrets? in which case, maybe a better name is needed?

Copy link
Contributor

Choose a reason for hiding this comment

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

I removed reset() and I renamed addAll() to replace()

const { secrets, reset, addAll } = useSecrets()

const handleExport = async () => {
if (secrets.length === 0) {
Copy link
Member

Choose a reason for hiding this comment

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

let's disable the export button if there are no secrets to export

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

Comment on lines 68 to 72
if (Platform.OS === 'android') {
androidExport(fileName, fileContent)
} else {
iosExport(fileName, fileContent)
}
Copy link
Member

Choose a reason for hiding this comment

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

these functions return promises, we should return the resulting promise back to the caller

Copy link
Contributor

Choose a reason for hiding this comment

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

Done


const mimeType = 'application/octet-stream'

const androidExport = async (fileName, fileContent) => {
Copy link
Member

Choose a reason for hiding this comment

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

this function and the one for ios have duplicated error handling. plus, this is somewhat inconsistent with the way we handle errors in the import function. we should identify a single error handling approach and apply it throughout. I would leave the error handling (and showing error messages to the user) to the caller code, meaning the React component.

if you look at the import function, you will also realize there is redundancy because error handling is done both in the function itself AND in the component which calls the function.

I do realize that there are some edge cases (things which are simpler to handle within the function and show a toast when they happen). But apart from those edge cases, let's make sure that exceptions are raised back to the caller and handle them only there.

Copy link
Contributor

Choose a reason for hiding this comment

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

I simplified it a bit by throwing errors with custom messages in the functions. In this way, we are showing the toasts just in the component as you suggested.
I did the same with the edge case in the import function (getSecretsFromFile())
Let me know if now looks good.

Fixed PR comments: error handling only in the components, removed reset and addAll used replace instead, minor other changes
@davideroffo davideroffo requested a review from simoneb July 12, 2022 13:41
Copy link
Member

@simoneb simoneb left a comment

Choose a reason for hiding this comment

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

Please make sure the deploy preview is tested thoroughly before merging. Test especially:

  • both ios and android
  • import and export work fine

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.

Feature: Backup/Migration
3 participants