Example #1
0
    async def create_user(self, organization_id: OrganizationID, user: User,
                          first_device: Device) -> None:
        org = self._organizations[organization_id]
        active_users_limit = self._organization_component._organizations[
            organization_id].active_users_limit
        active_users = (u for u in org.users.values() if u.revoked_on is None)
        if active_users_limit is not None and active_users_limit <= len(
                list(active_users)):
            raise UserActiveUsersLimitReached()

        if user.user_id in org.users:
            raise UserAlreadyExistsError(
                f"User `{user.user_id}` already exists")

        if user.human_handle and user.human_handle in org.human_handle_to_user_id:
            raise UserAlreadyExistsError(
                f"Human handle `{user.human_handle}` already corresponds to a non-revoked user"
            )

        org.users[user.user_id] = user
        org.devices[first_device.user_id][
            first_device.device_name] = first_device
        if user.human_handle:
            org.human_handle_to_user_id[user.human_handle] = user.user_id

        await self._send_event(
            BackendEvent.USER_CREATED,
            organization_id=organization_id,
            user_id=user.user_id,
            user_certificate=user.user_certificate,
            first_device_id=first_device.device_id,
            first_device_certificate=first_device.device_certificate,
        )
Example #2
0
async def _create_device(conn,
                         organization_id: OrganizationID,
                         device: Device,
                         first_device: bool = False) -> None:
    if not first_device:
        existing_devices = await conn.fetch(_q_get_user_devices,
                                            organization_id, device.user_id)
        if not existing_devices:
            raise UserNotFoundError(f"User `{device.user_id}` doesn't exists")

        if device.device_id in itertools.chain(*existing_devices):
            raise UserAlreadyExistsError(
                f"Device `{device.device_id}` already exists")

    try:
        result = await conn.execute(
            _q_insert_device,
            organization_id,
            device.user_id,
            device.device_id,
            device.device_certificate,
            device.device_certifier,
            device.created_on,
        )
    except UniqueViolationError:
        raise UserAlreadyExistsError(
            f"Device `{device.device_id}` already exists")

    if result != "INSERT 0 1":
        raise UserError(f"Insertion error: {result}")
Example #3
0
    async def create_user(self, organization_id: OrganizationID, user: User,
                          first_device: Device) -> None:
        org = self._organizations[organization_id]

        if user.user_id in org.users:
            raise UserAlreadyExistsError(
                f"User `{user.user_id}` already exists")

        if user.human_handle and user.human_handle in org.human_handle_to_user_id:
            raise UserAlreadyExistsError(
                f"Human handle `{user.human_handle}` already corresponds to a non-revoked user"
            )

        org.users[user.user_id] = user
        org.devices[first_device.user_id][
            first_device.device_name] = first_device
        if user.human_handle:
            org.human_handle_to_user_id[user.human_handle] = user.user_id

        await self._send_event(
            "user.created",
            organization_id=organization_id,
            user_id=user.user_id,
            user_certificate=user.user_certificate,
            first_device_id=first_device.device_id,
            first_device_certificate=first_device.device_certificate,
        )
Example #4
0
    async def _get_device_invitation(self, conn,
                                     organization_id: OrganizationID,
                                     device_id: DeviceID):
        if await self._device_exists(conn, organization_id, device_id):
            raise UserAlreadyExistsError(
                f"Device `{device_id}` already exists")

        result = await conn.fetchrow(
            """
SELECT device_invitations.device_id, devices.device_id, device_invitations.created_on
FROM device_invitations
LEFT JOIN devices ON device_invitations.creator = devices._id
WHERE
    device_invitations.organization = (
        SELECT _id from organizations WHERE organization_id = $1
    )
    AND device_invitations.device_id = $2
""",
            organization_id,
            device_id,
        )
        if not result:
            raise UserNotFoundError(device_id)

        return DeviceInvitation(device_id=DeviceID(result[0]),
                                creator=DeviceID(result[1]),
                                created_on=result[2])
