braidfs 0.0.121 → 0.0.123

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +91 -28
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -133,11 +133,6 @@ async function main() {
133
133
 
134
134
  if (req.url === '/favicon.ico') return
135
135
 
136
- if (!['::ffff:127.0.0.1', '127.0.0.1', '::1'].includes(req.socket.remoteAddress)) {
137
- res.writeHead(403, { 'Content-Type': 'text/plain' })
138
- return res.end('Access denied: only accessible from localhost')
139
- }
140
-
141
136
  // Free the CORS
142
137
  free_the_cors(req, res)
143
138
  if (req.method === 'OPTIONS') return
@@ -200,7 +195,7 @@ async function main() {
200
195
  res.writeHead(500, { 'Error-Message': '' + e })
201
196
  res.end('' + e)
202
197
  }
203
- }).listen(config.port, () => {
198
+ }).listen(config.port, 'localhost', () => {
204
199
  console.log(`daemon started on port ${config.port}`)
205
200
  console.log('!! only accessible from localhost !!')
206
201
 
@@ -476,6 +471,20 @@ async function sync_url(url) {
476
471
 
477
472
  if (!self.peer) self.peer = Math.random().toString(36).slice(2)
478
473
 
474
+ // create file if it doesn't exist
475
+ var fullpath = await get_fullpath()
476
+ if (freed) return
477
+ if (!(await file_exists(fullpath))) {
478
+ if (freed) return
479
+ await wait_on(require('fs').promises.writeFile(fullpath, ''))
480
+ if (freed) return
481
+ var stat = await require('fs').promises.stat(fullpath, { bigint: true })
482
+ if (freed) return
483
+ self.file_mtimeNs_str = '' + stat.mtimeNs
484
+ self.last_touch = Date.now()
485
+ }
486
+ if (freed) return
487
+
479
488
  await save_meta()
480
489
  })
481
490
  if (freed) return
@@ -531,7 +540,7 @@ async function sync_url(url) {
531
540
  subscribe: true,
532
541
  heartbeats: 120,
533
542
  peer: self.peer,
534
- ...(self.version != null ? {parents: ['' + self.version]} : {})
543
+ parents: self.version != null ? ['' + self.version] : []
535
544
  })
536
545
  if (freed || closed) return
537
546
 
@@ -540,7 +549,16 @@ async function sync_url(url) {
540
549
  if (res.status !== 209)
541
550
  return log_error(`Can't sync ${url} -- got bad response ${res.status} from server (expected 209)`)
542
551
 
543
- console.log(`connected to ${url}${res.headers.get('editable') !== 'true' ? ' (readonly)' : ''}`)
552
+ self.file_read_only = res.headers.get('editable') === 'false'
553
+
554
+ await wait_on(within_fiber(url, async () => {
555
+ var fullpath = await get_fullpath()
556
+ if (freed || closed) return
557
+
558
+ await set_read_only(fullpath, self.file_read_only)
559
+ }))
560
+
561
+ console.log(`connected to ${url}${self.file_read_only ? ' (readonly)' : ''}`)
544
562
 
545
563
  reconnect_rate_limiter.on_conn(url)
546
564
 
@@ -559,8 +577,12 @@ async function sync_url(url) {
559
577
  var fullpath = await get_fullpath()
560
578
  if (freed || closed) return
561
579
 
580
+ await wait_on(set_read_only(fullpath, false))
581
+ if (freed || closed) return
562
582
  await wait_on(require('fs').promises.writeFile(fullpath, update.body))
563
583
  if (freed || closed) return
584
+ await wait_on(set_read_only(fullpath, self.file_read_only))
585
+ if (freed || closed) return
564
586
 
565
587
  var stat = await require('fs').promises.stat(fullpath, { bigint: true })
566
588
  if (freed || closed) return
@@ -571,6 +593,55 @@ async function sync_url(url) {
571
593
  })
572
594
  }, retry)
573
595
 
