Skip to content

Commit c7a49fd

Browse files
feat: Use get_cookie_for_app to login (#206)
With this PR the cli uses `get_cookie_for_app` endpoint with a local callback server to authenticate the user via browser instead of `username/password`. As a fallback username/password works too.
1 parent d7c910d commit c7a49fd

2 files changed

Lines changed: 71 additions & 7 deletions

File tree

src/viur_cli/scriptor/cli.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from viur.scriptor import Modules
1313
from ..cli import cli
1414
from ..cli import scriptor_config
15+
from .login import ensure_login
1516

1617
# Global modules instance that will be initialized when needed
1718
_modules = None
@@ -43,7 +44,6 @@ def configure(url: str, username: str, working_dir: str):
4344
Manage configuration settings.
4445
"""
4546

46-
4747
if url:
4848
scriptor_config["base_url"] = url
4949

@@ -61,6 +61,14 @@ def setup():
6161
"""
6262

6363
base_url = scriptor_config.get("base_url")
64+
65+
try:
66+
click.echo("This Feature is only avalible on viur-core 3.8.19 or higher.")
67+
res = ensure_login("", host=base_url)
68+
if res:
69+
return
70+
except KeyboardInterrupt:
71+
pass
6472
try:
6573
session = requests.session()
6674
skey = session.get(base_url + "/json/skey")
@@ -96,13 +104,11 @@ def check_session(ctx: click.Context):
96104

97105
response = s.get(base_url + "/vi/user/view/self", cookies=scriptor_config.get("cookies", {}))
98106
if not response.ok:
99-
click.echo("Invalid session, please run `viur script setup` again.")
107+
click.echo("Invalid session, please run `viur script setup` again. okay ?")
100108
ctx.invoke(setup)
101109
ctx.close()
102-
#FIXME We need this ?
103-
# Update modules with cookies
104-
modules = get_modules()
105-
# modules.request.cookies = cookiejar_from_dict(scriptor_config.get("cookies", {}))
110+
# init modules
111+
get_modules()
106112

107113

108114
@script.command()
@@ -114,7 +120,6 @@ def pull(ctx: click.Context, force: bool):
114120
"""
115121
check_session(ctx)
116122

117-
118123
async def main():
119124
# In the new API, we don't need to call structure
120125
modules = get_modules()

src/viur_cli/scriptor/login.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python3
2+
import contextvars
3+
import json
4+
import urllib.parse
5+
import webbrowser
6+
from pathlib import Path
7+
from wsgiref.simple_server import make_server
8+
from ..cli import scriptor_config
9+
import requests
10+
11+
PORT = 60_000
12+
13+
14+
15+
def callback_app(environ: dict, start_response):
16+
qs = urllib.parse.parse_qs(environ["QUERY_STRING"])
17+
callback_app.cookie.set(qs["cookie"][0])
18+
callback_app.app.set(qs["app"][0])
19+
start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
20+
return [b"This was successful. You can now close this site."]
21+
22+
23+
callback_app.cookie = contextvars.ContextVar("Cookie")
24+
callback_app.app = contextvars.ContextVar("App")
25+
26+
27+
def ensure_login(
28+
app: str,
29+
*,
30+
open_browser: bool = True,
31+
host: str = None,
32+
) -> bool:
33+
34+
35+
with make_server('', PORT, callback_app) as httpd:
36+
sa = httpd.socket.getsockname()
37+
print("Serving HTTP on", sa[0], "port", sa[1], "...")
38+
39+
if host is None:
40+
host = f"https://{app}.appspot.com"
41+
url = f'{host}/vi/user/get_cookie_for_app?redirect_to=http://localhost:{PORT}'
42+
if open_browser:
43+
webbrowser.open(url)
44+
else:
45+
print("Open this URL in your browser:")
46+
print(url)
47+
48+
httpd.handle_request() # serve one request, then exit
49+
50+
cookie_str: str = callback_app.cookie.get()
51+
key, value = cookie_str.split(";", 1)[0].split("=")
52+
scriptor_config.get("cookies",{})[key] = value
53+
scriptor_config.save()
54+
55+
return True
56+
57+
58+
59+

0 commit comments

Comments
 (0)