Example #5
0
    async def cancel_device_invitation(self, organization_id: OrganizationID,
                                       device_id: DeviceID) -> None:
        async with self.dbh.pool.acquire() as conn:
            async with conn.transaction():

                if await self._device_exists(conn, organization_id, device_id):
                    raise UserAlreadyExistsError(
                        f"Device `{device_id}` already exists")

                result = await conn.execute(
                    """
DELETE FROM device_invitations
WHERE
    organization = (
        SELECT _id from organizations WHERE organization_id = $1
    )
    AND device_id = $2
""",
                    organization_id,
                    device_id,
                )
                if result not in ("DELETE 1", "DELETE 0"):
                    raise UserError(f"Deletion error: {result}")

                await send_signal(
                    conn,
                    "device.invitation.cancelled",
                    organization_id=organization_id,
                    device_id=device_id,
                )
Example #6
0
async def _create_user(conn, organization_id: OrganizationID, user: User,
                       first_device: Device) -> None:
    try:
        result = await conn.execute(
            _q_insert_user,
            organization_id,
            user.user_id,
            user.is_admin,
            user.user_certificate,
            user.user_certifier,
            user.created_on,
        )
    except UniqueViolationError:
        raise UserAlreadyExistsError(f"User `{user.user_id}` already exists")

    if result != "INSERT 0 1":
        raise UserError(f"Insertion error: {result}")

    await _create_device(conn,
                         organization_id,
                         first_device,
                         first_device=True)

    await send_signal(
        conn,
        "user.created",
        organization_id=organization_id,
        user_id=user.user_id,
        user_certificate=user.user_certificate,
        first_device_id=first_device.device_id,
        first_device_certificate=first_device.device_certificate,
    )
Example #7
0
    async def _get_user_invitation(self, conn, organization_id: OrganizationID,
                                   user_id: UserID):
        if await self._user_exists(conn, organization_id, user_id):
            raise UserAlreadyExistsError(f"User `{user_id}` already exists")

        result = await conn.fetchrow(
            """
SELECT user_invitations.user_id, devices.device_id, user_invitations.created_on
FROM user_invitations
LEFT JOIN devices ON user_invitations.creator = devices._id
WHERE
    user_invitations.organization = (
        SELECT _id from organizations WHERE organization_id = $1
    )
    AND user_invitations.user_id = $2
""",
            organization_id,
            user_id,
        )
        if not result:
            raise UserNotFoundError(user_id)

        return UserInvitation(user_id=UserID(result[0]),
                              creator=DeviceID(result[1]),
                              created_on=result[2])
Example #8
0
    async def create_user_invitation(self, organization_id: OrganizationID,
                                     invitation: UserInvitation) -> None:
        org = self._organizations[organization_id]

        if invitation.user_id in org.users:
            raise UserAlreadyExistsError(
                f"User `{invitation.user_id}` already exists")
        org.invitations[invitation.user_id] = invitation
Example #9
0
async def query_cancel_user_invitation(conn, organization_id: OrganizationID,
                                       user_id: UserID) -> None:
    if await _user_exists(conn, organization_id, user_id):
        raise UserAlreadyExistsError(f"User `{user_id}` already exists")

    result = await conn.execute(_q_delete_invitation, organization_id, user_id)
    if result not in ("DELETE 1", "DELETE 0"):
        raise UserError(f"Deletion error: {result}")
Example #10
0
    async def create_device_invitation(self, organization_id: OrganizationID,
                                       invitation: DeviceInvitation) -> None:
        org = self._organizations[organization_id]

        user = await self.get_user(organization_id,
                                   invitation.device_id.user_id)
        if invitation.device_id.device_name in user.devices:
            raise UserAlreadyExistsError(
                f"Device `{invitation.device_id}` already exists")
        org._invitations[invitation.device_id] = invitation
Example #11
0
    async def get_user_invitation(self, organization_id: OrganizationID,
                                  user_id: UserID) -> UserInvitation:
        org = self._organizations[organization_id]

        if user_id in org.users:
            raise UserAlreadyExistsError(user_id)
        try:
            return org.invitations[user_id]
        except KeyError:
            raise UserNotFoundError(user_id)
