Skip to content

Commit

Permalink
feat(client): add --token argument for swcli instance login command (s…
Browse files Browse the repository at this point in the history
…tar-whale#895)

add --token argument for swcli instance login command
  • Loading branch information
tianweidut authored and anda-ren committed Aug 10, 2022
1 parent 5c2a800 commit 722bb12
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 20 deletions.
19 changes: 15 additions & 4 deletions client/starwhale/core/instance/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
import typing as t

import click
Expand Down Expand Up @@ -28,15 +29,25 @@ def _select(instance: str) -> None:

@instance_cmd.command("login")
@click.argument("instance", default="")
@click.option("--username", prompt="username", required=True)
@click.password_option(confirmation_prompt=False)
@click.option("--username")
@click.option("--password")
@click.option("--token", help="Login token")
@click.option("--alias", type=str, help="Starwhale instance alias name", required=True)
def _login(instance: str, username: str, password: str, alias: str) -> None:
def _login(instance: str, username: str, password: str, token: str, alias: str) -> None:
"""Login Starwhale Instance
* INSTANCE: Instance URI, if ignore it, swcli will login current selected instance.
"""
InstanceTermView().login(instance, username, password, alias)
if not bool(password and username) ^ bool(token):
click.echo("token or password+username, only choose one type")
sys.exit(1)

if token:
kw = {"token": token}
else:
kw = {"username": username, "password": password}

InstanceTermView().login(instance, alias, **kw)


@instance_cmd.command("logout")
Expand Down
39 changes: 30 additions & 9 deletions client/starwhale/core/instance/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,21 @@ def select(self, instance: str) -> None:
else:
console.print(f":clap: select {self.current_instance} instance")

def login(self, instance: str, username: str, password: str, alias: str) -> None:
def login(self, instance: str, alias: str, **kw: str) -> None:
if instance == STANDALONE_INSTANCE:
console.print(f":pinching_hand: skip {instance} instance login")
return

instance = instance or self.sw_remote_addr
server = fmt_http_server(instance)
url = f"{server}/api/{SW_API_VERSION}/login"
r = requests.post(
url,
timeout=DEFAULT_HTTP_TIMEOUT,
data={"userName": username, "userPwd": password},
)
if kw.get("token"):
r = self._login_request_by_token(server, kw["token"])
else:
r = self._login_request_by_username(server, kw)

if r.status_code == HTTPStatus.OK:
console.print(f":man_cook: login {server} successfully!")
token = r.headers.get("Authorization")
token = r.headers.get("Authorization") or kw.get("token")
if not token:
console.print("cannot get token, please contract starwhale")
sys.exit(1)
Expand All @@ -58,14 +56,37 @@ def login(self, instance: str, username: str, password: str, alias: str) -> None

self.update_instance(
uri=server,
user_name=username,
user_name=_d.get("name", ""),
user_role=_role or UserRoleType.NORMAL,
sw_token=token,
alias=alias,
)
else:
wrap_sw_error_resp(r, "login failed!", exit=True)

def _login_request_by_token(self, server: str, token: str) -> requests.Response:
url = f"{server}/api/{SW_API_VERSION}/user/current"
return requests.get(
url,
timeout=DEFAULT_HTTP_TIMEOUT,
verify=False,
headers={"Authorization": token},
)

def _login_request_by_username(
self, server: str, auth_request: t.Dict[str, str]
) -> requests.Response:
url = f"{server}/api/{SW_API_VERSION}/login"
return requests.post(
url,
verify=False,
timeout=DEFAULT_HTTP_TIMEOUT,
data={
"userName": auth_request["username"],
"userPwd": auth_request["password"],
},
)

def logout(self, instance: str = "") -> None:
# TODO: do real logout request
instance = instance or self.current_instance
Expand Down
10 changes: 5 additions & 5 deletions client/tests/core/test_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ def test_workflow(self, rm: Mocker):

@Mocker()
def test_login(self, rm: Mocker):
InstanceTermView().login("local", "abc", "123", alias="local")
InstanceTermView().login("local", alias="local", username="abc", password="123")

with self.assertRaises(SystemExit):
InstanceTermView().select("pre-k8s")

rm.request(
HTTPMethod.POST,
"http://1.1.0.0:8182/api/v1/login",
json={"data": {"role": {"roleName": "admin"}}},
HTTPMethod.GET,
"http://1.1.0.0:8182/api/v1/user/current",
json={"data": {"name": "abc", "role": {"roleName": "admin"}}},
headers={"Authorization": "123"},
)
InstanceTermView().login("http://1.1.0.0:8182", "abc", "123", alias="pre-k8s")
InstanceTermView().login("http://1.1.0.0:8182", alias="pre-k8s", token="123")
InstanceTermView().select("pre-k8s")
InstanceTermView().logout("pre-k8s")

Expand Down
9 changes: 7 additions & 2 deletions client/tests/core/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,15 @@ def test_list_with_project(self, req: Mocker, mock_list: MagicMock):
req.request(
HTTPMethod.POST,
f"{base_url}/login",
json={"data": {"role": {"roleName": "admin"}}},
json={"data": {"name": "foo", "role": {"roleName": "admin"}}},
headers={"Authorization": "token"},
)
InstanceTermView().login("http://1.1.0.0:8182", "foo", "bar", alias="remote")
InstanceTermView().login(
"http://1.1.0.0:8182",
alias="remote",
username="foo",
password="bar",
)
instances = InstanceTermView().list()
assert len(instances) == 2 # local and remote

Expand Down

0 comments on commit 722bb12

Please sign in to comment.