@@ -71,6 +71,18 @@ def put(self, *args, **kwargs):
7171 def delete (self , * args , ** kwargs ):
7272 return self .send_request ("DELETE" , * args , ** kwargs )
7373
74+ def _exchange_oidc_for_seafile_token (self ):
75+ url = self .server .rstrip ("/" ) + "/api2/account/token/"
76+ headers = {"Authorization" : f"Bearer { self ._token } " }
77+
78+ resp = self .session .get (url , headers = headers )
79+
80+ if resp .status_code != 200 :
81+ raise Exception (f"Failed to exchange OIDC token for Seafile token: { resp .status_code } { resp .text } " )
82+
83+ self ._seafile_token = resp .text .strip ()
84+ return self ._seafile_token
85+
7486 def send_request (self , method : str , url : str , * args , ** kwargs ):
7587 if not url .startswith ("http" ):
7688 # sanity checks.
@@ -82,21 +94,31 @@ def send_request(self, method: str, url: str, *args, **kwargs):
8294 # We cannot deepcopy the whole thing, because some values (e.g. BufferedReader objects)
8395 # cannot be pickled
8496 kwargs = copy (kwargs )
85- headers = deepcopy (kwargs .get ("headers" , {}))
86- headers .setdefault ("Authorization" , "Bearer " + self ._token )
87- kwargs ["headers" ] = headers
97+ headers = kwargs .pop ("headers" , {}).copy ()
98+
99+ if self ._seafile_token :
100+ headers .setdefault ("Authorization" , "Token " + self ._seafile_token )
101+ else :
102+ headers .setdefault ("Authorization" , "Bearer " + self ._token )
88103
89104 expected = kwargs .pop ("expected" , 200 )
90105 if not hasattr (expected , "__iter__" ):
91106 expected = (expected ,)
92- resp = self .session .request (method , url , * args , ** kwargs )
107+
108+ resp = self .session .request (method , url , headers = headers , * args , ** kwargs )
109+
110+ if resp .status_code == 401 and not self ._seafile_token :
111+ self ._seafile_token = self ._exchange_oidc_for_seafile_token ()
112+
113+ headers ["Authorization" ] = "Token " + self ._seafile_token
114+ resp = self .session .request (method , url , headers = headers , * args , ** kwargs )
115+
93116 if resp .status_code not in expected :
94- msg = "Expected %s , but get %s" % ( " or " . join ( map ( str , expected )), resp .status_code )
117+ msg = f "Expected { expected } , but got { resp .status_code } "
95118 raise ClientHttpError (resp .status_code , msg )
96119
97120 return resp
98121
99-
100122class DriveApiClient (ClientBase ):
101123 """Wraps seafile web api"""
102124
@@ -110,6 +132,7 @@ def __init__(self, username=None, password=None, token=None, env=""):
110132 self .repos = Repos (self )
111133 self .groups = Groups (self )
112134 self .file = File (self )
135+ self ._seafile_token = None
113136
114137 def _set_env (self , env = "" ):
115138 super ()._set_env (env )
0 commit comments