Example #12
0
async def _do_create_user_with_human_handle(conn,
                                            organization_id: OrganizationID,
                                            user: User,
                                            first_device: Device) -> None:
    # Create human handle if needed
    await conn.execute(
        _q_insert_human_if_not_exists,
        organization_id,
        user.human_handle.email,
        user.human_handle.label,
    )

    # Now insert the new user
    try:
        result = await conn.execute(
            _q_insert_user_with_human_handle,
            organization_id,
            user.user_id,
            user.profile.value,
            user.user_certificate,
            user.redacted_user_certificate,
            user.user_certifier,
            user.created_on,
            user.human_handle.email,
        )

    except UniqueViolationError:
        raise UserAlreadyExistsError(f"User `{user.user_id}` already exists")

    if result != "INSERT 0 1":
        raise UserError(f"Insertion error: {result}")

    # Finally make sure there is only one non-revoked user with this human handle
    now = pendulum_now()
    not_revoked_users = await conn.fetch(_q_get_not_revoked_users_for_human,
                                         organization_id,
                                         user.human_handle.email, now)
    if len(not_revoked_users
           ) != 1 or not_revoked_users[0]["user_id"] != user.user_id:
        # Exception cancels the transaction so the user insertion is automatically cancelled
        raise UserAlreadyExistsError(
            f"Human handle `{user.human_handle}` already corresponds to a non-revoked user"
        )
async def _get_device_invitation(conn, organization_id: OrganizationID,
                                 device_id: DeviceID) -> DeviceInvitation:
    if await _device_exists(conn, organization_id, device_id):
        raise UserAlreadyExistsError(f"Device `{device_id}` already exists")

    result = await conn.fetchrow(_q_get_invitation, organization_id, device_id)
    if not result:
        raise UserNotFoundError(device_id)

    return DeviceInvitation(device_id=DeviceID(result[0]),
                            creator=DeviceID(result[1]),
                            created_on=result[2])
Example #14
0
async def _get_user_invitation(conn, organization_id: OrganizationID,
                               user_id: UserID):
    if await _user_exists(conn, organization_id, user_id):
        raise UserAlreadyExistsError(f"User `{user_id}` already exists")

    result = await conn.fetchrow(_q_get_invitation, organization_id, user_id)
    if not result:
        raise UserNotFoundError(user_id)

    return UserInvitation(user_id=UserID(result[0]),
                          creator=DeviceID(result[1]),
                          created_on=result[2])
Example #15
0
    async def create_user(self, organization_id: OrganizationID,
                          user: User) -> None:
        org = self._organizations[organization_id]

        if user.user_id in org._users:
            raise UserAlreadyExistsError(
                f"User `{user.user_id}` already exists")

        org._users[user.user_id] = user
        self.event_bus.send("user.created",
                            organization_id=organization_id,
                            user_id=user.user_id)
Example #16
0
    async def get_device_invitation(self, organization_id: OrganizationID,
                                    device_id: DeviceID) -> DeviceInvitation:
        org = self._organizations[organization_id]

        try:
            org._users[device_id.user_id].devices[device_id.device_name]
            raise UserAlreadyExistsError(device_id)
        except KeyError:
            pass
        try:
            return org._invitations[device_id]
        except KeyError:
            raise UserNotFoundError(device_id)
async def query_cancel_device_invitation(conn, organization_id: OrganizationID,
                                         device_id: DeviceID) -> None:
    if await _device_exists(conn, organization_id, device_id):
        raise UserAlreadyExistsError(f"Device `{device_id}` already exists")

    result = await conn.execute(_q_delete_invitation, organization_id,
                                device_id)
    if result not in ("DELETE 1", "DELETE 0"):
        raise UserError(f"Deletion error: {result}")

    await send_signal(conn,
                      "device.invitation.cancelled",
                      organization_id=organization_id,
                      device_id=device_id)
Example #18
0
    async def get_device_invitation(self, organization_id: OrganizationID,
                                    device_id: DeviceID) -> DeviceInvitation:
        org = self._organizations[organization_id]

        user_devices = self._get_user_devices(organization_id,
                                              device_id.user_id)
        if device_id.device_name in user_devices:
            raise UserAlreadyExistsError(device_id)

        try:
            return org.invitations[device_id]

        except KeyError:
            raise UserNotFoundError(device_id)
