Пример #1
0
async def test_tab_login_logout(aqtbot, running_backend, gui_factory,
                                autoclose_dialog, core_config, alice,
                                monkeypatch):
    password = "******"
    save_device_with_password(core_config.config_dir, alice, password)
    gui = await gui_factory()

    # Fix the return value of ensure_string_size, because it can depend of the size of the window
    monkeypatch.setattr("parsec.core.gui.main_window.ensure_string_size",
                        lambda s, size, font: (s[:16] + "..."))

    assert gui.tab_center.count() == 1
    assert gui.tab_center.tabText(0) == translate(
        "TEXT_TAB_TITLE_LOG_IN_SCREEN")
    assert not gui.add_tab_button.isEnabled()
    first_created_tab = gui.test_get_tab()

    await gui.test_switch_to_logged_in(alice)
    assert gui.tab_center.count() == 1
    assert gui.tab_center.tabText(0) == "CoolOrg - Alicey..."
    assert gui.add_tab_button.isEnabled()
    assert gui.test_get_tab() == first_created_tab

    await gui.test_logout()
    assert gui.tab_center.count() == 1
    assert gui.tab_center.tabText(0) == translate(
        "TEXT_TAB_TITLE_LOG_IN_SCREEN")
    assert not gui.add_tab_button.isEnabled()
    assert gui.test_get_tab() != first_created_tab
Пример #2
0
async def test_login_back_to_account_list(aqtbot, gui_factory,
                                          autoclose_dialog, core_config, alice,
                                          bob):
    # Create an existing device before starting the gui
    password = "******"
    save_device_with_password(core_config.config_dir, alice, password)
    save_device_with_password(core_config.config_dir, bob, password)

    gui = await gui_factory()
    lw = gui.test_get_login_widget()

    accounts_w = lw.widget.layout().itemAt(0).widget()
    assert accounts_w

    async with aqtbot.wait_signal(accounts_w.account_clicked):
        await aqtbot.mouse_click(
            accounts_w.accounts_widget.layout().itemAt(0).widget(),
            QtCore.Qt.LeftButton)

    def _password_widget_shown():
        assert isinstance(lw.widget.layout().itemAt(0).widget(),
                          LoginPasswordInputWidget)

    await aqtbot.wait_until(_password_widget_shown)

    password_w = lw.widget.layout().itemAt(0).widget()

    async with aqtbot.wait_signal(password_w.back_clicked):
        await aqtbot.mouse_click(password_w.button_back, QtCore.Qt.LeftButton)

    def _account_widget_shown():
        assert isinstance(lw.widget.layout().itemAt(0).widget(),
                          LoginAccountsWidget)
Пример #3
0
async def test_login(aqtbot, gui_factory, autoclose_dialog, core_config,
                     alice):
    # Create an existing device before starting the gui
    password = "******"
    save_device_with_password(core_config.config_dir, alice, password)

    gui = await gui_factory()
    lw = gui.test_get_login_widget()
    tabw = gui.test_get_tab()

    assert lw is not None

    # Available device is automatically selected for login
    assert (
        lw.combo_username.currentText() ==
        f"{alice.organization_id}: {alice.human_handle} @ {alice.device_label}"
    )

    await aqtbot.key_clicks(lw.line_edit_password, password)

    async with aqtbot.wait_signals(
        [lw.login_with_password_clicked, tabw.logged_in]):
        await aqtbot.mouse_click(lw.button_login, QtCore.Qt.LeftButton)

    lw = gui.test_get_login_widget()
    assert lw is None

    cw = gui.test_get_central_widget()
    assert cw is not None
Пример #4
0
 def _on_finished(self, new_device, password):
     save_device_with_password(config_dir=self.config.config_dir,
                               device=new_device,
                               password=password)
     show_info(self, _("TEXT_CLAIM_DEVICE_SUCCESSFUL"))
     self.status = (new_device, password)
     self.dialog.accept()
