Flutter Dart

GitHub License GitHub Version Pub Version GitHub Last Updated GitHub Commit Activity (main) GitHub Issues

Solid Pod

An Australian Solid Community package to access your Data Vault.

Implemented by the ANU Software Innovation Institute.

Authors: Anushka Vidanage, Graham Williams, Jessica Moore, Dawei Chen, Kevin Wang, Zheyuan Xu.

License: Free (as in Libre) and Open Source Software MIT

Introduction

SolidPod provides functionality for dart applications to manage personal online data stores (Pods) hosted in a Data Vault on a Solid Server. The package provides underlying functionality relied upon by the solidui package for quickly building Flutter-based applications. It supports high level access for an application to authenticate users to their Pods, access the users' data from their Pods, and then share the data stored in users' Pods with other Pods through Flutter Widgets.

What is Solid?

Solid (solidproject.org/) is an open standard for a server to host personal online data stores (Pods). Numerous providers of Solid Server hosting are emerging allowing users to host and migrate their Pods on any such servers (or to run their own server).

To know more about our work relatd to Solid Pods visit solidcommunity.au

Features

Solid is an open standard for a server providing Data Vaults hosting personal online data stores (Pods). Numerous providers of Solid Server hosts support users host and migrate their Pods. Anyone can also host their own Community Solid Server. To know more about our work visit the ANU's Software Innovation Institute and the Australian Solid Community.

Getting started

To start using the package add solidpod as a dependency in your pubspec.yaml file.

dependencies:
  solidpod: ^<latest-version>

An example project that uses solidpod can be found in the example folder of the git repository.

Prerequisites

If the package is being used to build either a macos or web app, the following changes are required in order to make the package fully functional.

Android

For a release be sure to update android/app/src/main/AndroidManifest.xml to include within the queries section of the manifest:

 <!-- If your app opens https URLs -->
 <intent>
          <action android:name="android.intent.action.VIEW" />
          <category android:name="android.intent.category.BROWSABLE" />
          <data android:scheme="https" />
 </intent>

macos

Inside the app directory go to the directory /macos/Runner/. Inside there are two files named DebugProfile.entitlements and Release.entitlements. Add the following lines inside the <dict> </dict> tag in both files.

 <key>com.apple.security.app-sandbox</key>
 <true/>
 <key>com.apple.security.cs.allow-jit</key>
 <true/>
 <key>com.apple.security.network.server</key>
 <true/>
 <key>com.apple.security.network.client</key>
    <true/>
 <key>keychain-access-groups</key>
    <array/>
 <key>com.apple.security.keychain</key>
    <true/>

Note: You may already have some of the above lines in those files. If so fill the missing.

web

Inside the app directory go to the directory /web/. Inside create a file called callback.html. Add the following piece of code into that file.

<!DOCTYPE html>
<html>

<head>
    <script>
        const AUTH_DESTINATION_KEY = "openidconnect_auth_destination_url";
        const AUTH_RESPONSE_KEY = "openidconnect_auth_response_info";

        window.onload = function () {
        if (window.opener && window.opener !== window) {
          // Used when working as a popup.
          // Uses post message to respond to the parent window
          var parent = window.opener ?? window.parent;
          parent.postMessage(location.href, "*");
            } else { //Used for redirect loop functionality.
                //Get the original page destination
                const destination =
                  sessionStorage.getItem(AUTH_DESTINATION_KEY || "/");
                sessionStorage.removeItem(AUTH_DESTINATION_KEY);
                // Store current window location used to get
                // authentication information
                sessionStorage.setItem(AUTH_RESPONSE_KEY, window.location);

                //Redirect to where we're going so that we can restore state completely
                location.assign(destination);
            }
        }
    </script>
</head>

<body>
</body>

</html>

Usage

Following are the usage of main functionalities supported by the package.

Authenticate Example

A function to authenticate a user against a given Solid server https://pods.solidcommunity.au/. Return a list containing authentication data.

final authData = await solidAuthenticate(
        'https://pods.solidcommunity.au/',
        context,
      );

Login Example

A simple login screen to authenticate a user against a Solid server. If your own home widget is called MyHome() then simply wrap this within the SolidLogin() widget:

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My Pod',
      home: const SolidLogin(
        child: Scaffold(body: MyHome()),
      ),
    );
  }

Change Security Key Example

Wrap the changeKeyPopup() function within a button widget. Parameters include the BuildContext and the widget that you need to return to after changing the key.

ElevatedButton(
 onPressed: () {
  changeKeyPopup(context, ReturnPage());
 },
 child: const Text('Change Security Key on Pod')
)

Read Pod File Example

Read data from the file data/myfiles/my-data-file.ttl and return to the widget ReturnPage().

final fileContent = await readPod(
        'data/myfiles/my-data-file.ttl',
        context,
        ReturnPage(),
      );