596
+ async function send_file(fullpath) {
597
+ var body = await require('fs').promises.readFile(fullpath)
598
+ if (freed || closed) return
599
+
600
+ try {
601
+ var a = new AbortController()
602
+ aborts.add(a)
603
+ var r = await braid_fetch(url, {
604
+ method: 'PUT',
605
+ signal: a.signal,
606
+ version: ['' + self.version],
607
+ body,
608
+ headers: {
609
+ ...(x => x && {Cookie: x})(config.cookies?.[new URL(url).hostname])
610
+ },
611
+ })
612
+ if (freed || closed) return
613
+
614
+ // if we're not authorized,
615
+ if (r.status == 401 || r.status == 403) {
616
+ // then revert it
617
+ console.log(`access denied: reverting local edits`)
618
+ unsync_url(url)
619
+ sync_url(url)
620
+ } else if (!r.ok) {
621
+ retry(new Error(`unexpected PUT status: ${r.status}`))
622
+ }
623
+ } catch (e) { retry(e) }
624
+ }
625
+
626
+ // if what we have now is newer than what the server has,
627
+ // go ahead and send it
628
+ await within_fiber(url, async () => {
629
+ if (freed || closed) return
630
+ var fullpath = await get_fullpath()
631
+ if (freed || closed) return
632
+ try {
633
+ var stat = await require('fs').promises.stat(fullpath, { bigint: true })
634
+ } catch (e) { return }
635
+ if (freed || closed) return
636
+
637
+ var server_v = JSON.parse(`[${res.headers.get('current-version')}]`)
638
+ if (self.version != null &&
639
+ '' + stat.mtimeNs === self.file_mtimeNs_str && (
640
+ !server_v.length ||
641
+ 1*server_v[0] < self.version
642
+ )) await send_file(fullpath)
643
+ })
644
+
574
645
  self.signal_file_needs_reading = () => {
575
646
  within_fiber(url, async () => {
576
647
  if (freed || closed) return
@@ -591,22 +662,7 @@ async function sync_url(url) {
591
662
  self.last_touch = Date.now()
592
663
 
593
664
  await save_meta()
594
-
595
- var body = await require('fs').promises.readFile(fullpath)
596
- if (freed || closed) return
597
-
598
- var a = new AbortController()
599
- aborts.add(a)
600
-
601
- await braid_fetch(url, {
602
- method: 'PUT',
603
- signal: a.signal,
604
- version: ['' + self.version],
605
- body,
606
- headers: {
607
- ...(x => x && {Cookie: x})(config.cookies?.[new URL(url).hostname])
608
- },
609
- })
665
+ await send_file(fullpath)
610
666
  }
611
667
  })
612
668
  }
@@ -1107,12 +1163,12 @@ async function sync_url(url) {
1107
1163
  if (res.status !== 209)
1108
1164
  return log_error(`Can't sync ${url} -- got bad response ${res.status} from server (expected 209)`)
1109
1165
 
1110
- console.log(`connected to ${url}${res.headers.get('editable') !== 'true' ? ' (readonly)' : ''}`)
1111
-
1112
1166
  reconnect_rate_limiter.on_conn(url)
1113
1167
 
1114
1168
  self.file_read_only = res.headers.get('editable') === 'false'
1115
1169
  self.signal_file_needs_writing()
1170
+
1171
+ console.log(`connected to ${url}${self.file_read_only ? ' (readonly)' : ''}`)
1116
1172
 
1117
1173
  initial_connect_done()
1118
1174
  res.subscribe(async update => {
@@ -1528,8 +1584,15 @@ async function set_read_only(fullpath, read_only) {
1528
1584
  })
1529
1585
  } else {
1530
1586
  let mode = (await require('fs').promises.stat(fullpath)).mode
1531
- if (read_only) mode &= ~0o222
1532
- else mode |= 0o200
1587
+
1588
+ // Check if chmod is actually needed
1589
+ if (read_only && (mode & 0o222) === 0) return
1590
+ if (!read_only && (mode & 0o200) !== 0) return
1591
+
1592
+ // Perform chmod only if necessary
1593
+ if (read_only) mode &= ~0o222 // Remove all write permissions
1594
+ else mode |= 0o200 // Add owner write permission
1595
+
1533
1596
  await require('fs').promises.chmod(fullpath, mode)
1534
1597
  }
1535
1598
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braidfs",
3
- "version": "0.0.121",
3
+ "version": "0.0.123",
4
4
  "description": "braid technology synchronizing files and webpages",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braidfs",