Пример #5
0
async def test_expired_notification_logging(aqtbot, running_backend,
                                            autoclose_dialog, expiredorgalice,
                                            gui_factory, core_config):

    # Log has alice on an expired organization
    save_device_with_password(core_config.config_dir, expiredorgalice,
                              "P@ssw0rd")

    gui = await gui_factory()
    lw = gui.test_get_login_widget()
    tabw = gui.test_get_tab()

    def _password_widget_shown():
        assert isinstance(lw.widget.layout().itemAt(0).widget(),
                          LoginPasswordInputWidget)

    await aqtbot.wait_until(_password_widget_shown)

    password_w = lw.widget.layout().itemAt(0).widget()

    await aqtbot.key_clicks(password_w.line_edit_password, "P@ssw0rd")

    async with aqtbot.wait_signals(
        [lw.login_with_password_clicked, tabw.logged_in]):
        await aqtbot.mouse_click(password_w.button_login, QtCore.Qt.LeftButton)

    # Assert dialog
    def _expired_notified():
        assert autoclose_dialog.dialogs == [("Error",
                                             "The organization has expired")]

    await aqtbot.wait_until(_expired_notified)
Пример #6
0
def test_keys_import(qtbot, core_config, alice, bob, monkeypatch):
    password = "******"
    save_device_with_password(core_config.config_dir, alice, password)

    tmp_path = core_config.config_dir.joinpath("tmp")
    tmp_path.mkdir()
    tmp_path.joinpath("devices").mkdir()

    fake_config = type("fake_config", (), {"config_dir": tmp_path})()

    w = KeysWidget(fake_config, parent=None)
    qtbot.addWidget(w)

    keys_layout = w.scroll_content.layout()
    assert keys_layout.count() == 0

    key_glob = list(core_config.config_dir.joinpath("devices").glob("*.keys"))
    assert len(key_glob) == 1

    monkeypatch.setattr(
        "parsec.core.gui.keys_widget.QFileDialog.getOpenFileName",
        lambda *x, **y: (key_glob[0], None),
    )

    monkeypatch.setattr(
        "parsec.core.gui.keys_widget.ask_question", lambda *x, **y: translate("ACTION_IMPORT_YES")
    )
    qtbot.mouseClick(w.button_import_key, QtCore.Qt.LeftButton)

    def key_imported():
        assert keys_layout.count() == 1

    qtbot.wait_until(key_imported)
Пример #7
0
async def test_link_file_unknown_org(core_config, gui_factory,
                                     autoclose_dialog, running_backend, alice):
    password = "******"
    save_device_with_password(core_config.config_dir, alice, password)

    # Cheating a bit but it does not matter, we just want a link that appears valid with
    # an unknown organization
    org_addr = BackendOrganizationAddr.build(
        running_backend.addr, "UnknownOrg",
        alice.organization_addr.root_verify_key)

    file_link = BackendOrganizationFileLinkAddr.build(
        org_addr, EntryID(), FsPath("/doesntmattereither"))

    gui = await gui_factory(core_config=core_config,
                            start_arg=file_link.to_url())
    lw = gui.test_get_login_widget()

    assert len(autoclose_dialog.dialogs) == 1
    assert autoclose_dialog.dialogs[0][0] == "Error"
    assert autoclose_dialog.dialogs[0][1] == translate(
        "TEXT_FILE_LINK_NOT_IN_ORG_organization").format(
            organization="UnknownOrg")

    accounts_w = lw.widget.layout().itemAt(0).widget()
    assert accounts_w

    assert isinstance(accounts_w, LoginPasswordInputWidget)
def test_password_save_and_load(path_exists, config_dir, alice):
    config_dir = config_dir if path_exists else config_dir / "dummy"
    save_device_with_password(config_dir, alice, "S3Cr37")

    key_file = get_key_file(config_dir, alice)
    alice_reloaded = load_device_with_password(key_file, "S3Cr37")
    assert alice == alice_reloaded
Пример #9
0
def test_share_workspace(tmpdir, alice, bob):
    # As usual Windows path require a big hack...
    config_dir = tmpdir.strpath.replace("\\", "\\\\")
    # Mocking
    factory_mock = MagicMock()
    share_mock = MagicMock()

    @asynccontextmanager
    async def logged_core_factory(*args, **kwargs):
        yield factory_mock(*args, **kwargs)

    async def share(*args, **kwargs):
        return share_mock(*args, **kwargs)

    factory_mock.return_value.user_fs.workspace_share = share

    password = "******"
    save_device_with_password(Path(config_dir), bob, password)

    with patch("parsec.core.cli.share_workspace.logged_core_factory",
               logged_core_factory):
        runner = CliRunner()
        args = (f"core share_workspace --password {password} "
                f"--device={bob.slughash} --config-dir={config_dir} "
                f"ws1 {alice.user_id}")
        result = runner.invoke(cli, args)

    print(result.output)
    assert result.exit_code == 0
    assert result.output == ""

    factory_mock.assert_called_once_with(ANY, bob)
    share_mock.assert_called_once_with("/ws1", alice.user_id)
