Exemplo n.º 1
0
    async def finish_reencryption_maintenance(
        self,
        organization_id: OrganizationID,
        author: DeviceID,
        realm_id: RealmID,
        encryption_revision: int,
    ) -> None:
        realm = self._get_realm(organization_id, realm_id)
        if realm.roles.get(author.user_id) != RealmRole.OWNER:
            raise RealmAccessError()
        if not realm.status.in_maintenance:
            raise RealmNotInMaintenanceError(
                f"Realm `{realm_id}` not under maintenance")
        if encryption_revision != realm.status.encryption_revision:
            raise RealmEncryptionRevisionError("Invalid encryption revision")
        if not self._vlob_component._maintenance_reencryption_is_finished_hook(
                organization_id, realm_id, encryption_revision):
            raise RealmMaintenanceError("Reencryption operations are not over")

        realm.status = RealmStatus(
            maintenance_type=None,
            maintenance_started_on=None,
            maintenance_started_by=None,
            encryption_revision=encryption_revision,
        )

        await self._send_event(
            BackendEvent.REALM_MAINTENANCE_FINISHED,
            organization_id=organization_id,
            author=author,
            realm_id=realm_id,
            encryption_revision=encryption_revision,
        )
Exemplo n.º 2
0
async def query_finish_reencryption_maintenance(
    conn,
    organization_id: OrganizationID,
    author: DeviceID,
    realm_id: RealmID,
    encryption_revision: int,
) -> None:
    # Retrieve realm and make sure it is not under maintenance
    status = await get_realm_status(conn, organization_id, realm_id)
    roles = await _get_realm_role_for_not_revoked(conn, organization_id,
                                                  realm_id, [author.user_id])
    if roles.get(author.user_id) != RealmRole.OWNER:
        raise RealmAccessError()
    if not status.in_maintenance:
        raise RealmNotInMaintenanceError(
            f"Realm `{realm_id}` not under maintenance")
    if encryption_revision != status.encryption_revision:
        raise RealmEncryptionRevisionError("Invalid encryption revision")

    # Test reencryption operations are over
    rep = await conn.fetch(*_query_finish_reencryption_maintenance_get_info(
        organization_id=organization_id.str,
        realm_id=realm_id,
        encryption_revision=encryption_revision,
    ))

    try:
        previous, current = rep
    except ValueError:
        raise RealmMaintenanceError("Reencryption operations are not over")
    assert previous["encryption_revision"] == encryption_revision - 1
    assert current["encryption_revision"] == encryption_revision
    assert previous["count"] >= current["count"]
    if previous["count"] != current["count"]:
        raise RealmMaintenanceError("Reencryption operations are not over")

    await conn.execute(*_query_finish_reencryption_maintenance_update_realm(
        organization_id=organization_id.str, realm_id=realm_id))

    await send_signal(
        conn,
        BackendEvent.REALM_MAINTENANCE_FINISHED,
        organization_id=organization_id,
        author=author,
        realm_id=realm_id,
        encryption_revision=encryption_revision,
    )
Exemplo n.º 3
0
async def query_finish_reencryption_maintenance(
    conn,
    organization_id: OrganizationID,
    author: DeviceID,
    realm_id: UUID,
    encryption_revision: int,
) -> None:
    # Retrieve realm and make sure it is not under maintenance
    rep = await get_realm_status(conn, organization_id, realm_id)
    roles = await get_realm_role_for_not_revoked(conn, organization_id,
                                                 realm_id, [author.user_id])
    if roles.get(author.user_id) != RealmRole.OWNER:
        raise RealmAccessError()
    if not rep["maintenance_type"]:
        raise RealmNotInMaintenanceError(
            f"Realm `{realm_id}` not under maintenance")
    if encryption_revision != rep["encryption_revision"]:
        raise RealmEncryptionRevisionError("Invalid encryption revision")

    # Test reencryption operations are over

    query = """
WITH cte_encryption_revisions AS (
    SELECT
        _id,
        encryption_revision
    FROM vlob_encryption_revision
    WHERE
        realm = ({})
        AND (encryption_revision = $3 OR encryption_revision = $3 - 1)
)
SELECT encryption_revision, COUNT(*) as count
FROM vlob_atom
INNER JOIN cte_encryption_revisions
ON cte_encryption_revisions._id = vlob_atom.vlob_encryption_revision
GROUP BY encryption_revision
ORDER BY encryption_revision
    """.format(
        q_realm_internal_id(organization_id=Parameter("$1"),
                            realm_id=Parameter("$2")))

    rep = await conn.fetch(query, organization_id, realm_id,
                           encryption_revision)

    try:
        previous, current = rep
    except ValueError:
        raise RealmMaintenanceError("Reencryption operations are not over")
    assert previous["encryption_revision"] == encryption_revision - 1
    assert current["encryption_revision"] == encryption_revision
    assert previous["count"] >= current["count"]
    if previous["count"] != current["count"]:
        raise RealmMaintenanceError("Reencryption operations are not over")

    query = """
UPDATE realm
SET
    maintenance_started_by=NULL,
    maintenance_started_on=NULL,
    maintenance_type=NULL
WHERE
    _id = ({})
""".format(
        q_realm_internal_id(organization_id=Parameter("$1"),
                            realm_id=Parameter("$2")))

    await conn.execute(query, organization_id, realm_id)

    await send_signal(
        conn,
        "realm.maintenance_finished",
        organization_id=organization_id,
        author=author,
        realm_id=realm_id,
        encryption_revision=encryption_revision,
    )