Skip to content

Commit

Permalink
✨ Add pagination support for listing Connection, Cred Ex, and Pres Ex…
Browse files Browse the repository at this point in the history
… records (#3033)

* ✨ use PaginatedQuerySchema for listing v1 and v2 Pres Ex records

Signed-off-by: ff137 <[email protected]>

* ✨ use PaginatedQuerySchema for listing v1 and v2 Cred Ex records

Signed-off-by: ff137 <[email protected]>

* ✨ use PaginatedQuerySchema for listing Connection records

Signed-off-by: ff137 <[email protected]>

* 🎨 update to relative import style

Signed-off-by: ff137 <[email protected]>

* ✅ update expected assertions

Signed-off-by: ff137 <[email protected]>

* 🎨 deduplicate reading of limit and offset query parameters

Signed-off-by: ff137 <[email protected]>

---------

Signed-off-by: ff137 <[email protected]>
  • Loading branch information
ff137 authored Jun 25, 2024
1 parent 59bb548 commit a556d56
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 12 deletions.
21 changes: 19 additions & 2 deletions aries_cloudagent/messaging/models/paginated_query.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Class for paginated query parameters."""

from marshmallow import fields
from typing import Tuple

from aries_cloudagent.storage.base import DEFAULT_PAGE_SIZE, MAXIMUM_PAGE_SIZE
from aiohttp.web import BaseRequest
from marshmallow import fields

from ...messaging.models.openapi import OpenAPISchema
from ...storage.base import DEFAULT_PAGE_SIZE, MAXIMUM_PAGE_SIZE


class PaginatedQuerySchema(OpenAPISchema):
Expand All @@ -29,3 +31,18 @@ class PaginatedQuerySchema(OpenAPISchema):
metadata={"description": "Offset for pagination", "example": 0},
error_messages={"validator_failed": "Value must be 0 or greater"},
)


def get_limit_offset(request: BaseRequest) -> Tuple[int, int]:
"""Read the limit and offset query parameters from a request as ints, with defaults.
Args:
request: aiohttp request object
Returns:
A tuple of the limit and offset values
"""

limit = int(request.query.get("limit", DEFAULT_PAGE_SIZE))
offset = int(request.query.get("offset", 0))
return limit, offset
6 changes: 2 additions & 4 deletions aries_cloudagent/multitenant/admin/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@
from ...core.profile import ProfileManagerProvider
from ...messaging.models.base import BaseModelError
from ...messaging.models.openapi import OpenAPISchema
from ...messaging.models.paginated_query import PaginatedQuerySchema
from ...messaging.models.paginated_query import PaginatedQuerySchema, get_limit_offset
from ...messaging.valid import UUID4_EXAMPLE, JSONWebToken
from ...multitenant.base import BaseMultitenantManager
from ...storage.base import DEFAULT_PAGE_SIZE
from ...storage.error import StorageError, StorageNotFoundError
from ...utils.endorsement_setup import attempt_auto_author_with_endorser_setup
from ...utils.profiles import subwallet_type_not_same_as_base_wallet_raise_web_exception
Expand Down Expand Up @@ -382,8 +381,7 @@ async def wallets_list(request: web.BaseRequest):
if wallet_name:
query["wallet_name"] = wallet_name

limit = int(request.query.get("limit", DEFAULT_PAGE_SIZE))
offset = int(request.query.get("offset", 0))
limit, offset = get_limit_offset(request)

try:
async with profile.session() as session:
Expand Down
12 changes: 10 additions & 2 deletions aries_cloudagent/protocols/connections/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from ....connections.models.conn_record import ConnRecord, ConnRecordSchema
from ....messaging.models.base import BaseModelError
from ....messaging.models.openapi import OpenAPISchema
from ....messaging.models.paginated_query import PaginatedQuerySchema, get_limit_offset
from ....messaging.valid import (
ENDPOINT_EXAMPLE,
ENDPOINT_VALIDATE,
Expand Down Expand Up @@ -236,7 +237,7 @@ class ConnectionStaticResultSchema(OpenAPISchema):
record = fields.Nested(ConnRecordSchema(), required=True)


class ConnectionsListQueryStringSchema(OpenAPISchema):
class ConnectionsListQueryStringSchema(PaginatedQuerySchema):
"""Parameters and validators for connections list request query string."""

alias = fields.Str(
Expand Down Expand Up @@ -468,11 +469,18 @@ async def connections_list(request: web.BaseRequest):
if request.query.get("connection_protocol"):
post_filter["connection_protocol"] = request.query["connection_protocol"]

limit, offset = get_limit_offset(request)

profile = context.profile
try:
async with profile.session() as session:
records = await ConnRecord.query(
session, tag_filter, post_filter_positive=post_filter, alt=True
session,
tag_filter,
limit=limit,
offset=offset,
post_filter_positive=post_filter,
alt=True,
)
results = [record.serialize() for record in records]
results.sort(key=connection_sort_key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ async def test_connections_list(self):
"their_public_did": "a_public_did",
"invitation_msg_id": "dummy_msg",
},
limit=100,
offset=0,
post_filter_positive={
"their_role": list(ConnRecord.Role.REQUESTER.value),
"connection_protocol": "connections/1.0",
Expand Down
7 changes: 6 additions & 1 deletion aries_cloudagent/protocols/issue_credential/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from ....messaging.credential_definitions.util import CRED_DEF_TAGS
from ....messaging.models.base import BaseModelError
from ....messaging.models.openapi import OpenAPISchema
from ....messaging.models.paginated_query import PaginatedQuerySchema, get_limit_offset
from ....messaging.valid import (
INDY_CRED_DEF_ID_EXAMPLE,
INDY_CRED_DEF_ID_VALIDATE,
Expand Down Expand Up @@ -57,7 +58,7 @@ class IssueCredentialModuleResponseSchema(OpenAPISchema):
"""Response schema for Issue Credential Module."""


class V10CredentialExchangeListQueryStringSchema(OpenAPISchema):
class V10CredentialExchangeListQueryStringSchema(PaginatedQuerySchema):
"""Parameters and validators for credential exchange list query."""

connection_id = fields.Str(
Expand Down Expand Up @@ -403,11 +404,15 @@ async def credential_exchange_list(request: web.BaseRequest):
if request.query.get(k, "") != ""
}

limit, offset = get_limit_offset(request)

try:
async with context.profile.session() as session:
records = await V10CredentialExchange.query(
session=session,
tag_filter=tag_filter,
limit=limit,
offset=offset,
post_filter_positive=post_filter,
)
results = [record.serialize() for record in records]
Expand Down
7 changes: 6 additions & 1 deletion aries_cloudagent/protocols/issue_credential/v2_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from ....messaging.decorators.attach_decorator import AttachDecorator
from ....messaging.models.base import BaseModelError
from ....messaging.models.openapi import OpenAPISchema
from ....messaging.models.paginated_query import PaginatedQuerySchema, get_limit_offset
from ....messaging.valid import (
INDY_CRED_DEF_ID_EXAMPLE,
INDY_CRED_DEF_ID_VALIDATE,
Expand Down Expand Up @@ -63,7 +64,7 @@ class V20IssueCredentialModuleResponseSchema(OpenAPISchema):
"""Response schema for v2.0 Issue Credential Module."""


class V20CredExRecordListQueryStringSchema(OpenAPISchema):
class V20CredExRecordListQueryStringSchema(PaginatedQuerySchema):
"""Parameters and validators for credential exchange record list query."""

connection_id = fields.Str(
Expand Down Expand Up @@ -566,11 +567,15 @@ async def credential_exchange_list(request: web.BaseRequest):
if request.query.get(k, "") != ""
}

limit, offset = get_limit_offset(request)

try:
async with profile.session() as session:
cred_ex_records = await V20CredExRecord.query(
session=session,
tag_filter=tag_filter,
limit=limit,
offset=offset,
post_filter_positive=post_filter,
)

Expand Down
7 changes: 6 additions & 1 deletion aries_cloudagent/protocols/present_proof/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from ....messaging.decorators.attach_decorator import AttachDecorator
from ....messaging.models.base import BaseModelError
from ....messaging.models.openapi import OpenAPISchema
from ....messaging.models.paginated_query import PaginatedQuerySchema, get_limit_offset
from ....messaging.valid import (
INDY_EXTRA_WQL_EXAMPLE,
INDY_EXTRA_WQL_VALIDATE,
Expand Down Expand Up @@ -54,7 +55,7 @@ class V10PresentProofModuleResponseSchema(OpenAPISchema):
"""Response schema for Present Proof Module."""


class V10PresentationExchangeListQueryStringSchema(OpenAPISchema):
class V10PresentationExchangeListQueryStringSchema(PaginatedQuerySchema):
"""Parameters and validators for presentation exchange list query."""

connection_id = fields.Str(
Expand Down Expand Up @@ -310,11 +311,15 @@ async def presentation_exchange_list(request: web.BaseRequest):
if request.query.get(k, "") != ""
}

limit, offset = get_limit_offset(request)

try:
async with context.profile.session() as session:
records = await V10PresentationExchange.query(
session=session,
tag_filter=tag_filter,
limit=limit,
offset=offset,
post_filter_positive=post_filter,
)
results = [record.serialize() for record in records]
Expand Down
7 changes: 6 additions & 1 deletion aries_cloudagent/protocols/present_proof/v2_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from ....messaging.decorators.attach_decorator import AttachDecorator
from ....messaging.models.base import BaseModelError
from ....messaging.models.openapi import OpenAPISchema
from ....messaging.models.paginated_query import PaginatedQuerySchema, get_limit_offset
from ....messaging.valid import (
INDY_EXTRA_WQL_EXAMPLE,
INDY_EXTRA_WQL_VALIDATE,
Expand Down Expand Up @@ -70,7 +71,7 @@ class V20PresentProofModuleResponseSchema(OpenAPISchema):
"""Response schema for Present Proof Module."""


class V20PresExRecordListQueryStringSchema(OpenAPISchema):
class V20PresExRecordListQueryStringSchema(PaginatedQuerySchema):
"""Parameters and validators for presentation exchange list query."""

connection_id = fields.Str(
Expand Down Expand Up @@ -448,11 +449,15 @@ async def present_proof_list(request: web.BaseRequest):
if request.query.get(k, "") != ""
}

limit, offset = get_limit_offset(request)

try:
async with profile.session() as session:
records = await V20PresExRecord.query(
session=session,
tag_filter=tag_filter,
limit=limit,
offset=offset,
post_filter_positive=post_filter,
)
results = [record.serialize() for record in records]
Expand Down

0 comments on commit a556d56

Please sign in to comment.