Ejemplo n.º 1
0
    def wrapper(config_dir, *args, **kwargs):
        assert "config" not in kwargs

        ssl_keyfile = kwargs["ssl_keyfile"]
        ssl_certfile = kwargs["ssl_certfile"]

        if ssl_certfile or ssl_keyfile:
            ssl_context = trio.ssl.create_default_context(
                trio.ssl.Purpose.SERVER_CLIENT)
            if ssl_certfile:
                ssl_context.load_cert_chain(ssl_certfile, ssl_keyfile)
            else:
                ssl_context.load_default_certs()
            kwargs["ssl_context"] = ssl_context

        configure_logging(kwargs["log_level"], kwargs["log_format"],
                          kwargs["log_file"], kwargs["log_filter"])

        config_dir = Path(
            config_dir) if config_dir else get_default_config_dir(os.environ)
        config = load_config(config_dir, debug="DEBUG" in os.environ)

        if config.sentry_url:
            configure_sentry_logging(config.sentry_url)

        kwargs["config"] = config
        return fn(**kwargs)
def bootstrap_organization(device, addr, config_dir, force, password):
    """
    Configure the organization and register it first user&device.
    """

    config_dir = Path(config_dir) if config_dir else get_default_config_dir(os.environ)
    debug = "DEBUG" in os.environ
    configure_logging(log_level="DEBUG" if debug else "WARNING")

    with cli_exception_handler(debug):
        trio_run(_bootstrap_organization, debug, device, addr, config_dir, force, password)
Ejemplo n.º 3
0
    def wrapper(config_dir, *args, **kwargs):
        assert "config" not in kwargs

        configure_logging(kwargs["log_level"], kwargs["log_format"],
                          kwargs["log_file"], kwargs["log_filter"])

        config_dir = Path(
            config_dir) if config_dir else get_default_config_dir(os.environ)
        config = load_config(config_dir, debug="DEBUG" in os.environ)

        if config.telemetry_enabled and config.sentry_url:
            configure_sentry_logging(config.sentry_url)

        kwargs["config"] = config
        return fn(**kwargs)
Ejemplo n.º 4
0
        def wrapper(**kwargs):
            # `click.open_file` considers "-" to be stdout
            if kwargs["log_file"] in (None, "-"):

                @contextmanager
                def open_log_file():
                    yield sys.stderr

            else:
                open_log_file = partial(click.open_file, kwargs["log_file"],
                                        "w")

            with open_log_file() as fd:

                configure_logging(log_level=kwargs["log_level"],
                                  log_format=kwargs["log_format"],
                                  log_stream=fd)

                return fn(**kwargs)
Ejemplo n.º 5
0
async def main():

    # Config
    configure_logging(LOG_LEVEL)
    config_dir = get_default_config_dir(os.environ)
    config = load_config(config_dir)
    devices = list_available_devices(config_dir)
    key_file = next(key_file for _, device_id, _, key_file in devices
                    if device_id == DEVICE_ID)
    device = load_device_with_password(key_file, PASSWORD)

    # Log in
    async with logged_core_factory(config, device) as core:

        # Get workspace
        user_manifest = core.user_fs.get_user_manifest()
        workspace_entry = user_manifest.workspaces[0]
        workspace = core.user_fs.get_workspace(workspace_entry.id)

        # await make_workspace_dir_inconsistent(device, workspace, "/bar")
        await make_workspace_dir_simple_versions(device, workspace, "/foo")
def status_organization(name, addr, administration_token):
    debug = "DEBUG" in os.environ
    configure_logging(log_level="DEBUG" if debug else "WARNING")

    with cli_exception_handler(debug):
        trio_run(_status_organization, name, addr, administration_token)
