Client can send and server can receive

main
Micke Nordin 2 months ago
parent 85e02a16b4
commit dd99e89b5d

@ -7,20 +7,115 @@ import argparse
import sys
import yaml
import uuid
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
from http.server import CGIHTTPRequestHandler, HTTPServer
from os import environ as env
from os import path, makedirs
from urllib.parse import urlparse, quote_plus
from os import path, makedirs, stat
from urllib.parse import urlparse
import pwd
import requests
class OCMHandler(BaseHTTPRequestHandler):
class OCMHandler(CGIHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.cgi_directories = ["/ocm"]
def do_GET(self):
if self.path in ["/.well-known/ocm", "/ocm-provider"]:
self.send_response(200)
self.end_headers()
self.wfile.write(self.discovery())
elif self.path == "/ocm/webdav":
self.send_response(200)
self.end_headers()
self.wfile.write(b"Hello, world!")
self.wfile.write(b"Hello World!")
elif self.path == "/ocm/webapp":
self.send_response(200)
self.end_headers()
self.wfile.write(b"Hello World!")
elif self.path == "/ocm/datatx":
self.send_response(200)
self.end_headers()
self.wfile.write(b"Hello World!")
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b"Not Found")
def do_POST(self):
if self.path == "/ocm/shares":
length = int(self.headers.get('content-length'))
payload = json.loads(self.rfile.read(length))
code, reply = self.validate_shares(payload)
self.send_response(code)
self.end_headers()
self.wfile.write(json.dumps(reply).encode("utf-8"))
elif self.path == "/ocm/webdav":
self.send_response(200)
self.end_headers()
self.wfile.write(b"{}")
elif self.path == "/ocm/webapp":
self.send_response(200)
self.end_headers()
self.wfile.write(b"{}")
elif self.path == "/ocm/datatx":
self.send_response(200)
self.end_headers
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b"Not Found")
def validate_shares(self, share) -> tuple[int, dict]:
# spec: https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1shares/post return (201, {})
share_with = share.get("shareWith")
displayname = find_displayname(share_with)
if displayname is None:
return (400, {})
reply = {
"recipientDisplayName": displayname
}
return (201, reply)
def discovery(self):
# spec: https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1.well-known~1ocm/get
return json.dumps({
"enabled": True,
"apiVersion": "1.1.0",
"endPoint": "http://127.0.0.1:8080/ocm",
"provider": "ocm-cli",
"resourceTypes": [
{
"name": "file",
"shareTypes": [
"user"
],
"protocols": {
"webdav": "http://127.0.0.1:8080/ocm/webdav",
"datatx": "http://127.0.0.1:8080/ocm/datatx"
}
},
{
"name": "folder",
"shareTypes": [
"user"
],
"protocols": {
"webdav": "http://127.0.0.1:8080/ocm/webdav",
"datatx": "http://127.0.0.1:8080/ocm/datatx"
}
}
],
"capabilities": [
"/invite-accepted"
]
}).encode('utf-8')
def find_displayname(user: str) -> str:
return pwd.getpwnam(user).pw_gecos.strip(',')
class OCM:
@ -28,7 +123,6 @@ class OCM:
host: str
server: HTTPServer
dir: str
legacy_mode = False
config_dir: str
config: dict
config_file: str
@ -37,7 +131,7 @@ class OCM:
def __init__(self, dir: str = env["PWD"]):
self.user = env["USER"]
self.fullname = pwd.getpwnam(self.user).pw_gecos.strip(',')
self.fullname = find_displayname(self.user)
self.dir = dir
self.config_dir = path.join(env["HOME"], ".config/ocm")
self.config_file = path.join(self.config_dir, "config.yaml")
@ -58,28 +152,29 @@ class OCM:
f.write(yaml.dump(self.config))
def get_share_payload(self, provider_id: str) -> dict:
if self.legacy_mode:
name = self.config[self.user][provider_id]["name"],
name = name[0]
owner = pwd.getpwuid(stat(name).st_uid).pw_name
return {
"name": self.config[self.user][provider_id]["name"],
"owner": self.user + '@localhost.local',
"permission":
self.config[self.user][provider_id]["permission"],
"shareWith": self.config[self.user][provider_id]["shareWith"],
"name": name,
"providerId": provider_id,
"owner": owner,
"sender": self.user,
"senderDisplayName": self.fullname,
"shareType": self.config[self.user][provider_id]["shareType"],
"resourceType": self.config[self.user][provider_id]["resourceType"],
"protocol": {
"name": "webdav",
"options": {
"webdav": {
"sharedSecret":
self.config[self.user][provider_id]["token"],
"permissions":
'{http://open-cloud-mesh.org/ns}share-permissions'
"permissions": self.config[self.user][provider_id]["permissions"],
"uri": f'/{self.user}/{provider_id}'
}
},
"providerId": provider_id,
"resourceType": "file",
# self.config[self.user][provider_id]["resourceType"],
"shareType": self.config[self.user][provider_id]["shareType"],
"shareWith": self.config[self.user][provider_id]["shareWith"],
}
return {}
def main(self):
parser = argparse.ArgumentParser()
@ -110,11 +205,17 @@ class OCM:
def receive(self):
self.server.serve_forever()
def create_share(self, receiver, resource_type, name, share_endpoint) -> None:
def create_share(
self,
receiver,
resource_type,
name,
share_endpoint
) -> None:
provider_id = uuid.uuid4().hex
self.config[self.user][provider_id] = {
"name": name,
"permission": "read",
"permissions": ["read"],
"resourceType": resource_type,
"shareType": "user",
"shareWith": receiver,
@ -122,7 +223,6 @@ class OCM:
}
self.write_config()
payload = self.get_share_payload(provider_id)
print(payload)
headers = {
'Content-Type': 'application/json',
@ -132,49 +232,31 @@ class OCM:
share_endpoint,
headers=headers,
json=payload)
if share_req.status_code != 200:
if share_req.status_code != 201:
print("Error: " + str(share_req.status_code))
print(share_req.text)
sys.exit(1)
share_data = share_req.json()
print(share_data)
def share(self, file, directory, to):
uparse = urlparse(to)
cloudid = f'{uparse.username}@{uparse.hostname}'
if not cloudid:
print("Username not specified")
sys.exit(1)
else:
print("Sharing with " + cloudid)
sharee = uparse.username
print("Sharing with " + sharee)
discovery_endpoint = uparse.scheme + "://" + \
uparse.hostname + "/.well-known/ocm"
req = requests.get(discovery_endpoint)
if req.status_code != 200:
print("Could not find ocm-provider at " + discovery_endpoint)
print("Trying again with legacy endpoint")
# Fallback on legacy endpoint
discovery_endpoint = uparse.scheme + \
'://' + uparse.hostname + "/ocm-provider"
uparse.hostname + f":{uparse.port}/.well-known/ocm"
req = requests.get(discovery_endpoint)
if req.status_code != 200:
print("Could not find ocm-provider at " + discovery_endpoint)
sys.exit(1)
data = req.json()
share_endpoint = data['endPoint'] + "/shares"
print(share_endpoint)
enabled = data['enabled']
if not enabled:
print("OCM is not enabled on this server")
sys.exit(1)
api_version = data['apiVersion']
resource_types = data['resourceTypes']
if api_version == '1.0-proposal1':
self.legacy_mode = True
# provider = uparse.hostname
# else:
# provider = data['provider']
file_or_folder = file
resource_type = "file"
if directory:
@ -191,7 +273,7 @@ class OCM:
sys.exit(1)
self.create_share(
cloudid, resource_type, file_or_folder, share_endpoint)
sharee, resource_type, file_or_folder, share_endpoint)
if __name__ == "__main__":

Loading…
Cancel
Save