Пример #10
0
async def _claim_invitation(config, addr, password):
    async with backend_invited_cmds_factory(addr=addr) as cmds:
        try:
            async with spinner("Retrieving invitation info"):
                initial_ctx = await claimer_retrieve_info(cmds)
        except BackendConnectionRefused:
            raise RuntimeError("Invitation not found")

        if initial_ctx.greeter_human_handle:
            display_greeter = click.style(initial_ctx.greeter_human_handle,
                                          fg="yellow")
        else:
            display_greeter = click.style(initial_ctx.greeter_user_id,
                                          fg="yellow")
        click.echo(f"Invitation greeter: {display_greeter}")
        while True:
            try:
                if isinstance(initial_ctx, DeviceClaimInitialCtx):
                    new_device = await _do_claim_device(initial_ctx)
                else:
                    assert isinstance(initial_ctx, UserClaimInitialCtx)
                    new_device = await _do_claim_user(initial_ctx)
                if new_device:
                    break
            except InviteError as exc:
                click.secho(str(exc), fg="red")
            click.secho("Restarting the invitation process", fg="red")

        device_display = click.style(new_device.slughash, fg="yellow")
        with operation(f"Saving device {device_display}"):
            save_device_with_password(config.config_dir, new_device, password)
Пример #11
0
 async def _claim_device(token, addr, device_id, password, config):
     device = await actual_claim_device(
         organization_addr=addr,
         new_device_id=device_id,
         token=token,
         keepalive=config.backend_connection_keepalive,
     )
     save_device_with_password(config.config_dir, device, password)
Пример #12
0
 def _on_finalize_clicked(self):
     password = self.widget_password.password
     try:
         save_device_with_password(self.config.config_dir, self.new_device, password)
         self.succeeded.emit(self.new_device, password)
     except LocalDeviceAlreadyExistsError as exc:
         show_error(self, _("TEXT_CLAIM_USER_DEVICE_ALREADY_EXISTS"), exception=exc)
         self.failed.emit(None)
Пример #13
0
def keys_widget(qtbot, core_config, alice, bob):
    password = "******"
    save_device_with_password(core_config.config_dir, alice, password)
    save_device_with_password(core_config.config_dir, bob, password)

    w = KeysWidget(core_config, parent=None)
    qtbot.addWidget(w)
    assert w.scroll_content.layout().count() == 2
    return w
Пример #14
0
 async def claim_task():
     nonlocal bob_device
     bob_device = await retry_claim(claim_user,
                                    alice_device.organization_addr,
                                    bob_device_id, token)
     save_device_with_password(config_dir,
                               bob_device,
                               password,
                               force=force)
Пример #15
0
def test_available_devices_slughash_uniqueness(organization_factory,
                                               local_device_factory,
                                               config_dir):
    def _to_available(device):
        return AvailableDevice(
            key_file_path=get_default_key_file(config_dir, device),
            organization_id=device.organization_id,
            device_id=device.device_id,
            human_handle=device.human_handle,
            device_label=device.device_label,
            slug=device.slug,
        )

    def _assert_different_as_available(d1, d2):
        available_device_d1 = _to_available(d1)
        available_device_d2 = _to_available(d2)
        assert available_device_d1.slughash != available_device_d2.slughash
        # Make sure slughash is consistent between LocalDevice and AvailableDevice
        assert available_device_d1.slughash == d1.slughash
        assert available_device_d2.slughash == d2.slughash

    o1 = organization_factory("org1")
    o2 = organization_factory("org2")

    # Different user id
    o1u1d1 = local_device_factory("u1@d1", o1)
    o1u2d1 = local_device_factory("u2@d1", o1)
    _assert_different_as_available(o1u1d1, o1u2d1)

    # Different device name
    o1u1d2 = local_device_factory("u1@d2", o1)
    _assert_different_as_available(o1u1d1, o1u1d2)

    # Different organization id
    o2u1d1 = local_device_factory("u1@d1", o2)
    _assert_different_as_available(o1u1d1, o2u1d1)

    # Same organization_id, but different root verify key !
    dummy_key = SigningKey.generate().verify_key
    o1u1d1_bad_rvk = o1u1d1.evolve(
        organization_addr=o1u1d1.organization_addr.build(
            backend_addr=o1u1d1.organization_addr,
            organization_id=o1u1d1.organization_addr.organization_id,
            root_verify_key=dummy_key,
        ))
    _assert_different_as_available(o1u1d1, o1u1d1_bad_rvk)

    # Finally make sure slughash is stable through save/load
    save_device_with_password(config_dir, o1u1d1, "S3Cr37")
    key_file = get_key_file(config_dir, o1u1d1)
    o1u1d1_reloaded = load_device_with_password(key_file, "S3Cr37")
    available_device = _to_available(o1u1d1)
    available_device_reloaded = _to_available(o1u1d1_reloaded)
    assert available_device.slughash == available_device_reloaded.slughash