Example #19
0
async def query_create_user_invitation(conn, organization_id: OrganizationID,
                                       invitation: UserInvitation) -> None:
    if await _user_exists(conn, organization_id, invitation.user_id):
        raise UserAlreadyExistsError(
            f"User `{invitation.user_id}` already exists")

    result = await conn.execute(*_q_insert_invitation(
        organization_id=organization_id,
        creator=invitation.creator,
        user_id=invitation.user_id,
        created_on=invitation.created_on,
    ))

    if result not in ("INSERT 0 1", "UPDATE 1"):
        raise UserError(f"Insertion error: {result}")
async def _create_device_invitation(conn, organization_id: OrganizationID,
                                    invitation: DeviceInvitation) -> None:
    if await _device_exists(conn, organization_id, invitation.device_id):
        raise UserAlreadyExistsError(
            f"Device `{invitation.device_id}` already exists")

    result = await conn.execute(
        _q_insert_invitation,
        organization_id,
        invitation.creator,
        invitation.device_id,
        invitation.created_on,
    )

    if result not in ("INSERT 0 1", "UPDATE 1"):
        raise UserError(f"Insertion error: {result}")
Example #21
0
async def query_cancel_device_invitation(conn, organization_id: OrganizationID,
                                         device_id: DeviceID) -> None:
    if await _device_exists(conn, organization_id, device_id):
        raise UserAlreadyExistsError(f"Device `{device_id}` already exists")

    result = await conn.execute(*_q_delete_invitation(
        organization_id=organization_id, device_id=device_id))
    if result not in ("DELETE 1", "DELETE 0"):
        raise UserError(f"Deletion error: {result}")

    await send_signal(
        conn,
        BackendEvent.DEVICE_INVITATION_CANCELLED,
        organization_id=organization_id,
        device_id=device_id,
    )
Example #22
0
async def _do_create_user_without_human_handle(
    conn, organization_id: OrganizationID, user: User, first_device: Device
) -> None:
    try:
        result = await conn.execute(
            _q_insert_user,
            organization_id,
            user.user_id,
            user.is_admin,
            user.user_certificate,
            user.user_certifier,
            user.created_on,
        )

    except UniqueViolationError:
        raise UserAlreadyExistsError(f"User `{user.user_id}` already exists")

    if result != "INSERT 0 1":
        raise UserError(f"Insertion error: {result}")
Example #23
0
    async def create_device(self,
                            organization_id: OrganizationID,
                            device: Device,
                            encrypted_answer: bytes = b"") -> None:
        org = self._organizations[organization_id]

        if device.user_id not in org._users:
            raise UserNotFoundError(f"User `{device.user_id}` doesn't exists")

        user = org._users[device.user_id]
        if device.device_name in user.devices:
            raise UserAlreadyExistsError(
                f"Device `{device.device_id}` already exists")

        org._users[device.user_id] = user.evolve(
            devices=DevicesMapping(*user.devices.values(), device))
        self.event_bus.send(
            "device.created",
            organization_id=organization_id,
            device_id=device.device_id,
            encrypted_answer=encrypted_answer,
        )
Example #24
0
    async def create_device(self,
                            organization_id: OrganizationID,
                            device: Device,
                            encrypted_answer: bytes = b"") -> None:
        org = self._organizations[organization_id]

        if device.user_id not in org.users:
            raise UserNotFoundError(f"User `{device.user_id}` doesn't exists")

        user_devices = org.devices[device.user_id]
        if device.device_name in user_devices:
            raise UserAlreadyExistsError(
                f"Device `{device.device_id}` already exists")

        user_devices[device.device_name] = device
        await self._send_event(
            "device.created",
            organization_id=organization_id,
            device_id=device.device_id,
            device_certificate=device.device_certificate,
            encrypted_answer=encrypted_answer,
        )
