Ejemplo n.º 1
0
 def _on_claim_clicked(self):
     # No try/except given `self.line_edit_device` has already been validated against `DeviceLabel`
     device_label = DeviceLabel(
         validators.trim_user_name(self.line_edit_device.text()))
     try:
         user_name = validators.trim_user_name(
             self.line_edit_user_full_name.text())
         human_handle = HumanHandle(email=self.line_edit_user_email.text(),
                                    label=user_name)
         device_label = DeviceLabel(self.line_edit_device.text())
     except ValueError as exc:
         show_error(self,
                    _("TEXT_CLAIM_USER_INVALID_HUMAN_HANDLE"),
                    exception=exc)
         return
     self.button_ok.setDisabled(True)
     self.widget_info.setDisabled(True)
     self.label_wait.show()
     self.claim_job = self.jobs_ctx.submit_job(
         self.claim_success,
         self.claim_error,
         self.claimer.claim_user,
         device_label=device_label,
         human_handle=human_handle,
     )
Ejemplo n.º 2
0
async def _bootstrap_organization(
    config: CoreConfig,
    addr: BackendOrganizationBootstrapAddr,
    device_label: Optional[DeviceLabel],
    human_label: Optional[str],
    human_email: Optional[str],
    save_device_with_selected_auth: Callable,
) -> None:
    if not human_label:
        human_label = await aprompt("User fullname")
    if not human_email:
        human_email = await aprompt("User email")
    human_handle = HumanHandle(email=human_email, label=human_label)
    if not device_label:
        device_label_raw = await aprompt("Device label",
                                         default=platform.node())
        device_label = DeviceLabel(device_label_raw)

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

    # We don't have to worry about overwritting an existing keyfile
    # given their names are base on the device's slughash which is intended
    # to be globally unique.

    # The organization is brand new, of course there is no existing
    # remote user manifest, hence our placeholder is non-speculative.
    await user_storage_non_speculative_init(data_base_dir=config.data_base_dir,
                                            device=new_device)
    await save_device_with_selected_auth(config_dir=config.config_dir,
                                         device=new_device)
Ejemplo n.º 3
0
async def ask_info_new_user(
    default_device_label: str, default_user_label: str, default_user_email: str
) -> Tuple[DeviceLabel, HumanHandle, UserProfile]:
    while True:
        granted_label = await aprompt("New user label", default=default_user_label)
        granted_email = await aprompt("New user email", default=default_user_email)
        try:
            granted_human_handle = HumanHandle(email=granted_email, label=granted_label)
            break
        except ValueError:
            click.echo("Invalid user label and/or email")
            continue

    while True:
        try:
            granted_device_label = DeviceLabel(
                await aprompt("New user device label", default=default_device_label)
            )
            break
        except ValueError:
            click.echo("Invalid value")
            continue

    choices = list(UserProfile)
    for i, choice in enumerate(UserProfile):
        display_choice = click.style(choice.value, fg="yellow")
        click.echo(f" {i} - {display_choice}")
    choice_index = await aprompt(
        "New user profile", default="1", type=click.Choice([str(i) for i, _ in enumerate(choices)])
    )
    granted_profile = choices[int(choice_index)]
    return granted_device_label, granted_human_handle, granted_profile
Ejemplo n.º 4
0
 def _on_create_user_clicked(self):
     assert not self.create_user_job
     handle = None
     # No try/except given `self.line_edit_device` has already been validated against `DeviceLabel`
     device_label = DeviceLabel(
         validators.trim_user_name(self.line_edit_device.text()))
     try:
         user_name = validators.trim_user_name(
             self.line_edit_user_full_name.text())
         handle = HumanHandle(label=user_name,
                              email=self.line_edit_user_email.text())
     except ValueError as exc:
         show_error(self,
                    _("TEXT_GREET_USER_INVALID_HUMAN_HANDLE"),
                    exception=exc)
         return
     self.button_create_user.setDisabled(True)
     self.button_create_user.setText(_("TEXT_GREET_USER_WAITING"))
     self.create_user_job = self.jobs_ctx.submit_job(
         self.create_user_success,
         self.create_user_error,
         self.greeter.create_new_user,
         human_handle=handle,
         device_label=device_label,
         profile=self.combo_profile.currentData(),
     )
