foss42 / apidash

API Dash is a beautiful open-source cross-platform API Client built using Flutter which can help you easily create & customize your API requests, visually inspect responses and generate API integration code. It is supported for macOS, Windows, Linux, Android & iOS. A lightweight alternative to postman/insomnia.
https://apidash.dev
Apache License 2.0
1.59k stars 301 forks source link

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

Closed AcousticDeveloper closed 1 month ago

AcousticDeveloper commented 6 months ago

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):

Tanish2002 commented 6 months ago

@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 commented 6 months ago

@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 commented 6 months ago

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 commented 6 months ago

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

Sarath191181208 commented 4 months ago

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 commented 4 months ago

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