Ejemplo n.º 7
0
def run_cmd(
    host,
    port,
    db,
    db_drop_deleted_data,
    db_min_connections,
    db_max_connections,
    blockstore,
    administration_token,
    ssl_keyfile,
    ssl_certfile,
    log_level,
    log_format,
    log_file,
    log_filter,
    sentry_url,
    debug,
    dev,
):
    configure_logging(log_level, log_format, log_file, log_filter)
    if sentry_url:
        configure_sentry_logging(sentry_url)

    with cli_exception_handler(debug):

        config = BackendConfig(
            administration_token=administration_token,
            db_url=db,
            db_drop_deleted_data=db_drop_deleted_data,
            db_min_connections=db_min_connections,
            db_max_connections=db_max_connections,
            blockstore_config=blockstore,
            debug=debug,
        )

        if ssl_certfile or ssl_keyfile:
            ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
            if ssl_certfile:
                ssl_context.load_cert_chain(ssl_certfile, ssl_keyfile)
            else:
                ssl_context.load_default_certs()
        else:
            ssl_context = None

        async def _run_backend():
            async with backend_app_factory(config=config) as backend:

                async def _serve_client(stream):
                    if ssl_context:
                        stream = trio.SSLStream(stream, ssl_context, server_side=True)

                    try:
                        await backend.handle_client(stream)

                    except Exception:
                        # If we are here, something unexpected happened...
                        logger.exception("Unexpected crash")
                        await stream.aclose()

                await trio.serve_tcp(_serve_client, port, host=host)

        click.echo(
            f"Starting Parsec Backend on {host}:{port} (db={config.db_type}, "
            f"blockstore={config.blockstore_config.type})"
        )
        try:
            trio_run(_run_backend, use_asyncio=True)
        except KeyboardInterrupt:
            click.echo("bye ;-)")
Ejemplo n.º 8
0
def create_organization(name, addr, administration_token, expiration_date):
    debug = "DEBUG" in os.environ
    configure_logging(log_level="DEBUG" if debug else "WARNING")
    with cli_exception_handler(debug):
        trio_run(_create_organization, debug, name, addr, administration_token,
                 expiration_date)
Ejemplo n.º 9
0
def run_cmd(
    host,
    port,
    db,
    db_min_connections,
    db_max_connections,
    db_first_tries_number,
    db_first_tries_sleep,
    blockstore,
    administration_token,
    spontaneous_organization_bootstrap,
    organization_bootstrap_webhook,
    backend_addr,
    email_host,
    email_port,
    email_host_user,
    email_host_password,
    email_use_ssl,
    email_use_tls,
    email_sender,
    forward_proto_enforce_https,
    ssl_keyfile,
    ssl_certfile,
    log_level,
    log_format,
    log_file,
    log_filter,
    sentry_url,
    debug,
    dev,
):

    # Start a local backend
    configure_logging(log_level, log_format, log_file, log_filter)
    if sentry_url:
        configure_sentry_logging(sentry_url)

    with cli_exception_handler(debug):

        if ssl_certfile or ssl_keyfile:
            ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
            if ssl_certfile:
                ssl_context.load_cert_chain(ssl_certfile, ssl_keyfile)
            else:
                ssl_context.load_default_certs()
        else:
            ssl_context = None

        if email_host == "MOCKED":
            tmpdir = tempfile.mkdtemp(prefix="tmp-email-folder-")
            if email_sender:
                email_config = MockedEmailConfig(sender=email_sender,
                                                 tmpdir=tmpdir)
            else:
                email_config = MockedEmailConfig(sender=DEFAULT_EMAIL_SENDER,
                                                 tmpdir=tmpdir)
        else:
            if not email_sender:
                raise ValueError(
                    "--email-sender is required when --email-host is provided")
            email_config = SmtpEmailConfig(
                host=email_host,
                port=email_port,
                host_user=email_host_user,
                host_password=email_host_password,
                use_ssl=email_use_ssl,
                use_tls=email_use_tls,
                sender=email_sender,
            )

        config = BackendConfig(
            administration_token=administration_token,
            db_url=db,
            db_min_connections=db_min_connections,
            db_max_connections=db_max_connections,
            db_first_tries_number=db_first_tries_number,
            db_first_tries_sleep=db_first_tries_sleep,
            spontaneous_organization_bootstrap=
            spontaneous_organization_bootstrap,
            organization_bootstrap_webhook_url=organization_bootstrap_webhook,
            blockstore_config=blockstore,
            email_config=email_config,
            ssl_context=True if ssl_context else False,
            forward_proto_enforce_https=forward_proto_enforce_https,
            backend_addr=backend_addr,
            debug=debug,
        )

        async def _run_backend():
            async with backend_app_factory(config=config) as backend:

                async def _serve_client(stream):
                    if ssl_context:
                        stream = trio.SSLStream(stream,
                                                ssl_context,
                                                server_side=True)

                    try:
                        await backend.handle_client(stream)

                    except Exception:
                        # If we are here, something unexpected happened...
                        logger.exception("Unexpected crash")
                        await stream.aclose()

                await trio.serve_tcp(_serve_client, port, host=host)

        click.echo(f"Starting Parsec Backend on {host}:{port}"
                   f" (db={config.db_type}"
                   f" blockstore={config.blockstore_config.type}"
                   f" backend_addr={config.backend_addr}"
                   f" email_config={str(email_config)})")
        try:
            trio_run(_run_backend, use_asyncio=True)
        except KeyboardInterrupt:
            click.echo("bye ;-)")