Ejemplo n.º 5
0
def generate_ALICE_local_device():
    return LocalDevice(
        organization_addr=BackendOrganizationAddr.from_url(
            "parsec://alice_dev1.example.com:9999/CoolOrg?no_ssl=true&rvk=XYUXM4ZM5SGKSTXNZ4FK7VATZUKZGY7A7LOJ42CXFR32DYL5TO6Qssss"
        ),
        device_id=DeviceID("alice@dev1"),
        device_label=DeviceLabel("My dev1 machine"),
        human_handle=HumanHandle("*****@*****.**", "Alicey McAliceFace"),
        signing_key=SigningKey(
            unhexlify(
                "d544f66ece9c85d5b80275db9124b5f04bb038081622bed139c1e789c5217400"
            )),
        private_key=PrivateKey(
            unhexlify(
                "74e860967fd90d063ebd64fb1ba6824c4c010099dd37508b7f2875a5db2ef8c9"
            )),
        profile=UserProfile.ADMIN,
        user_manifest_id=EntryID.from_hex("a4031e8bcdd84df8ae12bd3d05e6e20f"),
        user_manifest_key=SecretKey(
            unhexlify(
                "26bf35a98c1e54e90215e154af92a1af2d1142cdd0dba25b990426b0b30b0f9a"
            )),
        local_symkey=SecretKey(
            unhexlify(
                "125a78618995e2e0f9a19bc8617083c809c03deb5457d5b82df5bcaec9966cd4"
            )),
    )
Ejemplo n.º 6
0
def generate_BOB_local_device():
    return LocalDevice(
        organization_addr=BackendOrganizationAddr.from_url(
            "parsec://bob_dev1.example.com:9999/CoolOrg?no_ssl=true&rvk=XYUXM4ZM5SGKSTXNZ4FK7VATZUKZGY7A7LOJ42CXFR32DYL5TO6Qssss"
        ),
        device_id=DeviceID("bob@dev1"),
        device_label=DeviceLabel("My dev1 machine"),
        human_handle=HumanHandle("*****@*****.**", "Boby McBobFace"),
        signing_key=SigningKey(
            unhexlify(
                "85f47472a2c0f30f01b769617db248f3ec8d96a490602a9262f95e9e43432b30"
            )),
        private_key=PrivateKey(
            unhexlify(
                "16767ec446f2611f971c36f19c2dc11614d853475ac395d6c1d70ba46d07dd49"
            )),
        profile=UserProfile.STANDARD,
        user_manifest_id=EntryID.from_hex("71568d41afcb4e2380b3d164ace4fb85"),
        user_manifest_key=SecretKey(
            unhexlify(
                "65de53d2c6cd965aa53a1ba5cc7e54b331419e6103466121996fa99a97197a48"
            )),
        local_symkey=SecretKey(
            unhexlify(
                "93f25b18491016f20b10dcf4eb7986716d914653d6ab4e778701c13435e6bdf0"
            )),
    )
Ejemplo n.º 7
0
async def _do_greet_device(device: LocalDevice, initial_ctx: DeviceGreetInitialCtx) -> bool:
    async with spinner("Waiting for claimer"):
        in_progress_ctx = await initial_ctx.do_wait_peer()

    display_greeter_sas = click.style(str(in_progress_ctx.greeter_sas), fg="yellow")
    click.echo(f"Code to provide to claimer: {display_greeter_sas}")
    async with spinner("Waiting for claimer"):
        in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()

    choices = in_progress_ctx.generate_claimer_sas_choices(size=3)
    for i, choice in enumerate(choices):
        display_choice = click.style(choice, fg="yellow")
        click.echo(f" {i} - {display_choice}")
    code = await aprompt(
        f"Select code provided by claimer", type=click.Choice([str(x) for x in range(len(choices))])
    )
    if choices[int(code)] != in_progress_ctx.claimer_sas:
        click.secho("Wrong code provided", fg="red")
        return False

    async with spinner("Waiting for claimer"):
        in_progress_ctx = await in_progress_ctx.do_signify_trust()
        in_progress_ctx = await in_progress_ctx.do_get_claim_requests()

    granted_device_label = await aprompt(
        "New device label", default=in_progress_ctx.requested_device_label
    )
    async with spinner("Creating the device in the backend"):
        await in_progress_ctx.do_create_new_device(
            author=device, device_label=DeviceLabel(granted_device_label)
        )

    return True
Ejemplo n.º 8
0
async def _do_claim_device(initial_ctx: DeviceClaimInitialCtx) -> LocalDevice:
    async with spinner("Initializing connection with greeter for claiming device"):
        in_progress_ctx = await initial_ctx.do_wait_peer()

    choices = in_progress_ctx.generate_greeter_sas_choices(size=3)
    for i, choice in enumerate(choices):
        display_choice = click.style(choice, fg="yellow")
        click.echo(f" {i} - {display_choice}")
    code = await aprompt(
        f"Select code provided by greeter", type=click.Choice([str(x) for x in range(len(choices))])
    )
    if choices[int(code)] != in_progress_ctx.greeter_sas:
        click.secho("Wrong code provided", fg="red")
        return None

    in_progress_ctx = await in_progress_ctx.do_signify_trust()
    display_claimer_sas = click.style(str(in_progress_ctx.claimer_sas), fg="yellow")
    click.echo(f"Code to provide to greeter: {display_claimer_sas}")
    async with spinner("Waiting for greeter"):
        in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()

    requested_device_label = await aprompt("Device label", default=platform.node())
    async with spinner("Waiting for greeter (finalizing)"):
        new_device = await in_progress_ctx.do_claim_device(
            requested_device_label=DeviceLabel(requested_device_label)
        )

    return new_device
