From b98d95ba22c7a5b1bcf89fb8ac0a8b159f8c8184 Mon Sep 17 00:00:00 2001 From: ken Date: Mon, 14 Aug 2017 17:19:44 +0000 Subject: [PATCH] fs 0.0.1 --- src/strapp.js | 65 +++++++- src/strappFileSystem.js | 360 ++++++++++++++++------------------------ 2 files changed, 204 insertions(+), 221 deletions(-) diff --git a/src/strapp.js b/src/strapp.js index 9ec9d09..aefbc1b 100644 --- a/src/strapp.js +++ b/src/strapp.js @@ -6,8 +6,17 @@ * @copyright August 2017 - Ken Grimes, Jordan Lavatai * @summmary Bootstrapper for the strapp.io mechanism */ +import LocalForage from "localforage" const StrappFile = (() => { + const localforage = LocalForage.createInstance({ + driver: [LocalForage.LOCALSTORAGE, + LocalForage.INDEXEDDB, + LocalForage.WEBSQL], + name: 'strapp', + version: 0.1, + storeName: 'strapp' + }) const authorize = (pubKey, mode, stat) => { let allowed if (pubKey === stat.owner) @@ -50,6 +59,15 @@ const StrappFile = (() => { static PermissionDenied() { return new Promise((resolve, reject) => reject('Permission denied')) } + static get(path) { + return localforage.getItem(path) + } + static set(path, data) { + return localforage.setItem(path, data) + } + static delete(path) { + return localforage.removeItem(path) + } HEAD(opt) { if (authorize(opt.pubKey, 'r', this.stat)) return new Promise((resolve, reject) => resolve('')) @@ -86,13 +104,46 @@ const StrappFile = (() => { } } StrappFile.defaults = { - type: 'mime/type', - perm: 0, - owner: 'thisOwnerPubKey', - group: 'groupname', - changed: 'time', - created: 'time', - accessed: 'time - not saved' + stat: { + type: 'mime/type', + perm: 0, + owner: 'thisOwnerPubKey', + group: 'groupname', + changed: 'time', + created: 'time', + accessed: 'time - not saved' + } } return StrappFile })() + +const StrappPeerConnection = (() => { + class StrappPeerConnection extends StrappFile { + GET(opts) { + //get metadata (held in filesystem), with owner, usage info, etc + //if unauthed, send message down socket + } + PUT(opts) { + //create w/ sdp, register callback (or pipe), set owner + } + POST(opts) { + //send msg + } + CONNECT(opts) { + //send routing message down socket + //POST(opts.routemessage) + } + } + return StrappPeerConnection +})() + +const StrappDirectory = (() => { + class StrappDirectory extends StrappFile { + } + return StrappDirectory +})() + + + +export default StrappFile +export { StrappPeerConnection, StrappDirectory } diff --git a/src/strappFileSystem.js b/src/strappFileSystem.js index 6f0b9d4..00f1050 100644 --- a/src/strappFileSystem.js +++ b/src/strappFileSystem.js @@ -1,224 +1,156 @@ /** - * @file File System Interface - * @desc Provides basic file commands for interacting with Strapp - * file system as well as storage (and backups) of file system - * @author Jordan Lavatai and Ken Grimes - * @version 0.0.1 - * @license AGPL-3.0 - * @copyright Strapp.io - */ - -import localforage from "localforage" -import StrappPeerConnection from "strappPeerConnection" - -/* File constructor */ -class File extends Object { - constructor(...props) { - super() - return Object.assign(this, new.target.defaults, ...props) - } - get() { - return this.data - } - post(postedData) { - this.data += postedData - this.lastModified = new Date() - } - put(putData) { - this.data = putData - this.lastModified = new Date() - } - delete() { - this.data = '' - this.lastModified = new Date() +* @file Strapp File System +* @author Jordan Lavatai, Ken Grimes +* @version 0.0.1 +* @license AGPL-3.0 +* @copyright August 2017 - Ken Grimes, Jordan Lavatai +* @summmary File system implementation for a strapp node +*/ +import LocalForage from "localforage" + +const StrappFile = (() => { + const localforage = LocalForage.createInstance({ + driver: [LocalForage.LOCALSTORAGE, + LocalForage.INDEXEDDB, + LocalForage.WEBSQL], + name: 'strapp', + version: 0.1, + storeName: 'strapp' + }) + const authorize = (pubKey, mode, stat) => { + let allowed + if (pubKey === stat.owner) + allowed = (stat.perms >>> 16) & 0xF + else { + let gAccess = false + let uGroups = StrappFile.get(`acct/${pubKey}/groups`).split(' ') + for (let i = 0; i < uGroups.length; i++) { + if (uGroups[i] === stat.group) { + gAccess = true + break + } + } + if (gAccess) + allowed = (stat.perms >>> 8) & 0xF + else + allowed = stat.perms & 0xF + } + switch(mode){ + case 'r+': + case 'rw': + case 'wr': + return (allowed & 0x6) === 0x6 + case 'w': + return (allowed & 0x2) === 0x2 + case 'r': + return (allowed & 0x4) === 0x4 + case 'x': + return (allowed & 0x1) === 0x1 + default: + console.log(`Unknown access mode: ${mode}`) + return false + } } - connect() { - + class StrappFile extends Object { + constructor(...props) { + super() + return Object.assign(this, new.target.defaults, ...props) + } + static PermissionDenied() { + return new Promise((resolve, reject) => reject('Permission denied')) + } + static get(path) { + return localforage.getItem(path) + } + static set(path, data) { + return localforage.setItem(path, data) + } + static delete(path) { + return localforage.removeItem(path) + } + static routeMessage(lmkid) { + //split lmkid by spaces + //regex sanitize. if '/', MSG. else if ' ', resolve method + } + HEAD(opt) { + if (authorize(opt.pubKey, 'r', this.stat)) + return new Promise((resolve, reject) => resolve('')) + else + return StrappFile.PermissionDenied() + } + GET(opt) { + if (authorize(opt.pubKey, 'r', this.stat)) + return StrappFile.get(this.path) + else return StrappFile.PermissionDenied() + } + PUT(opt) { + if (authorize(opt.pubKey, 'w', this.stat)) + return StrappFile.set(this.path, opt.data) + else return StrappFile.PermissionDenied() + } + POST(opt) { + return this.PUT(Object.assign(opt, { data: this.GET(opt) + opt.data })) + } + DELETE(opt) { + if (authorize(opt.pubKey, 'w', this.stat)) + return StrappFile.delete(this.path) + else return StrappFile.PermissionDenied() + } + OPTIONS(opt) { + return this.stat + } + CONNECT(opt) { //make channel + return this.GET(opt) + } + TRACE(opt) { + } + PATCH(opt) { + } } - options(publicKey) { - return this.availPermissions(publicKey) + StrappFile.defaults = { + stat: { + type: 'mime/type', + perm: 0, + owner: 'thisOwnerPubKey', + group: 'groupname', + changed: 'time', + created: 'time', + accessed: 'time - not saved' + } } -} -/* TODO: Continue to flesh this out */ -File.defaults = { - name: '', - data: '', - mode: {}, - size: 0 - //lastModified: new Date()? - //lastAccessed: new Date()? - -} - - -/* Filesystem maintains the current session memory for the strapp instance. Files can be - created and killed from the filesystem without leveraging localForage. Files that are - in the filesystem can be stored to localForage while files that are in localForage can be loaded - to the filesystem. When a Filesystem is first intialized, it attempts to get its strappID it populates itself from localForage and - overwrites any files in its current memory. Files that have restore() as a property (which will be some method needed to - make the file functions e.g. strappPeerConnections will restore() themselves lazily, i.e. when they are needed.*/ - - /* TODO: Should it be possible to create/preserve/destroy a file to both localForage and fileSystem? (same time) */ - /* TODO: Should initFileSystem not overwrite files? */ - -/* These are the default files on all file systems */ -let defaultFiles = [ "..", ".", "accounts", "ice", "log", "run" ] - - -/* TODO: Protect data via closures? */ -const fs = { - /* TODO: What if files are added to file system before init is is called? */ - initFileSystem(){ - this.db = localforage.createInstance({ name: "database" }) - /* Iterate through all files on localforage, adding them to FileSystem - and calling their restore methods */ - this.db.iterate( (value, key, n) => { - /* just btw, return !undefined to exit early */ - this.loadFile(key, true) - - }).catch( (err) => { - console.log(`error: ${err} when iterating through localForage during initFileSystem`) - }) - /* Add the hardcoded default files if they dont already exist */ - /* Restore these files --> need the private/public key*/ - initialFiles.map( (val, idx, array) => { - if (this.fileExists(val)) { - let file = this.getFile(val) - let restoreProp = file['restore'] - if (restoreProp === undefined && typeof restoreFx === 'function') { - //restore file - } - /* Else don't do anything, file exists in FS and doesnt need to be restored */ - } - else { - /* TODO: Remove checking for every file --> although its only for the default files which - will probably be a low number. Still, unnecessary. Could make initialFiles a - Map object with fileType in it and switch(val.fileType) */ - if (val === '..') { - let file = new StrappPeerConnection() - /* Connect with host */ - } - else { - /* Each default file is going to have specific permissions, */ - let filedata = new File() - filedata.name = val - filedata.mode = - this.createFile(val,) - } - } - - }) - - }, - - fileExists(filename) { - return this.files[filename] === undefined ? false : true - }, - - /* Create a file in the file system, if specified overwrites any file that is already there - else does nothing */ - createFile(filename, filedata, overwrite = false){ - filedata.name = filename - if (this.files[filename] === undefined) { - this.files[filename] = filedata + return StrappFile +})() + +const StrappPeerConnection = (() => { + class StrappPeerConnection extends StrappFile { + GET(opts) { + //get metadata (held in filesystem), with owner, usage info, etc + //if unauthed, send message down socket } - else { - if (overwrite) { - console.log(`Overwriting ${filename}`) - this.files[filename] = filedata - } - else { - console.log(`Didn't overwrite file so nothing happened`) - } + PUT(opts) { + //create w/ sdp, register callback (or pipe), set owner } - }, - - /* Get a file from browser session memory */ - /* TODO: Option to get from localForage? */ - getFile(filename) { - return this.files[filename] - }, - - /* Save a file to file system*/ - saveFile(filename, filedata) { - /* TODO: Determine if file to be saved is of saveable nature e.g. SPC's cant really be saved */ - this.db.setItem(filename, filedata) - }, - - /* Delete file from localForage */ - removeFile(filename) { - this.db.removeItem(filename) - }, - - /* Delete a file from file system */ - killFile(filename) { - delete this.files[filename] - - }, - - /* Store file in file system to localForage */ - storeFile(filename) { - this.db.setItem(filename, this.files[filename].filedata) - }, - - /* Load file from localForage to file system */ - loadFile(filename, overwrite = false) { - let filedata = this.db.getItem(filename) - filedata = filedata.restore === undefined ? filedata : filedata.restore() - this.createFile(filename, filedata, overwrite) - }, - - saveFileSystem() { - /* TODO: save all files in filesystem to localforage */ - }, - db: {}, - files: {} - -} - -/* File System API */ - - -/* Load file system from localStorage/indexedDB if strapp.js is running on a host */ -function loadFileSystem(){ - -} - -/* Store file system before shutting down if strapp.js is running on a host- */ -function storeFileSystem(){} - - - -/* addFile - adds a created file to a file */ -//@arg fileType - what to set the type property -//@arg fileData - what to set the data property -//@arg filePos - where to create the file - -/* Determine if a publicKey has permissions to execute methods - -/* rm - Delete file */ - -/* ls - display file contents */ - //open file -//return all of file files - -/* cat - display file data */ -//return file data - -/* open - Open file */ - //traverse to file path -/* perm - display file permissions (if you have permissions) */ -/* find - find a file */ -//@arg fileToFind -/* stat - info about a file */ -//@arg path - path to the file -/* exists - determine if a file contains a file */ -//@arg {String} searchedFile - file to be searched -//@arg {String} fileName -//@arg {Number} Depth to look -//@return {Boolean} true if exists, false if doesn't - + POST(opts) { + //send msg + } + MSG(opts) { + //send routing message down socket + //POST(opts.routemessage) + } + } + return StrappPeerConnection +})() +const StrappDirectory = (() => { + class StrappDirectory extends StrappFile { + CONNECT(opts) { + //send routing message to the directory (handle the next part here) + } + } + return StrappDirectory +})() +export default StrappFile +export { StrappPeerConnection, StrappDirectory } -- 2.18.0