Ejemplo n.º 10
0
async def initialize_test_organization(
    config_dir: Path,
    backend_address: BackendAddr,
    password: str,
    administration_token: str,
    force: bool,
) -> Tuple[LocalDevice, LocalDevice, LocalDevice]:

    configure_logging("WARNING")

    organization_id = OrganizationID("Org")

    # Create organization

    async with apiv1_backend_administration_cmds_factory(
        backend_address, administration_token
    ) as administration_cmds:

        rep = await administration_cmds.organization_create(organization_id)
        assert rep["status"] == "ok"
        bootstrap_token = rep["bootstrap_token"]

        organization_bootstrap_addr = BackendOrganizationBootstrapAddr.build(
            backend_address, organization_id, bootstrap_token
        )

    # Bootstrap organization and Alice user

    async with apiv1_backend_anonymous_cmds_factory(organization_bootstrap_addr) as anonymous_cmds:
        alice_device = await bootstrap_organization(
            cmds=anonymous_cmds,
            human_handle=HumanHandle(label="Alice", email="*****@*****.**"),
            device_label="laptop",
        )
        save_device_with_password(config_dir, alice_device, password, force=force)

    # Create a workspace for Alice

    config = load_config(config_dir, debug="DEBUG" in os.environ)
    async with logged_core_factory(config, alice_device) as core:
        alice_ws_id = await core.user_fs.workspace_create("alice_workspace")
        await core.user_fs.sync()

    # Register a new device for Alice

    other_alice_device = None
    async with backend_authenticated_cmds_factory(
        addr=alice_device.organization_addr,
        device_id=alice_device.device_id,
        signing_key=alice_device.signing_key,
    ) as alice_cmds:
        rep = await alice_cmds.invite_new(type=InvitationType.DEVICE)
        assert rep["status"] == "ok"
        invitation_addr = BackendInvitationAddr.build(
            backend_addr=alice_device.organization_addr,
            organization_id=alice_device.organization_id,
            invitation_type=InvitationType.DEVICE,
            token=rep["token"],
        )

        async with backend_invited_cmds_factory(addr=invitation_addr) as invited_cmds:

            async def invite_task():
                initial_ctx = DeviceGreetInitialCtx(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_device(
                    author=alice_device, device_label=in_progress_ctx.requested_device_label
                )

            async def claim_task():
                nonlocal other_alice_device
                initial_ctx = await claimer_retrieve_info(cmds=invited_cmds)
                in_progress_ctx = await initial_ctx.do_wait_peer()
                in_progress_ctx = await in_progress_ctx.do_signify_trust()
                in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()
                other_alice_device = await in_progress_ctx.do_claim_device(
                    requested_device_label="pc"
                )

            async with trio.open_service_nursery() as nursery:
                nursery.start_soon(invite_task)
                nursery.start_soon(claim_task)

            save_device_with_password(config_dir, other_alice_device, password, force=force)

        # Invite Bob in

        bob_device = None
        rep = await alice_cmds.invite_new(type=InvitationType.USER, claimer_email="*****@*****.**")
        assert rep["status"] == "ok"
        invitation_addr = BackendInvitationAddr.build(
            backend_addr=alice_device.organization_addr,
            organization_id=alice_device.organization_id,
            invitation_type=InvitationType.USER,
            token=rep["token"],
        )

        async with backend_invited_cmds_factory(addr=invitation_addr) as invited_cmds:

            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,
                )

            async def claim_task():
                nonlocal bob_device
                initial_ctx = await claimer_retrieve_info(cmds=invited_cmds)
                in_progress_ctx = await initial_ctx.do_wait_peer()
                in_progress_ctx = await in_progress_ctx.do_signify_trust()
                in_progress_ctx = await in_progress_ctx.do_wait_peer_trust()
                bob_device = await in_progress_ctx.do_claim_user(
                    requested_human_handle=HumanHandle(label="Bob", email="*****@*****.**"),
                    requested_device_label="laptop",
                )

            async with trio.open_service_nursery() as nursery:
                nursery.start_soon(invite_task)
                nursery.start_soon(claim_task)

            save_device_with_password(config_dir, bob_device, password, force=force)

    # Create bob workspace and share with Alice

    async with logged_core_factory(config, bob_device) as core:
        bob_ws_id = await core.user_fs.workspace_create("bob_workspace")
        await core.user_fs.workspace_share(bob_ws_id, alice_device.user_id, WorkspaceRole.MANAGER)

    # Share Alice workspace with bob

    async with logged_core_factory(config, alice_device) as core:
        await core.user_fs.workspace_share(alice_ws_id, bob_device.user_id, WorkspaceRole.MANAGER)

    # Synchronize every device
    for device in (alice_device, other_alice_device, bob_device):
        async with logged_core_factory(config, device) as core:
            await core.user_fs.process_last_messages()
            await core.user_fs.sync()

    return (alice_device, other_alice_device, bob_device)
