Beispiel #1
0
async def _greet_invitation(config, device, token):
    async with backend_authenticated_cmds_factory(
            addr=device.organization_addr,
            device_id=device.device_id,
            signing_key=device.signing_key,
            keepalive=config.backend_connection_keepalive,
    ) as cmds:
        async with spinner("Retrieving invitation info"):
            rep = await cmds.invite_list()
            if rep["status"] != "ok":
                raise RuntimeError(f"Backend error: {rep}")
        for invitation in rep["invitations"]:
            if invitation["token"] == token:
                break
        else:
            raise RuntimeError(f"Invitation not found")

        if invitation["type"] == InvitationType.USER:
            initial_ctx = UserGreetInitialCtx(cmds=cmds, token=token)
            do_greet = partial(_do_greet_user, device, initial_ctx)
        else:
            assert invitation["type"] == InvitationType.DEVICE
            initial_ctx = DeviceGreetInitialCtx(cmds=cmds, token=token)
            do_greet = partial(_do_greet_device, device, initial_ctx)

        while True:
            try:
                greet_done = await do_greet()
                if greet_done:
                    break
            except InviteError as exc:
                click.secho(str(exc), fg="red")
            click.secho("Restarting the invitation process", fg="red")
Beispiel #2
0
    async def _run_greeter():
        initial_ctx = UserGreetInitialCtx(cmds=alice_backend_cmds,
                                          token=invitation_addr.token)

        in_progress_ctx = await initial_ctx.do_wait_peer()

        await oob_send.send(in_progress_ctx.greeter_sas)

        in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()

        choices = in_progress_ctx.generate_claimer_sas_choices(size=5)
        assert len(choices) == 5
        assert in_progress_ctx.claimer_sas in choices

        claimer_sas = await oob_recv.receive()
        assert claimer_sas == in_progress_ctx.claimer_sas

        in_progress_ctx = await in_progress_ctx.do_signify_trust()

        in_progress_ctx = await in_progress_ctx.do_get_claim_requests()

        assert in_progress_ctx.requested_device_label == requested_device_label
        assert in_progress_ctx.requested_human_handle == requested_human_handle

        await in_progress_ctx.do_create_new_user(
            author=alice,
            device_label=granted_device_label,
            human_handle=granted_human_handle,
            profile=granted_profile,
        )
Beispiel #3
0
 async def _reset_greeter(self):
     async with trio.open_nursery() as nursery:
         greeter_initial_ctx = UserGreetInitialCtx(
             cmds=alice2_backend_cmds, token=self.invitation_addr.token)
         nursery.start_soon(greeter_initial_ctx.do_wait_peer)
         yield
         nursery.cancel_scope.cancel()
Beispiel #4
0
async def _init_ctx_create(cmds, token):
    initial_ctx = UserGreetInitialCtx(cmds=cmds, token=token)
    in_progress_ctx = await initial_ctx.do_wait_peer()
    in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()
    in_progress_ctx = await in_progress_ctx.do_signify_trust()
    in_progress_ctx = await in_progress_ctx.do_get_claim_requests()
    return in_progress_ctx
Beispiel #5
0
 async def start_greeting_user(self, token: UUID) -> UserGreetInProgress1Ctx:
     """
     Raises:
         BackendConnectionError
         InviteError
     """
     initial_ctx = UserGreetInitialCtx(cmds=self._backend_conn.cmds, token=token)
     return await initial_ctx.do_wait_peer()
 async def invite_task():
     initial_ctx = UserGreetInitialCtx(cmds=alice_cmds, token=invitation_addr.token)
     in_progress_ctx = await initial_ctx.do_wait_peer()
     in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()
     in_progress_ctx = await in_progress_ctx.do_signify_trust()
     in_progress_ctx = await in_progress_ctx.do_get_claim_requests()
     await in_progress_ctx.do_create_new_user(
         author=alice_device,
         human_handle=in_progress_ctx.requested_human_handle,
         device_label=in_progress_ctx.requested_device_label,
         profile=UserProfile.STANDARD,
     )
