SAFE NFS API - notes on where and how files are stored

I’ve been confused by some of the SAFE NFS API and hope I’ve now getting a grip on it. For others, and to check out what I understand here is a short summary of how to create NFS directories and folders. Heading links go to the relevant API documentation.

Fellow devs please check the following and let me know if I have anything wrong.

Create a directory

Request: POST /nfs/directory/:rootPath/:directoryPath
Request payload:

{
    isPrivate: Boolean,
    metadata: base64 String,
}

:directoryPath is a full directory path such as ‘/work/websites/safepress’
:rootPath is either of

  • ‘app’ (this app alone: the directory and any subdirectories are accessible only by the app itself)
  • ‘drive’ (shared: the directory and any subdirectories are accessible by any app authorised by the user)

Note: The SAFE Demo App stores both ‘public’ and ‘private’ directories as ‘app’, so they are not visible to any other apps, authorised or not.

isPrivate is a boolean value within the payload for create directory such that:

  • ‘true’ will create a directory that can only be accessed by an authorised app (i.e. user has logged in and accepted the app request for authorisation).
  • ‘false’ will create a directory that can be accessed by anyone, because unauthorised apps are able to access it. This is because the directory listing will not be encrypted, although in order to access such a directory an app will need a way of identifying the directory to the API. This might be through a kind of crawler, looking for public data related to known apps, or through the user deliberately sharing a way to access the directory or a particular file (e.g. by registering a service and sharing a URL based on the service, such as publishing a website using the SAFE Demo App).

Assumptions

@Krishna please can you answer:

  • for a directory to be public, all its ancestor directories must be public, but a private directory can be created inside any public directory. Is this correct?
  • are private (encrypted) directories listed or hidden in the directory listing of a public directory?
  • is there a way of creating a safe web URL for unauthorised access that does not involve an NFS service or a public ID? If not, I think it would be a useful feature. :slight_smile:

Comments Appreciated On…

For remoteStorage.js apps there is a function (getItemURL) which returns a URL for sharing a given file. My thoughts on how best to implement this using SAFE API are as follows. If there are any better ways, particularly to do with the low level API which I don’t yet understand, please let me know:

  • default to ‘app’ / isPrivate=‘true’: to prevent unauthorised access to RS.js application data, but allow sharing of selected files, that are copied to a shared-files directory when getItemURL() is first used on the file.
  • optionally use ‘app’ / :isPrivate=‘false’: to allow sharing ‘live’ files. This means data is theoretically insecure (unencrypted) but obvious in its location. A sophisticated programmer could write malware to look for this data when installed on a machine that is using this particular app. I think it becomes very much more difficult to search for such data on SAFE Network itself, even for known apps, without first having some access on a device the user is using to access SAFEnetwork, but I am NOT sure of this.
1 Like

There is no restriction at all. You can create private directory within public directory and vice versa. It is upto the app to restrict or not.

No. If the directory is created as private, no one else can decrypt the directory even if they know the directory key. Consider that a public folder contains a private folder. The public folder files can be read by anyone, but only the owner will be able to read the private folder.

The reading of a directory is completely based on the directory’s metadata and not related to its ancestors.

As of now, we don’t have any other option. I hope the apps should be able to achieve this using the low level apis.

2 Likes

Would this allow a directory to exist within multiple (ancestor) directories?

1 Like

Thanks @Krishna!

If there is a private directory within a public directory, and I request a listing of what is in the public directory, will I see the private directory name? If not, will there be anything at all to indicate the private directory is there?

My wanting to share safe web URLs without needing service/public ID was meant to include whether or not this be possible using the low level API. I now see that public ID’s will not help this so think it is an important feature for any application wanting to share web style URLs. So I hope it can be included :slight_smile: I already know of one app that needs it for me to get it working.

I haven’t had time to read up on the low level API yet so it’s time I did. If you can include the above in the tutorial that would be great :slight_smile:

So finally VERSIONED_DIRECTORY_LISTING_TAG and UNVERSIONED_DIRECTORY_LISTING_TAG tags above 15000 isn’t a bug, as low level api only manages tags 500, 501 and those above 15000. I am referring to this post:

@dirvine:

@tfa:
Respectively 15100 & 15101, that’s strange!

That’s just plain wrong, a bug and needs fixed. All the reserved types are not currently reserved in code but will be (it’s an esy thing that needs focus).

The metadata in the response should help to differentiate it. There is a isPrivate property in the get directory response.. The info section refers to the meta information of the directory.

I am not sure about the exact requirement here. If you want to expose a public folder to others without the means of public id, you can definitely do it using low level apis. You can use Structured Data and create your own data structure to represent a folder/directory etc. Other applications can lookup for the structured data and get the contents of the structured data and process it based on how your application defines it. How other apps can find your structured data etc has to be decided by the application.

For example, an application can have its own data structure for representing a directory. When the user decides to share a folder, he can generate a random share key for that folder and hit share. At that point the application can create a new structured data and copy the directory information into the structured data. The id of the structured data can be hash(appName + sharekey). This share key can be passed to other users to get the folder content. The application at the other end should simple generate the id of the structured data using the same logic hash(appName + shareKey), and then fetch the structured data for that id and read its contents to get the directory. This is a weird example :wink: I just tried to explain on how these components can be used.

Currently we don’t have NFS exposing low level api. So it is not possible to fetch the directory key corresponding to a directory. We might need to expose an api to get directory key so that it can be used to store in a structured data or use it how ever the app would want to. This is just my thought and needs to discussed to know if this can lead to some other loop holes.

Can you share an example of link what you are ideally looking for?

1 Like

Yes, even in the demo app the directory structure is like this,

                          App Root Folder
                                  |
            ----------------------------------------------
            |                                             |
         Private                                   Public
     (All your private files)         (All the services/websites published)

We can have nested folder structures

@Krishna so, just to confirm cos you seem to skip over to answer what I might ask next… Is it correct to say:

the listing of a public directory will show the names of both public and private subdirectories.

And accessing the metadata for a directory can be used to determine which are which because this includes isPrivate

Correct?

Regarding sharing links, the aim is not sharing from one app to another, but to provide a download link anyone can use regardless of the apps they are using (e.g. type into browser address bar).

Similar examples:

  • I have a file stored in Dropbox (or in our case, in my SAFE NFS storage), and want to provide a SAFE URL on SAFEtwitter so anyone can download that particular file.

  • user runs a web app from SAFEnetwork which captures a picture from her Webcam and saves it to her remoteStorage (a file on SAFEnetwork). The app wishes to display the image to the user within the application by inserting an tag into the web page DOM. To do this it gets a SAFE URL for the image, that displays in the browser.

If the second example sounds a bit odd, it’s a real example of a RS.js app I have working with SAFEnetwork, called gHost. Everything works except displaying the image, because I don’t yet have a way of creating a URL without forcing the user to create a public ID, and I don’t think that’s a reasonable approach because each app that wants to do something like this would have to create (steal from the user) a precious public ID, or piggyback on an existing one, which is not SAFE.

Perhaps an alternative would be to support a reserved file URL data type that launcher recognises, and which can include the xor address of the file in the URL (or whatever the correct terminology is)? You could then provide an API to return this canonical URL for a given file within user NFS storage, and that URL could be used like a web URL to download, or display, or share, the corresponding file. .

Forgive me if I’m not using the right terms here :slight_smile:

Actually I think I said it wrong

can “myDir” exist under say “root/public/myDir” AND “root/private/media/songs/myDir” AND perhaps others. All at the same time and be accessed.

#####I just picked reasonable sounding directory names and not meant to reflect actual implementaation.