Skip to content

Commit 673d1d8

Browse files
committed
fix(rsconnect): handle cookies, and a xsf header thing
1 parent a3e07f0 commit 673d1d8

File tree

2 files changed

+22
-28
lines changed

2 files changed

+22
-28
lines changed

pins/rsconnect/api.py

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,15 @@ class RsConnectApi:
133133
api_key: "str | None"
134134
server_url: "str"
135135

136-
def __init__(self, server_url, api_key=None):
136+
def __init__(
137+
self,
138+
server_url: "str | None",
139+
api_key: "str | None" = None,
140+
session: "requests.Session | None" = None,
141+
):
137142
self.server_url = server_url
138143
self.api_key = api_key
144+
self.session = requests.Session() if session is None else session
139145

140146
# utility functions -------------------------------------------------------
141147

@@ -165,10 +171,16 @@ def _get_api_key(self):
165171
if self.api_key is not None:
166172
return self.api_key
167173

168-
return os.environ[RSC_API_KEY]
174+
return os.environ.get(RSC_API_KEY)
169175

170176
def _get_headers(self):
171-
return {"Authorization": f"key {self._get_api_key()}"}
177+
api_key = self._get_api_key()
178+
rsc_xsrf = self.session.cookies.get("RSC-XSRF")
179+
180+
d_key = {"Authorization": f"key {api_key}"} if api_key is not None else {}
181+
d_rsc = {"X-RSC-XSRF": rsc_xsrf} if rsc_xsrf is not None else {}
182+
183+
return {**d_key, **d_rsc}
172184

173185
def _validate_json_response(self, data: "dict | list"):
174186
if isinstance(data, list):
@@ -209,7 +221,7 @@ def _raw_query(self, url, method="GET", return_request=False, **kwargs):
209221

210222
headers = self._get_headers()
211223

212-
r = requests.request(method, url, headers=headers, **kwargs)
224+
r = self.session.request(method, url, headers=headers, **kwargs)
213225

214226
if return_request:
215227
return r
@@ -418,46 +430,28 @@ def misc_get_applications(
418430

419431

420432
# ported from github.com/rstudio/connectapi
433+
# TODO: could just move these methods into RsConnectApi?
421434
class _HackyConnect(RsConnectApi):
422435
"""Handles logging in to connect, rather than using an API key.
423436
424437
This class allows you to create users and generate API keys on a fresh
425438
RStudio Connect service.
426439
"""
427440

428-
xsrf: "None | str"
429-
430-
def __init__(self, *args, **kwargs):
431-
self.xsrf = None
432-
super().__init__(*args, **kwargs)
433-
434-
def _get_headers(self):
435-
return {"X-RSC-XSRF": self.xsrf}
436-
437441
def login(self, user, password):
438442
res = self.query(
439443
"__login__",
440444
"POST",
441445
return_request=True,
442446
json={"username": user, "password": password},
443447
)
444-
self.xsrf = res.cookies["RSC-XSRF"]
445448
return res
446449

447450
def create_first_admin(self, user, password, email, keyname="first-key"):
448-
# TODO(question): this is run in the R rsconnect, but it returns json
449-
# error codes. tests run okay without it...
450-
# self.query_v1(
451-
# "users", "POST", json=dict(username=user, password=password, email=email)
452-
#
453-
# )
451+
self.login(user, password)
454452

455-
res = self.login(user, password)
453+
self.query("me")
456454

457-
self.query("me", cookies=res.cookies)
458-
459-
api_key = self.query(
460-
"keys", "POST", json=dict(name=keyname), cookies=res.cookies
461-
)
455+
api_key = self.query("keys", "POST", json=dict(name=keyname))
462456

463457
return RsConnectApi(self.server_url, api_key=api_key["key"])

script/setup-rsconnect/dump_api_keys.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
OUT_FILE = sys.argv[1]
77

8-
rsc = _HackyConnect("http://localhost:3939")
9-
108

119
def get_api_key(user, password, email):
10+
rsc = _HackyConnect("http://localhost:3939")
11+
1212
return rsc.create_first_admin(user, password, email).api_key
1313

1414

0 commit comments

Comments
 (0)