Ejemplo n.º 9
0
 def validate(self, string, pos):
     try:
         if len(string) == 0:
             return QValidator.Intermediate, string, pos
         DeviceLabel(string)
         return QValidator.Acceptable, string, pos
     except ValueError:
         return QValidator.Invalid, string, pos
Ejemplo n.º 10
0
 async def _do_claimer_claim_device():
     with pytest.raises(
             BackendInvitationAlreadyUsed) as exc_info:
         await claimer_in_progress_ctx.do_claim_device(
             requested_device_label=DeviceLabel(
                 "TheSecretDevice"))
     assert str(
         exc_info.value
     ) == "Invalid handshake: Invitation already deleted"
Ejemplo n.º 11
0
def test_list_devices_support_key_file(config_dir, type):
    if type == "password":
        data_extra = {"type": "password", "salt": b"12345"}
        available_device_extra = {"type": DeviceFileType.PASSWORD}

    elif type == "smartcard":
        data_extra = {
            "type": "smartcard",
            "encrypted_key": b"12345",
            "certificate_id": "42",
            "certificate_sha1": b"12345",
        }
        available_device_extra = {"type": DeviceFileType.SMARTCARD}

    # Device information
    user_id = uuid4().hex
    device_name = uuid4().hex
    organization_id = "Org"
    rvk_hash = (uuid4().hex)[:10]
    device_id = f"{user_id}@{device_name}"
    slug = f"{rvk_hash}#{organization_id}#{device_id}"
    human_label = "Billy Mc BillFace"
    human_email = "*****@*****.**"
    device_label = "My device"

    # Craft file data
    key_file_data = packb({
        "ciphertext":
        b"whatever",
        "human_handle": (human_email.encode(), human_label.encode()),
        "device_label":
        device_label,
        "device_id":
        device_id,
        "organization_id":
        organization_id,
        "slug":
        slug,
        **data_extra,
    })

    key_file_path = get_devices_dir(config_dir) / "device.keys"
    key_file_path.parent.mkdir(parents=True)
    key_file_path.write_bytes(key_file_data)

    devices = list_available_devices(config_dir)
    expected_device = AvailableDevice(
        key_file_path=key_file_path,
        organization_id=OrganizationID(organization_id),
        device_id=DeviceID(device_id),
        human_handle=HumanHandle(human_email, human_label),
        device_label=DeviceLabel(device_label),
        slug=slug,
        **available_device_extra,
    )
    assert devices == [expected_device]
    assert get_key_file(config_dir, expected_device) == key_file_path
Ejemplo n.º 12
0
def test_device_certificate():
    from parsec.api.data.certif import (
        _RsDeviceCertificateContent,
        DeviceCertificateContent,
        _PyDeviceCertificateContent,
    )

    assert DeviceCertificateContent is _RsDeviceCertificateContent

    def _assert_device_certificate_eq(py, rs):
        assert py.author == rs.author
        assert py.timestamp == rs.timestamp
        assert py.device_id == rs.device_id
        assert py.device_label == rs.device_label
        assert py.verify_key == rs.verify_key

    kwargs = {
        "author": DeviceID.new(),
        "timestamp": pendulum.now(),
        "device_id": DeviceID("bob@dev1"),
        "device_label": DeviceLabel("dev machine"),
        "verify_key": SigningKey.generate().verify_key,
    }

    py_dc = _PyDeviceCertificateContent(**kwargs)
    rs_dc = DeviceCertificateContent(**kwargs)
    _assert_device_certificate_eq(py_dc, rs_dc)

    kwargs = {
        "author": DeviceID.new(),
        "timestamp": pendulum.now(),
        "device_id": DeviceID("alice@dev1"),
        "device_label": None,
        "verify_key": SigningKey.generate().verify_key,
    }

    py_dc = py_dc.evolve(**kwargs)
    rs_dc = rs_dc.evolve(**kwargs)
    _assert_device_certificate_eq(py_dc, rs_dc)

    sign_key = SigningKey.generate()
    py_data = py_dc.dump_and_sign(sign_key)
    rs_data = rs_dc.dump_and_sign(sign_key)

    py_dc = _PyDeviceCertificateContent.verify_and_load(
        rs_data, sign_key.verify_key, expected_author=py_dc.author, expected_device=py_dc.device_id
    )
    rs_dc = DeviceCertificateContent.verify_and_load(
        py_data, sign_key.verify_key, expected_author=rs_dc.author, expected_device=rs_dc.device_id
    )
    _assert_device_certificate_eq(py_dc, rs_dc)

    py_dc = _PyDeviceCertificateContent.unsecure_load(rs_data)
    rs_dc = DeviceCertificateContent.unsecure_load(py_data)
    _assert_device_certificate_eq(py_dc, rs_dc)