async def _bootstrap_organization(debug, device_id,
                                  organization_bootstrap_addr, config_dir,
                                  force, password):
    root_signing_key = SigningKey.generate()
    root_verify_key = root_signing_key.verify_key
    organization_addr = organization_bootstrap_addr.generate_organization_addr(
        root_verify_key)

    device_display = click.style(device_id, fg="yellow")
    device = generate_new_device(device_id,
                                 organization_addr,
                                 profile=UserProfile.ADMIN)

    with operation(f"Creating locally {device_display}"):
        save_device_with_password(config_dir, device, password, force=force)

    now = pendulum.now()
    user_certificate = UserCertificateContent(
        author=None,
        timestamp=now,
        user_id=device.user_id,
        public_key=device.public_key,
        profile=device.profile,
    )
    redacted_user_certificate = user_certificate.evolve(human_handle=None)
    device_certificate = DeviceCertificateContent(author=None,
                                                  timestamp=now,
                                                  device_id=device_id,
                                                  verify_key=device.verify_key)
    redacted_device_certificate = device_certificate.evolve(device_label=None)

    user_certificate = user_certificate.dump_and_sign(root_signing_key)
    device_certificate = device_certificate.dump_and_sign(root_signing_key)
    redacted_user_certificate = redacted_user_certificate.dump_and_sign(
        root_signing_key)
    redacted_device_certificate = redacted_device_certificate.dump_and_sign(
        root_signing_key)

    async with spinner(f"Sending {device_display} to server"):
        async with apiv1_backend_anonymous_cmds_factory(
                organization_bootstrap_addr) as cmds:
            await cmds.organization_bootstrap(
                organization_id=organization_bootstrap_addr.organization_id,
                bootstrap_token=organization_bootstrap_addr.token,
                root_verify_key=root_verify_key,
                user_certificate=user_certificate,
                device_certificate=device_certificate,
                redacted_user_certificate=redacted_user_certificate,
                redacted_device_certificate=redacted_device_certificate,
            )

    organization_addr_display = click.style(organization_addr.to_url(),
                                            fg="yellow")
    click.echo(f"Organization url: {organization_addr_display}")
Пример #17
0
async def test_expired_notification_from_connection(aqtbot, running_backend,
                                                    autoclose_dialog,
                                                    expiredorgalice,
                                                    gui_factory, core_config):
    save_device_with_password(core_config.config_dir, expiredorgalice,
                              "P@ssw0rd")
    gui = await gui_factory()
    lw = gui.test_get_login_widget()
    tabw = gui.test_get_tab()

    # Force logging on an expired organization
    with freeze_time("1989-12-17"):

        def _password_widget_shown():
            assert isinstance(lw.widget.layout().itemAt(0).widget(),
                              LoginPasswordInputWidget)

        await aqtbot.wait_until(_password_widget_shown)

        password_w = lw.widget.layout().itemAt(0).widget()

        await aqtbot.key_clicks(password_w.line_edit_password, "P@ssw0rd")

        async with aqtbot.wait_signals(
            [lw.login_with_password_clicked, tabw.logged_in]):
            await aqtbot.mouse_click(password_w.button_login,
                                     QtCore.Qt.LeftButton)

        # Assert logged in
        def _notified():
            assert autoclose_dialog.dialogs == []
            central_widget = gui.test_get_central_widget()
            assert central_widget is not None

        await aqtbot.wait_until(_notified)

    # Trigger another handshake
    with pytest.raises(BackendConnectionRefused):
        async with backend_authenticated_cmds_factory(
                expiredorgalice.organization_addr,
                expiredorgalice.device_id,
                expiredorgalice.signing_key,
        ) as cmds:
            async with cmds.acquire_transport():
                # This shall never happen, we shall have been rejected while acquiring the transport
                assert False

    # Assert dialog
    def _expired_notified():
        assert autoclose_dialog.dialogs == [("Error",
                                             "The organization has expired")]

    await aqtbot.wait_until(_expired_notified)