Example #25
0
    async def create_device_invitation(self, organization_id: OrganizationID,
                                       invitation: DeviceInvitation) -> None:
        async with self.dbh.pool.acquire() as conn:
            async with conn.transaction():

                if await self._device_exists(conn, organization_id,
                                             invitation.device_id):
                    raise UserAlreadyExistsError(
                        f"Device `{invitation.device_id}` already exists")

                result = await conn.execute(
                    """
INSERT INTO device_invitations (
    organization,
    creator,
    device_id,
    created_on
)
VALUES (
    (SELECT _id FROM organizations WHERE organization_id = $1),
    (SELECT _id FROM devices WHERE device_id = $2),
    $3, $4
)
ON CONFLICT (device_id)
DO UPDATE
SET
    organization = excluded.organization,
    creator = excluded.creator,
    created_on = excluded.created_on
""",
                    organization_id,
                    invitation.creator,
                    invitation.device_id,
                    invitation.created_on,
                )

                if result not in ("INSERT 0 1", "UPDATE 1"):
                    raise UserError(f"Insertion error: {result}")
Example #26
0
    async def _create_user(conn, organization_id: OrganizationID,
                           user: User) -> None:
        try:
            result = await conn.execute(
                """
INSERT INTO users (
    organization,
    user_id,
    is_admin,
    certified_user,
    user_certifier,
    created_on
)
SELECT
    _id,
    $2, $3, $4,
    (
        SELECT _id
        FROM devices
        WHERE
            device_id = $5
            AND organization = organizations._id
    ),
    $6
FROM organizations
WHERE organization_id = $1
""",
                organization_id,
                user.user_id,
                user.is_admin,
                user.certified_user,
                user.user_certifier,
                user.created_on,
            )
        except UniqueViolationError:
            raise UserAlreadyExistsError(
                f"User `{user.user_id}` already exists")

        if result != "INSERT 0 1":
            raise UserError(f"Insertion error: {result}")

        await conn.executemany(
            """
INSERT INTO devices (
    organization,
    user_,
    device_id,
    certified_device,
    device_certifier,
    created_on,
    revocated_on,
    certified_revocation,
    revocation_certifier
)
SELECT
    _id,
    (
        SELECT _id
        FROM users
        WHERE
            user_id = $2
            AND organization = organizations._id
    ),
    $3, $4,
    (
        SELECT _id
        FROM devices
        WHERE
            device_id = $5
            AND organization = organizations._id
    ),
    $6, $7, $8, $9
FROM organizations
WHERE organization_id = $1
""",
            [(
                organization_id,
                device.user_id,
                device.device_id,
                device.certified_device,
                device.device_certifier,
                device.created_on,
                device.revocated_on,
                device.certified_revocation,
                device.revocation_certifier,
            ) for device in user.devices.values()],
        )
Example #27
0
    async def _create_device(self, conn, organization_id: OrganizationID,
                             device: Device) -> None:
        existing_devices = await conn.fetch(
            """
SELECT device_id FROM devices
WHERE user_ = (
    SELECT _id FROM users
    WHERE
        organization = (
            SELECT _id from organizations WHERE organization_id = $1
        )
        AND user_id = $2
)
            """,
            organization_id,
            device.user_id,
        )
        if not existing_devices:
            raise UserNotFoundError(f"User `{device.user_id}` doesn't exists")

        if device.device_id in itertools.chain(*existing_devices):
            raise UserAlreadyExistsError(
                f"Device `{device.device_id}` already exists")

        result = await conn.execute(
            """
INSERT INTO devices (
    organization,
    user_,
    device_id,
    certified_device,
    device_certifier,
    created_on,
    revocated_on,
    certified_revocation,
    revocation_certifier
)
SELECT
    _id,
    (
        SELECT _id
        FROM users
        WHERE
            user_id = $2
            AND organization = organizations._id
    ),
    $3, $4,
    (
        SELECT _id
        FROM devices
        WHERE
            device_id = $5
            AND organization = organizations._id
    ),
    $6, $7, $8, $9
FROM organizations
WHERE organization_id = $1
""",
            organization_id,
            device.user_id,
            device.device_id,
            device.certified_device,
            device.device_certifier,
            device.created_on,
            device.revocated_on,
            device.certified_revocation,
            device.revocation_certifier,
        )

        if result != "INSERT 0 1":
            raise UserError(f"Insertion error: {result}")