Example #1
0
    q_user_internal_id,
    q_device_internal_id,
)

_q_get_user_devices = (Query.from_(t_device).select(
    t_device.device_id).where(t_device.user_ == q_user_internal_id(
        organization_id=Parameter("$1"), user_id=Parameter("$2"))).get_sql())

_q_insert_user = (Query.into(t_user).columns(
    "organization", "user_id", "is_admin", "user_certificate",
    "user_certifier", "created_on").insert(
        q_organization_internal_id(Parameter("$1")),
        Parameter("$2"),
        Parameter("$3"),
        Parameter("$4"),
        q_device_internal_id(organization_id=Parameter("$1"),
                             device_id=Parameter("$5")),
        Parameter("$6"),
    ).get_sql())

_q_insert_device = (Query.into(t_device).columns(
    "organization", "user_", "device_id", "device_certificate",
    "device_certifier", "created_on").insert(
        q_organization_internal_id(Parameter("$1")),
        q_user_internal_id(organization_id=Parameter("$1"),
                           user_id=Parameter("$2")),
        Parameter("$3"),
        Parameter("$4"),
        q_device_internal_id(organization_id=Parameter("$1"),
                             device_id=Parameter("$5")),
        Parameter("$6"),
    ).get_sql())
Example #2
0
    async def update(
        self,
        organization_id: OrganizationID,
        author: DeviceID,
        encryption_revision: int,
        vlob_id: UUID,
        version: int,
        timestamp: pendulum.Pendulum,
        blob: bytes,
    ) -> None:
        async with self.dbh.pool.acquire() as conn, conn.transaction():

            realm_id = await _get_realm_id_from_vlob_id(conn, organization_id, vlob_id)
            await _check_realm_and_write_access(
                conn, organization_id, author, realm_id, encryption_revision
            )

            query = """
SELECT
    version,
    created_on
FROM vlob_atom
WHERE
    organization = ({})
    AND vlob_id = $2
ORDER BY version DESC LIMIT 1
""".format(
                q_organization_internal_id(Parameter("$1"))
            )

            previous = await conn.fetchrow(query, organization_id, vlob_id)
            if not previous:
                raise VlobNotFoundError(f"Vlob `{vlob_id}` doesn't exist")

            elif previous["version"] != version - 1:
                raise VlobVersionError()

            elif previous["created_on"] > timestamp:
                raise VlobTimestampError()

            query = """
INSERT INTO vlob_atom (
    organization,
    vlob_encryption_revision,
    vlob_id,
    version,
    blob,
    size,
    author,
    created_on
)
SELECT
    ({}),
    ({}),
    $5,
    $9,
    $6,
    $7,
    ({}),
    $8
RETURNING _id
""".format(
                q_organization_internal_id(Parameter("$1")),
                q_vlob_encryption_revision_internal_id(
                    organization_id=Parameter("$1"),
                    realm_id=Parameter("$3"),
                    encryption_revision=Parameter("$4"),
                ),
                q_device_internal_id(organization_id=Parameter("$1"), device_id=Parameter("$2")),
            )

            try:
                vlob_atom_internal_id = await conn.fetchval(
                    query,
                    organization_id,
                    author,
                    realm_id,
                    encryption_revision,
                    vlob_id,
                    blob,
                    len(blob),
                    timestamp,
                    version,
                )

            except UniqueViolationError:
                # Should not occurs in theory given we are in a transaction
                raise VlobVersionError()

            await _vlob_updated(
                conn, vlob_atom_internal_id, organization_id, author, realm_id, vlob_id, version
            )
Example #3
0
async def query_start_reencryption_maintenance(
    conn,
    organization_id: OrganizationID,
    author: DeviceID,
    realm_id: UUID,
    encryption_revision: int,
    per_participant_message: Dict[UserID, bytes],
    timestamp: pendulum.Pendulum,
) -> None:
    # Retrieve realm and make sure it is not under maintenance
    rep = await get_realm_status(conn, organization_id, realm_id)
    if rep["maintenance_type"]:
        raise RealmInMaintenanceError(
            f"Realm `{realm_id}` alrealy in maintenance")
    if encryption_revision != rep["encryption_revision"] + 1:
        raise RealmEncryptionRevisionError("Invalid encryption revision")

    roles = await get_realm_role_for_not_revoked(conn, organization_id,
                                                 realm_id)
    if per_participant_message.keys() ^ roles.keys():
        raise RealmParticipantsMismatchError(
            "Realm participants and message recipients mismatch")

    if roles.get(author.user_id) != RealmRole.OWNER:
        raise RealmAccessError()

    query = """
UPDATE realm
SET
    encryption_revision=$6,
    maintenance_started_by=({}),
    maintenance_started_on=$4,
    maintenance_type=$5
WHERE
    _id = ({})
""".format(
        q_device_internal_id(organization_id=Parameter("$1"),
                             device_id=Parameter("$3")),
        q_realm_internal_id(organization_id=Parameter("$1"),
                            realm_id=Parameter("$2")),
    )

    await conn.execute(query, organization_id, realm_id, author, timestamp,
                       "REENCRYPTION", encryption_revision)

    query = """
INSERT INTO vlob_encryption_revision(
    realm,
    encryption_revision
) SELECT
    ({}),
    $3
""".format(
        q_realm_internal_id(organization_id=Parameter("$1"),
                            realm_id=Parameter("$2")))

    await conn.execute(query, organization_id, realm_id, encryption_revision)

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

    for recipient, body in per_participant_message.items():
        await send_message(conn, organization_id, author, recipient, timestamp,
                           body)
Example #4
0
    async def create(
        self,
        organization_id: OrganizationID,
        author: DeviceID,
        realm_id: UUID,
        encryption_revision: int,
        vlob_id: UUID,
        timestamp: pendulum.Pendulum,
        blob: bytes,
    ) -> None:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            await _check_realm_and_write_access(
                conn, organization_id, author, realm_id, encryption_revision
            )

            # Actually create the vlob
            try:
                query = """
INSERT INTO vlob_atom (
    organization,
    vlob_encryption_revision,
    vlob_id,
    version,
    blob,
    size,
    author,
    created_on
)
SELECT
    ({}),
    ({}),
    $5,
    1,
    $6,
    $7,
    ({}),
    $8
RETURNING _id
""".format(
                    q_organization_internal_id(organization_id=Parameter("$1")),
                    Query.from_(t_vlob_encryption_revision)
                    .where(
                        (
                            t_vlob_encryption_revision.realm
                            == q_realm_internal_id(
                                organization_id=Parameter("$1"), realm_id=Parameter("$3")
                            )
                        )
                        & (t_vlob_encryption_revision.encryption_revision == Parameter("$4"))
                    )
                    .select("_id"),
                    q_device_internal_id(
                        organization_id=Parameter("$1"), device_id=Parameter("$2")
                    ),
                )

                vlob_atom_internal_id = await conn.fetchval(
                    query,
                    organization_id,
                    author,
                    realm_id,
                    encryption_revision,
                    vlob_id,
                    blob,
                    len(blob),
                    timestamp,
                )

            except UniqueViolationError:
                raise VlobAlreadyExistsError()

            await _vlob_updated(
                conn, vlob_atom_internal_id, organization_id, author, realm_id, vlob_id
            )