From 765e281a609f389166bcedc77abc2ef256de37fd Mon Sep 17 00:00:00 2001 From: Mourits de Beer <31511766+ff137@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:52:43 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Deprecate=20count/start=20query?= =?UTF-8?q?=20params=20and=20implement=20limit/offset=20(#6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * art: Modify count/start query params to be Integers, not Strings Signed-off-by: ff137 * memo: Update openapi spec Signed-off-by: ff137 * rewind: Revert start/count field to remain String type; mark as deprecated Signed-off-by: ff137 * sparkles: Implement limit/offset alongside deprecated count/start Signed-off-by: ff137 * art: Standardise naming convention from count/start to limit/offset Signed-off-by: ff137 * rewind: Revert start/count field to remain String type; mark as deprecated Signed-off-by: ff137 * sparkles: Implement limit/offset alongside deprecated count/start Signed-off-by: ff137 * art: Remove unused query string schema from `w3c_creds_list` Signed-off-by: ff137 * art: Rename args Signed-off-by: ff137 * memo: Update openapi specs Signed-off-by: ff137 * white_check_mark: Signed-off-by: ff137 --------- Signed-off-by: ff137 --- acapy_agent/anoncreds/holder.py | 23 ++-- acapy_agent/anoncreds/tests/test_holder.py | 10 +- acapy_agent/holder/routes.py | 53 ++++++-- acapy_agent/indy/credx/holder.py | 23 ++-- .../indy/credx/tests/test_cred_issuance.py | 16 +-- acapy_agent/indy/models/xform.py | 8 +- .../protocols/present_proof/v1_0/routes.py | 48 +++++-- .../protocols/present_proof/v2_0/routes.py | 60 ++++++--- open-api/openapi.json | 117 +++++++++++------- open-api/swagger.json | 107 +++++++++------- 10 files changed, 294 insertions(+), 171 deletions(-) diff --git a/acapy_agent/anoncreds/holder.py b/acapy_agent/anoncreds/holder.py index 04a1a16fac..ae14e4be5d 100644 --- a/acapy_agent/anoncreds/holder.py +++ b/acapy_agent/anoncreds/holder.py @@ -379,12 +379,12 @@ async def store_credential_w3c( return credential_id - async def get_credentials(self, start: int, count: int, wql: dict): + async def get_credentials(self, *, offset: int, limit: int, wql: dict): """Get credentials stored in the wallet. Args: - start: Starting index - count: Number of records to return + offset: Starting index + limit: Number of records to return wql: wql query dict """ @@ -395,8 +395,8 @@ async def get_credentials(self, start: int, count: int, wql: dict): rows = self.profile.store.scan( category=CATEGORY_CREDENTIAL, tag_filter=wql, - offset=start, - limit=count, + offset=offset, + limit=limit, profile=self.profile.settings.get("wallet.askar_profile"), ) async for row in rows: @@ -413,8 +413,9 @@ async def get_credentials_for_presentation_request_by_referent( self, presentation_request: dict, referents: Sequence[str], - start: int, - count: int, + *, + offset: int, + limit: int, extra_query: Optional[dict] = None, ): """Get credentials stored in the wallet. @@ -422,8 +423,8 @@ async def get_credentials_for_presentation_request_by_referent( Args: presentation_request: Valid presentation request from issuer referents: Presentation request referents to use to search for creds - start: Starting index - count: Maximum number of records to return + offset: Starting index + limit: Maximum number of records to return extra_query: wql query dict """ @@ -466,8 +467,8 @@ async def get_credentials_for_presentation_request_by_referent( rows = self.profile.store.scan( category=CATEGORY_CREDENTIAL, tag_filter=tag_filter, - offset=start, - limit=count, + offset=offset, + limit=limit, profile=self.profile.settings.get("wallet.askar_profile"), ) async for row in rows: diff --git a/acapy_agent/anoncreds/tests/test_holder.py b/acapy_agent/anoncreds/tests/test_holder.py index ba69a7ebd7..6f8dae681d 100644 --- a/acapy_agent/anoncreds/tests/test_holder.py +++ b/acapy_agent/anoncreds/tests/test_holder.py @@ -397,7 +397,7 @@ async def test_store_credential_failed_trx(self, *_): async def test_get_credentials(self, _): async with self.profile.session() as session: await session.handle.insert(CATEGORY_CREDENTIAL, json.dumps(MOCK_CRED)) - result = await self.holder.get_credentials(0, 10, {}) + result = await self.holder.get_credentials(offset=0, limit=10, wql={}) assert isinstance(result, list) assert len(result) == 1 @@ -410,9 +410,9 @@ async def test_get_credentials_errors(self): ) with self.assertRaises(AnonCredsHolderError): - await self.holder.get_credentials(0, 10, {}) + await self.holder.get_credentials(offset=0, limit=10, wql={}) with self.assertRaises(AnonCredsHolderError): - await self.holder.get_credentials(0, 10, {}) + await self.holder.get_credentials(offset=0, limit=10, wql={}) async def test_get_credentials_for_presentation_request_by_referent(self): self.profile.store.scan = mock.Mock( @@ -432,13 +432,13 @@ async def test_get_credentials_for_presentation_request_by_referent(self): "restrictions": [{"schema_name": "MYCO Biomarker"}], } await self.holder.get_credentials_for_presentation_request_by_referent( - mock_pres_req, None, start=0, count=10 + mock_pres_req, None, offset=0, limit=10 ) # non-existent referent with self.assertRaises(AnonCredsHolderError): await self.holder.get_credentials_for_presentation_request_by_referent( - mock_pres_req, "not-found-ref", start=0, count=10 + mock_pres_req, "not-found-ref", offset=0, limit=10 ) @mock.patch.object(Credential, "load", return_value=MockCredential()) diff --git a/acapy_agent/holder/routes.py b/acapy_agent/holder/routes.py index 37c1d5e1e7..cda58ccc75 100644 --- a/acapy_agent/holder/routes.py +++ b/acapy_agent/holder/routes.py @@ -33,6 +33,7 @@ NUM_STR_WHOLE_VALIDATE, UUID4_EXAMPLE, ) +from ..storage.base import DEFAULT_PAGE_SIZE, MAXIMUM_PAGE_SIZE from ..storage.error import StorageError, StorageNotFoundError from ..storage.vc_holder.base import VCHolder from ..storage.vc_holder.vc_record import VCRecordSchema @@ -66,17 +67,41 @@ class CredentialsListQueryStringSchema(OpenAPISchema): start = fields.Str( required=False, + load_default=0, validate=NUM_STR_WHOLE_VALIDATE, - metadata={"description": "Start index", "example": NUM_STR_WHOLE_EXAMPLE}, + metadata={ + "description": "Start index (DEPRECATED - use offset instead)", + "example": NUM_STR_WHOLE_EXAMPLE, + "deprecated": True, + }, ) count = fields.Str( required=False, + load_default=10, validate=NUM_STR_NATURAL_VALIDATE, metadata={ - "description": "Maximum number to retrieve", + "description": "Maximum number to retrieve (DEPRECATED - use limit instead)", "example": NUM_STR_NATURAL_EXAMPLE, + "deprecated": True, + }, + ) + limit = fields.Int( + required=False, + validate=lambda x: x > 0 and x <= MAXIMUM_PAGE_SIZE, + metadata={"description": "Number of results to return", "example": 50}, + error_messages={ + "validator_failed": ( + "Value must be greater than 0 and " + f"less than or equal to {MAXIMUM_PAGE_SIZE}" + ) }, ) + offset = fields.Int( + required=False, + validate=lambda x: x >= 0, + metadata={"description": "Offset for pagination", "example": 0}, + error_messages={"validator_failed": "Value must be 0 or greater"}, + ) wql = fields.Str( required=False, validate=INDY_WQL_VALIDATE, @@ -379,25 +404,32 @@ async def credentials_list(request: web.BaseRequest): """ context: AdminRequestContext = request["context"] - start = request.query.get("start") - count = request.query.get("count") + + # Handle both old style start/count and new limit/offset + # TODO: Remove start/count and swap to PaginatedQuerySchema and get_limit_offset + if "limit" in request.query or "offset" in request.query: + # New style - use limit/offset + limit = int(request.query.get("limit", DEFAULT_PAGE_SIZE)) + offset = int(request.query.get("offset", 0)) + else: + # Old style - use start/count + limit = int(request.query.get("count", "10")) + offset = int(request.query.get("start", "0")) # url encoded json wql encoded_wql = request.query.get("wql") or "{}" wql = json.loads(encoded_wql) - # defaults - start = int(start) if isinstance(start, str) else 0 - count = int(count) if isinstance(count, str) else 10 - if context.settings.get(wallet_type_config) == "askar-anoncreds": holder = AnonCredsHolder(context.profile) - credentials = await holder.get_credentials(start, count, wql) + credentials = await holder.get_credentials(limit=limit, offset=offset, wql=wql) else: async with context.profile.session() as session: holder = session.inject(IndyHolder) try: - credentials = await holder.get_credentials(start, count, wql) + credentials = await holder.get_credentials( + limit=limit, offset=offset, wql=wql + ) except IndyHolderError as err: raise web.HTTPBadRequest(reason=err.roll_up) from err @@ -476,7 +508,6 @@ async def w3c_cred_remove(request: web.BaseRequest): summary="Fetch W3C credentials from wallet", ) @request_schema(W3CCredentialsListRequestSchema()) -@querystring_schema(CredentialsListQueryStringSchema()) @response_schema(VCRecordListSchema(), 200, description="") @tenant_authentication async def w3c_creds_list(request: web.BaseRequest): diff --git a/acapy_agent/indy/credx/holder.py b/acapy_agent/indy/credx/holder.py index 27ba7837e2..089f1620d1 100644 --- a/acapy_agent/indy/credx/holder.py +++ b/acapy_agent/indy/credx/holder.py @@ -236,12 +236,12 @@ async def store_credential( return credential_id - async def get_credentials(self, start: int, count: int, wql: dict): + async def get_credentials(self, *, offset: int, limit: int, wql: dict): """Get credentials stored in the wallet. Args: - start: Starting index - count: Number of records to return + offset: Starting index + limit: Number of records to return wql: wql query dict """ @@ -252,8 +252,8 @@ async def get_credentials(self, start: int, count: int, wql: dict): rows = self._profile.store.scan( category=CATEGORY_CREDENTIAL, tag_filter=wql, - offset=start, - limit=count, + offset=offset, + limit=limit, profile=self._profile.settings.get("wallet.askar_profile"), ) async for row in rows: @@ -270,8 +270,9 @@ async def get_credentials_for_presentation_request_by_referent( self, presentation_request: dict, referents: Sequence[str], - start: int, - count: int, + *, + offset: int, + limit: int, extra_query: Optional[dict] = None, ): """Get credentials stored in the wallet. @@ -279,8 +280,8 @@ async def get_credentials_for_presentation_request_by_referent( Args: presentation_request: Valid presentation request from issuer referents: Presentation request referents to use to search for creds - start: Starting index - count: Maximum number of records to return + offset: Starting index + limit: Maximum number of records to return extra_query: wql query dict """ @@ -323,8 +324,8 @@ async def get_credentials_for_presentation_request_by_referent( rows = self._profile.store.scan( category=CATEGORY_CREDENTIAL, tag_filter=tag_filter, - offset=start, - limit=count, + offset=offset, + limit=limit, profile=self._profile.settings.get("wallet.askar_profile"), ) async for row in rows: diff --git a/acapy_agent/indy/credx/tests/test_cred_issuance.py b/acapy_agent/indy/credx/tests/test_cred_issuance.py index 9b8c222dc2..f0154b0a7b 100644 --- a/acapy_agent/indy/credx/tests/test_cred_issuance.py +++ b/acapy_agent/indy/credx/tests/test_cred_issuance.py @@ -132,7 +132,7 @@ async def test_issue_store_non_rev(self): assert not await self.holder.get_mime_type(cred_id, "name") - creds = await self.holder.get_credentials(None, None, None) + creds = await self.holder.get_credentials(offset=None, limit=None, wql=None) assert len(creds) == 1 assert creds[0] == stored_cred @@ -142,9 +142,9 @@ async def test_issue_store_non_rev(self): await self.holder.get_credentials_for_presentation_request_by_referent( PRES_REQ_NON_REV, None, - 0, - 10, - {}, + offset=0, + limit=10, + extra_query={}, ) ) assert pres_creds == [ @@ -247,7 +247,7 @@ async def test_issue_store_rev(self): assert found stored_cred = json.loads(found) - creds = await self.holder.get_credentials(None, None, None) + creds = await self.holder.get_credentials(offset=None, limit=None, wql=None) assert len(creds) == 1 assert creds[0] == stored_cred @@ -257,9 +257,9 @@ async def test_issue_store_rev(self): await self.holder.get_credentials_for_presentation_request_by_referent( PRES_REQ_REV, None, - 0, - 10, - {}, + offset=0, + limit=10, + extra_query={}, ) ) assert pres_creds == [ diff --git a/acapy_agent/indy/models/xform.py b/acapy_agent/indy/models/xform.py index 6e80794889..c8082ce576 100644 --- a/acapy_agent/indy/models/xform.py +++ b/acapy_agent/indy/models/xform.py @@ -34,8 +34,8 @@ async def indy_proof_req_preview2indy_requested_creds( credentials = await holder.get_credentials_for_presentation_request_by_referent( presentation_request=indy_proof_req, referents=(referent,), - start=0, - count=100, + offset=0, + limit=100, ) if not credentials: raise ValueError( @@ -87,8 +87,8 @@ async def indy_proof_req_preview2indy_requested_creds( credentials = await holder.get_credentials_for_presentation_request_by_referent( presentation_request=indy_proof_req, referents=(referent,), - start=0, - count=100, + offset=0, + limit=100, ) if not credentials: raise ValueError( diff --git a/acapy_agent/protocols/present_proof/v1_0/routes.py b/acapy_agent/protocols/present_proof/v1_0/routes.py index ef9cad6a2d..9d82f2f9b5 100644 --- a/acapy_agent/protocols/present_proof/v1_0/routes.py +++ b/acapy_agent/protocols/present_proof/v1_0/routes.py @@ -39,6 +39,7 @@ UUID4_EXAMPLE, UUID4_VALIDATE, ) +from ....storage.base import DEFAULT_PAGE_SIZE, MAXIMUM_PAGE_SIZE from ....storage.error import StorageError, StorageNotFoundError from ....utils.tracing import AdminAPIMessageTracingSchema, get_timer, trace_event from ....wallet.error import WalletNotFoundError @@ -240,21 +241,42 @@ class CredentialsFetchQueryStringSchema(OpenAPISchema): ) start = fields.Str( required=False, + load_default="0", validate=NUM_STR_WHOLE_VALIDATE, metadata={ - "description": "Start index", + "description": "Start index (DEPRECATED - use offset instead)", "strict": True, "example": NUM_STR_WHOLE_EXAMPLE, + "deprecated": True, }, ) count = fields.Str( required=False, + load_default="10", validate=NUM_STR_NATURAL_VALIDATE, metadata={ - "description": "Maximum number to retrieve", + "description": "Maximum number to retrieve (DEPRECATED - use limit instead)", "example": NUM_STR_NATURAL_EXAMPLE, + "deprecated": True, }, ) + limit = fields.Int( + required=False, + validate=lambda x: x > 0 and x <= MAXIMUM_PAGE_SIZE, + metadata={"description": "Number of results to return", "example": 50}, + error_messages={ + "validator_failed": ( + "Value must be greater than 0 and " + f"less than or equal to {MAXIMUM_PAGE_SIZE}" + ) + }, + ) + offset = fields.Int( + required=False, + validate=lambda x: x >= 0, + metadata={"description": "Offset for pagination", "example": 0}, + error_messages={"validator_failed": "Value must be 0 or greater"}, + ) extra_query = fields.Str( required=False, validate=INDY_EXTRA_WQL_VALIDATE, @@ -418,25 +440,29 @@ async def presentation_exchange_credentials_list(request: web.BaseRequest): except StorageNotFoundError as err: raise web.HTTPNotFound(reason=err.roll_up) from err - start = request.query.get("start") - count = request.query.get("count") + # Handle both old style start/count and new limit/offset + # TODO: Remove start/count and swap to PaginatedQuerySchema and get_limit_offset + if "limit" in request.query or "offset" in request.query: + # New style - use limit/offset + limit = int(request.query.get("limit", DEFAULT_PAGE_SIZE)) + offset = int(request.query.get("offset", 0)) + else: + # Old style - use start/count + limit = int(request.query.get("count", "10")) + offset = int(request.query.get("start", "0")) # url encoded json extra_query encoded_extra_query = request.query.get("extra_query") or "{}" extra_query = json.loads(encoded_extra_query) - # defaults - start = int(start) if isinstance(start, str) else 0 - count = int(count) if isinstance(count, str) else 10 - holder = profile.inject(IndyHolder) try: credentials = await holder.get_credentials_for_presentation_request_by_referent( pres_ex_record._presentation_request.ser, presentation_referents, - start, - count, - extra_query, + offset=offset, + limit=limit, + extra_query=extra_query, ) except IndyHolderError as err: if pres_ex_record: diff --git a/acapy_agent/protocols/present_proof/v2_0/routes.py b/acapy_agent/protocols/present_proof/v2_0/routes.py index 55b4b7d69f..76fe68c1f6 100644 --- a/acapy_agent/protocols/present_proof/v2_0/routes.py +++ b/acapy_agent/protocols/present_proof/v2_0/routes.py @@ -40,7 +40,7 @@ UUID4_EXAMPLE, UUID4_VALIDATE, ) -from ....storage.base import BaseStorage +from ....storage.base import DEFAULT_PAGE_SIZE, MAXIMUM_PAGE_SIZE, BaseStorage from ....storage.error import StorageError, StorageNotFoundError from ....storage.vc_holder.base import VCHolder from ....storage.vc_holder.vc_record import VCRecord @@ -57,12 +57,7 @@ from . import problem_report_for_record, report_problem from .formats.handler import V20PresFormatHandlerError from .manager import V20PresManager -from .message_types import ( - ATTACHMENT_FORMAT, - PRES_20_PROPOSAL, - PRES_20_REQUEST, - SPEC_URI, -) +from .message_types import ATTACHMENT_FORMAT, PRES_20_PROPOSAL, PRES_20_REQUEST, SPEC_URI from .messages.pres_format import V20PresFormat from .messages.pres_problem_report import ProblemReportReason from .messages.pres_proposal import V20PresProposal @@ -353,21 +348,42 @@ class V20CredentialsFetchQueryStringSchema(OpenAPISchema): ) start = fields.Str( required=False, + load_default="0", validate=NUM_STR_WHOLE_VALIDATE, metadata={ - "description": "Start index", + "description": "Start index (DEPRECATED - use offset instead)", "strict": True, "example": NUM_STR_WHOLE_EXAMPLE, + "deprecated": True, }, ) count = fields.Str( required=False, + load_default="10", validate=NUM_STR_NATURAL_VALIDATE, metadata={ - "description": "Maximum number to retrieve", + "description": "Maximum number to retrieve (DEPRECATED - use limit instead)", "example": NUM_STR_NATURAL_EXAMPLE, + "deprecated": True, + }, + ) + limit = fields.Int( + required=False, + validate=lambda x: x > 0 and x <= MAXIMUM_PAGE_SIZE, + metadata={"description": "Number of results to return", "example": 50}, + error_messages={ + "validator_failed": ( + "Value must be greater than 0 and " + f"less than or equal to {MAXIMUM_PAGE_SIZE}" + ) }, ) + offset = fields.Int( + required=False, + validate=lambda x: x >= 0, + metadata={"description": "Offset for pagination", "example": 0}, + error_messages={"validator_failed": "Value must be 0 or greater"}, + ) extra_query = fields.Str( required=False, validate=INDY_EXTRA_WQL_VALIDATE, @@ -549,17 +565,21 @@ async def present_proof_credentials_list(request: web.BaseRequest): except StorageNotFoundError as err: raise web.HTTPNotFound(reason=err.roll_up) from err - start = request.query.get("start") - count = request.query.get("count") + # Handle both old style start/count and new limit/offset + # TODO: Remove start/count and swap to PaginatedQuerySchema and get_limit_offset + if "limit" in request.query or "offset" in request.query: + # New style - use limit/offset + limit = int(request.query.get("limit", DEFAULT_PAGE_SIZE)) + offset = int(request.query.get("offset", 0)) + else: + # Old style - use start/count + limit = int(request.query.get("count", "10")) + offset = int(request.query.get("start", "0")) # url encoded json extra_query encoded_extra_query = request.query.get("extra_query") or "{}" extra_query = json.loads(encoded_extra_query) - # defaults - start = int(start) if isinstance(start, str) else 0 - count = int(count) if isinstance(count, str) else 10 - wallet_type = profile.settings.get_value("wallet.type") if wallet_type == "askar-anoncreds": indy_holder = AnonCredsHolder(profile) @@ -576,9 +596,9 @@ async def present_proof_credentials_list(request: web.BaseRequest): await indy_holder.get_credentials_for_presentation_request_by_referent( indy_pres_request, pres_referents, - start, - count, - extra_query, + offset=offset, + limit=limit, + extra_query=extra_query, ) ) @@ -737,7 +757,7 @@ async def present_proof_credentials_list(request: web.BaseRequest): search = dif_holder.search_credentials( proof_types=proof_type, pd_uri_list=uri_group ) - cred_group = await search.fetch(count) + cred_group = await search.fetch(limit) ( cred_group_vcrecord_list, cred_group_vcrecord_ids_set, @@ -751,7 +771,7 @@ async def present_proof_credentials_list(request: web.BaseRequest): proof_types=proof_type, pd_uri_list=uri_list, ) - records = await search.fetch(count) + records = await search.fetch(limit) # Avoiding addition of duplicate records vcrecord_list, vcrecord_ids_set = await process_vcrecords_return_list( records, record_ids diff --git a/open-api/openapi.json b/open-api/openapi.json index 444c97fbbe..398b1d02ef 100644 --- a/open-api/openapi.json +++ b/open-api/openapi.json @@ -2054,18 +2054,34 @@ "/credentials" : { "get" : { "parameters" : [ { - "description" : "Maximum number to retrieve", + "description" : "Maximum number to retrieve (DEPRECATED - use limit instead)", "in" : "query", "name" : "count", "schema" : { + "default" : "10", "pattern" : "^[1-9][0-9]*$", "type" : "string" } }, { - "description" : "Start index", + "description" : "Number of results to return", + "in" : "query", + "name" : "limit", + "schema" : { + "type" : "integer" + } + }, { + "description" : "Offset for pagination", + "in" : "query", + "name" : "offset", + "schema" : { + "type" : "integer" + } + }, { + "description" : "Start index (DEPRECATED - use offset instead)", "in" : "query", "name" : "start", "schema" : { + "default" : "0", "pattern" : "^[0-9]*$", "type" : "string" } @@ -2096,31 +2112,6 @@ }, "/credentials/w3c" : { "post" : { - "parameters" : [ { - "description" : "Maximum number to retrieve", - "in" : "query", - "name" : "count", - "schema" : { - "pattern" : "^[1-9][0-9]*$", - "type" : "string" - } - }, { - "description" : "Start index", - "in" : "query", - "name" : "start", - "schema" : { - "pattern" : "^[0-9]*$", - "type" : "string" - } - }, { - "description" : "(JSON) WQL query", - "in" : "query", - "name" : "wql", - "schema" : { - "pattern" : "^{.*}$", - "type" : "string" - } - } ], "requestBody" : { "content" : { "*/*" : { @@ -4923,10 +4914,11 @@ "type" : "string" } }, { - "description" : "Maximum number to retrieve", + "description" : "Maximum number to retrieve (DEPRECATED - use limit instead)", "in" : "query", "name" : "count", "schema" : { + "default" : "10", "pattern" : "^[1-9][0-9]*$", "type" : "string" } @@ -4938,6 +4930,20 @@ "pattern" : "^{\\s*\".*?\"\\s*:\\s*{.*?}\\s*(,\\s*\".*?\"\\s*:\\s*{.*?}\\s*)*\\s*}$", "type" : "string" } + }, { + "description" : "Number of results to return", + "in" : "query", + "name" : "limit", + "schema" : { + "type" : "integer" + } + }, { + "description" : "Offset for pagination", + "in" : "query", + "name" : "offset", + "schema" : { + "type" : "integer" + } }, { "description" : "Proof request referents of interest, comma-separated", "in" : "query", @@ -4946,10 +4952,11 @@ "type" : "string" } }, { - "description" : "Start index", + "description" : "Start index (DEPRECATED - use offset instead)", "in" : "query", "name" : "start", "schema" : { + "default" : "0", "pattern" : "^[0-9]*$", "type" : "string" } @@ -5341,10 +5348,11 @@ "type" : "string" } }, { - "description" : "Maximum number to retrieve", + "description" : "Maximum number to retrieve (DEPRECATED - use limit instead)", "in" : "query", "name" : "count", "schema" : { + "default" : "10", "pattern" : "^[1-9][0-9]*$", "type" : "string" } @@ -5356,6 +5364,20 @@ "pattern" : "^{\\s*\".*?\"\\s*:\\s*{.*?}\\s*(,\\s*\".*?\"\\s*:\\s*{.*?}\\s*)*\\s*}$", "type" : "string" } + }, { + "description" : "Number of results to return", + "in" : "query", + "name" : "limit", + "schema" : { + "type" : "integer" + } + }, { + "description" : "Offset for pagination", + "in" : "query", + "name" : "offset", + "schema" : { + "type" : "integer" + } }, { "description" : "Proof request referents of interest, comma-separated", "in" : "query", @@ -5364,10 +5386,11 @@ "type" : "string" } }, { - "description" : "Start index", + "description" : "Start index (DEPRECATED - use offset instead)", "in" : "query", "name" : "start", "schema" : { + "default" : "0", "pattern" : "^[0-9]*$", "type" : "string" } @@ -8376,12 +8399,12 @@ "type" : "string" }, "kid" : { - "description" : "Optional kid to bind to the keypair, such as a verificationMethod.", + "description" : "Optional kid to bind to the keypair, such as a verificationMethod.", "example" : "did:web:example.com#key-01", "type" : "string" }, "seed" : { - "description" : "Optional seed to generate the key pair. Must enable insecure wallet mode.", + "description" : "Optional seed to generate the key pair. Must enable insecure wallet mode.", "example" : "00000000000000000000000000000000", "type" : "string" } @@ -8450,7 +8473,7 @@ }, "wallet_type" : { "description" : "Type of the wallet to create. Must be same as base wallet.", - "enum" : [ "askar", "askar-anoncreds", "in_memory" ], + "enum" : [ "askar", "askar-anoncreds" ], "example" : "askar", "type" : "string" }, @@ -9322,7 +9345,7 @@ "type" : "string" }, "mediation_id" : { - "description" : "Medation ID to use for endpoint information.", + "description" : "Mediation ID to use for endpoint information.", "example" : "3fa85f64-5717-4562-b3fc-2c963f66afa6", "pattern" : "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}", "type" : "string" @@ -9553,47 +9576,47 @@ "additionalProperties" : true, "properties" : { "challenge" : { - "description" : "The value is used once for a particular domain and window of time. This value is used to mitigate replay attacks.", + "description" : "The value is used once for a particular domain and window of time. This value is used to mitigate replay attacks.", "example" : "3fa85f64-5717-4562-b3fc-2c963f66afa6", "type" : "string" }, "created" : { - "description" : "The date and time the proof was created is OPTIONAL and, if included, MUST be specified as an [XMLSCHEMA11-2] dateTimeStamp string", + "description" : "The date and time the proof was created is OPTIONAL and, if included, MUST be specified as an [XMLSCHEMA11-2] dateTimeStamp string", "example" : "2010-01-01T19:23:24Z", "type" : "string" }, "cryptosuite" : { - "description" : "An identifier for the cryptographic suite that can be used to verify the proof.", + "description" : "An identifier for the cryptographic suite that can be used to verify the proof.", "example" : "eddsa-jcs-2022", "type" : "string" }, "domain" : { - "description" : "It conveys one or more security domains in which the proof is meant to be used.", + "description" : "It conveys one or more security domains in which the proof is meant to be used.", "example" : "example.com", "type" : "string" }, "expires" : { - "description" : "The expires property is OPTIONAL and, if present, specifies when the proof expires. If present, it MUST be an [XMLSCHEMA11-2] dateTimeStamp string", + "description" : "The expires property is OPTIONAL and, if present, specifies when the proof expires. If present, it MUST be an [XMLSCHEMA11-2] dateTimeStamp string", "example" : "2010-01-01T19:23:24Z", "type" : "string" }, "id" : { - "description" : "An optional identifier for the proof, which MUST be a URL [URL], such as a UUID as a URN", + "description" : "An optional identifier for the proof, which MUST be a URL [URL], such as a UUID as a URN", "example" : "urn:uuid:6a1676b8-b51f-11ed-937b-d76685a20ff5", "type" : "string" }, "nonce" : { - "description" : "One use of this field is to increase privacy by decreasing linkability that is the result of deterministically generated signatures.", + "description" : "One use of this field is to increase privacy by decreasing linkability that is the result of deterministically generated signatures.", "example" : "CF69iO3nfvqRsRBNElE8b4wO39SyJHPM7Gg1nExltW5vSfQA1lvDCR/zXX1To0/4NLo==", "type" : "string" }, "previousProof" : { - "description" : "Each value identifies another data integrity proof that MUST verify before the current proof is processed.", + "description" : "Each value identifies another data integrity proof that MUST verify before the current proof is processed.", "example" : "urn:uuid:6a1676b8-b51f-11ed-937b-d76685a20ff5", "type" : "string" }, "proofPurpose" : { - "description" : "The proof purpose acts as a safeguard to prevent the proof from being misused by being applied to a purpose other than the one that was intended.", + "description" : "The proof purpose acts as a safeguard to prevent the proof from being misused by being applied to a purpose other than the one that was intended.", "example" : "assertionMethod", "type" : "string" }, @@ -9603,12 +9626,12 @@ "type" : "string" }, "type" : { - "description" : "The specific type of proof MUST be specified as a string that maps to a URL [URL].", + "description" : "The specific type of proof MUST be specified as a string that maps to a URL [URL].", "example" : "DataIntegrityProof", "type" : "string" }, "verificationMethod" : { - "description" : "A verification method is the means and information needed to verify the proof. ", + "description" : "A verification method is the means and information needed to verify the proof.", "example" : "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", "pattern" : "\\w+:(\\/?\\/?)[^\\s]+", "type" : "string" @@ -14085,7 +14108,7 @@ "UpdateKeyRequest" : { "properties" : { "kid" : { - "description" : "New kid to bind to the key pair, such as a verificationMethod.", + "description" : "New kid to bind to the key pair, such as a verificationMethod.", "example" : "did:web:example.com#key-02", "type" : "string" }, diff --git a/open-api/swagger.json b/open-api/swagger.json index 3267ac846e..b3f325664f 100644 --- a/open-api/swagger.json +++ b/open-api/swagger.json @@ -1718,16 +1718,30 @@ "parameters" : [ { "name" : "count", "in" : "query", - "description" : "Maximum number to retrieve", + "description" : "Maximum number to retrieve (DEPRECATED - use limit instead)", "required" : false, "type" : "string", + "default" : "10", "pattern" : "^[1-9][0-9]*$" + }, { + "name" : "limit", + "in" : "query", + "description" : "Number of results to return", + "required" : false, + "type" : "integer" + }, { + "name" : "offset", + "in" : "query", + "description" : "Offset for pagination", + "required" : false, + "type" : "integer" }, { "name" : "start", "in" : "query", - "description" : "Start index", + "description" : "Start index (DEPRECATED - use offset instead)", "required" : false, "type" : "string", + "default" : "0", "pattern" : "^[0-9]*$" }, { "name" : "wql", @@ -1759,27 +1773,6 @@ "schema" : { "$ref" : "#/definitions/W3CCredentialsListRequest" } - }, { - "name" : "count", - "in" : "query", - "description" : "Maximum number to retrieve", - "required" : false, - "type" : "string", - "pattern" : "^[1-9][0-9]*$" - }, { - "name" : "start", - "in" : "query", - "description" : "Start index", - "required" : false, - "type" : "string", - "pattern" : "^[0-9]*$" - }, { - "name" : "wql", - "in" : "query", - "description" : "(JSON) WQL query", - "required" : false, - "type" : "string", - "pattern" : "^{.*}$" } ], "responses" : { "200" : { @@ -4050,9 +4043,10 @@ }, { "name" : "count", "in" : "query", - "description" : "Maximum number to retrieve", + "description" : "Maximum number to retrieve (DEPRECATED - use limit instead)", "required" : false, "type" : "string", + "default" : "10", "pattern" : "^[1-9][0-9]*$" }, { "name" : "extra_query", @@ -4061,6 +4055,18 @@ "required" : false, "type" : "string", "pattern" : "^{\\s*\".*?\"\\s*:\\s*{.*?}\\s*(,\\s*\".*?\"\\s*:\\s*{.*?}\\s*)*\\s*}$" + }, { + "name" : "limit", + "in" : "query", + "description" : "Number of results to return", + "required" : false, + "type" : "integer" + }, { + "name" : "offset", + "in" : "query", + "description" : "Offset for pagination", + "required" : false, + "type" : "integer" }, { "name" : "referent", "in" : "query", @@ -4070,9 +4076,10 @@ }, { "name" : "start", "in" : "query", - "description" : "Start index", + "description" : "Start index (DEPRECATED - use offset instead)", "required" : false, "type" : "string", + "default" : "0", "pattern" : "^[0-9]*$" } ], "responses" : { @@ -4389,9 +4396,10 @@ }, { "name" : "count", "in" : "query", - "description" : "Maximum number to retrieve", + "description" : "Maximum number to retrieve (DEPRECATED - use limit instead)", "required" : false, "type" : "string", + "default" : "10", "pattern" : "^[1-9][0-9]*$" }, { "name" : "extra_query", @@ -4400,6 +4408,18 @@ "required" : false, "type" : "string", "pattern" : "^{\\s*\".*?\"\\s*:\\s*{.*?}\\s*(,\\s*\".*?\"\\s*:\\s*{.*?}\\s*)*\\s*}$" + }, { + "name" : "limit", + "in" : "query", + "description" : "Number of results to return", + "required" : false, + "type" : "integer" + }, { + "name" : "offset", + "in" : "query", + "description" : "Offset for pagination", + "required" : false, + "type" : "integer" }, { "name" : "referent", "in" : "query", @@ -4409,9 +4429,10 @@ }, { "name" : "start", "in" : "query", - "description" : "Start index", + "description" : "Start index (DEPRECATED - use offset instead)", "required" : false, "type" : "string", + "default" : "0", "pattern" : "^[0-9]*$" } ], "deprecated" : true, @@ -7007,12 +7028,12 @@ "kid" : { "type" : "string", "example" : "did:web:example.com#key-01", - "description" : "Optional kid to bind to the keypair, such as a verificationMethod." + "description" : "Optional kid to bind to the keypair, such as a verificationMethod." }, "seed" : { "type" : "string", "example" : "00000000000000000000000000000000", - "description" : "Optional seed to generate the key pair. Must enable insecure wallet mode." + "description" : "Optional seed to generate the key pair. Must enable insecure wallet mode." } } }, @@ -7081,7 +7102,7 @@ "type" : "string", "example" : "askar", "description" : "Type of the wallet to create. Must be same as base wallet.", - "enum" : [ "askar", "askar-anoncreds", "in_memory" ] + "enum" : [ "askar", "askar-anoncreds" ] }, "wallet_webhook_urls" : { "type" : "array", @@ -7909,7 +7930,7 @@ "mediation_id" : { "type" : "string", "example" : "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "description" : "Medation ID to use for endpoint information.", + "description" : "Mediation ID to use for endpoint information.", "pattern" : "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" } } @@ -8135,47 +8156,47 @@ "challenge" : { "type" : "string", "example" : "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "description" : "The value is used once for a particular domain and window of time. This value is used to mitigate replay attacks." + "description" : "The value is used once for a particular domain and window of time. This value is used to mitigate replay attacks." }, "created" : { "type" : "string", "example" : "2010-01-01T19:23:24Z", - "description" : "The date and time the proof was created is OPTIONAL and, if included, MUST be specified as an [XMLSCHEMA11-2] dateTimeStamp string" + "description" : "The date and time the proof was created is OPTIONAL and, if included, MUST be specified as an [XMLSCHEMA11-2] dateTimeStamp string" }, "cryptosuite" : { "type" : "string", "example" : "eddsa-jcs-2022", - "description" : "An identifier for the cryptographic suite that can be used to verify the proof." + "description" : "An identifier for the cryptographic suite that can be used to verify the proof." }, "domain" : { "type" : "string", "example" : "example.com", - "description" : "It conveys one or more security domains in which the proof is meant to be used." + "description" : "It conveys one or more security domains in which the proof is meant to be used." }, "expires" : { "type" : "string", "example" : "2010-01-01T19:23:24Z", - "description" : "The expires property is OPTIONAL and, if present, specifies when the proof expires. If present, it MUST be an [XMLSCHEMA11-2] dateTimeStamp string" + "description" : "The expires property is OPTIONAL and, if present, specifies when the proof expires. If present, it MUST be an [XMLSCHEMA11-2] dateTimeStamp string" }, "id" : { "type" : "string", "example" : "urn:uuid:6a1676b8-b51f-11ed-937b-d76685a20ff5", - "description" : "An optional identifier for the proof, which MUST be a URL [URL], such as a UUID as a URN" + "description" : "An optional identifier for the proof, which MUST be a URL [URL], such as a UUID as a URN" }, "nonce" : { "type" : "string", "example" : "CF69iO3nfvqRsRBNElE8b4wO39SyJHPM7Gg1nExltW5vSfQA1lvDCR/zXX1To0/4NLo==", - "description" : "One use of this field is to increase privacy by decreasing linkability that is the result of deterministically generated signatures." + "description" : "One use of this field is to increase privacy by decreasing linkability that is the result of deterministically generated signatures." }, "previousProof" : { "type" : "string", "example" : "urn:uuid:6a1676b8-b51f-11ed-937b-d76685a20ff5", - "description" : "Each value identifies another data integrity proof that MUST verify before the current proof is processed." + "description" : "Each value identifies another data integrity proof that MUST verify before the current proof is processed." }, "proofPurpose" : { "type" : "string", "example" : "assertionMethod", - "description" : "The proof purpose acts as a safeguard to prevent the proof from being misused by being applied to a purpose other than the one that was intended." + "description" : "The proof purpose acts as a safeguard to prevent the proof from being misused by being applied to a purpose other than the one that was intended." }, "proofValue" : { "type" : "string", @@ -8185,12 +8206,12 @@ "type" : { "type" : "string", "example" : "DataIntegrityProof", - "description" : "The specific type of proof MUST be specified as a string that maps to a URL [URL]." + "description" : "The specific type of proof MUST be specified as a string that maps to a URL [URL]." }, "verificationMethod" : { "type" : "string", "example" : "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", - "description" : "A verification method is the means and information needed to verify the proof. ", + "description" : "A verification method is the means and information needed to verify the proof.", "pattern" : "\\w+:(\\/?\\/?)[^\\s]+" } }, @@ -12479,7 +12500,7 @@ "kid" : { "type" : "string", "example" : "did:web:example.com#key-02", - "description" : "New kid to bind to the key pair, such as a verificationMethod." + "description" : "New kid to bind to the key pair, such as a verificationMethod." }, "multikey" : { "type" : "string",