Ejemplo n.º 13
0
async def generate_recovery_device(
    original_device: LocalDevice, ) -> LocalDevice:
    """
    Raises:
        BackendConnectionError
    """
    now = pendulum.now()
    # Unique enough label is expected, but unicity is not strongly enforced
    new_device_label = DeviceLabel(
        f"recovery-{now.year}-{now.month}-{now.day}-{secrets.token_hex(2)}")
    return await _create_new_device_for_self(original_device, new_device_label)
Ejemplo n.º 14
0
async def test_create_organization_same_name(
    gui,
    aqtbot,
    running_backend,
    catch_create_org_widget,
    autoclose_dialog,
    organization_bootstrap_addr,
):
    # Create an org
    human_handle = HumanHandle(email="*****@*****.**", label="Zack")

    await bootstrap_organization(organization_bootstrap_addr,
                                 human_handle=human_handle,
                                 device_label=DeviceLabel("PC1"))

    # Now create an org with the same name
    aqtbot.key_click(gui, "n", QtCore.Qt.ControlModifier, 200)

    co_w = await catch_create_org_widget()
    assert co_w

    def _user_widget_ready():
        assert isinstance(co_w.current_widget, CreateOrgUserInfoWidget)

    await aqtbot.wait_until(_user_widget_ready)

    # Adding a few spaces to the name
    await aqtbot.key_clicks(co_w.current_widget.line_edit_user_full_name,
                            "Gordon Freeman")
    await aqtbot.key_clicks(co_w.current_widget.line_edit_user_email,
                            "*****@*****.**")
    await aqtbot.key_clicks(co_w.current_widget.line_edit_org_name,
                            "AnomalousMaterials")
    await aqtbot.key_clicks(co_w.current_widget.line_edit_device, "HEV")
    assert not co_w.button_validate.isEnabled()

    aqtbot.mouse_click(co_w.current_widget.check_accept_contract,
                       QtCore.Qt.LeftButton)

    def _user_widget_button_validate_ready():
        assert co_w.button_validate.isEnabled()

    await aqtbot.wait_until(_user_widget_button_validate_ready)

    async with aqtbot.wait_signal(co_w.req_error):
        aqtbot.mouse_click(co_w.button_validate, QtCore.Qt.LeftButton)

    def _modal_shown():
        assert autoclose_dialog.dialogs == [
            ("Error", "This organization name is already used.")
        ]

    await aqtbot.wait_until(_modal_shown)
Ejemplo n.º 15
0
async def _get_device(conn, organization_id: OrganizationID,
                      device_id: DeviceID) -> Device:
    row = await conn.fetchrow(*_q_get_device(
        organization_id=organization_id.str, device_id=device_id.str))
    if not row:
        raise UserNotFoundError(device_id)

    return Device(
        device_id=device_id,
        device_label=DeviceLabel(row["device_label"]),
        device_certificate=row["device_certificate"],
        redacted_device_certificate=row["redacted_device_certificate"],
        device_certifier=DeviceID(row["device_certifier"]),
        created_on=row["created_on"],
    )
Ejemplo n.º 16
0
async def _get_user_devices(conn, organization_id: OrganizationID,
                            user_id: UserID) -> Tuple[Device, ...]:
    results = await conn.fetch(*_q_get_user_devices(
        organization_id=organization_id.str, user_id=user_id.str))

    return tuple(
        Device(
            device_id=DeviceID(row["device_id"]),
            device_label=DeviceLabel(row["device_label"]
                                     ) if row["device_label"] else None,
            device_certificate=row["device_certificate"],
            redacted_device_certificate=row["redacted_device_certificate"],
            device_certifier=DeviceID(row["device_certifier"]
                                      ) if row["device_certifier"] else None,
            created_on=row["created_on"],
        ) for row in results)
 async def _on_validate_clicked(self):
     if isinstance(self.current_page, DeviceRecoveryImportPage1Widget):
         # No try/except given `self.line_edit_device` has already been validated against `DeviceLabel`
         device_label = DeviceLabel(
             validators.trim_user_name(
                 self.current_page.line_edit_device.text()))
         self.jobs_ctx.submit_job(
             self.create_new_device_success,
             self.create_new_device_failure,
             self._create_new_device,
             device_label=device_label,
             file_path=PurePath(self.current_page.get_recovery_key_file()),
             passphrase=self.current_page.get_passphrase(),
         )
     else:
         try:
             self.button_validate.setEnabled(False)
             auth_method = self.current_page.get_auth_method()
             if auth_method == DeviceFileType.PASSWORD:
                 save_device_with_password_in_config(
                     config_dir=self.config.config_dir,
                     device=self.new_device,
                     password=self.current_page.get_auth(),
                 )
             else:
                 await save_device_with_smartcard_in_config(
                     config_dir=self.config.config_dir,
                     device=self.new_device)
             show_info(self, translate("TEXT_RECOVERY_IMPORT_SUCCESS"))
             self.dialog.accept()
         except LocalDeviceCryptoError as exc:
             self.button_validate.setEnabled(True)
             if auth_method == DeviceFileType.SMARTCARD:
                 show_error(self,
                            translate("TEXT_INVALID_SMARTCARD"),
                            exception=exc)
         except LocalDeviceNotFoundError as exc:
             if auth_method == DeviceFileType.PASSWORD:
                 show_error(self,
                            translate("TEXT_CANNOT_SAVE_DEVICE"),
                            exception=exc)
             self.button_validate.setEnabled(True)
         except LocalDeviceError as exc:
             show_error(self,
                        translate("TEXT_CANNOT_SAVE_DEVICE"),
                        exception=exc)
             self.button_validate.setEnabled(True)
