Skip to content

Commit 9b6aff0

Browse files
committed
uftp: add helper; store credentials etc in fs class
1 parent 14a789e commit 9b6aff0

2 files changed

Lines changed: 66 additions & 3 deletions

File tree

pyunicore/uftp/uftp.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from time import strftime
88
from time import strptime
99

10+
from pyunicore.client import Resource
1011
from pyunicore.client import Transport
1112
from pyunicore.credentials import Credential
1213

@@ -17,8 +18,6 @@ class UFTP:
1718
Uses ftplib to open the session and interact with the UFTPD server
1819
"""
1920

20-
uftp_session_tag = "___UFTP___MULTI___FILE___SESSION___MODE___"
21-
2221
def __init__(self):
2322
self.ftp = None
2423
self.uid = os.getuid()
@@ -48,7 +47,7 @@ def authenticate(self, security, base_url, base_dir="", preferences=None, persis
4847
if preferences is not None:
4948
transport.preferences = preferences
5049
req = {
51-
"serverPath": base_dir + self.uftp_session_tag,
50+
"serverPath": base_dir,
5251
}
5352
if persistent:
5453
req["persistent"] = "true"
@@ -152,3 +151,65 @@ def get_write_socket(self, path, offset):
152151
def get_read_socket(self, path, offset):
153152
path = self.normalize(path)
154153
return self.ftp.transfercmd("RETR %s" % path, rest=offset)
154+
155+
156+
class AuthServer:
157+
"""
158+
Helper to interact with an UFTP Authserver.
159+
"""
160+
161+
def __init__(self, security: Credential | Transport, url: str):
162+
if isinstance(security, Credential):
163+
self.transport = Transport(security)
164+
elif isinstance(security, Transport):
165+
self.transport = security._clone()
166+
else:
167+
raise TypeError("Need Credential or Transport object")
168+
self.auth_url = url
169+
parts = url.split("/rest/auth/")
170+
if len(parts) == 1:
171+
raise ValueError(f"Not an AuthServer URL: {url}")
172+
self.base_url = parts[0] + "/rest/auth"
173+
self.server_name = parts[1].split(":")[0]
174+
self.info = self.transport.get(url=self.base_url)
175+
176+
def authenticate(self, base_dir="", persistent=True):
177+
"""authenticate to the auth server and return a tuple (host, port, one-time-password)"""
178+
if base_dir != "" and not base_dir.endswith("/"):
179+
base_dir += "/"
180+
req = {"serverPath": base_dir}
181+
if persistent:
182+
req["persistent"] = "true"
183+
auth_url = self.base_url + "/" + self.server_name
184+
params = self.transport.post(url=auth_url, json=req).json()
185+
return params["serverHost"], params["serverPort"], params["secret"]
186+
187+
def is_sharing_supported(self) -> bool:
188+
try:
189+
return self.info[self.server_name]["dataSharing"]["enabled"]
190+
except KeyError:
191+
return False
192+
193+
def get_sharing_endpoint(self) -> Resource:
194+
resource_url = self.info[self.server_name]["dataSharing"]["href"]
195+
return Resource(security=self.transport, resource_url=resource_url)
196+
197+
def issue_auth_token(self, lifetime=-1, renewable=False, limited=False) -> str:
198+
"""
199+
Issue an authentication token (JWT) from this Auth server
200+
Args:
201+
lifetime: lifetime in seconds. If <=0, the server default will be used
202+
limited: if True, the token will only be useable on this server
203+
renewable: if True, the token can be used to get a new token
204+
"""
205+
url = self.base_url + "/token"
206+
params = {}
207+
if lifetime > 0:
208+
params["lifetime"] = lifetime
209+
if renewable:
210+
params["renewable"] = "true"
211+
if limited:
212+
params["limited"] = "true"
213+
return self.transport.get(
214+
url=url, headers={"Accept": "text/plain"}, to_json=False, params=params
215+
).text

pyunicore/uftp/uftpfs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class UFTPFS(FTPFS):
3838

3939
def __init__(self, auth_url, creds, base_path="/"):
4040
"""Creates a new UFTP FS instance authenticating using the given URL and credentials"""
41+
self.uftp_auth_credentials = creds
42+
self.uftp_auth_url = auth_url
4143
self.uftp_host, self.uftp_port, self.uftp_password = UFTP().authenticate(
4244
creds, auth_url, base_path
4345
)

0 commit comments

Comments
 (0)