async def amain(
    backend_address="ws://*****:*****@laptop",
    bob_device_id="bob@laptop",
    other_device_name="pc",
    alice_workspace="alicews",
    bob_workspace="bobws",
    password="******",
    administrator_token=DEFAULT_ADMINISTRATOR_TOKEN,
    force=False,
):

    configure_logging("WARNING")

    config_dir = get_default_config_dir(os.environ)
    organization_id = OrganizationID(organization_id)
    backend_address = BackendAddr(backend_address)
    alice_device_id = DeviceID(alice_device_id)
    bob_device_id = DeviceID(bob_device_id)
    alice_slugid = f"{organization_id}:{alice_device_id}"
    bob_slugid = f"{organization_id}:{bob_device_id}"

    # Create organization

    async with backend_administrator_cmds_factory(backend_address, administrator_token) as cmds:

        bootstrap_token = await cmds.organization_create(organization_id)

        organization_bootstrap_addr = BackendOrganizationBootstrapAddr.build(
            backend_address, organization_id, bootstrap_token
        )

    # Bootstrap organization and Alice user

    async with backend_anonymous_cmds_factory(organization_bootstrap_addr) as cmds:
        root_signing_key = SigningKey.generate()
        root_verify_key = root_signing_key.verify_key
        organization_addr = organization_bootstrap_addr.generate_organization_addr(root_verify_key)

        alice_device = generate_new_device(alice_device_id, organization_addr)

        save_device_with_password(config_dir, alice_device, password, force=force)

        now = pendulum.now()
        certified_user = certify_user(
            None, root_signing_key, alice_device.user_id, alice_device.public_key, now
        )
        certified_device = certify_device(
            None, root_signing_key, alice_device_id, alice_device.verify_key, now
        )

        await cmds.organization_bootstrap(
            organization_bootstrap_addr.organization_id,
            organization_bootstrap_addr.bootstrap_token,
            root_verify_key,
            certified_user,
            certified_device,
        )

    # Create a workspace for Alice

    config = load_config(config_dir, debug="DEBUG" in os.environ)
    async with logged_core_factory(config, alice_device) as core:
        await core.fs.workspace_create(f"/{alice_workspace}")

    # Register a new device for Alice

    token = generate_invitation_token()
    other_alice_device_id = DeviceID("@".join((alice_device.user_id, other_device_name)))
    other_alice_slugid = f"{organization_id}:{other_alice_device_id}"

    async def invite_task():
        async with backend_cmds_factory(
            alice_device.organization_addr, alice_device.device_id, alice_device.signing_key
        ) as cmds:
            await invite_and_create_device(alice_device, cmds, other_device_name, token)

    async def claim_task():
        async with backend_anonymous_cmds_factory(alice_device.organization_addr) as cmds:
            other_alice_device = await retry(claim_device, cmds, other_alice_device_id, token)
            save_device_with_password(config_dir, other_alice_device, password, force=force)

    async with trio.open_nursery() as nursery:
        nursery.start_soon(invite_task)
        nursery.start_soon(claim_task)

    # Invite Bob in

    token = generate_invitation_token()

    async def invite_task():
        async with backend_cmds_factory(
            alice_device.organization_addr, alice_device.device_id, alice_device.signing_key
        ) as cmds:
            await invite_and_create_user(
                alice_device, cmds, bob_device_id.user_id, token, is_admin=True
            )

    async def claim_task():
        async with backend_anonymous_cmds_factory(alice_device.organization_addr) as cmds:
            bob_device = await retry(claim_user, cmds, bob_device_id, token)
            save_device_with_password(config_dir, bob_device, password, force=force)

    async with trio.open_nursery() as nursery:
        nursery.start_soon(invite_task)
        nursery.start_soon(claim_task)

    # Create bob workspace and share with Alice

    bob_device = load_device_with_password(
        config.config_dir, organization_id, bob_device_id, password
    )

    async with logged_core_factory(config, bob_device) as core:
        await core.fs.workspace_create(f"/{bob_workspace}")
        await core.fs.share(f"/{bob_workspace}", alice_device_id.user_id)

    # Share Alice workspace with bob

    async with logged_core_factory(config, alice_device) as core:
        await core.fs.share(f"/{alice_workspace}", bob_device_id.user_id)

    # Print out

    click.echo(
        f"""
Mount alice and bob drives using:

    $ parsec core run -P {password} -D {alice_slugid}
    $ parsec core run -P {password} -D {other_alice_slugid}
    $ parsec core run -P {password} -D {bob_slugid}
"""
    )