Ejemplo n.º 18
0
def test_list_devices_support_legacy_file_with_meaningful_name(config_dir):
    # Legacy path might exceed the 256 characters limit in some cases (see issue #1356)
    # So we use the `\\?\` workaround: https://stackoverflow.com/a/57502760/2846140
    if sys.platform == "win32":
        config_dir = Path("\\\\?\\" + str(config_dir.resolve()))

    # Device information
    user_id = uuid4().hex
    device_name = uuid4().hex
    organization_id = "Org"
    rvk_hash = (uuid4().hex)[:10]
    device_id = f"{user_id}@{device_name}"
    slug = f"{rvk_hash}#{organization_id}#{device_id}"
    human_label = "Billy Mc BillFace"
    human_email = "*****@*****.**"
    device_label = "My device"

    # Craft file data without the user_id, organization_id and slug fields
    key_file_data = packb({
        "type":
        "password",
        "salt":
        b"12345",
        "ciphertext":
        b"whatever",
        "human_handle": (human_email.encode(), human_label.encode()),
        "device_label":
        device_label,
    })

    key_file_path = get_devices_dir(config_dir) / slug / f"{slug}.keys"
    key_file_path.parent.mkdir(parents=True)
    key_file_path.write_bytes(key_file_data)

    devices = list_available_devices(config_dir)
    expected_device = AvailableDevice(
        key_file_path=key_file_path,
        organization_id=OrganizationID(organization_id),
        device_id=DeviceID(device_id),
        human_handle=HumanHandle(human_email, human_label),
        device_label=DeviceLabel(device_label),
        slug=slug,
        type=DeviceFileType.PASSWORD,
    )
    assert devices == [expected_device]
    assert get_key_file(config_dir, expected_device) == key_file_path
Ejemplo n.º 19
0
 def _on_claim_clicked(self):
     if not self.new_device:
         # No try/except given `self.line_edit_device` has already been validated against `DeviceLabel`
         device_label = DeviceLabel(
             validators.trim_user_name(self.line_edit_device.text()))
         self.button_ok.setDisabled(True)
         self.widget_info.setDisabled(True)
         self.label_wait.show()
         self.claim_job = self.jobs_ctx.submit_job(
             self.claim_success,
             self.claim_error,
             self.claimer.claim_device,
             device_label=device_label,
         )
     else:
         self.succeeded.emit(self.new_device,
                             self.widget_auth.get_auth_method(),
                             self.widget_auth.get_auth())
Ejemplo n.º 20
0
        def __init__(self):
            self.requested_device_label = DeviceLabel("PC1")
            self.password = "******"
            self.steps_done = []

            self.author = alice
            self.cmds = alice_backend_cmds

            # Set during bootstrap
            self.invitation_addr = None
            self.claim_device_widget = None
            self.claim_device_instructions_widget = None

            # Set by step 2
            self.claim_device_code_exchange_widget = None

            # Set by step 4
            self.claim_device_provide_info_widget = None
Ejemplo n.º 21
0
        def __init__(self):
            self.requested_human_handle = HumanHandle(
                email="*****@*****.**", label="Bender B. Rodriguez")
            self.requested_device_label = DeviceLabel("PC1")
            self.steps_done = []

            # Set during bootstrap
            self.author = None
            self.devices_widget = None
            self.invitation_addr = None
            self.greet_device_widget = None
            self.greet_device_information_widget = None
            self.cmds = None

            # Set by step 2
            self.greet_device_code_exchange_widget = None

            # Set by step 5
            self.claimer_claim_task = None
Ejemplo n.º 22
0
        def __init__(self):
            self.requested_human_handle = HumanHandle(email="*****@*****.**",
                                                      label="Philip J. Fry")
            self.requested_device_label = DeviceLabel("PC1")
            self.password = "******"
            self.steps_done = []

            self.author = alice
            self.cmds = alice_backend_cmds

            # Set during bootstrap
            self.invitation_addr = None
            self.claim_user_widget = None
            self.claim_user_instructions_widget = None

            # Set by step 2
            self.claim_user_code_exchange_widget = None

            # Set by step 4
            self.claim_user_provide_info_widget = None
