remotivelabs-cli 0.3.2__py3-none-any.whl → 0.3.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of remotivelabs-cli might be problematic. Click here for more details.

cli/cloud/auth/login.py CHANGED
@@ -184,32 +184,9 @@ def login(headless: bool = False) -> bool: # noqa: C901, PLR0915
184
184
  Initiate login
185
185
  """
186
186
 
187
- #
188
- # Check login.md flowchart for better understanding
189
- #
190
-
191
- active_token_file = settings.get_active_token_file()
192
- if active_token_file:
193
- # check if the active token is valid, if not, prompt user to select a new token
194
- if not Rest.has_access("/api/whoami") or active_token_file.is_expired():
195
- settings.clear_active_account()
196
- newly_activated_token_file = _do_prompt_to_use_existing_credentials()
197
- if newly_activated_token_file:
198
- return True
199
-
200
- # intentional fall through to login since we have no token
201
-
202
- else:
203
- # no active token, prompt user to select a new token
204
- newly_activated_token_file = _do_prompt_to_use_existing_credentials()
205
- if newly_activated_token_file:
206
- return True
207
-
208
- # intentional fall through to login since we have no token
209
-
210
- #
211
- # 2. Login in if no valid token found...
212
- #
187
+ newly_activated_token_file = _do_prompt_to_use_existing_credentials()
188
+ if newly_activated_token_file:
189
+ return True
213
190
 
214
191
  prepare_local_webserver()
215
192
 
cli/cloud/auth_tokens.py CHANGED
@@ -19,7 +19,7 @@ def _prompt_choice( # noqa: C901
19
19
  ) -> Optional[TokenFile]:
20
20
  accounts = settings.list_accounts()
21
21
 
22
- table = Table("#", "Active", "Type", "Token", "Account", "Created", "Expires")
22
+ table = Table("#", "Active", "Type", "Token ID", "Account", "Created", "Expires")
23
23
 
24
24
  included_tokens: list[TokenFile] = []
25
25
  excluded_tokens: list[TokenFile] = []
@@ -56,6 +56,9 @@ def _prompt_choice( # noqa: C901
56
56
  str(choice.expires),
57
57
  )
58
58
  print_unformatted(table)
59
+ print_unformatted(
60
+ ":point_right: To get the access token for your activated account, use [bold]remotive cloud auth print-access-token[/bold]"
61
+ )
59
62
 
60
63
  if skip_prompt:
61
64
  return None
cli/topology/cmd.py CHANGED
@@ -5,10 +5,12 @@ import typer
5
5
  from cli.topology.start_trial import (
6
6
  MissingOrganizationError,
7
7
  NoActiveAccountError,
8
+ NoOrganizationOrPermissionError,
8
9
  NotAuthorizedError,
9
10
  NotAuthorizedToStartTrialError,
10
11
  NotSignedInError,
11
12
  SubscriptionExpiredError,
13
+ get_organization_and_account,
12
14
  start_trial,
13
15
  )
14
16
  from cli.typer import typer_utils
@@ -30,12 +32,34 @@ def start_trial_cmd( # noqa: C901
30
32
 
31
33
  You can read more at https://docs.remotivelabs.com/docs/remotive-topology.
32
34
  """
35
+
33
36
  try:
34
- subscription = start_trial(organization)
35
- if subscription.type == "trial":
36
- print_generic_message(f"topology trial active, expires {subscription.end_date}")
37
- elif subscription.type == "paid":
38
- print_generic_message(f"you already have a topology subscription, expires {subscription.end_date or 'Never'}")
37
+ (valid_organization, _) = get_organization_and_account(organization_uid=organization)
38
+ ok_to_start_trial = typer.confirm(
39
+ f"You are about to start trial of RemotiveTopology for {valid_organization.display_name}"
40
+ f" (uid={valid_organization.uid}), continue?",
41
+ default=True,
42
+ )
43
+ if not ok_to_start_trial:
44
+ return
45
+
46
+ (subscription, created) = start_trial(organization)
47
+
48
+ def print_start_trial_result() -> None:
49
+ assert subscription.type in ("trial", "paid"), f"Unexpected subscription type: {subscription.type}"
50
+ kind = None
51
+ status = None
52
+ if subscription.type == "trial":
53
+ status = "started now" if created else "is already active"
54
+ kind = "trial subscription"
55
+ elif subscription.type == "paid":
56
+ status = "started now" if created else "is already started"
57
+ kind = "subscription"
58
+
59
+ end_text = subscription.end_date or "Never"
60
+ print_generic_message(f"RemotiveTopology {kind} for {valid_organization.display_name} {status}, expires {end_text}")
61
+
62
+ print_start_trial_result()
39
63
 