Beispiel #7
0
    async def _run_greeter():
        async with backend_authenticated_cmds_factory(
                alice.organization_addr, alice.device_id,
                alice.signing_key) as alice_backend_cmds:
            initial_ctx = UserGreetInitialCtx(cmds=alice_backend_cmds,
                                              token=invitation_addr.token)
            in_progress_ctx = await initial_ctx.do_wait_peer()
            in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()
            in_progress_ctx = await in_progress_ctx.do_signify_trust()
            in_progress_ctx = await in_progress_ctx.do_get_claim_requests()

            # ...this is where the limit should be enforced
            with pytest.raises(InviteActiveUsersLimitReachedError):
                await in_progress_ctx.do_create_new_user(
                    author=alice,
                    device_label=in_progress_ctx.requested_device_label,
                    human_handle=in_progress_ctx.requested_human_handle,
                    profile=UserProfile.STANDARD,
                )
Beispiel #8
0
        async def step_2_start_greeter(self):
            cui_w = self.claim_user_instructions_widget

            self.greeter_initial_ctx = UserGreetInitialCtx(
                cmds=self.cmds, token=self.invitation_addr.token)
            self.greeter_in_progress_ctx = await self.greeter_initial_ctx.do_wait_peer(
            )

            cuce_w = await catch_claim_user_widget()
            assert isinstance(cuce_w, ClaimUserCodeExchangeWidget)

            def _greeter_sas_code_choices_displayed():
                assert not cui_w.isVisible()
                assert cuce_w.isVisible()
                assert cuce_w.widget_greeter_code.isVisible()
                assert cuce_w.code_input_widget.isVisible()
                assert cuce_w.code_input_widget.code_layout.count() == 4
                # TODO: better check on codes

            await aqtbot.wait_until(_greeter_sas_code_choices_displayed)

            self.claim_user_code_exchange_widget = cuce_w

            return "step_3_exchange_greeter_sas"
Beispiel #9
0
async def test_claimer_handle_command_failure(backend, running_backend, alice,
                                              alice_backend_cmds, monkeypatch,
                                              fail_on_step):
    invitation = await backend.invite.new_for_device(
        organization_id=alice.organization_id, greeter_user_id=alice.user_id)
    invitation_addr = BackendInvitationAddr.build(
        backend_addr=alice.organization_addr.get_backend_addr(),
        organization_id=alice.organization_id,
        invitation_type=InvitationType.DEVICE,
        token=invitation.token,
    )

    async def _cancel_invitation():
        await backend.invite.delete(
            organization_id=alice.organization_id,
            greeter=alice.user_id,
            token=invitation_addr.token,
            on=pendulum_now(),
            reason=InvitationDeletedReason.CANCELLED,
        )

    async with backend_invited_cmds_factory(
            addr=invitation_addr) as claimer_cmds:
        greeter_initial_ctx = UserGreetInitialCtx(cmds=alice_backend_cmds,
                                                  token=invitation_addr.token)
        claimer_initial_ctx = await claimer_retrieve_info(claimer_cmds)

        claimer_in_progress_ctx = None
        greeter_in_progress_ctx = None

        async def _do_claimer():
            nonlocal claimer_in_progress_ctx
            if fail_on_step == "wait_peer":
                return
            claimer_in_progress_ctx = await claimer_initial_ctx.do_wait_peer()
            if fail_on_step == "signify_trust":
                return
            claimer_in_progress_ctx = await claimer_in_progress_ctx.do_signify_trust(
            )
            if fail_on_step == "wait_peer_trust":
                return
            claimer_in_progress_ctx = await claimer_in_progress_ctx.do_wait_peer_trust(
            )

        async def _do_greeter():
            nonlocal greeter_in_progress_ctx
            if fail_on_step == "wait_peer":
                return
            greeter_in_progress_ctx = await greeter_initial_ctx.do_wait_peer()
            if fail_on_step == "signify_trust":
                return
            greeter_in_progress_ctx = await greeter_in_progress_ctx.do_wait_peer_trust(
            )
            if fail_on_step == "wait_peer_trust":
                return
            greeter_in_progress_ctx = await greeter_in_progress_ctx.do_signify_trust(
            )

        async with real_clock_timeout():

            async with trio.open_nursery() as nursery:
                nursery.start_soon(_do_claimer)
                nursery.start_soon(_do_greeter)

        deleted_event = trio.Event()

        async def _send_event(*args, **kwargs):
            if BackendEvent.INVITE_STATUS_CHANGED in args and (
                    kwargs.get("status") == InvitationStatus.DELETED):
                deleted_event.set()
            await trio.sleep(0)

        backend.invite._send_event = _send_event
        monkeypatch.setattr("parsec.backend.postgresql.invite.send_signal",
                            _send_event)

        async with real_clock_timeout():
            await _cancel_invitation()
            await deleted_event.wait()
            with pytest.raises(BackendInvitationAlreadyUsed) as exc_info:
                if fail_on_step == "wait_peer":
                    await claimer_initial_ctx.do_wait_peer()
                elif fail_on_step == "signify_trust":
                    await claimer_in_progress_ctx.do_signify_trust()
                elif fail_on_step == "wait_peer_trust":
                    await claimer_in_progress_ctx.do_wait_peer_trust()
                elif fail_on_step == "claim_device":
                    await claimer_in_progress_ctx.do_claim_device(
                        requested_device_label=DeviceLabel("TheSecretDevice"))
                else:
                    raise AssertionError(f"Unknown step {fail_on_step}")
            assert str(exc_info.value
                       ) == "Invalid handshake: Invitation already deleted"