Ejemplo n.º 23
0
async def test_greet_user_modified_claim_info(GreetUserTestBed, backend,
                                              coolorg):
    granted_email = "*****@*****.**"
    granted_label = "Don Diego De La Vega"
    granted_device_label = DeviceLabel("Tornado")

    class ModifiedClaimInfoTestBed(GreetUserTestBed):
        async def step_5_provide_claim_info(self):
            await super().step_5_provide_claim_info()

            self.granted_email = granted_email
            self.granted_label = granted_label
            self.granted_device_label = granted_device_label

            guci_w = self.greet_user_check_informations_widget

            guci_w.line_edit_user_full_name.setText(self.granted_label)
            guci_w.line_edit_user_email.setText(self.granted_email)
            guci_w.line_edit_device.setText(self.granted_device_label.str)
            for index in range(guci_w.combo_profile.model().rowCount()):
                item = guci_w.combo_profile.model().item(index)
                if item.text() == translate("TEXT_USER_PROFILE_ADMIN"):
                    item = guci_w.combo_profile.setCurrentIndex(index)
                    break
            else:
                assert False

            return "step_6_validate_claim_info"

    await ModifiedClaimInfoTestBed().run()

    # Now check in the backend if everything went as expected
    results, _ = await backend.user.find_humans(
        organization_id=coolorg.organization_id, query="zorro")
    assert len(results) == 1
    assert results[0].human_handle.label == granted_label
    assert results[0].human_handle.email == granted_email
    user = await backend.user.get_user(organization_id=coolorg.organization_id,
                                       user_id=results[0].user_id)
    assert user.profile == UserProfile.ADMIN
Ejemplo n.º 24
0
async def query_get_user_with_device(
        conn, organization_id: OrganizationID,
        device_id: DeviceID) -> Tuple[User, Device]:
    d_row = await conn.fetchrow(*_q_get_device(
        organization_id=organization_id.str, device_id=device_id.str))
    u_row = await conn.fetchrow(*_q_get_user(
        organization_id=organization_id.str, user_id=device_id.user_id.str))
    if not u_row or not d_row:
        raise UserNotFoundError(device_id)

    human_handle = None
    if u_row["human_email"]:
        human_handle = HumanHandle(email=u_row["human_email"],
                                   label=u_row["human_label"])

    device = Device(
        device_id=device_id,
        device_label=DeviceLabel(d_row["device_label"])
        if d_row["device_label"] else None,
        device_certificate=d_row["device_certificate"],
        redacted_device_certificate=d_row["redacted_device_certificate"],
        device_certifier=DeviceID(d_row["device_certifier"])
        if d_row["device_certifier"] else None,
        created_on=d_row["created_on"],
    )
    user = User(
        user_id=device_id.user_id,
        human_handle=human_handle,
        profile=UserProfile(u_row["profile"]),
        user_certificate=u_row["user_certificate"],
        redacted_user_certificate=u_row["redacted_user_certificate"],
        user_certifier=DeviceID(u_row["user_certifier"])
        if u_row["user_certifier"] else None,
        created_on=u_row["created_on"],
        revoked_on=u_row["revoked_on"],
        revoked_user_certificate=u_row["revoked_user_certificate"],
        revoked_user_certifier=DeviceID(u_row["revoked_user_certifier"])
        if u_row["revoked_user_certifier"] else None,
    )
    return user, device
Ejemplo n.º 25
0
async def _add_random_users(
    cmds: BackendAuthenticatedCmds,
    author: LocalDevice,
    alice_core: LoggedCore,
    bob_core: LoggedCore,
    alice_ws_id: EntryID,
    bob_ws_id: EntryID,
    additional_users_number: int,
):
    """
    Add random number of users with random role, and share workspaces with them.
    1 out of 5 users will be revoked from organization.
    """
    for _ in range(additional_users_number):
        name = "test_" + str(uuid4())[:9]
        user_profile = random.choice(list(UserProfile))
        if user_profile == UserProfile.OUTSIDER:
            realm_role = random.choice([WorkspaceRole.READER, WorkspaceRole.CONTRIBUTOR])
        else:
            realm_role = random.choice(list(WorkspaceRole))
        # Workspace_choice : 0 = add user to first_ws, 1 = add to second_ws, 2 = add in both workspace, other = nothing
        workspace_choice = random.randint(0, 3)
        # invite user to organization
        user_device = await _register_new_user(
            cmds=cmds,
            author=author,
            device_label=DeviceLabel("desktop"),
            human_handle=HumanHandle(email=f"{name}@gmail.com", label=name),
            profile=user_profile,
        )
        # Share workspace with new user
        if workspace_choice == 0 or workspace_choice == 2:
            await alice_core.user_fs.workspace_share(alice_ws_id, user_device.user_id, realm_role)
        if workspace_choice == 1 or workspace_choice == 2:
            await bob_core.user_fs.workspace_share(bob_ws_id, user_device.user_id, realm_role)
        # One chance out of 5 to be revoked from organization
        if not random.randint(0, 4):
            await alice_core.revoke_user(user_device.user_id)