Пример #18
0
def bob_available_device(bob, tmp_path):
    key_file_path = tmp_path / "bob_device.keys"
    save_device_with_password(key_file=key_file_path, device=bob, password="", force=True)
    return AvailableDevice(
        key_file_path=key_file_path,
        organization_id=bob.organization_id,
        device_id=bob.device_id,
        human_handle=bob.human_handle,
        device_label=bob.device_label,
        slug=bob.slug,
        type=DeviceFileType.PASSWORD,
    )
Пример #19
0
def test_same_device_id_different_orginazations(config_dir, alice, otheralice):
    devices = (alice, otheralice)

    for device in devices:
        save_device_with_password(config_dir, device,
                                  f"S3Cr37-{device.organization_id}")

    for device in devices:
        key_file = get_key_file(config_dir, device)
        device_reloaded = load_device_with_password(
            key_file, f"S3Cr37-{device.organization_id}")
        assert device == device_reloaded
Пример #20
0
async def logged_gui(aqtbot, gui_factory, autoclose_dialog, core_config, alice,
                     running_backend, monkeypatch):
    save_device_with_password(core_config.config_dir, alice, "P@ssw0rd")
    monkeypatch.setattr(
        "parsec.core.gui.workspaces_widget.WorkspacesWidget.RESET_TIMER_THRESHOLD",
        0)

    gui = await gui_factory()
    lw = gui.test_get_login_widget()
    tabw = gui.test_get_tab()

    await aqtbot.key_clicks(lw.line_edit_password, "P@ssw0rd")

    async with aqtbot.wait_signals(
        [lw.login_with_password_clicked, tabw.logged_in]):
        await aqtbot.mouse_click(lw.button_login, QtCore.Qt.LeftButton)

    central_widget = gui.test_get_central_widget()
    assert central_widget is not None

    wk_widget = gui.test_get_workspaces_widget()
    async with aqtbot.wait_signal(wk_widget.list_success):
        pass

    add_button = wk_widget.button_add_workspace
    assert add_button is not None

    monkeypatch.setattr("parsec.core.gui.workspaces_widget.get_text_input",
                        lambda *args, **kwargs: ("Workspace"))

    async with aqtbot.wait_signals(
        [
            wk_widget.create_success, wk_widget.list_success,
            wk_widget.mountpoint_started
        ],
            timeout=2000,
    ):
        await aqtbot.mouse_click(add_button, QtCore.Qt.LeftButton)

    def workspace_button_ready():
        assert wk_widget.layout_workspaces.count() == 1
        wk_button = wk_widget.layout_workspaces.itemAt(0).widget()
        assert not isinstance(wk_button, QtWidgets.QLabel)

    await aqtbot.wait_until(workspace_button_ready)
    wk_button = wk_widget.layout_workspaces.itemAt(0).widget()
    assert wk_button.name == "Workspace"

    async with aqtbot.wait_signal(wk_widget.load_workspace_clicked):
        await aqtbot.mouse_click(wk_button, QtCore.Qt.LeftButton)

    yield gui
Пример #21
0
async def logged_gui(aqtbot, gui_factory, core_config, alice, bob,
                     fixtures_customization):
    # Logged as bob (i.e. standard profile) by default
    if fixtures_customization.get("logged_gui_as_admin", False):
        device = alice
    else:
        device = bob

    save_device_with_password(core_config.config_dir, device, "P@ssw0rd")

    gui = await gui_factory()
    await gui.test_switch_to_logged_in(device)
    return gui
Пример #22
0
async def _claim_device(config, organization_addr, new_device_id, token,
                        password):
    async with spinner("Waiting for referee to reply"):
        device = await actual_claim_device(
            organization_addr=organization_addr,
            new_device_id=new_device_id,
            token=token,
            keepalive=config.backend_connection_keepalive,
        )

    device_display = click.style(new_device_id, fg="yellow")
    with operation(f"Saving locally {device_display}"):
        save_device_with_password(config.config_dir, device, password)
