1
1
"""Client.py
2
2
Client is the Python public API for TerminusDB"""
3
+ import base64
3
4
import copy
4
5
import gzip
5
6
import json
@@ -269,19 +270,16 @@ def ref(self):
269
270
return self ._ref
270
271
271
272
@ref .setter
272
- def ref (self , value ):
273
- if isinstance ( value , str ) :
273
+ def ref (self , value : Optional [ str ] ):
274
+ if value is not None :
274
275
value = value .lower ()
275
- if value in ["local" , "remote" , None ]:
276
- self ._ref = value
277
- else :
278
- raise ValueError ("ref can only be 'local' or 'remote'" )
276
+ self ._ref = value
279
277
280
278
def connect (
281
279
self ,
282
280
team : str = "admin" ,
283
281
db : Optional [str ] = None ,
284
- remote_auth : str = None ,
282
+ remote_auth : Optional [ dict ] = None ,
285
283
use_token : bool = False ,
286
284
jwt_token : Optional [str ] = None ,
287
285
api_token : Optional [str ] = None ,
@@ -302,7 +300,7 @@ def connect(
302
300
Name of the team, default to be "admin"
303
301
db: optional, str
304
302
Name of the database connected
305
- remote_auth: optional, str
303
+ remote_auth: optional, dict
306
304
Remote Auth setting
307
305
key: optional, str
308
306
API key for connecting, default to be "root"
@@ -331,10 +329,13 @@ def connect(
331
329
332
330
self .team = team
333
331
self .db = db
334
- self ._remote_auth = remote_auth
332
+ self ._remote_auth_dict = remote_auth
335
333
self ._key = key
336
334
self .user = user
337
- self ._use_token = use_token
335
+ if api_token :
336
+ self ._use_token = True
337
+ else :
338
+ self ._use_token = use_token
338
339
self ._jwt_token = jwt_token
339
340
self ._api_token = api_token
340
341
self .branch = branch
@@ -623,7 +624,7 @@ def set_db(self, dbid: str, team: Optional[str] = None) -> str:
623
624
return self .connect (
624
625
team = team ,
625
626
db = dbid ,
626
- remote_auth = self ._remote_auth ,
627
+ remote_auth = self ._remote_auth_dict ,
627
628
key = self ._key ,
628
629
user = self .user ,
629
630
branch = self .branch ,
@@ -1674,7 +1675,9 @@ def pull(
1674
1675
1675
1676
return json .loads (_finish_response (result ))
1676
1677
1677
- def fetch (self , remote_id : str ) -> dict :
1678
+ def fetch (self , remote_id : str ,
1679
+ remote_auth : Optional [dict ] = None ,
1680
+ ) -> dict :
1678
1681
"""Fatch the brach from a remote
1679
1682
1680
1683
Parameters
@@ -1702,6 +1705,7 @@ def push(
1702
1705
remote_branch : Optional [str ] = None ,
1703
1706
message : Optional [str ] = None ,
1704
1707
author : Optional [str ] = None ,
1708
+ remote_auth : Optional [dict ] = None ,
1705
1709
) -> dict :
1706
1710
"""Push changes from a branch to a remote repo
1707
1711
@@ -1715,6 +1719,8 @@ def push(
1715
1719
optional commit message
1716
1720
author: str, optional
1717
1721
option to overide the author of the operation
1722
+ remote_auth: dict, optional
1723
+ optional remote authorization (uses client remote auth otherwise)
1718
1724
1719
1725
Raises
1720
1726
------
@@ -1744,10 +1750,13 @@ def push(
1744
1750
"author" : author ,
1745
1751
"message" : message ,
1746
1752
}
1753
+ if self ._remote_auth_dict or remote_auth :
1754
+ headers = {'Authorization-Remote' : self ._generate_remote_header (remote_auth ) if remote_auth else self ._remote_auth ()}
1755
+ headers .update (self ._default_headers )
1747
1756
1748
1757
result = self ._session .post (
1749
1758
self ._push_url (),
1750
- headers = self . _default_headers ,
1759
+ headers = headers ,
1751
1760
json = rc_args ,
1752
1761
auth = self ._auth (),
1753
1762
)
@@ -2232,7 +2241,8 @@ def patch_resource(
2232
2241
return json .loads (result )
2233
2242
2234
2243
def clonedb (
2235
- self , clone_source : str , newid : str , description : Optional [str ] = None
2244
+ self , clone_source : str , newid : str , description : Optional [str ] = None ,
2245
+ remote_auth : Optional [dict ] = None
2236
2246
) -> None :
2237
2247
"""Clone a remote repository and create a local copy.
2238
2248
@@ -2244,6 +2254,8 @@ def clonedb(
2244
2254
Identifier of the new repository to create.
2245
2255
Description : str, optional
2246
2256
Optional description about the cloned database.
2257
+ remote_auth : str, optional
2258
+ Optional remote authorization (uses client remote auth otherwise)
2247
2259
2248
2260
Raises
2249
2261
------
@@ -2255,15 +2267,19 @@ def clonedb(
2255
2267
>>> client = Client("http://127.0.0.1:6363/")
2256
2268
>>> client.clonedb("http://terminusdb.com/some_user/test_db", "my_test_db")
2257
2269
"""
2258
- self ._check_connection ()
2270
+ self ._check_connection (check_db = False )
2259
2271
if description is None :
2260
2272
description = f"New database { newid } "
2273
+
2274
+ if self ._remote_auth_dict or remote_auth :
2275
+ headers = {'Authorization-Remote' : self ._generate_remote_header (remote_auth ) if remote_auth else self ._remote_auth ()}
2276
+ headers .update (self ._default_headers )
2261
2277
rc_args = {"remote_url" : clone_source , "label" : newid , "comment" : description }
2262
2278
2263
2279
_finish_response (
2264
2280
self ._session .post (
2265
2281
self ._clone_url (newid ),
2266
- headers = self . _default_headers ,
2282
+ headers = headers ,
2267
2283
json = rc_args ,
2268
2284
auth = self ._auth (),
2269
2285
)
@@ -2312,7 +2328,25 @@ def _auth(self):
2312
2328
return APITokenAuth (os .environ ["TERMINUSDB_ACCESS_TOKEN" ])
2313
2329
else :
2314
2330
raise RuntimeError ("Client not connected." )
2315
- # TODO: remote_auth
2331
+
2332
+ def _remote_auth (self ):
2333
+ if self ._remote_auth_dict :
2334
+ return self ._generate_remote_header (self ._remote_auth_dict )
2335
+ elif "TERMINUSDB_REMOTE_ACCESS_TOKEN" in os .environ :
2336
+ token = os .environ ["TERMINUSDB_REMOTE_ACCESS_TOKEN" ]
2337
+ return f"Token { token } "
2338
+
2339
+ def _generate_remote_header (self , remote_auth : dict ):
2340
+ key_type = remote_auth ['type' ]
2341
+ key = remote_auth ['key' ]
2342
+ if key_type == 'http_basic' :
2343
+ username = remote_auth ['username' ]
2344
+ http_basic_creds = base64 .b64encode (f"{ username } :{ key } " .encode ('utf-8' ))
2345
+ return f"Basic { http_basic_creds } "
2346
+ elif key_type == 'token' :
2347
+ return f"Token { key } "
2348
+ # JWT is the only key type remaining
2349
+ return f"Bearer { key } "
2316
2350
2317
2351
def create_organization (self , org : str ) -> Optional [dict ]:
2318
2352
"""
0 commit comments