SAFE Services NPM Module
Created Tuesday 09 January 2018
This is a draft specification for a services nodejs module, posted here for feedback. It may well not make sense, so all levels of question are welcome and I’m happy to go back to the drawing board if this is not a good approach. I’m writing it up now in case it is a good approach!
Background
The idea for this springs from my attempt to show how Solid Apps can use SAFE Network as a drop in replacement for SOLID servers (work in progress). In a nutshell, I’ve managed to minimise the changes needed in Solid apps by intercepting the standard browser fetch() and handling any safe:
URIs. I plan to implement this as if it were a standard web service, the Linked Data Platform (LDP) so that apps using this service will need very few changes to swap Solid storage for SAFE storage.
I have yet to implement the LDP service logic, but my work on RemoteStorage suggests that this is feasible and shouldn’t take long now I have a framework in place (and almost saving an RDF/Turtle format blog post from solid-plume to SAFE network, alpha 2). Just a teeny bug holding that up atm. Still far from complete though!
This spec is a bit scrappy, for which I apologise, being exported from my PIM app (I use Zim Wiki).
The idea
solid-safenetwork.js can be the basis of a safe-services.js NPM module
-
solid - LDP service (
safe://ldp.<name>
)
* supports useful subset of LDP RESTful API
* handles GET,PUT,POST,DELETE,PATCH
* fakes LDP style response headers, metadata etc
* what about permissions? -
share / short - SAFE URL SERVICES (
safe://share.<name>
andsafe://short.<name>
)
* SAFE NFS file sharing via URLs:safe://share.<name>/original-path
(original-path is key to datamap, can be cleared & share invalidated)
* shortened URIs as a service:safe://short.<name>/shortname
(shortname is key to datamap, can be cleared & shortname invalidated)
* Interface supports (for example example):
* upload file and provide share URI, ability to over-ride default share name
* choose a public or private SAFE file and create a share URI (as above). If file is private a public copy is made (with a warning).
* I/f can be via JS and also REST like (using fetch()) -
www - WEB services (
safe://[www.]<name>
)
* mimics http style GET - as Browser now
* basic POST,PUT,DELETE etc for simple websites
* WebDav and other standard server APIs -
other:
* RemoteStorage
* Dropbox
* etc
safe-services.js module
- a nodejs module built for use in the browser (solid-safenetwork wip branch is the prototype, and demonstrates how it will work)
- safe-services.js supports a set of standards based services (e.g. LDP for Solid apps, RemoteStorage etc)
- each service is implemented in a modular fashion making it easy to add your own service or provide alternative implementations to an existing app
- works with web apps using window.fetch(), which can be easily converted from XmlHttpRequest() in order to use this module
- could be included in the SAFE browser DOM API, avoiding the need for apps to be modified at all
Implementation
- Dual interface:
- ServiceInterface methods and helpers for service operations. Maybe later, until then…
- RESTful API based on
safe:
URIs for easy conversion of any web application that already accesses a standard web service using RESTful fetch() operations (GET/PUT/POST/DELETE). Uses protoFetch in the same way as solid-safenetwork to minimise code changes to existing web apps.
- Services would be checked in a similar way to the browser supporting www:
* safe fetch() handles all safe: URIs
* if it is www or no prefix, it can hand it over to the browser (until implemeting www services - see above)
* if one of a standard set of service prefixes (e.g. ldp for Solid apps), it checks the service ID and if supported calls the relevant service fetch() implementation
* if not, the library can be configured to either assume it is really www and pass to the browser, or check the actual service ID and either handle it or generate an unsupported service error. Making this optional avoids the need to do extra processing for anything but a standard service prefix.
Dream Code
module.exports = SafenetworkServices
module.exports.serviceInterface = SafenetworkServiceInterface
SafenetworkServices
Allows app to initialise a service interface, access an initialised service interface, list all initialised services
Maybe query for a list of services supported by the library
// SafenetworkServices.InitialiseSevice(publicID,"LDP",permissions)
//
// adds an object to self for each initialised service, accessible as self.services[serviceName] (e.g. self.services[“LDP”])
//
// Returns a Promise which if successful resolves to a SafenetworkServiceInterface
SafenetworkServiceInterface
// SafenetworkServiceInterface
//
// Common interface:
// ???>>>MEATYBITTODO<<< status, permissions, initialise a previously uninitialised publicID to support the given service (maybe put this in SafenetworkServices?), access objects to read service related information from a publicID (with handling if not yet initialised)
//
// Service specific interface
// - helpful to have some standards to follow (e.g. for storage services in general - could use LDP or RemoteStorage as a template)
// - this can, but need not include, a RESTful API to allow access to the service as if it was a standard HTTP API being accessed through fetch()
Application Logic
- User visits SAFE website/app (safe: URI) which has safe-services.js support (ie uses this nodejs module!)
- App checks to see if logged into SAFE Network:
- ☐ How to check - can an app check to see what if any container rights it has without trying auth? If so, use a check for ‘Read’ on _public.
- App updates “Log In/Out”
-
Immediately, or when needed, or lazily… app interrogates the public ID to initialise read-only safe-services. Example
SafenetworkServices.InitialiseSevice(publicID,"LDP",permissions)
// Returns a Promise resolving an initialised SafenetworkServiceInterface object if successful
-
If user chooses Log In, App attempts to authorise with SAFE Authenticator (including request for ‘Read’ on _public)
- This causes Authenticator to prompt user to Log in to SAFE, and optionally authenticates the app.
- App updates Log In/Out and other UI according to auth result.
See 3a. / 3b. below.
- If user chooses Log Out, App frees SAFE application objects and updates Log In/Out and other UI
See 3a. below.
3a. If User Not Logged In to SAFE
The UI disables ability to modify any SAFE services used by the app (e.g. to create online content, upload files, share etc.)
Content is displayed but anything accessed through services will be read-only, until the user chooses to Log In3b. If User Logged In to SAFE
Immediately, or when needed, or lazily… app interrogates the public ID to initialise any read-write services. Example:
SafenetworkServices.InitialiseSevice(publicID,"LDP",permissions)
// Returns a Promise resolving an initialised SafenetworkServiceInterface object if successful
The App interrogates the service (e.g. for permissions granted by the user) and updates UI to reflect ability to modify any SAFE services used by the app (e.g. to create online content, upload files, share etc.).
Content may be accessed and displayed, and the UI allows it to be created, updated etc. according to user granted permssions.