Пример #23
0
def test_change_password(config_dir, alice):
    old_password = "******"
    new_password = "******"

    save_device_with_password(config_dir, alice, old_password)
    key_file = get_key_file(config_dir, alice)

    change_device_password(key_file, old_password, new_password)

    alice_reloaded = load_device_with_password(key_file, new_password)
    assert alice == alice_reloaded

    with pytest.raises(LocalDeviceCryptoError):
        load_device_with_password(key_file, old_password)
Пример #24
0
async def test_tab_login_logout_two_tabs_logged_in(aqtbot, running_backend,
                                                   gui_factory,
                                                   autoclose_dialog,
                                                   core_config, alice, bob,
                                                   monkeypatch):
    password = "******"
    save_device_with_password(core_config.config_dir, alice, password)
    gui = await gui_factory()

    # Fix the return value of ensure_string_size, because it can depend of the size of the window
    monkeypatch.setattr("parsec.core.gui.main_window.ensure_string_size",
                        lambda s, size, font: (s[:16] + "..."))

    assert gui.tab_center.count() == 1
    assert gui.tab_center.tabText(0) == translate(
        "TEXT_TAB_TITLE_LOG_IN_SCREEN")

    await gui.test_switch_to_logged_in(alice)
    assert gui.tab_center.count() == 1
    assert gui.tab_center.tabText(0) == "CoolOrg - Alicey..."
    alice_logged_tab = gui.test_get_tab()

    await aqtbot.mouse_click(gui.add_tab_button, QtCore.Qt.LeftButton)
    assert gui.tab_center.count() == 2
    assert gui.tab_center.tabText(0) == "CoolOrg - Alicey..."
    assert gui.tab_center.tabText(1) == translate(
        "TEXT_TAB_TITLE_LOG_IN_SCREEN")

    save_device_with_password(core_config.config_dir, bob, password)
    await gui.test_switch_to_logged_in(bob)
    assert gui.tab_center.count() == 2
    assert gui.tab_center.tabText(0) == "CoolOrg - Alicey..."
    assert gui.tab_center.tabText(1) == "CoolOrg - Boby M..."
    bob_logged_tab = gui.test_get_tab()
    assert bob_logged_tab != alice_logged_tab

    gui.switch_to_tab(0)

    def _logged_tab_displayed():
        assert alice_logged_tab == gui.test_get_tab()

    await aqtbot.wait_until(_logged_tab_displayed)

    await gui.test_logout()
    assert gui.tab_center.count() == 2
    assert gui.tab_center.tabText(0) == "CoolOrg - Boby M..."
    assert gui.tab_center.tabText(1) == translate(
        "TEXT_TAB_TITLE_LOG_IN_SCREEN")
Пример #25
0
async def _do_create_org(config, human_handle, device_name, password,
                         backend_addr):
    try:
        async with apiv1_backend_anonymous_cmds_factory(
                addr=backend_addr) as cmds:
            new_device = await bootstrap_organization(
                cmds=cmds, human_handle=human_handle, device_label=device_name)
            save_device_with_password(config_dir=config.config_dir,
                                      device=new_device,
                                      password=password)
            return new_device, password
    except InviteAlreadyUsedError as exc:
        raise JobResultError("invite-already-used", exc=exc)
    except BackendConnectionRefused as exc:
        raise JobResultError("connection-refused", exc=exc)
    except BackendNotAvailable as exc:
        raise JobResultError("connection-error", exc=exc)
Пример #26
0
async def _do_claim_user(
    config,
    password: str,
    password_check: str,
    token: str,
    user_id: str,
    device_name: str,
    organization_addr: BackendOrganizationClaimUserAddr,
):
    if password != password_check:
        raise JobResultError("password-mismatch")
    if len(password) < 8:
        raise JobResultError("password-size")

    try:
        device_id = DeviceID(f"{user_id}@{device_name}")
    except ValueError as exc:
        raise JobResultError("bad-device_name") from exc

    try:
        device = await core_claim_user(
            organization_addr=organization_addr.to_organization_addr(),
            new_device_id=device_id,
            token=token,
            keepalive=config.backend_connection_keepalive,
        )

    except InviteClaimBackendOfflineError as exc:
        raise JobResultError("backend-offline", info=str(exc)) from exc

    except InviteClaimError as exc:
        if "Cannot retrieve invitation creator" in str(exc):
            raise JobResultError("not_found", info=str(exc)) from exc
        else:
            raise JobResultError("refused-by-backend", info=str(exc)) from exc

    try:
        save_device_with_password(config.config_dir, device, password)

    except LocalDeviceAlreadyExistsError as exc:
        raise JobResultError("user-exists") from exc

    return device, password