Ejemplo n.º 26
0
async def test_user_create_human_handle_already_exists(alice_backend_sock, alice, bob):
    now = pendulum.now()
    bob2_device_id = DeviceID("bob2@dev1")
    user_certificate = UserCertificateContent(
        author=alice.device_id,
        timestamp=now,
        user_id=bob2_device_id.user_id,
        human_handle=bob.human_handle,
        public_key=bob.public_key,
        profile=UserProfile.STANDARD,
    )
    redacted_user_certificate = user_certificate.evolve(human_handle=None)
    device_certificate = DeviceCertificateContent(
        author=alice.device_id,
        timestamp=now,
        device_id=bob2_device_id,
        device_label=DeviceLabel("dev2"),
        verify_key=bob.verify_key,
    )
    redacted_device_certificate = device_certificate.evolve(device_label=None)

    user_certificate = user_certificate.dump_and_sign(alice.signing_key)
    redacted_user_certificate = redacted_user_certificate.dump_and_sign(alice.signing_key)
    device_certificate = device_certificate.dump_and_sign(alice.signing_key)
    redacted_device_certificate = redacted_device_certificate.dump_and_sign(alice.signing_key)

    rep = await user_create(
        alice_backend_sock,
        user_certificate=user_certificate,
        device_certificate=device_certificate,
        redacted_user_certificate=redacted_user_certificate,
        redacted_device_certificate=redacted_device_certificate,
    )
    assert rep == {
        "status": "already_exists",
        "reason": f"Human handle `{bob.human_handle}` already corresponds to a non-revoked user",
    }
Ejemplo n.º 27
0
def test_invite_device_data():
    from parsec.api.data.invite import _RsInviteDeviceData, InviteDeviceData, _PyInviteDeviceData

    assert InviteDeviceData is _RsInviteDeviceData

    dl = DeviceLabel("label")
    sk = SigningKey.generate()
    vk = sk.verify_key
    sek = SecretKey.generate()

    py_idd = _PyInviteDeviceData(requested_device_label=dl, verify_key=vk)
    rs_idd = InviteDeviceData(requested_device_label=dl, verify_key=vk)

    assert rs_idd.requested_device_label.str == py_idd.requested_device_label.str

    rs_encrypted = rs_idd.dump_and_encrypt(key=sek)
    py_encrypted = py_idd.dump_and_encrypt(key=sek)

    # Decrypt Rust-encrypted with Rust
    rs_idd2 = InviteDeviceData.decrypt_and_load(rs_encrypted, sek)
    assert rs_idd.requested_device_label.str == rs_idd2.requested_device_label.str

    # Decrypt Python-encrypted with Python
    rs_idd3 = InviteDeviceData.decrypt_and_load(py_encrypted, sek)
    assert rs_idd.requested_device_label.str == rs_idd3.requested_device_label.str

    # Decrypt Rust-encrypted with Python
    py_idd2 = _PyInviteDeviceData.decrypt_and_load(rs_encrypted, sek)
    assert rs_idd.requested_device_label.str == py_idd2.requested_device_label.str

    # With requested_human_handle and requested_device_label as None
    py_idd = _PyInviteDeviceData(requested_device_label=None, verify_key=vk)
    rs_idd = InviteDeviceData(requested_device_label=None, verify_key=vk)

    assert py_idd.requested_device_label is None
    assert rs_idd.requested_device_label is None
Ejemplo n.º 28
0
        def __init__(self):
            self.requested_email = "*****@*****.**"
            self.requested_label = "Philip J. Fry"
            self.requested_device_label = DeviceLabel("PC1")
            self.granted_email = self.requested_email
            self.granted_label = self.requested_label
            self.granted_device_label = self.requested_device_label
            self.steps_done = []

            # Set during bootstrap
            self.author = None
            self.users_widget = None
            self.invitation_widget = None
            self.invitation_addr = None
            self.greet_user_widget = None
            self.greet_user_information_widget = None
            self.cmds = None

            # Set by step 2
            self.greet_user_code_exchange_widget = None

            # Set by step 5
            self.claimer_claim_task = None
            self.greet_user_check_informations_widget = None
