fs 0.0.1
[henge/kiak.git] / src / strappFileSystem.js
1 /**
2 * @file Strapp File System
3 * @author Jordan Lavatai, Ken Grimes
4 * @version 0.0.1
5 * @license AGPL-3.0
6 * @copyright August 2017 - Ken Grimes, Jordan Lavatai
7 * @summmary File system implementation for a strapp node
8 */
9 import LocalForage from "localforage"
10
11 const StrappFile = (() => {
12 const localforage = LocalForage.createInstance({
13 driver: [LocalForage.LOCALSTORAGE,
14 LocalForage.INDEXEDDB,
15 LocalForage.WEBSQL],
16 name: 'strapp',
17 version: 0.1,
18 storeName: 'strapp'
19 })
20 const authorize = (pubKey, mode, stat) => {
21 let allowed
22 if (pubKey === stat.owner)
23 allowed = (stat.perms >>> 16) & 0xF
24 else {
25 let gAccess = false
26 let uGroups = StrappFile.get(`acct/${pubKey}/groups`).split(' ')
27 for (let i = 0; i < uGroups.length; i++) {
28 if (uGroups[i] === stat.group) {
29 gAccess = true
30 break
31 }
32 }
33 if (gAccess)
34 allowed = (stat.perms >>> 8) & 0xF
35 else
36 allowed = stat.perms & 0xF
37 }
38 switch(mode){
39 case 'r+':
40 case 'rw':
41 case 'wr':
42 return (allowed & 0x6) === 0x6
43 case 'w':
44 return (allowed & 0x2) === 0x2
45 case 'r':
46 return (allowed & 0x4) === 0x4
47 case 'x':
48 return (allowed & 0x1) === 0x1
49 default:
50 console.log(`Unknown access mode: ${mode}`)
51 return false
52 }
53 }
54 class StrappFile extends Object {
55 constructor(...props) {
56 super()
57 return Object.assign(this, new.target.defaults, ...props)
58 }
59 static PermissionDenied() {
60 return new Promise((resolve, reject) => reject('Permission denied'))
61 }
62 static get(path) {
63 return localforage.getItem(path)
64 }
65 static set(path, data) {
66 return localforage.setItem(path, data)
67 }
68 static delete(path) {
69 return localforage.removeItem(path)
70 }
71 static routeMessage(lmkid) {
72 //split lmkid by spaces
73 //regex sanitize. if '/', MSG. else if ' ', resolve method
74 }
75 HEAD(opt) {
76 if (authorize(opt.pubKey, 'r', this.stat))
77 return new Promise((resolve, reject) => resolve(''))
78 else
79 return StrappFile.PermissionDenied()
80 }
81 GET(opt) {
82 if (authorize(opt.pubKey, 'r', this.stat))
83 return StrappFile.get(this.path)
84 else return StrappFile.PermissionDenied()
85 }
86 PUT(opt) {
87 if (authorize(opt.pubKey, 'w', this.stat))
88 return StrappFile.set(this.path, opt.data)
89 else return StrappFile.PermissionDenied()
90 }
91 POST(opt) {
92 return this.PUT(Object.assign(opt, { data: this.GET(opt) + opt.data }))
93 }
94 DELETE(opt) {
95 if (authorize(opt.pubKey, 'w', this.stat))
96 return StrappFile.delete(this.path)
97 else return StrappFile.PermissionDenied()
98 }
99 OPTIONS(opt) {
100 return this.stat
101 }
102 CONNECT(opt) { //make channel
103 return this.GET(opt)
104 }
105 TRACE(opt) {
106 }
107 PATCH(opt) {
108 }
109 }
110 StrappFile.defaults = {
111 stat: {
112 type: 'mime/type',
113 perm: 0,
114 owner: 'thisOwnerPubKey',
115 group: 'groupname',
116 changed: 'time',
117 created: 'time',
118 accessed: 'time - not saved'
119 }
120 }
121 return StrappFile
122 })()
123
124 const StrappPeerConnection = (() => {
125 class StrappPeerConnection extends StrappFile {
126 GET(opts) {
127 //get metadata (held in filesystem), with owner, usage info, etc
128 //if unauthed, send message down socket
129 }
130 PUT(opts) {
131 //create w/ sdp, register callback (or pipe), set owner
132 }
133 POST(opts) {
134 //send msg
135 }
136 MSG(opts) {
137 //send routing message down socket
138 //POST(opts.routemessage)
139 }
140 }
141 return StrappPeerConnection
142 })()
143
144 const StrappDirectory = (() => {
145 class StrappDirectory extends StrappFile {
146 CONNECT(opts) {
147 //send routing message to the directory (handle the next part here)
148 }
149 }
150 return StrappDirectory
151 })()
152
153
154
155 export default StrappFile
156 export { StrappPeerConnection, StrappDirectory }