Beispiel #10
0
async def test_claimer_handle_cancel_event(backend, running_backend, alice,
                                           alice_backend_cmds, fail_on_step):
    invitation = await backend.invite.new_for_device(
        organization_id=alice.organization_id, greeter_user_id=alice.user_id)
    invitation_addr = BackendInvitationAddr.build(
        backend_addr=alice.organization_addr.get_backend_addr(),
        organization_id=alice.organization_id,
        invitation_type=InvitationType.DEVICE,
        token=invitation.token,
    )

    async def _cancel_invitation():
        await backend.invite.delete(
            organization_id=alice.organization_id,
            greeter=alice.user_id,
            token=invitation_addr.token,
            on=pendulum_now(),
            reason=InvitationDeletedReason.CANCELLED,
        )

    async with backend_invited_cmds_factory(
            addr=invitation_addr) as claimer_cmds:
        greeter_initial_ctx = UserGreetInitialCtx(cmds=alice_backend_cmds,
                                                  token=invitation_addr.token)
        claimer_initial_ctx = await claimer_retrieve_info(claimer_cmds)

        claimer_in_progress_ctx = None
        greeter_in_progress_ctx = None

        async def _do_claimer():
            nonlocal claimer_in_progress_ctx
            if fail_on_step == "wait_peer":
                return
            claimer_in_progress_ctx = await claimer_initial_ctx.do_wait_peer()
            if fail_on_step == "signify_trust":
                return
            claimer_in_progress_ctx = await claimer_in_progress_ctx.do_signify_trust(
            )
            if fail_on_step == "wait_peer_trust":
                return
            claimer_in_progress_ctx = await claimer_in_progress_ctx.do_wait_peer_trust(
            )

        async def _do_greeter():
            nonlocal greeter_in_progress_ctx
            if fail_on_step == "wait_peer":
                return
            greeter_in_progress_ctx = await greeter_initial_ctx.do_wait_peer()
            if fail_on_step == "signify_trust":
                return
            greeter_in_progress_ctx = await greeter_in_progress_ctx.do_wait_peer_trust(
            )
            if fail_on_step == "wait_peer_trust":
                return
            greeter_in_progress_ctx = await greeter_in_progress_ctx.do_signify_trust(
            )

        async with real_clock_timeout():
            async with trio.open_nursery() as nursery:

                nursery.start_soon(_do_claimer)
                nursery.start_soon(_do_greeter)

        async with real_clock_timeout():

            async with trio.open_nursery() as nursery:

                async def _do_claimer_wait_peer():
                    with pytest.raises(
                            BackendInvitationAlreadyUsed) as exc_info:
                        await claimer_initial_ctx.do_wait_peer()
                    assert str(
                        exc_info.value
                    ) == "Invalid handshake: Invitation already deleted"

                async def _do_claimer_signify_trust():
                    with pytest.raises(
                            BackendInvitationAlreadyUsed) as exc_info:
                        await claimer_in_progress_ctx.do_signify_trust()
                    assert str(
                        exc_info.value
                    ) == "Invalid handshake: Invitation already deleted"

                async def _do_claimer_wait_peer_trust():
                    with pytest.raises(
                            BackendInvitationAlreadyUsed) as exc_info:
                        await claimer_in_progress_ctx.do_wait_peer_trust()
                    assert str(
                        exc_info.value
                    ) == "Invalid handshake: Invitation already deleted"

                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"

                steps = {
                    "wait_peer": _do_claimer_wait_peer,
                    "signify_trust": _do_claimer_signify_trust,
                    "wait_peer_trust": _do_claimer_wait_peer_trust,
                    "claim_device": _do_claimer_claim_device,
                }
                _do_claimer = steps[fail_on_step]

                with backend.event_bus.listen() as spy:
                    nursery.start_soon(_do_claimer)
                    # Be sure that _do_claimer got valid invitations before cancelation
                    await spy.wait_with_timeout(
                        BackendEvent.INVITE_CONDUIT_UPDATED)
                    await _cancel_invitation()
                    await spy.wait_with_timeout(
                        BackendEvent.INVITE_STATUS_CHANGED)
