RemoteRF 2.2.1__tar.gz → 2.2.3__tar.gz
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.
- {remoterf-2.2.1/src/remoterf.egg-info → remoterf-2.2.3}/PKG-INFO +1 -1
- {remoterf-2.2.1 → remoterf-2.2.3}/pyproject.toml +1 -1
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/acc_login.py +2 -1
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/app.py +8 -3
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/deployment/homes.py +21 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/remoterf_cli.py +45 -8
- {remoterf-2.2.1 → remoterf-2.2.3/src/remoterf.egg-info}/PKG-INFO +1 -1
- remoterf-2.2.3/tests/test_cli_login_fresh.py +162 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_homes.py +1 -6
- remoterf-2.2.1/tests/test_cli_login_fresh.py +0 -82
- {remoterf-2.2.1 → remoterf-2.2.3}/LICENSE +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/README.md +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/setup.cfg +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/deployment_capabilities.proto +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/deployment_capabilities_pb2.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/deployment_capabilities_pb2_grpc.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/grpc.proto +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/grpc_pb2.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/v2_codec.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/tos_notice.txt +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/utils/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/utils/ansi_codes.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/utils/api_token.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/utils/banner.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/utils/list_string.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/utils/process_arg.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/config/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/config/cert_fetcher.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/config/config.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/banner_note.txt +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/direct_path.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/dynamic_v2_transport.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/grpc_acc.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/grpc_client.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/secure_channel.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/core/v2_errors.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/deployment/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/deployment/backend.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/deployment/direct.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/deployment/http.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/deployment/state.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/_virtual.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/adalm_pluto/adalm_pluto_remote.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/dynamic_device.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/dynamic_v2.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/hackrf/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/hackrf/hackrf_remote.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/rtl_sdr/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/rtl_sdr/rtl_sdr_remote.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/sim_sdr/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/sim_sdr/sim_sdr_remote.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/support/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/support/ti_mmwave.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/support/uhd.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/support/uhd_dsp.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/support/uhd_v2.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/ti_mmwave/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/ti_mmwave/ti_mmwave_remote.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/usrp/__init__.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/usrp/usrp_remote.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/drivers/usrp/usrp_remote.pyi +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/version.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf.egg-info/SOURCES.txt +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf.egg-info/dependency_links.txt +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf.egg-info/entry_points.txt +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf.egg-info/requires.txt +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf.egg-info/top_level.txt +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_banner.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_config_address.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_deployment_accounts.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_direct_path_fixed.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_direct_path_partner.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_direct_path_race.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_dynamic_device_codegen.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_dynamic_v2.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_federated_devices.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_fetch_idl_fallback.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_finish_prompt.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_gate_i_direct_path.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_grpc_client_target.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_native_account_credentials.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_native_devices.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_partner_dynamic_v2.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_pluto_virtual.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_process_arg.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_remoterf_cli.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_ti_mmwave.py +0 -0
- {remoterf-2.2.1 → remoterf-2.2.3}/tests/test_upgrade_rescue.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author-email: Ethan Ge <ethoGalaxy@gmail.com>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "remoterf"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.3"
|
|
8
8
|
description = "A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "GPL-3.0-or-later"
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
16
|
def main(*, register=False, enrollment_code=None, server_label=None, show_banner=True,
|
|
17
|
-
home=None, route=None):
|
|
17
|
+
home=None, route=None, username=None):
|
|
18
18
|
from .app import run
|
|
19
19
|
return run(
|
|
20
20
|
register=register,
|
|
@@ -23,4 +23,5 @@ def main(*, register=False, enrollment_code=None, server_label=None, show_banner
|
|
|
23
23
|
show_banner=show_banner,
|
|
24
24
|
home=home,
|
|
25
25
|
route=route,
|
|
26
|
+
username=username,
|
|
26
27
|
)
|
|
@@ -116,6 +116,8 @@ def _password_confirmation(*, enforce_policy=False):
|
|
|
116
116
|
|
|
117
117
|
# The code typed at `remoterf -r`, used once for this registration.
|
|
118
118
|
pending_enrollment_code = None
|
|
119
|
+
# A username already given (found on Global): the login asks only the password.
|
|
120
|
+
pending_username = None
|
|
119
121
|
# The saved home this shell is attached to (None on a bare direct profile).
|
|
120
122
|
home_name = None
|
|
121
123
|
# The route it was reached over (None on a bare direct profile or an HTTPS home).
|
|
@@ -249,7 +251,9 @@ def _account_command(command):
|
|
|
249
251
|
return False
|
|
250
252
|
if command in ('l', 'login'):
|
|
251
253
|
printf(f"Login to {_home_name()}", (Sty.BOLD, Sty.BLUE))
|
|
252
|
-
|
|
254
|
+
global pending_username
|
|
255
|
+
account.username = pending_username or _ask('Username or Email' if account.is_https_home else 'Username')
|
|
256
|
+
pending_username = None
|
|
253
257
|
account.password = _ask('Password (Hidden)', hidden=True)
|
|
254
258
|
ok = bool(account.login_user(remember=not account.is_https_home))
|
|
255
259
|
if ok:
|
|
@@ -1585,8 +1589,9 @@ def interactive_reserve_next_days_auto():
|
|
|
1585
1589
|
|
|
1586
1590
|
|
|
1587
1591
|
def run(backend=None, *, register=False, enrollment_code=None, server_label=None,
|
|
1588
|
-
show_banner=True, home=None, route=None):
|
|
1589
|
-
global account, session, server_addr, pending_enrollment_code, home_name, current_route
|
|
1592
|
+
show_banner=True, home=None, route=None, username=None):
|
|
1593
|
+
global account, session, server_addr, pending_enrollment_code, home_name, current_route, pending_username
|
|
1594
|
+
pending_username = username
|
|
1590
1595
|
home_name = home
|
|
1591
1596
|
current_route = route
|
|
1592
1597
|
from ..deployment.backend import selected_backend
|
|
@@ -268,6 +268,27 @@ def connect(name: str) -> dict:
|
|
|
268
268
|
return route
|
|
269
269
|
|
|
270
270
|
|
|
271
|
+
# Global's own account home, by its name on Global's broker.
|
|
272
|
+
GLOBAL_HOME = "home"
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def lookup_username(global_origin: str, username: str) -> str | None:
|
|
276
|
+
"""The deployment that holds this username on Global, or None."""
|
|
277
|
+
from .http import AccountBackendError, JsonTransport
|
|
278
|
+
|
|
279
|
+
transport = JsonTransport(global_origin)
|
|
280
|
+
try:
|
|
281
|
+
return transport.request(
|
|
282
|
+
"POST", "/v2/broker/usernames/lookup", data={"username": username}
|
|
283
|
+
)["deployment"]
|
|
284
|
+
except AccountBackendError as exc:
|
|
285
|
+
if exc.code == "not_found":
|
|
286
|
+
return None
|
|
287
|
+
raise
|
|
288
|
+
finally:
|
|
289
|
+
transport.close()
|
|
290
|
+
|
|
291
|
+
|
|
271
292
|
def register_home(host: str) -> tuple[str, dict, dict]:
|
|
272
293
|
"""Learn a deployment from its code, save it, and connect to it."""
|
|
273
294
|
document = discover(host)
|
|
@@ -180,7 +180,8 @@ def print_help() -> None:
|
|
|
180
180
|
|
|
181
181
|
def _account_shell(*, register: bool, enrollment_code: str | None = None,
|
|
182
182
|
server_label: str | None = None, show_banner: bool = True,
|
|
183
|
-
home: str | None = None, route: dict | None = None
|
|
183
|
+
home: str | None = None, route: dict | None = None,
|
|
184
|
+
username: str | None = None) -> int:
|
|
184
185
|
ok, _ = _ensure_config_present()
|
|
185
186
|
if not ok:
|
|
186
187
|
_print_server_unavailable()
|
|
@@ -198,6 +199,7 @@ def _account_shell(*, register: bool, enrollment_code: str | None = None,
|
|
|
198
199
|
show_banner=show_banner,
|
|
199
200
|
home=home,
|
|
200
201
|
route=route,
|
|
202
|
+
username=username,
|
|
201
203
|
)
|
|
202
204
|
or 0
|
|
203
205
|
)
|
|
@@ -212,7 +214,7 @@ def _global_origin() -> str:
|
|
|
212
214
|
return os.getenv('REMOTERF_GLOBAL_ORIGIN', 'https://global.remoterf.net')
|
|
213
215
|
|
|
214
216
|
|
|
215
|
-
def _use_global(*, register: bool, show_banner: bool = True) -> int:
|
|
217
|
+
def _use_global(*, register: bool, show_banner: bool = True, username: str | None = None) -> int:
|
|
216
218
|
"""Register or log in with the RemoteRF Global identity itself.
|
|
217
219
|
|
|
218
220
|
A Global-native account is complete on its own: it needs no deployment
|
|
@@ -238,7 +240,7 @@ def _use_global(*, register: bool, show_banner: bool = True) -> int:
|
|
|
238
240
|
except (RuntimeError, ValueError) as exc:
|
|
239
241
|
print(f'Could not reach RemoteRF Global: {exc}')
|
|
240
242
|
return 2
|
|
241
|
-
return _account_shell(register=register, show_banner=show_banner)
|
|
243
|
+
return _account_shell(register=register, show_banner=show_banner, username=username)
|
|
242
244
|
|
|
243
245
|
|
|
244
246
|
@contextmanager
|
|
@@ -397,13 +399,11 @@ def _login(target: str | None) -> int:
|
|
|
397
399
|
# Nothing saved. A legacy address in .env still logs in there;
|
|
398
400
|
# a fresh install has nothing to log in to, so `-l` is `-r`.
|
|
399
401
|
if not _ensure_config_present()[0]:
|
|
400
|
-
return
|
|
402
|
+
return _login_by_username()
|
|
401
403
|
return _account_shell(register=False)
|
|
402
404
|
if target == 'global':
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
printf('Run: ', Sty.GRAY, 'remoterf --register', Sty.CYAN)
|
|
406
|
-
return 2
|
|
405
|
+
# Global's address is built in, so a fresh install can log in to an
|
|
406
|
+
# existing Global account without registering again.
|
|
407
407
|
return _use_global(register=False)
|
|
408
408
|
if target not in homes.homes():
|
|
409
409
|
printf(f'No saved home named {target!r}.', Sty.WARNING)
|
|
@@ -411,6 +411,43 @@ def _login(target: str | None) -> int:
|
|
|
411
411
|
return _use_home(target, register=False)
|
|
412
412
|
|
|
413
413
|
|
|
414
|
+
def _login_by_username() -> int:
|
|
415
|
+
"""A fresh install: Global knows which lab holds a username, so the
|
|
416
|
+
account is found by name. Enter registers, as `-l` here always did."""
|
|
417
|
+
from remoterf.deployment import homes
|
|
418
|
+
|
|
419
|
+
try:
|
|
420
|
+
name = input('Username (Enter to register): ').strip()
|
|
421
|
+
except (EOFError, KeyboardInterrupt):
|
|
422
|
+
print()
|
|
423
|
+
return 1
|
|
424
|
+
if not name:
|
|
425
|
+
return _register()
|
|
426
|
+
try:
|
|
427
|
+
with _working("Looking up your account…"):
|
|
428
|
+
deployment = homes.lookup_username(_global_origin(), name)
|
|
429
|
+
except (RuntimeError, ValueError) as exc:
|
|
430
|
+
printf(f'Could not reach RemoteRF Global: {_reason(exc)}', Sty.WARNING)
|
|
431
|
+
return 2
|
|
432
|
+
if deployment is None:
|
|
433
|
+
printf(f'No RemoteRF account named {name!r} was found.', Sty.WARNING)
|
|
434
|
+
printf('Run: ', Sty.GRAY, 'remoterf --register', Sty.CYAN)
|
|
435
|
+
return 2
|
|
436
|
+
if deployment == homes.GLOBAL_HOME:
|
|
437
|
+
return _use_global(register=False, username=name)
|
|
438
|
+
host = f'{deployment}.{homes.GLOBAL_DOMAIN}'
|
|
439
|
+
try:
|
|
440
|
+
with _working(f"Looking up {host}…"):
|
|
441
|
+
lab, home, route = homes.register_home(host)
|
|
442
|
+
except (RuntimeError, ValueError) as exc:
|
|
443
|
+
printf(f'Could not reach {host}: {_reason(exc)}', Sty.WARNING)
|
|
444
|
+
return 2
|
|
445
|
+
return _account_shell(
|
|
446
|
+
register=False, server_label=f'{lab} ({_route_label(route)})',
|
|
447
|
+
home=lab, route={**route, 'home': home}, username=name,
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
|
|
414
451
|
def _print_pick_a_target() -> int:
|
|
415
452
|
_print_homes()
|
|
416
453
|
printf('Choose one: ', Sty.GRAY, 'remoterf --login <name>', Sty.CYAN)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author-email: Ethan Ge <ethoGalaxy@gmail.com>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""`remoterf -l` on a fresh install is `remoterf -r`; a configured client logs in."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import tempfile
|
|
5
|
+
from unittest import mock
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _fresh_home():
|
|
9
|
+
tmp = tempfile.TemporaryDirectory()
|
|
10
|
+
env = {k: v for k, v in os.environ.items() if not k.startswith("REMOTERF_")}
|
|
11
|
+
env["HOME"] = tmp.name
|
|
12
|
+
return tmp, mock.patch.dict(os.environ, env, clear=True)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_login_on_a_fresh_install_registers_on_enter():
|
|
16
|
+
from remoterf import remoterf_cli
|
|
17
|
+
|
|
18
|
+
tmp, env = _fresh_home()
|
|
19
|
+
with tmp, env, \
|
|
20
|
+
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
21
|
+
mock.patch("builtins.input", return_value=""), \
|
|
22
|
+
mock.patch("remoterf.deployment.homes.lookup_username") as lookup, \
|
|
23
|
+
mock.patch.object(remoterf_cli, "_register", return_value=0) as register, \
|
|
24
|
+
mock.patch.object(remoterf_cli, "_account_shell") as shell:
|
|
25
|
+
assert remoterf_cli._login(None) == 0
|
|
26
|
+
register.assert_called_once_with()
|
|
27
|
+
shell.assert_not_called()
|
|
28
|
+
lookup.assert_not_called()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_login_on_a_fresh_install_finds_the_account_by_username():
|
|
32
|
+
from remoterf import remoterf_cli
|
|
33
|
+
|
|
34
|
+
tmp, env = _fresh_home()
|
|
35
|
+
route = {"kind": "relay", "host": "ucla.global.remoterf.net", "port": 12321}
|
|
36
|
+
with tmp, env, \
|
|
37
|
+
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
38
|
+
mock.patch("builtins.input", return_value="ian"), \
|
|
39
|
+
mock.patch("remoterf.deployment.homes.lookup_username", return_value="ucla") as lookup, \
|
|
40
|
+
mock.patch("remoterf.deployment.homes.register_home",
|
|
41
|
+
return_value=("ucla", {"display_name": "UCLA"}, route)) as register_home, \
|
|
42
|
+
mock.patch.object(remoterf_cli, "_account_shell", return_value=0) as shell:
|
|
43
|
+
assert remoterf_cli._login(None) == 0
|
|
44
|
+
assert lookup.call_args.args[1] == "ian"
|
|
45
|
+
register_home.assert_called_once_with("ucla.global.remoterf.net")
|
|
46
|
+
assert shell.call_args.kwargs["register"] is False
|
|
47
|
+
assert shell.call_args.kwargs["home"] == "ucla"
|
|
48
|
+
assert shell.call_args.kwargs["username"] == "ian"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_login_on_a_fresh_install_finds_a_global_account():
|
|
52
|
+
from remoterf import remoterf_cli
|
|
53
|
+
|
|
54
|
+
tmp, env = _fresh_home()
|
|
55
|
+
with tmp, env, \
|
|
56
|
+
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
57
|
+
mock.patch("builtins.input", return_value="ian"), \
|
|
58
|
+
mock.patch("remoterf.deployment.homes.lookup_username", return_value="home"), \
|
|
59
|
+
mock.patch.object(remoterf_cli, "_use_global", return_value=0) as use_global:
|
|
60
|
+
assert remoterf_cli._login(None) == 0
|
|
61
|
+
use_global.assert_called_once_with(register=False, username="ian")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_login_on_a_fresh_install_with_an_unknown_username():
|
|
65
|
+
from remoterf import remoterf_cli
|
|
66
|
+
|
|
67
|
+
tmp, env = _fresh_home()
|
|
68
|
+
with tmp, env, \
|
|
69
|
+
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
70
|
+
mock.patch("builtins.input", return_value="nobody"), \
|
|
71
|
+
mock.patch("remoterf.deployment.homes.lookup_username", return_value=None), \
|
|
72
|
+
mock.patch.object(remoterf_cli, "_register") as register, \
|
|
73
|
+
mock.patch.object(remoterf_cli, "_account_shell") as shell:
|
|
74
|
+
assert remoterf_cli._login(None) == 2
|
|
75
|
+
register.assert_not_called()
|
|
76
|
+
shell.assert_not_called()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_login_global_on_a_fresh_install_logs_in_to_global():
|
|
80
|
+
from remoterf import remoterf_cli
|
|
81
|
+
|
|
82
|
+
tmp, env = _fresh_home()
|
|
83
|
+
with tmp, env, \
|
|
84
|
+
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
85
|
+
mock.patch.object(remoterf_cli, "_use_global", return_value=0) as use_global:
|
|
86
|
+
assert remoterf_cli._login("global") == 0
|
|
87
|
+
use_global.assert_called_once_with(register=False)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_login_with_a_legacy_address_still_logs_in_there():
|
|
91
|
+
from remoterf import remoterf_cli
|
|
92
|
+
|
|
93
|
+
tmp, env = _fresh_home()
|
|
94
|
+
with tmp, env, \
|
|
95
|
+
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
96
|
+
mock.patch.object(remoterf_cli, "_ensure_config_present", return_value=(True, "")), \
|
|
97
|
+
mock.patch.object(remoterf_cli, "_register") as register, \
|
|
98
|
+
mock.patch.object(remoterf_cli, "_account_shell", return_value=0) as shell:
|
|
99
|
+
assert remoterf_cli._login(None) == 0
|
|
100
|
+
shell.assert_called_once_with(register=False)
|
|
101
|
+
register.assert_not_called()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_register_without_a_code_makes_a_global_account(monkeypatch):
|
|
105
|
+
from remoterf import remoterf_cli
|
|
106
|
+
|
|
107
|
+
monkeypatch.setattr("builtins.input", lambda prompt="": "")
|
|
108
|
+
with mock.patch("remoterf.config.config._confirm_tos", return_value=True), \
|
|
109
|
+
mock.patch("remoterf.config.config.forget_tos_agreement"), \
|
|
110
|
+
mock.patch("remoterf.config.config.remember_tos_agreement"), \
|
|
111
|
+
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
112
|
+
mock.patch.object(remoterf_cli, "_use_global", return_value=0) as use_global, \
|
|
113
|
+
mock.patch.object(remoterf_cli, "_account_shell") as shell:
|
|
114
|
+
assert remoterf_cli._register() == 0
|
|
115
|
+
use_global.assert_called_once_with(register=True, show_banner=False)
|
|
116
|
+
shell.assert_not_called()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_register_global_asks_for_the_tos_like_register(monkeypatch):
|
|
120
|
+
from remoterf import remoterf_cli
|
|
121
|
+
|
|
122
|
+
for arg in ("global", "-global"):
|
|
123
|
+
monkeypatch.setattr("sys.argv", ["remoterf", "-r", arg])
|
|
124
|
+
with mock.patch("remoterf.config.config._confirm_tos", return_value=True) as confirm, \
|
|
125
|
+
mock.patch("remoterf.config.config.forget_tos_agreement") as forget, \
|
|
126
|
+
mock.patch("remoterf.config.config.remember_tos_agreement") as remember, \
|
|
127
|
+
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
128
|
+
mock.patch.object(remoterf_cli, "_use_global", return_value=0) as use_global:
|
|
129
|
+
assert remoterf_cli.main() == 0
|
|
130
|
+
forget.assert_called_once_with()
|
|
131
|
+
confirm.assert_called_once()
|
|
132
|
+
remember.assert_called_once_with()
|
|
133
|
+
use_global.assert_called_once_with(register=True, show_banner=False)
|
|
134
|
+
|
|
135
|
+
# Declining stops before any account is made.
|
|
136
|
+
monkeypatch.setattr("sys.argv", ["remoterf", "-r", "global"])
|
|
137
|
+
with mock.patch("remoterf.config.config._confirm_tos", return_value=False), \
|
|
138
|
+
mock.patch("remoterf.config.config.forget_tos_agreement"), \
|
|
139
|
+
mock.patch("remoterf.config.config.remember_tos_agreement") as remember, \
|
|
140
|
+
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
141
|
+
mock.patch.object(remoterf_cli, "_use_global") as use_global:
|
|
142
|
+
assert remoterf_cli.main() == 1
|
|
143
|
+
remember.assert_not_called()
|
|
144
|
+
use_global.assert_not_called()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_a_found_username_is_not_asked_again():
|
|
148
|
+
from remoterf.core import app
|
|
149
|
+
|
|
150
|
+
account = mock.Mock(is_https_home=False, backend=None)
|
|
151
|
+
account.login_user.return_value = True
|
|
152
|
+
with mock.patch.object(app, "account", account), \
|
|
153
|
+
mock.patch.object(app, "pending_username", "ian"), \
|
|
154
|
+
mock.patch.object(app, "local_capabilities",
|
|
155
|
+
return_value={"registration_policy": {}}), \
|
|
156
|
+
mock.patch.object(app, "_home_name", return_value="ucla"), \
|
|
157
|
+
mock.patch.object(app, "_remember_login"), \
|
|
158
|
+
mock.patch.object(app, "_ask", return_value="secret") as ask:
|
|
159
|
+
assert app._account_command("login") is True
|
|
160
|
+
assert app.pending_username is None
|
|
161
|
+
assert account.username == "ian"
|
|
162
|
+
ask.assert_called_once_with("Password (Hidden)", hidden=True)
|
|
@@ -366,13 +366,8 @@ def test_login_names_a_home_explicitly(monkeypatch, reachable):
|
|
|
366
366
|
assert run_cli(["-l", "nope"], monkeypatch, _account_shell=shell) == 2
|
|
367
367
|
|
|
368
368
|
|
|
369
|
-
def
|
|
369
|
+
def test_login_global_works_without_a_saved_global_account(monkeypatch):
|
|
370
370
|
homes.save_home("ucla", document())
|
|
371
|
-
assert run_cli(["-l", "global"], monkeypatch, _account_shell=mock.Mock()) == 2
|
|
372
|
-
|
|
373
|
-
homes.remember_global_account(
|
|
374
|
-
"https://global.remoterf.net", "897541e5-b61f-45f7-a814-8ffeaad2ae69"
|
|
375
|
-
)
|
|
376
371
|
used_global = mock.Mock(return_value=0)
|
|
377
372
|
assert run_cli(["-l", "global"], monkeypatch, _use_global=used_global) == 0
|
|
378
373
|
used_global.assert_called_once_with(register=False)
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"""`remoterf -l` on a fresh install is `remoterf -r`; a configured client logs in."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
import tempfile
|
|
5
|
-
from unittest import mock
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def _fresh_home():
|
|
9
|
-
tmp = tempfile.TemporaryDirectory()
|
|
10
|
-
env = {k: v for k, v in os.environ.items() if not k.startswith("REMOTERF_")}
|
|
11
|
-
env["HOME"] = tmp.name
|
|
12
|
-
return tmp, mock.patch.dict(os.environ, env, clear=True)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def test_login_on_a_fresh_install_registers():
|
|
16
|
-
from remoterf import remoterf_cli
|
|
17
|
-
|
|
18
|
-
tmp, env = _fresh_home()
|
|
19
|
-
with tmp, env, \
|
|
20
|
-
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
21
|
-
mock.patch.object(remoterf_cli, "_register", return_value=0) as register, \
|
|
22
|
-
mock.patch.object(remoterf_cli, "_account_shell") as shell:
|
|
23
|
-
assert remoterf_cli._login(None) == 0
|
|
24
|
-
register.assert_called_once_with()
|
|
25
|
-
shell.assert_not_called()
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def test_login_with_a_legacy_address_still_logs_in_there():
|
|
29
|
-
from remoterf import remoterf_cli
|
|
30
|
-
|
|
31
|
-
tmp, env = _fresh_home()
|
|
32
|
-
with tmp, env, \
|
|
33
|
-
mock.patch("remoterf.config.config.require_tos_for_login", return_value=True), \
|
|
34
|
-
mock.patch.object(remoterf_cli, "_ensure_config_present", return_value=(True, "")), \
|
|
35
|
-
mock.patch.object(remoterf_cli, "_register") as register, \
|
|
36
|
-
mock.patch.object(remoterf_cli, "_account_shell", return_value=0) as shell:
|
|
37
|
-
assert remoterf_cli._login(None) == 0
|
|
38
|
-
shell.assert_called_once_with(register=False)
|
|
39
|
-
register.assert_not_called()
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def test_register_without_a_code_makes_a_global_account(monkeypatch):
|
|
43
|
-
from remoterf import remoterf_cli
|
|
44
|
-
|
|
45
|
-
monkeypatch.setattr("builtins.input", lambda prompt="": "")
|
|
46
|
-
with mock.patch("remoterf.config.config._confirm_tos", return_value=True), \
|
|
47
|
-
mock.patch("remoterf.config.config.forget_tos_agreement"), \
|
|
48
|
-
mock.patch("remoterf.config.config.remember_tos_agreement"), \
|
|
49
|
-
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
50
|
-
mock.patch.object(remoterf_cli, "_use_global", return_value=0) as use_global, \
|
|
51
|
-
mock.patch.object(remoterf_cli, "_account_shell") as shell:
|
|
52
|
-
assert remoterf_cli._register() == 0
|
|
53
|
-
use_global.assert_called_once_with(register=True, show_banner=False)
|
|
54
|
-
shell.assert_not_called()
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def test_register_global_asks_for_the_tos_like_register(monkeypatch):
|
|
58
|
-
from remoterf import remoterf_cli
|
|
59
|
-
|
|
60
|
-
for arg in ("global", "-global"):
|
|
61
|
-
monkeypatch.setattr("sys.argv", ["remoterf", "-r", arg])
|
|
62
|
-
with mock.patch("remoterf.config.config._confirm_tos", return_value=True) as confirm, \
|
|
63
|
-
mock.patch("remoterf.config.config.forget_tos_agreement") as forget, \
|
|
64
|
-
mock.patch("remoterf.config.config.remember_tos_agreement") as remember, \
|
|
65
|
-
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
66
|
-
mock.patch.object(remoterf_cli, "_use_global", return_value=0) as use_global:
|
|
67
|
-
assert remoterf_cli.main() == 0
|
|
68
|
-
forget.assert_called_once_with()
|
|
69
|
-
confirm.assert_called_once()
|
|
70
|
-
remember.assert_called_once_with()
|
|
71
|
-
use_global.assert_called_once_with(register=True, show_banner=False)
|
|
72
|
-
|
|
73
|
-
# Declining stops before any account is made.
|
|
74
|
-
monkeypatch.setattr("sys.argv", ["remoterf", "-r", "global"])
|
|
75
|
-
with mock.patch("remoterf.config.config._confirm_tos", return_value=False), \
|
|
76
|
-
mock.patch("remoterf.config.config.forget_tos_agreement"), \
|
|
77
|
-
mock.patch("remoterf.config.config.remember_tos_agreement") as remember, \
|
|
78
|
-
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
79
|
-
mock.patch.object(remoterf_cli, "_use_global") as use_global:
|
|
80
|
-
assert remoterf_cli.main() == 1
|
|
81
|
-
remember.assert_not_called()
|
|
82
|
-
use_global.assert_not_called()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remoterf-2.2.1 → remoterf-2.2.3}/src/remoterf/common/grpc/deployment_capabilities_pb2_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|