Ejemplo n.º 12
0
async def initialize_test_organization(
    config_dir: Path,
    backend_address: BackendAddr,
    password: str,
    administration_token: str,
    additional_users_number: int,
    additional_devices_number: int,
) -> Tuple[LocalDevice, LocalDevice, LocalDevice]:
    configure_logging(log_level="WARNING")
    organization_id = OrganizationID("Org")

    # Create organization
    async with apiv1_backend_administration_cmds_factory(
        backend_address, administration_token) as administration_cmds:

        rep = await administration_cmds.organization_create(organization_id)
        assert rep["status"] == "ok", rep
        bootstrap_token = rep["bootstrap_token"]

        organization_bootstrap_addr = BackendOrganizationBootstrapAddr.build(
            backend_address, organization_id, bootstrap_token)
    # Bootstrap organization and Alice user and create device "laptop" for Alice

    async with apiv1_backend_anonymous_cmds_factory(
            organization_bootstrap_addr) as anonymous_cmds:
        alice_device = await bootstrap_organization(
            cmds=anonymous_cmds,
            human_handle=HumanHandle(label="Alice", email="*****@*****.**"),
            device_label="laptop",
        )
        save_device_with_password(config_dir=config_dir,
                                  device=alice_device,
                                  password=password)

    config = load_config(config_dir, debug="DEBUG" in os.environ)
    # Create context manager, alice_core will be needed for the rest of the script
    async with logged_core_factory(config, alice_device) as alice_core:
        async with backend_authenticated_cmds_factory(
                addr=alice_device.organization_addr,
                device_id=alice_device.device_id,
                signing_key=alice_device.signing_key,
        ) as alice_cmds:

            # Create new device "pc" for Alice
            other_alice_device = await _register_new_device(
                cmds=alice_cmds, author=alice_device, device_label="pc")
            save_device_with_password(config_dir=config_dir,
                                      device=other_alice_device,
                                      password=password)
            # Invite Bob in organization
            bob_device = await _register_new_user(
                cmds=alice_cmds,
                author=alice_device,
                device_label="laptop",
                human_handle=HumanHandle(email="*****@*****.**", label="Bob"),
                profile=UserProfile.STANDARD,
            )
            save_device_with_password(config_dir=config_dir,
                                      device=bob_device,
                                      password=password)

            # Invite Toto in organization
            toto_device = await _register_new_user(
                cmds=alice_cmds,
                author=alice_device,
                device_label="laptop",
                human_handle=HumanHandle(email="*****@*****.**",
                                         label="Toto"),
                profile=UserProfile.OUTSIDER,
            )
            save_device_with_password(config_dir=config_dir,
                                      device=toto_device,
                                      password=password)
            # Create Alice workspace
            alice_ws_id = await alice_core.user_fs.workspace_create(
                "alice_workspace")
            # Create context manager
            async with logged_core_factory(config, bob_device) as bob_core:
                # Create Bob workspace
                bob_ws_id = await bob_core.user_fs.workspace_create(
                    "bob_workspace")
                # Bob share workspace with Alice
                await bob_core.user_fs.workspace_share(bob_ws_id,
                                                       alice_device.user_id,
                                                       WorkspaceRole.MANAGER)
                # Alice share workspace with Bob
                await alice_core.user_fs.workspace_share(
                    alice_ws_id, bob_device.user_id, WorkspaceRole.MANAGER)
                # Add additional random users
                await _add_random_users(
                    cmds=alice_cmds,
                    author=alice_device,
                    alice_core=alice_core,
                    bob_core=bob_core,
                    alice_ws_id=alice_ws_id,
                    bob_ws_id=bob_ws_id,
                    additional_users_number=additional_users_number,
                )
                # Add additional random device for alice
                await _add_random_device(
                    cmds=alice_cmds,
                    device=alice_device,
                    additional_devices_number=additional_devices_number,
                )

    # Synchronize every device
    for device in (alice_device, other_alice_device, bob_device):
        async with logged_core_factory(config, device) as core:
            await core.user_fs.process_last_messages()
            await core.user_fs.sync()
    return (alice_device, other_alice_device, bob_device)