40
64
  except NotSignedInError:
41
65
  print_generic_error(
@@ -46,7 +70,7 @@ def start_trial_cmd( # noqa: C901
46
70
 
47
71
  except NoActiveAccountError:
48
72
  print_hint(
49
- "You have not actived your account, please run [bold]remotive cloud auth activate[/bold] to choose an account"
73
+ "You have not activated your account, please run [bold]remotive cloud auth activate[/bold] to choose an account"
50
74
  "or [bold]remotive cloud auth login[/bold] to sign-in"
51
75
  )
52
76
  raise typer.Exit(3)
@@ -63,15 +87,25 @@ def start_trial_cmd( # noqa: C901
63
87
  raise typer.Exit(5)
64
88
 
65
89
  except NotAuthorizedToStartTrialError as e:
66
- print_generic_error(f"You are not allowed to start-trial topology in organization {e.organization}")
90
+ print_generic_error(f"You are not allowed to start-trial topology in organization {e.organization.display_name}.")
67
91
  raise typer.Exit(6)
68
92
 
69
93
  except SubscriptionExpiredError as e:
70
94
  if e.subscription.type == "trial":
71
- print_generic_error(f"Your Topology trial expired {e.subscription.end_date}, please contact support@remotivelabs.com")
95
+ print_generic_error(
96
+ f"RemotiveTopology trial in {e.organization.display_name} expired"
97
+ f" {e.subscription.end_date}, please contact support@remotivelabs.com"
98
+ )
72
99
  raise typer.Exit(7)
73
100
 
74
- print_generic_error(f"Your Topology subscription has expired {e.subscription.end_date}, please contact support@remotivelabs.com")
101
+ print_generic_error(
102
+ f"RemotiveTopology subscription in {e.organization.display_name} has expired"
103
+ f" {e.subscription.end_date}, please contact support@remotivelabs.com"
104
+ )
105
+ raise typer.Exit(7)
106
+
107
+ except NoOrganizationOrPermissionError as e:
108
+ print_generic_error(f"Organization id {e.organization} does not exist or you do not have permission to access it.")
75
109
  raise typer.Exit(7)
76
110
 
77
111
  except Exception as e:
@@ -26,6 +26,14 @@ class NotAuthorizedError(Exception):
26
26
  self.account = account
27
27
 
28
28
 
29
+ class NoOrganizationOrPermissionError(Exception):
30
+ """Raised when the user is trying to access an organization that it does not have access to or it does not exist"""
31
+
32
+ def __init__(self, account: Account, organization_uid: str):
33
+ self.account = account
34
+ self.organization = organization_uid
35
+
36
+
29
37
  class MissingOrganizationError(Exception):
30
38
  """Raised when the user has not specified an organization and no default organization is set"""
31
39
 
@@ -33,7 +41,7 @@ class MissingOrganizationError(Exception):
33
41
  class NotAuthorizedToStartTrialError(Exception):
34
42
  """Raised when the user is not authorized to start a topology trial"""
35
43
 
36
- def __init__(self, account: Account, organization: str):
44
+ def __init__(self, account: Account, organization: Organization):
37
45
  self.account = account
38
46
  self.organization = organization
39
47
 
@@ -41,8 +49,15 @@ class NotAuthorizedToStartTrialError(Exception):
41
49
  class SubscriptionExpiredError(Exception):
42
50
  """Raised when the subscription has expired"""
43
51
 
44
- def __init__(self, subscription: Subscription):
52
+ def __init__(self, subscription: Subscription, organization: Organization):
45
53
  self.subscription = subscription
54
+ self.organization = organization
55
+
56
+
57
+ @dataclass
58
+ class Organization:
59
+ uid: str
60
+ display_name: str
46
61
 
47
62
 
48
63
  @dataclass
@@ -67,12 +82,7 @@ class Subscription:
67
82
  )
68
83
 
69
84
 
70
- def start_trial(organization: str | None = None) -> Subscription:
71
- """
72
- Start a 30 day trial subscription for running RemotiveTopology.
73
-
74
- # TODO: move authentication (and basic authorization) to a logged_in decorator
75
- """
85
+ def get_organization_and_account(organization_uid: str | None = None) -> tuple[Organization, Account]:
76
86
  active_account = settings.get_active_account()
77
87
  active_token_file = settings.get_active_token_file()
78
88
 
@@ -84,22 +94,41 @@ def start_trial(organization: str | None = None) -> Subscription:
84
94
  if not RestHelper.has_access("/api/whoami"):
85
95
  raise NotAuthorizedError(account=active_account)
86
96
 
87
- valid_org = organization or active_account.default_organization
88
- if not valid_org:
97
+ org_uid = organization_uid or active_account.default_organization
98
+ if not org_uid:
89
99
  raise MissingOrganizationError()
90
100
 
91
- res = RestHelper.handle_get(f"/api/bu/{valid_org}/features/topology", return_response=True, allow_status_codes=[403, 404])
101
+ response = RestHelper.handle_get(f"/api/bu/{organization_uid}", return_response=True, allow_status_codes=[403, 404])
102
+ if response.status_code in (403, 404):
103
+ raise NoOrganizationOrPermissionError(account=active_account, organization_uid=org_uid)
104
+
105
+ display_name = response.json()["displayName"]
106
+
107
+ return Organization(uid=org_uid, display_name=display_name), active_account
108
+
109
+
110
+ def start_trial(organization_uid: str | None = None) -> tuple[Subscription, bool]:
111
+ """
112
+ Start a 30 day trial subscription for running RemotiveTopology,
113
+ If a trial is already started in this organization, returns the existing trial instead.
114
+ Returns (subscription, created_now).
115
+ """
116
+
117
+ (organization, active_account) = get_organization_and_account(organization_uid)
118
+
119
+ res = RestHelper.handle_get(f"/api/bu/{organization.uid}/features/topology", return_response=True, allow_status_codes=[403, 404])
92
120
  if res.status_code == 403:
93
- raise NotAuthorizedToStartTrialError(account=active_account, organization=valid_org)
121
+ raise NotAuthorizedToStartTrialError(account=active_account, organization=organization)
122
+
123
+ created_now = False
94
124
  if res.status_code == 404:
95
- created = RestHelper.handle_post(f"/api/bu/{valid_org}/features/topology", return_response=True)
125
+ created = RestHelper.handle_post(f"/api/bu/{organization.uid}/features/topology", return_response=True)
96
126
  subscription = Subscription.from_dict(created.json())
127
+ created_now = True
97
128
  else:
98
- # 200 OK means we already have a valid subscription
99
129
  subscription = Subscription.from_dict(res.json())
100
130
 
101
- # check subscription validity
102
131
  if subscription.end_date < datetime.datetime.now().date():
103
- raise SubscriptionExpiredError(subscription=subscription)
132
+ raise SubscriptionExpiredError(subscription=subscription, organization=organization)
104
133
 
105
- return subscription
134
+ return subscription, created_now
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: remotivelabs-cli
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: CLI for operating RemotiveCloud and RemotiveBroker
5
5
  Author: Johan Rask
6
6
  Author-email: johan.rask@remotivelabs.com
@@ -19,8 +19,8 @@ cli/broker/signals.py,sha256=1xldsY3SVcVp-EEsrd6_uoBjrTRMSEONHpOA6SmWxJ4,8245
19
19
  cli/cloud/__init__.py,sha256=xFaDg2zho_glvDBDB0_8HRNICVwHeYFEz-yMhzTcCjI,987
20
20
  cli/cloud/auth/__init__.py,sha256=MtQ01-n8CgZb9Y_SvxwZUgj44Yo0dFAU3_XwhQiUYtw,54
21
21
  cli/cloud/auth/cmd.py,sha256=lv9D0Q7G1RgI2IO1vkz_VVBA_STCPmdJax3QkeiMwg4,3968
22
- cli/cloud/auth/login.py,sha256=3kc9L6-HOBwzf4Fxis2SBm_q5ObTuzSn4Ic_GkLF0Jk,11121
23
- cli/cloud/auth_tokens.py,sha256=ExIsCmzoM_MCaYQ5aL4j0Cdyq81IFJ4HJAt-zn1H2L4,5061
22
+ cli/cloud/auth/login.py,sha256=s_VdOunFLFWVl68sGTJgaJNksQquYGTfm5pJ6mBbEx0,10321
23
+ cli/cloud/auth_tokens.py,sha256=Tj6-fMkOGjT_XHU8m8nMQcIj55MaLwqfedv15yKsYp0,5225
24
24
  cli/cloud/brokers.py,sha256=cXYKm_-CYJZH0muXAPwUMKIiqBiW6Y9WG5kmkQb3FuU,3849
25
25
  cli/cloud/configs.py,sha256=atInBsh16woPmjC0dpnRTpbY4WRgseBOWe8VwpqwO_o,3745
26
26
  cli/cloud/licenses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -58,8 +58,8 @@ cli/tools/can/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  cli/tools/can/can.py,sha256=ovTqzsjJP-z9H5RiJ3f_OXMpELqM3d09JY4JfPpT3-Q,2171
59
59
  cli/tools/tools.py,sha256=jhLfrFDqkmWV3eBAzNwBf6WgDGrz7sOhgVCia36Twn8,232
60
60
  cli/topology/__init__.py,sha256=MyorYLmC2wAd_z5GdQENEYLgoCiNYgwQ16BOX93IBtI,52
61
- cli/topology/cmd.py,sha256=vtAw-vIJxf2dogVaqqUm8jRzUJrC7fVuov3sSV7l0sc,3101
62
- cli/topology/start_trial.py,sha256=GNB2E-Ia18UpXQZ4fViGq5-pRq69vinDBLwzImsz2GY,3414
61
+ cli/topology/cmd.py,sha256=TCSwURxTmAyU4Lvu-Rk8ymPardmAARuFEn-kTckksvw,4408
62
+ cli/topology/start_trial.py,sha256=b0PWAFS9Q67kCLq9zZ-t6vl0c3WMiF4BF4nN5yqyZ-I,4538
63
63
  cli/typer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
64
  cli/typer/typer_utils.py,sha256=eUrVOEOKY_MnfiJMAxvEurP1Q79z9pq83mJjocP8lhI,686
65
65
  cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -67,8 +67,8 @@ cli/utils/console.py,sha256=JF39S9oS1lehFexjdLQKp17oINNvFZJLg_M2SDCjkvA,1754
67
67
  cli/utils/rest_helper.py,sha256=ZHc7TMNVa07kJWDQ_OEoeaGhzYu8BinSXJJX8R_wX_8,14135
68
68
  cli/utils/time.py,sha256=TEKcNZ-pQoJ7cZ6hQmVD0sTRwRm2rBy51-MuDNdO4S4,296
69
69
  cli/utils/versions.py,sha256=mHs_BCk0-wwPfCHIIQBlpFkgipSWkw9jUaZ-USH8ODY,3824
70
- remotivelabs_cli-0.3.2.dist-info/LICENSE,sha256=qDPP_yfuv1fF-u7EfexN-cN3M8aFgGVndGhGLovLKz0,608
71
- remotivelabs_cli-0.3.2.dist-info/METADATA,sha256=QMZTstCqkjghu2nqeUb7jyHqJO3aXeKFV_lTq0Nnj4k,1521
72
- remotivelabs_cli-0.3.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
73
- remotivelabs_cli-0.3.2.dist-info/entry_points.txt,sha256=lvDhPgagLqW_KTnLPCwKSqfYlEp-1uYVosRiPjsVj10,45
74
- remotivelabs_cli-0.3.2.dist-info/RECORD,,
70
+ remotivelabs_cli-0.3.4.dist-info/LICENSE,sha256=qDPP_yfuv1fF-u7EfexN-cN3M8aFgGVndGhGLovLKz0,608
71
+ remotivelabs_cli-0.3.4.dist-info/METADATA,sha256=ROqIXVSgE__Tey6UbKorZorckyXtHcvSRc21IeMQqEE,1521
72
+ remotivelabs_cli-0.3.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
73
+ remotivelabs_cli-0.3.4.dist-info/entry_points.txt,sha256=lvDhPgagLqW_KTnLPCwKSqfYlEp-1uYVosRiPjsVj10,45
74
+ remotivelabs_cli-0.3.4.dist-info/RECORD,,