Ejemplo n.º 29
0
def test_invite_user_data():
    from parsec.api.data.invite import _RsInviteUserData, InviteUserData, _PyInviteUserData

    assert InviteUserData is _RsInviteUserData

    dl = DeviceLabel("label")
    hh = HumanHandle("*****@*****.**",
                     "Hubert Farnsworth")
    pk = PrivateKey.generate()
    sik = SigningKey.generate()
    sek = SecretKey.generate()

    py_iud = _PyInviteUserData(
        requested_device_label=dl,
        requested_human_handle=hh,
        public_key=pk.public_key,
        verify_key=sik.verify_key,
    )
    rs_iud = InviteUserData(
        requested_device_label=dl,
        requested_human_handle=hh,
        public_key=pk.public_key,
        verify_key=sik.verify_key,
    )

    assert rs_iud.requested_device_label.str == py_iud.requested_device_label.str
    assert str(rs_iud.requested_human_handle) == str(
        py_iud.requested_human_handle)
    rs_encrypted = rs_iud.dump_and_encrypt(key=sek)
    py_encrypted = py_iud.dump_and_encrypt(key=sek)

    # Decrypt Rust-encrypted with Rust
    rs_iud2 = InviteUserData.decrypt_and_load(rs_encrypted, sek)
    assert rs_iud.requested_device_label.str == rs_iud2.requested_device_label.str
    assert str(rs_iud.requested_human_handle) == str(
        rs_iud2.requested_human_handle)

    # Decrypt Python-encrypted with Python
    rs_iud3 = InviteUserData.decrypt_and_load(py_encrypted, sek)
    assert rs_iud.requested_device_label.str == rs_iud3.requested_device_label.str
    assert str(rs_iud.requested_human_handle) == str(
        rs_iud3.requested_human_handle)

    # Decrypt Rust-encrypted with Python
    py_iud2 = _PyInviteUserData.decrypt_and_load(rs_encrypted, sek)
    assert rs_iud.requested_device_label.str == py_iud2.requested_device_label.str
    assert str(rs_iud.requested_human_handle) == str(
        py_iud2.requested_human_handle)

    # With requested_human_handle and requested_device_label as None
    py_iud = _PyInviteUserData(
        requested_device_label=None,
        requested_human_handle=None,
        public_key=pk.public_key,
        verify_key=sik.verify_key,
    )
    rs_iud = InviteUserData(
        requested_device_label=None,
        requested_human_handle=None,
        public_key=pk.public_key,
        verify_key=sik.verify_key,
    )

    assert py_iud.requested_device_label is None
    assert rs_iud.requested_device_label is None
    assert py_iud.requested_human_handle is None
    assert rs_iud.requested_human_handle is None
async def test_good(
    running_backend,
    backend,
    user_fs_factory,
    with_labels,
    data_base_dir,
    backend_version,
    monkeypatch,
):
    org_id = OrganizationID("NewOrg")
    org_token = "123456"
    await backend.organization.create(org_id, org_token)

    organization_addr = BackendOrganizationBootstrapAddr.build(
        running_backend.addr, org_id, org_token)

    if with_labels:
        human_handle = HumanHandle(email="*****@*****.**", label="Zack")
        device_label = DeviceLabel("PC1")
    else:
        human_handle = None
        device_label = None

    if backend_version == "2.5":
        _handle_request = AsyncMock(
            return_value=HTTPResponse.build_msgpack(404, {}))
        monkeypatch.setattr("parsec.backend.http.HTTPComponent.handle_request",
                            _handle_request)

    if backend_version == "2.6":
        _handle_request = AsyncMock(return_value=HTTPResponse.build_msgpack(
            200, {"status": "unknown_command"}))
        monkeypatch.setattr("parsec.backend.http.HTTPComponent.handle_request",
                            _handle_request)

    if backend_version == "latest":
        _handle_request = None

    new_device = await bootstrap_organization(organization_addr,
                                              human_handle=human_handle,
                                              device_label=device_label)

    if _handle_request is not None:
        _handle_request.assert_awaited_once()

    assert new_device is not None
    assert new_device.organization_id == org_id
    assert new_device.device_label == device_label
    assert new_device.human_handle == human_handle
    assert new_device.profile == UserProfile.ADMIN

    # This function should always be called as part of bootstrap organization
    # (yeah, we should improve the ergonomics...)
    await user_storage_non_speculative_init(data_base_dir=data_base_dir,
                                            device=new_device)

    # Test the behavior of this new device
    async with user_fs_factory(new_device,
                               data_base_dir=data_base_dir) as newfs:
        # New user should start with a non-speculative user manifest
        um = newfs.get_user_manifest()
        assert um.is_placeholder
        assert not um.speculative

        await newfs.workspace_create(EntryName("wa"))
        await newfs.sync()
        um = newfs.get_user_manifest()
        assert not um.is_placeholder
        assert not um.speculative

    # Test the device in correct in the backend
    backend_user, backend_device = await backend.user.get_user_with_device(
        org_id, new_device.device_id)
    assert backend_user.user_id == new_device.user_id
    assert backend_user.human_handle == new_device.human_handle
    assert backend_user.profile == new_device.profile
    assert backend_user.user_certifier is None
    if with_labels:
        assert backend_user.user_certificate != backend_user.redacted_user_certificate
    else:
        assert backend_user.user_certificate == backend_user.redacted_user_certificate

    assert backend_device.device_id == new_device.device_id
    assert backend_device.device_label == new_device.device_label
    assert backend_device.device_certifier is None
    if with_labels:
        assert backend_device.device_certificate != backend_device.redacted_device_certificate
    else:
        assert backend_device.device_certificate == backend_device.redacted_device_certificate