Ejemplo n.º 13
0
async def initialize_test_organization(
    backend_address,
    organization_id,
    alice_device_id,
    bob_device_id,
    other_device_name,
    alice_workspace,
    bob_workspace,
    password,
    administration_token,
    force,
):

    configure_logging("WARNING")

    config_dir = get_default_config_dir(os.environ)
    alice_slugid = f"{organization_id}:{alice_device_id}"
    bob_slugid = f"{organization_id}:{bob_device_id}"

    # Create organization
    async with backend_administration_cmds_factory(
        backend_address, administration_token) as cmds:

        rep = await cmds.organization_create(organization_id)
        assert rep["status"] == "ok"
        bootstrap_token = rep["bootstrap_token"]

        organization_bootstrap_addr = BackendOrganizationBootstrapAddr.build(
            backend_address, organization_id, bootstrap_token)

    # Bootstrap organization and Alice user

    async with backend_anonymous_cmds_factory(
            organization_bootstrap_addr) as cmds:
        root_signing_key = SigningKey.generate()
        root_verify_key = root_signing_key.verify_key
        organization_addr = organization_bootstrap_addr.generate_organization_addr(
            root_verify_key)

        alice_device = generate_new_device(alice_device_id, organization_addr,
                                           True)

        save_device_with_password(config_dir,
                                  alice_device,
                                  password,
                                  force=force)

        now = pendulum.now()
        user_certificate = UserCertificateContent(
            author=None,
            timestamp=now,
            user_id=alice_device.user_id,
            public_key=alice_device.public_key,
            is_admin=True,
        ).dump_and_sign(author_signkey=root_signing_key)
        device_certificate = DeviceCertificateContent(
            author=None,
            timestamp=now,
            device_id=alice_device.device_id,
            verify_key=alice_device.verify_key,
        ).dump_and_sign(author_signkey=root_signing_key)

        rep = await cmds.organization_bootstrap(
            organization_bootstrap_addr.organization_id,
            organization_bootstrap_addr.token,
            root_verify_key,
            user_certificate,
            device_certificate,
        )
        assert rep["status"] == "ok"

    # Create a workspace for Alice

    config = load_config(config_dir, debug="DEBUG" in os.environ)
    async with logged_core_factory(config, alice_device) as core:
        alice_ws_id = await core.user_fs.workspace_create(f"{alice_workspace}")
        await core.user_fs.sync()

    # Register a new device for Alice

    token = generate_invitation_token()
    other_alice_device_id = DeviceID(
        f"{alice_device.user_id}@{other_device_name}")
    other_alice_slugid = f"{organization_id}:{other_alice_device_id}"

    async def invite_task():
        await invite_and_create_device(alice_device, other_device_name, token)

    other_alice_device = None

    async def claim_task():
        nonlocal other_alice_device
        other_alice_device = await retry_claim(claim_device,
                                               alice_device.organization_addr,
                                               other_alice_device_id, token)
        save_device_with_password(config_dir,
                                  other_alice_device,
                                  password,
                                  force=force)

    async with trio.open_service_nursery() as nursery:
        nursery.start_soon(invite_task)
        nursery.start_soon(claim_task)

    # Invite Bob in

    token = generate_invitation_token()
    bob_device = None

    async def invite_task():
        await invite_and_create_user(alice_device,
                                     bob_device_id.user_id,
                                     token,
                                     is_admin=False)

    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)

    async with trio.open_service_nursery() as nursery:
        nursery.start_soon(invite_task)
        nursery.start_soon(claim_task)

    # Create bob workspace and share with Alice

    async with logged_core_factory(config, bob_device) as core:
        bob_ws_id = await core.user_fs.workspace_create(f"{bob_workspace}")
        await core.user_fs.workspace_share(bob_ws_id, alice_device_id.user_id,
                                           WorkspaceRole.MANAGER)

    # Share Alice workspace with bob

    async with logged_core_factory(config, alice_device) as core:
        await core.user_fs.workspace_share(alice_ws_id, bob_device_id.user_id,
                                           WorkspaceRole.MANAGER)

    # Synchronize every device
    for device in (alice_device, other_alice_device, bob_device):
        async with logged_core_factory(config, device) as core:
            await core.user_fs.process_last_messages()
            await core.user_fs.sync()

    return alice_slugid, other_alice_slugid, bob_slugid