Пример #27
0
async def _bootstrap_organization(config, addr, password, force):
    label = await aprompt("User fullname")
    email = await aprompt("User email")
    human_handle = HumanHandle(email=email, label=label)
    device_label = await aprompt("Device label", default=platform.node())

    async with apiv1_backend_anonymous_cmds_factory(addr=addr) as cmds:
        async with spinner("Bootstrapping organization in the backend"):
            new_device = await do_bootstrap_organization(
                cmds=cmds,
                human_handle=human_handle,
                device_label=device_label)

        device_display = click.style(new_device.slughash, fg="yellow")
        with operation(f"Saving device {device_display}"):
            save_device_with_password(config_dir=config.config_dir,
                                      device=new_device,
                                      password=password,
                                      force=force)
Пример #28
0
def test_password_save_already_existing(config_dir, alice, alice2, otheralice):
    save_device_with_password(config_dir, alice, "S3Cr37")

    # Different devices should not overwrite each other
    save_device_with_password(config_dir, otheralice, "S3Cr37")
    save_device_with_password(config_dir, alice2, "S3Cr37")

    # Overwritting self is allowed
    save_device_with_password(config_dir, alice, "S3Cr37")

    devices = list_available_devices(config_dir)
    assert len(devices) == 3
Пример #29
0
def test_list_devices(organization_factory, local_device_factory, config_dir):
    org1 = organization_factory("org1")
    org2 = organization_factory("org2")

    o1d11 = local_device_factory("d1@1", org1)
    o1d12 = local_device_factory("d1@2", org1)
    o1d21 = local_device_factory("d2@1", org1)

    o2d11 = local_device_factory("d1@1", org2, has_human_handle=False)
    o2d12 = local_device_factory("d1@2", org2, has_device_label=False)
    o2d21 = local_device_factory("d2@1",
                                 org2,
                                 has_human_handle=False,
                                 has_device_label=False)

    for device in [o1d11, o1d12, o1d21]:
        save_device_with_password(config_dir, device, "S3Cr37")

    for device in [o2d11, o2d12, o2d21]:
        save_device_with_password(config_dir, device, "secret")

    # Also add dummy stuff that should be ignored
    device_dir = config_dir / "devices"
    (device_dir / "bad1").touch()
    (device_dir / "373955f566#corp#bob@laptop").mkdir()
    dummy_slug = "a54ed6df3a#corp#alice@laptop"
    (device_dir / dummy_slug).mkdir()
    (device_dir / dummy_slug / f"{dummy_slug}.keys").write_bytes(b"dummy")

    devices = list_available_devices(config_dir)

    expected_devices = {
        AvailableDevice(
            key_file_path=get_key_file(config_dir, d),
            organization_id=d.organization_id,
            device_id=d.device_id,
            human_handle=d.human_handle,
            device_label=d.device_label,
            slug=d.slug,
        )
        for d in [o1d11, o1d12, o1d21, o2d11, o2d12, o2d21]
    }
    assert set(devices) == expected_devices
Пример #30
0
async def logged_gui(aqtbot, gui_factory, autoclose_dialog, core_config, alice, bob):
    save_device_with_password(core_config.config_dir, alice, "P@ssw0rd")

    gui = await gui_factory()
    lw = gui.test_get_login_widget()
    tabw = gui.test_get_tab()

    assert lw is not None

    await aqtbot.key_clicks(lw.line_edit_password, "P@ssw0rd")

    async with aqtbot.wait_signals([lw.login_with_password_clicked, tabw.logged_in]):
        await aqtbot.mouse_click(lw.button_login, QtCore.Qt.LeftButton)

    central_widget = gui.test_get_central_widget()
    assert central_widget is not None

    save_device_with_password(core_config.config_dir, bob, "P@ssw0rd")

    yield gui