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

Saving state never terminates if persistent files cannot be accessed / modified #359

Closed
AcousticDeveloper opened this issue Mar 25, 2024 · 6 comments · Fixed by #464
Closed
Labels
bug Something isn't working

Comments

@AcousticDeveloper
Copy link
Contributor

Describe the bug/problem
To store data API Dash requires 4 files, namely -

  1. apidash-data.hive
  2. apidash-data.lock
  3. apidash-settings.hive
  4. apidash-settings.lock

Now in Windows, these files are generated inside %USERPROFILE%/Documents directory and in Linux, these are generated under ~/ directory. If these locations are protected, i.e. external programs cannot create files in these locations or modify existing files, then if API Dash tries to access these files, it throws an error and the UI never updates.

Steps to Reproduce the bug/problem
Reproducing this issue can be achieved via many ways, i.e. revoking write access to the generated files and trying to save a request. A simpler way to reproduce this issue on Windows is to enable Ransomware Protection which will disallow external programs trying to generate files under some predefined directories (%USERPROFILE%/Documents being one of them) and then trying to save a request.

After clicking save, the saving state never terminates.

Screenshot 2024-03-25 154145

API Dash throws error in the terminal stating it cannot access the files user to store persistent data.

Screenshot 2024-03-25 153740

Expected behavior
User should be presented with an error message stating that the respective files could not be read / modified and file permissions needs to be updated by the user.

An enhancement to the solution is to add a default location for persistent data and then give the user ability to load data and settings from custom location using file path. This will allow users to version control request templates and share the existing requests among developers.

Device Info (The device where you encountered this issue):

  • OS: Windows 11
@AcousticDeveloper AcousticDeveloper added the bug Something isn't working label Mar 25, 2024
@Tanish2002
Copy link
Contributor

@animator what would we want here? Do we need a popup(stating the directory is read-only) or exit the app if files cannot be accessed?

The former might be tricky since hive is initialized before the actual flutter app, so I will have to prop drill this info to the actual app.

@AcousticDeveloper
Copy link
Contributor Author

@Tanish2002 During my specific encounter to the issue, the app did not open while the files weren't created. Thus if the files aren't available at all, then an error window should notify the user that required files cannot be created. But in case the files were available (read access given, no write access) then the core functionality of sending requests is working, thus closing the application is not the solution, in that case an error message can be shown if the user tries to save the state, stating that write permission is required.

@animator what would we want here? Do we need a popup(stating the directory is read-only) or exit the app if files cannot be accessed?

@Tanish2002
Copy link
Contributor

required files cannot be created. But in case the files were available (read access given, no write access) then the core functionality of sending requests is working, thus closing the application is not the solution, in that case an error message can be shown if the user tries to save the state, stating that write permission is required.

Yeah, we can add checks for both, if the file can be created and if the file can be written.

The first check will check if files are already present or not. If not then try to create a temp file to see if files can be created in this directory. If present then it will check if the files can be written. If any of the checks fails we can use some backup plan.

The issue currently is that hive is initialized before the app and state providers.
Here is the main function:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  GoogleFonts.config.allowRuntimeFetching = false;
  await openBoxes();
  if (kIsLinux) {
    await setupInitialWindow();
  }
  if (kIsMacOS || kIsWindows) {
    var win = getInitialSize();
    await setupWindow(sz: win.$1, off: win.$2);
  }
  runApp(
    const ProviderScope(
      child: DashApp(),
    ),
  );
}

Here await openBoxes(); runs before runApp so for this to work, I'll have to make openBoxes return a boolean representing failed or passed. Then this boolean can be used either by passing this to DashApp(Where it can handle the popup) or just showing some error widget.

@animator
Copy link
Member

animator commented Apr 3, 2024

Adding to what @Tanish2002 suggested. This should be the desired flow:

  • When the user opens the app for the first time he/she should be prompted to choose a folder where the data will be stored.
  • A quick write (hive initialization) is then performed in this location to check if proper write permissions are in place. In case of any error, the user is prompted to choose a new location and notified of the permission issue.
  • This location (key: value) has to be stored somewhere (like shared preferences) to which the app always has the access.
  • As this location is now established, the next time the app is opened, hive uses this path for initilization.
  • User has the option to change this path from Settings.

@Sarath191181208
Copy link

Sarath191181208 commented Jun 15, 2024

Hi guys,
I am a newbie in flutter, but I still want to make a positive contribution and wanted to contribute towards this issue.
I worked on this a little bit and created something like this:

  // main.dart
  runApp(
    const HiveDirectorySelector(
      child: ProviderScope(
        child: DashApp(),
      ),
    ),
  );
# hive_directory_selector.dart pseudo code
HiveDirectorySelector StatefulWidget
    build()
        FutureBuilder
            future: getHiveSaveFolder(), # loads from shared preferences
            builder: (BuildContext ctx, AsyncSnapshot<String?> snapshot)
                if (snapshot.connectionState != ConnectionState.done)
                    return CircularProgressIndicator();
                
                if (snapshot.data == null)
                    selectFolder();
                    CircularProgressIndicator();
                
                return widget.child;
    
    selectFolder()
        selectedDirectory = await FilePicker.platform.getDirectoryPath();
        if (selectedDirectory != null)
            setHiveSaveFolder(selectedDirectory); # saves to shared preferences
            setState(() {});

The rough draft of the code is here: https://github.com/Sarath191181208/apidash/tree/resolve-issue-359-hivefolderpicker

@ashitaprasad
Copy link
Member

@Sarath191181208 Can you please raise a PR. It is much easier to execute and review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
5 participants