Ejemplo n.º 14
0
def run_cmd(
    host,
    port,
    db,
    blockstore,
    ssl_keyfile,
    ssl_certfile,
    log_level,
    log_format,
    log_file,
    log_filter,
):
    configure_logging(log_level, log_format, log_file, log_filter)

    debug = "DEBUG" in os.environ
    with cli_exception_handler(debug):

        try:
            config = config_factory(blockstore_type=blockstore,
                                    db_url=db,
                                    debug=debug,
                                    environ=os.environ)

        except ValueError as exc:
            raise ValueError(f"Invalid configuration: {exc}")

        if config.sentry_url:
            configure_sentry_logging(config.sentry_url)

        backend = BackendApp(config)

        if ssl_certfile or ssl_keyfile:
            ssl_context = trio.ssl.create_default_context(
                trio.ssl.Purpose.SERVER_AUTH)
            if ssl_certfile:
                ssl_context.load_cert_chain(ssl_certfile, ssl_keyfile)
            else:
                ssl_context.load_default_certs()
        else:
            ssl_context = None

        async def _serve_client(stream):
            if ssl_context:
                stream = trio.ssl.SSLStream(stream,
                                            ssl_context,
                                            server_side=True)

            try:
                await backend.handle_client(stream)

            except Exception as exc:
                # If we are here, something unexpected happened...
                logger.error("Unexpected crash", exc_info=exc)
                await stream.aclose()

        async def _run_backend():
            async with trio.open_nursery() as nursery:
                await backend.init(nursery)

                try:
                    await trio.serve_tcp(_serve_client, port, host=host)

                finally:
                    await backend.teardown()

        print(
            f"Starting Parsec Backend on {host}:{port} (db={config.db_type}, "
            f"blockstore={config.blockstore_config.type})")
        try:
            trio_asyncio.run(_run_backend)
        except KeyboardInterrupt:
            print("bye ;-)")