Write to Pod File Example

Write data to the file myfiles/my-data-file.ttl and return to the widget ReturnPage().

// Turtle string to be written to the file
final turtleString =
  '@prefix somePrefix: <http://www.perceive.net/schemas/relationship/> .
<http://example.org/#green-goblin> somePrefix:enemyOf
<http://example.org/#spiderman> .';

await writePod(
 'myfiles/my-data-file.ttl',
 turtleString,
 context,
 ReturnPage(),
 encrypted: false // non-required parameter. By default set to true
);

writePod() also supports using inherited encryption keys and .acl files. For instance, consider the following use-case.

Use-case: Write two files parentDir/child-1.ttl and parentDir/child-1.ttl into a single directory parentDir. Use a single .acl file for both the files and use a single encryption key to encrypt both the files.

Above can be achieved using following lines of code.

// Turtle string to be written to the file
final childDataString = '<Sample TTL Data>';

await writePod(
 'parentDir/child-1.ttl',
 childDataString,
 context,
 ReturnPage(),
 createAcl: false,
 inheritKeyFrom: 'parentDir/',
);

await writePod(
 'parentDir/child-2.ttl',
 childDataString,
 context,
 ReturnPage(),
 createAcl: false,
 inheritKeyFrom: 'parentDir/',
);

The above will create a single .acl file for the directory parentDir and use that as .acl file for both child-1.ttl and child-2.ttl files. Also it will create a single key associated with the directory parentDir and encrypt both files using that key.

Grant Permission UI Example

Wrap the GrantPermissionUi widget around a button to navigate to the grant permission page.

ElevatedButton(
 child: const Text(
  'Add/Delete Permissions'),
 onPressed: () => Navigator.push(
 context,
 MaterialPageRoute(
  builder: (context) => const GrantPermissionUi(
  child: ReturnPage(),
  ),
 ),
 ),
)

To add/delete permissions to a specific file use:

ElevatedButton(
 child: const Text(
  'Add/Delete Permissions from a Specific File'),
 onPressed: () => Navigator.push(
 context,
 MaterialPageRoute(
  builder: (context) => const GrantPermissionUi(
  fileName: 'my-data-file.ttl',
  child: ReturnPage(),
  ),
 ),
 ),
)

To add/delete permissions to a specific directory use:

ElevatedButton(
 child: const Text(
  'Add/Delete Permissions from a Specific Directory'),
 onPressed: () => Navigator.push(
 context,
 MaterialPageRoute(
  builder: (context) => const GrantPermissionUi(
  fileName: 'parentDir/',
  child: ReturnPage(),
  isFile: false,
  ),
 ),
 ),
)

View Permission UI Example

Wrap the SharedResourcesUi widget around a button to navigate to the view permission page.

ElevatedButton(
 child: const Text(
  'View Resources your WebID have access to'),
 onPressed: () => Navigator.push(
 context,
 MaterialPageRoute(
  builder: (context) => const SharedResourcesUi(
  child: ReturnPage(),
  ),
 ),
 ),
)

To view permissions to a specific resource from a specific webID use:

ElevatedButton(
 child: const Text(
  'View access to specific Resource'),
 onPressed: () => Navigator.push(
 context,
 MaterialPageRoute(
  builder: (context) => const SharedResourcesUi(
  fileName: 'my-data-file.ttl',
  sourceWebId: 'https://pods.solidcommunity.au/john-doe/profile/card#me',
  child: ReturnPage(),
  ),
 ),
 ),
)

Large File Manager Example

To upload a large file in application myapp, use:

await writeLargeFile(
     // Name of the file in POD
     remoteFileName: 'my-large-file.bin',
     // Path of the file where it is locally stored
     localFilePath: 'D:/my-large-file.bin',
     context: context,
     child: ReturnPage(),
)

The uploaded file will be stored in the myapp/data folder.

To download a large file use:

await readLargeFile(
     // Name of the file in POD
     remoteFileName: 'my-large-file.bin',
     // Path of the file where it will be locally downloaded
     localFilePath: 'D:/my-large-file.bin',
     context: context,
     child: ReturnPage(),
)

To delete a large file use:

await deleteLargeFile(
     // Name of the file in POD
     remoteFileName: 'my-large-file.bin',
     context: context,
     child: ReturnPage(),
)

Ontology

A Solid Pod's internal storage structure consists of turtle files containing security information about the pod's content (data files) and access. The internal structure is based on the solidpod ontology, which captures essential concepts about the app's security information, data files, encryption, shared resources, and access control lists.

Ontolgy

Additional information

The source code can be accessed via the GitHub repository. You can also file issues at GitHub Issues. The authors of the package will respond to issues as best we can but.

Time-stamp: <Monday 2025-11-17 09:16:21 +1100 Graham Williams>

Libraries

solidpod
Support for flutter apps accessing solid PODs.