async def bootstrap(
        self,
        id: OrganizationID,
        user: User,
        first_device: Device,
        bootstrap_token: str,
        root_verify_key: VerifyKey,
    ) -> None:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            organization = await self._get(conn, id)

            if organization.is_bootstrapped():
                raise OrganizationAlreadyBootstrappedError()

            if organization.bootstrap_token != bootstrap_token:
                raise OrganizationInvalidBootstrapTokenError()

            try:
                await _create_user(conn, id, user, first_device)
            except UserError as exc:
                raise OrganizationFirstUserCreationError(exc) from exc

            result = await conn.execute(*_q_bootstrap_organization(
                organization_id=id,
                bootstrap_token=bootstrap_token,
                root_verify_key=root_verify_key.encode(),
            ))

            if result != "UPDATE 1":
                raise OrganizationError(f"Update error: {result}")
Beispiel #2
0
    async def bootstrap(
        self,
        id: OrganizationID,
        user: User,
        first_device: Device,
        bootstrap_token: str,
        root_verify_key: VerifyKey,
    ) -> None:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            # The FOR UPDATE in the query ensure the line is locked in the
            # organization table until the end of the transaction. Hence
            # preventing concurrent bootstrap operation form going any further.
            organization = await self._get(conn, id, for_update=True)

            if organization.is_bootstrapped():
                raise OrganizationAlreadyBootstrappedError()

            if organization.bootstrap_token != bootstrap_token:
                raise OrganizationInvalidBootstrapTokenError()

            try:
                await q_create_user(conn, id, user, first_device)
            except UserError as exc:
                raise OrganizationFirstUserCreationError(exc) from exc

            result = await conn.execute(*_q_bootstrap_organization(
                organization_id=id.str,
                bootstrap_token=bootstrap_token,
                root_verify_key=root_verify_key.encode(),
            ))

            if result != "UPDATE 1":
                raise OrganizationError(f"Update error: {result}")
Beispiel #3
0
    async def set_expiration_date(self,
                                  id: OrganizationID,
                                  expiration_date: Pendulum = None) -> None:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            result = await conn.execute(_q_update_organisation_expiration_date,
                                        id, expiration_date)

            if result == "UPDATE 0":
                raise OrganizationNotFoundError

            if result != "UPDATE 1":
                raise OrganizationError(f"Update error: {result}")
Beispiel #4
0
    async def update(
        self,
        id: OrganizationID,
        is_expired: Union[UnsetType, bool] = Unset,
        active_users_limit: Union[UnsetType, Optional[int]] = Unset,
        user_profile_outsider_allowed: Union[UnsetType, bool] = Unset,
    ) -> None:
        """
        Raises:
            OrganizationNotFoundError
            OrganizationError
        """
        fields: dict = {}

        with_is_expired = is_expired is not Unset
        with_active_users_limit = active_users_limit is not Unset
        with_user_profile_outsider_allowed = user_profile_outsider_allowed is not Unset

        if (not with_is_expired and not with_active_users_limit
                and not with_user_profile_outsider_allowed):
            # Nothing to update, just make sure the organization exists and
            # pretent we actually did an update
            await self.get(id=id)
            return

        if with_is_expired:
            fields["is_expired"] = is_expired
        if with_active_users_limit:
            fields["active_users_limit"] = active_users_limit
        if with_user_profile_outsider_allowed:
            fields[
                "user_profile_outsider_allowed"] = user_profile_outsider_allowed

        q = _q_update_factory(
            with_is_expired=with_is_expired,
            with_active_users_limit=with_active_users_limit,
            with_user_profile_outsider_allowed=
            with_user_profile_outsider_allowed,
        )

        async with self.dbh.pool.acquire() as conn, conn.transaction():
            result = await conn.execute(*q(organization_id=id.str, **fields))

            if result == "UPDATE 0":
                raise OrganizationNotFoundError

            if result != "UPDATE 1":
                raise OrganizationError(f"Update error: {result}")

            if with_is_expired and is_expired:
                await send_signal(conn,
                                  BackendEvent.ORGANIZATION_EXPIRED,
                                  organization_id=id)
    async def create(self, id: OrganizationID, bootstrap_token: str) -> None:
        async with self.dbh.pool.acquire() as conn:
            try:
                result = await conn.execute(
                    """
                    INSERT INTO organizations (
                        organization_id, bootstrap_token
                    ) VALUES ($1, $2)
                    """,
                    id,
                    bootstrap_token,
                )
            except UniqueViolationError:
                raise OrganizationAlreadyExistsError()

            if result != "INSERT 0 1":
                raise OrganizationError(f"Insertion error: {result}")
    async def set_expiration_date(self,
                                  id: OrganizationID,
                                  expiration_date: DateTime = None) -> None:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            result = await conn.execute(
                *_q_update_organisation_expiration_date(
                    organization_id=id, expiration_date=expiration_date))

            if result == "UPDATE 0":
                raise OrganizationNotFoundError

            if result != "UPDATE 1":
                raise OrganizationError(f"Update error: {result}")

            if expiration_date is not None and expiration_date <= DateTime.now(
            ):
                await send_signal(conn,
                                  BackendEvent.ORGANIZATION_EXPIRED,
                                  organization_id=id)
Beispiel #7
0
    async def update(
        self,
        id: OrganizationID,
        expiration_date: Union[UnsetType, Optional[DateTime]] = Unset,
        user_profile_outsider_allowed: Union[UnsetType, bool] = Unset,
    ) -> None:
        """
        Raises:
            OrganizationNotFoundError
            OrganizationError
        """
        fields: dict = {}

        with_expiration_date = expiration_date is not Unset
        with_user_profile_outsider_allowed = user_profile_outsider_allowed is not Unset

        if with_expiration_date:
            fields["expiration_date"] = expiration_date
        if with_user_profile_outsider_allowed:
            fields[
                "user_profile_outsider_allowed"] = user_profile_outsider_allowed

        q = _q_update_factory(
            with_expiration_date=with_expiration_date,
            with_user_profile_outsider_allowed=
            with_user_profile_outsider_allowed,
        )
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            result = await conn.execute(*q(organization_id=id, **fields))

            if result == "UPDATE 0":
                raise OrganizationNotFoundError

            if result != "UPDATE 1":
                raise OrganizationError(f"Update error: {result}")

            if isinstance(expiration_date,
                          DateTime) and expiration_date <= DateTime.now():
                await send_signal(conn,
                                  BackendEvent.ORGANIZATION_EXPIRED,
                                  organization_id=id)
    async def bootstrap(
        self,
        organization_id: OrganizationID,
        user: User,
        bootstrap_token: str,
        root_verify_key: VerifyKey,
    ) -> None:
        async with self.dbh.pool.acquire() as conn:
            async with conn.transaction():
                organization = await self._get(conn, organization_id)

                if organization.is_bootstrapped():
                    raise OrganizationAlreadyBootstrappedError()

                if organization.bootstrap_token != bootstrap_token:
                    raise OrganizationInvalidBootstrapTokenError()

                try:
                    await self.user_component._create_user(conn, organization_id, user)
                except UserError as exc:
                    raise OrganizationFirstUserCreationError(exc) from exc

                result = await conn.execute(
                    """
                    UPDATE organizations
                    SET root_verify_key = $3
                    WHERE organization_id = $1
                        AND bootstrap_token = $2
                        AND root_verify_key IS NULL;
                    """,
                    organization_id,
                    bootstrap_token,
                    root_verify_key.encode(),
                )

                if result != "UPDATE 1":
                    raise OrganizationError(f"Update error: {result}")