Ejemplo n.º 15
0
def run_cmd(
    host,
    port,
    db,
    db_min_connections,
    db_max_connections,
    maximum_database_connection_attempts,
    pause_before_retry_database_connection,
    blockstore,
    administration_token,
    spontaneous_organization_bootstrap,
    organization_bootstrap_webhook,
    backend_addr,
    email_host,
    email_port,
    email_host_user,
    email_host_password,
    email_use_ssl,
    email_use_tls,
    email_sender,
    forward_proto_enforce_https,
    ssl_keyfile,
    ssl_certfile,
    log_level,
    log_format,
    log_file,
    sentry_url,
    debug,
    dev,
):

    # Start a local backend
    configure_logging(log_level=log_level,
                      log_format=log_format,
                      log_file=log_file)
    if sentry_url:
        configure_sentry_logging(sentry_url)

    with cli_exception_handler(debug):

        if ssl_certfile or ssl_keyfile:
            ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
            if ssl_certfile:
                ssl_context.load_cert_chain(ssl_certfile, ssl_keyfile)
            else:
                ssl_context.load_default_certs()
        else:
            ssl_context = None

        if email_host == "MOCKED":
            tmpdir = tempfile.mkdtemp(prefix="tmp-email-folder-")
            if email_sender:
                email_config = MockedEmailConfig(sender=email_sender,
                                                 tmpdir=tmpdir)
            else:
                email_config = MockedEmailConfig(sender=DEFAULT_EMAIL_SENDER,
                                                 tmpdir=tmpdir)
        else:
            if not email_sender:
                raise ValueError(
                    "--email-sender is required when --email-host is provided")
            email_config = SmtpEmailConfig(
                host=email_host,
                port=email_port,
                host_user=email_host_user,
                host_password=email_host_password,
                use_ssl=email_use_ssl,
                use_tls=email_use_tls,
                sender=email_sender,
            )

        app_config = BackendConfig(
            administration_token=administration_token,
            db_url=db,
            db_min_connections=db_min_connections,
            db_max_connections=db_max_connections,
            spontaneous_organization_bootstrap=
            spontaneous_organization_bootstrap,
            organization_bootstrap_webhook_url=organization_bootstrap_webhook,
            blockstore_config=blockstore,
            email_config=email_config,
            ssl_context=True if ssl_context else False,
            forward_proto_enforce_https=forward_proto_enforce_https,
            backend_addr=backend_addr,
            debug=debug,
        )

        click.echo(f"Starting Parsec Backend on {host}:{port}"
                   f" (db={app_config.db_type}"
                   f" blockstore={app_config.blockstore_config.type}"
                   f" backend_addr={app_config.backend_addr}"
                   f" email_config={str(email_config)})")
        try:
            retry_policy = RetryPolicy(maximum_database_connection_attempts,
                                       pause_before_retry_database_connection)
            trio_run(_run_backend,
                     host,
                     port,
                     ssl_context,
                     retry_policy,
                     app_config,
                     use_asyncio=True)
        except KeyboardInterrupt:
            click.echo("bye ;-)")