72 lines
3.0 KiB
Python
72 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
import http.server, json, os, urllib.parse, shutil
|
|
|
|
VAULT_DIR = '/opt/jarvis-vault'
|
|
|
|
class VaultHandler(http.server.BaseHTTPRequestHandler):
|
|
def _send(self, data, status=200):
|
|
self.send_response(status)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.send_header('Access-Control-Allow-Origin', '*')
|
|
self.send_header('Access-Control-Allow-Methods', 'GET,PUT,DELETE,OPTIONS')
|
|
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
|
|
self.end_headers()
|
|
self.wfile.write(json.dumps(data).encode())
|
|
|
|
def do_OPTIONS(self):
|
|
self._send({})
|
|
|
|
def do_GET(self):
|
|
parsed = urllib.parse.urlparse(self.path)
|
|
params = urllib.parse.parse_qs(parsed.query)
|
|
path = params.get('path', [None])[0]
|
|
|
|
if parsed.path == '/tree':
|
|
files = []
|
|
for root, dirs, fnames in os.walk(VAULT_DIR):
|
|
for f in fnames:
|
|
rel = os.path.relpath(os.path.join(root, f), VAULT_DIR)
|
|
files.append(rel)
|
|
self._send({'files': sorted(files)})
|
|
|
|
elif parsed.path == '/read' and path:
|
|
full = os.path.join(VAULT_DIR, path)
|
|
if not os.path.realpath(full).startswith(os.path.realpath(VAULT_DIR)):
|
|
return self._send({'error': 'Invalid path'}, 400)
|
|
if os.path.isfile(full):
|
|
with open(full) as f:
|
|
self._send({'path': path, 'content': f.read()})
|
|
else:
|
|
self._send({'error': 'Not found'}, 404)
|
|
else:
|
|
self._send({'error': 'Not found'}, 404)
|
|
|
|
def do_PUT(self):
|
|
parsed = urllib.parse.urlparse(self.path)
|
|
params = urllib.parse.parse_qs(parsed.query)
|
|
path = params.get('path', [None])[0]
|
|
if not path: return self._send({'error': 'Missing path'}, 400)
|
|
length = int(self.headers.get('Content-Length', 0))
|
|
content = self.rfile.read(length).decode() if length else ''
|
|
full = os.path.join(VAULT_DIR, path)
|
|
if not os.path.realpath(full).startswith(os.path.realpath(VAULT_DIR)):
|
|
return self._send({'error': 'Invalid'}, 400)
|
|
os.makedirs(os.path.dirname(full), exist_ok=True)
|
|
with open(full, 'w') as f: f.write(content)
|
|
self._send({'saved': True})
|
|
|
|
def do_DELETE(self):
|
|
parsed = urllib.parse.urlparse(self.path)
|
|
params = urllib.parse.parse_qs(parsed.query)
|
|
path = params.get('path', [None])[0]
|
|
if not path: return self._send({'error': 'Missing path'}, 400)
|
|
full = os.path.join(VAULT_DIR, path)
|
|
if not os.path.realpath(full).startswith(os.path.realpath(VAULT_DIR)):
|
|
return self._send({'error': 'Invalid'}, 400)
|
|
if os.path.isfile(full): os.remove(full)
|
|
elif os.path.isdir(full): shutil.rmtree(full)
|
|
else: return self._send({'error': 'Not found'}, 404)
|
|
self._send({'deleted': True})
|
|
|
|
http.server.HTTPServer(('0.0.0.0', 8801), VaultHandler).serve_forever()
|