示例#1
0
    def _find_humans(
        self,
        organization_id: OrganizationID,
        query: Optional[str] = None,
        page: int = 1,
        per_page: int = 100,
        omit_revoked: bool = False,
        omit_non_human: bool = False,
    ) -> Tuple[List[HumanFindResultItem], int]:
        assert page >= 1
        assert per_page >= 1

        org = self._organizations[organization_id]

        # Query is run against human handle field, hence non-human are automatically ignored
        users: Iterable[User]
        if query:
            # Handle a case insensitive find search to be conform with postgresql query
            users = []
            query_parts = query.lower().split()
            for user in org.users.values():
                if not user.human_handle:
                    continue
                lemail = str(user.human_handle.email).lower()
                llabel = str(user.human_handle.label).lower()
                if all([part in lemail for part in query_parts]) or all(
                    [part in llabel for part in query_parts]):
                    users.append(user)
        else:
            users = org.users.values()
            if omit_non_human:
                users = [r for r in users if r.human_handle is not None]
        # Sort human by label
        users = [
            *sorted(
                [res for res in users if res.human_handle is not None],
                key=lambda r: r.human_handle.label.lower(),  # type: ignore
            ),
            *[res for res in users if res.human_handle is None],
        ]
        now = pendulum.now()
        results = [
            HumanFindResultItem(
                user_id=user.user_id,
                human_handle=user.human_handle,
                revoked=(user.revoked_on is not None
                         and user.revoked_on <= now),
            ) for user in users
        ]

        if omit_revoked:
            results = [res for res in results if not res.revoked]

        total = len(results)

        # Handle pagination
        paginated_results = results[(page - 1) * per_page:page * per_page]

        return paginated_results, total
示例#2
0
async def query_find_humans(
    conn,
    organization_id: OrganizationID,
    omit_revoked: bool = False,
    omit_non_human: bool = False,
    page: int = 1,
    per_page: int = 100,
    query: Optional[str] = None,
) -> Tuple[List[HumanFindResultItem], int]:
    if page >= 1:
        offset = (page - 1) * per_page
    else:
        return ([], 0)

    q = _q_human_factory(with_query=bool(query),
                         omit_revoked=omit_revoked,
                         omit_non_human=omit_non_human)
    if query:
        args = q(
            organization_id=organization_id.str,
            now=pendulum_now(),
            query=_escape_sql_like_arg(query),
            offset=offset,
            limit=per_page,
        )
    else:
        args = q(organization_id=organization_id.str,
                 now=pendulum_now(),
                 offset=offset,
                 limit=per_page)

    raw_results = await conn.fetch(*args)
    total = raw_results[0]["total"]
    results = [
        HumanFindResultItem(
            user_id=UserID(user_id),
            human_handle=HumanHandle(email=email, label=label)
            if email else None,
            revoked=is_revoked,
        ) for user_id, email, label, is_revoked, _, _ in raw_results[1:]
    ]

    return results, total
示例#3
0
    async def find_humans(
        self,
        organization_id: OrganizationID,
        query: str = None,
        page: int = 1,
        per_page: int = 100,
        omit_revoked: bool = False,
        omit_non_human: bool = False,
    ) -> Tuple[List[HumanFindResultItem], int]:
        org = self._organizations[organization_id]

        if query:
            data = []
            query_terms = [qt.lower() for qt in query.split()]
            for user in org.users.values():
                if user.human_handle:
                    user_terms = (
                        *[x.lower() for x in user.human_handle.label.split()],
                        user.human_handle.email.lower(),
                        user.user_id.lower(),
                    )
                else:
                    user_terms = (user.user_id.lower(), )

                for qt in query_terms:
                    if not any(ut.startswith(qt) for ut in user_terms):
                        break
                else:
                    # All query term have match the current user
                    data.append(user)

        else:
            data = org.users.values()

        now = pendulum.now()
        results = [
            HumanFindResultItem(
                user_id=user.user_id,
                human_handle=user.human_handle,
                revoked=(user.revoked_on is not None
                         and user.revoked_on <= now),
            ) for user in data
        ]

        if omit_revoked:
            results = [res for res in results if not res.revoked]

        # PostgreSQL does case insensitive sort
        humans = sorted(
            [res for res in results if res.human_handle],
            key=lambda r:
            (r.human_handle.label.lower(), r.user_id.lower()),  # type: ignore
        )
        non_humans = sorted([res for res in results if not res.human_handle],
                            key=lambda r: r.user_id.lower())

        if omit_non_human:
            results = humans
        else:
            # Keeping non-human last
            results = [*humans, *non_humans]

        return (results[(page - 1) * per_page:page * per_page], len(results))
示例#4
0
async def query_find_humans(
    conn,
    organization_id: OrganizationID,
    query: str,
    page: int,
    per_page: int,
    omit_revoked: bool,
    omit_non_human: bool,
) -> Tuple[List[HumanFindResultItem], int]:
    if query:

        if omit_revoked:
            q = _q_human_factory(query=True,
                                 omit_revoked=True,
                                 omit_non_human=omit_non_human)
            args = (pendulum_now(), organization_id, query)

        else:
            q = _q_human_factory(query=True,
                                 omit_revoked=False,
                                 omit_non_human=omit_non_human)
            args = (pendulum_now(), organization_id, query)

    else:

        if omit_revoked:
            q = _q_human_factory(query=False,
                                 omit_revoked=True,
                                 omit_non_human=omit_non_human)
            args = (pendulum_now(), organization_id)

        else:
            q = _q_human_factory(query=False,
                                 omit_revoked=False,
                                 omit_non_human=omit_non_human)
            args = (pendulum_now(), organization_id)

    raw_results = await conn.fetch(q, *args)

    humans = [
        HumanFindResultItem(
            user_id=UserID(user_id),
            human_handle=HumanHandle(email=email, label=label),
            revoked=revoked,
        ) for user_id, email, label, revoked in raw_results
        if email is not None
    ]
    non_humans = [
        HumanFindResultItem(user_id=UserID(user_id),
                            human_handle=None,
                            revoked=revoked)
        for user_id, email, label, revoked in raw_results if email is None
    ]
    results = [
        *sorted(humans,
                key=lambda x:
                (x.human_handle.label.lower(), x.user_id.lower())),
        *sorted(non_humans, key=lambda x: x.user_id.lower()),
    ]
    # TODO: should user LIMIT and OFFSET in the SQL query instead
    return results[(page - 1) * per_page:page * per_page], len(results)