Beispiel #11
0
async def test_claimer_handle_reset(backend, running_backend, alice,
                                    alice_backend_cmds):
    invitation = await backend.invite.new_for_device(
        organization_id=alice.organization_id, greeter_user_id=alice.user_id)
    invitation_addr = BackendInvitationAddr.build(
        backend_addr=alice.organization_addr.get_backend_addr(),
        organization_id=alice.organization_id,
        invitation_type=InvitationType.DEVICE,
        token=invitation.token,
    )

    async with backend_invited_cmds_factory(
            addr=invitation_addr) as claimer_cmds:
        greeter_initial_ctx = UserGreetInitialCtx(cmds=alice_backend_cmds,
                                                  token=invitation_addr.token)
        claimer_initial_ctx = await claimer_retrieve_info(claimer_cmds)

        claimer_in_progress_ctx = None
        greeter_in_progress_ctx = None

        # Step 1
        async with real_clock_timeout():
            async with trio.open_nursery() as nursery:

                async def _do_claimer():
                    nonlocal claimer_in_progress_ctx
                    claimer_in_progress_ctx = await claimer_initial_ctx.do_wait_peer(
                    )

                async def _do_greeter():
                    nonlocal greeter_in_progress_ctx
                    greeter_in_progress_ctx = await greeter_initial_ctx.do_wait_peer(
                    )

                nursery.start_soon(_do_claimer)
                nursery.start_soon(_do_greeter)

        # Claimer restart the conduit while greeter try to do step 2
        async with real_clock_timeout():
            async with trio.open_nursery() as nursery:

                async def _do_claimer():
                    nonlocal claimer_in_progress_ctx
                    claimer_in_progress_ctx = await claimer_initial_ctx.do_wait_peer(
                    )

                nursery.start_soon(_do_claimer)
                with pytest.raises(InvitePeerResetError):
                    await greeter_in_progress_ctx.do_wait_peer_trust()

                # Greeter redo step 1
                greeter_in_progress_ctx = await greeter_initial_ctx.do_wait_peer(
                )

        # Now do the other way around: greeter restart conduit while claimer try step 2
        async with real_clock_timeout():
            async with trio.open_nursery() as nursery:

                async def _do_greeter():
                    nonlocal greeter_in_progress_ctx
                    greeter_in_progress_ctx = await greeter_initial_ctx.do_wait_peer(
                    )

                nursery.start_soon(_do_greeter)
                with pytest.raises(InvitePeerResetError):
                    await claimer_in_progress_ctx.do_signify_trust()

                # Claimer redo step 1
                claimer_in_progress_ctx = await claimer_initial_ctx.do_wait_peer(
                )