Skip to content

Commit

Permalink
📝 Update wallet credentials docstrings (#814)
Browse files Browse the repository at this point in the history
* update wallet credentials docstrings

* make endpoint POST has a body

* remove wql,count,start not used in agent

* rename to record_id as it is in the credential

* update docstrings

* update docstrings and revert back to credential_id

* extend models and add credential_id field

* remove unused imports

* route classes with get indy credential by id

* update docstrings and revert back to credential_id

* formatting

* remove full stop

* rename models

* formatting

* update models

* update docstrings

* formatting

* add description to models

* update docstrings

* remove link from docstrings

* minor updates to docstrings

* reduce and rename

* add deprecated and change description

* 🎨

---------

Co-authored-by: ff137 <[email protected]>
Co-authored-by: cl0ete <[email protected]>
  • Loading branch information
cl0ete and ff137 authored Nov 4, 2024
1 parent 69e8fa9 commit 2bbe280
Show file tree
Hide file tree
Showing 2 changed files with 220 additions and 32 deletions.
38 changes: 38 additions & 0 deletions app/models/wallet.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
from typing import List, Optional

from aries_cloudcontroller.models.indy_cred_info import (
IndyCredInfo as IndyCredInfoAcaPy,
)
from aries_cloudcontroller.models.vc_record import VCRecord as VCRecordAcaPy
from pydantic import BaseModel, Field


class SetDidEndpointRequest(BaseModel):
endpoint: str = Field(...)


class VCRecord(VCRecordAcaPy):
credential_id: str = Field(
..., alias="record_id", description="Credential identifier"
)
record_id: str = Field(
...,
alias="credential_id",
description="(deprecated - renamed to credential_id) Credential identifier",
deprecated=True,
)


class VCRecordList(BaseModel):
results: Optional[List[VCRecord]] = None


class IndyCredInfo(IndyCredInfoAcaPy):
credential_id: str = Field(
..., alias="referent", description="Credential identifier"
)
referent: str = Field(
...,
alias="credential_id",
description="(deprecated - renamed to credential_id) Credential identifier",
deprecated=True,
)


class CredInfoList(BaseModel):
results: Optional[List[IndyCredInfo]] = None
214 changes: 182 additions & 32 deletions app/routes/wallet/credentials.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,98 @@
from typing import Optional
from typing import List, Optional

from aries_cloudcontroller import (
AttributeMimeTypesResult,
CredInfoList,
CredRevokedResult,
IndyCredInfo,
VCRecord,
VCRecordList,
W3CCredentialsListRequest,
)
from fastapi import APIRouter, Depends

from app.dependencies.acapy_clients import client_from_auth
from app.dependencies.auth import AcaPyAuth, acapy_auth_from_header
from app.exceptions import handle_acapy_call
from app.models.wallet import CredInfoList, IndyCredInfo, VCRecord, VCRecordList
from app.util.pagination import limit_query_parameter, offset_query_parameter
from shared.log_config import get_logger

logger = get_logger(__name__)

router = APIRouter(prefix="/v1/wallet/credentials", tags=["wallet"])


@router.get("", response_model=CredInfoList)
@router.get(
"",
response_model=CredInfoList,
summary="Fetch a list of credentials from the wallet",
)
async def list_credentials(
count: Optional[str] = None,
start: Optional[str] = None,
limit: Optional[int] = limit_query_parameter,
offset: Optional[int] = offset_query_parameter,
wql: Optional[str] = None,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> CredInfoList:
"""Fetch a list of credentials from the wallet."""
"""
Fetch a list of credentials from the wallet
---
The `wql` (Wallet Query Language) parameter can be used to filter credentials returned from the wallet.
The following string will look for the credential with the attribute `age` with value `21`:
{"attr::age::value": "21"}
Optional Parameters:
---
limit: int
The number of records to return.
offset: int
The number of records to skip before starting to return records.
wql: str
A WQL query to filter records.
Returns:
---
CredInfoList
A list of credential records.
"""
logger.debug("GET request received: List credentials")

async with client_from_auth(auth) as aries_controller:
logger.debug("Fetching credentials")
results = await handle_acapy_call(
logger=logger,
acapy_call=aries_controller.credentials.get_records,
count=count,
start=start,
count=str(limit),
start=str(offset),
wql=wql,
)

logger.debug("Successfully listed credentials.")
return results


@router.get("/{credential_id}", response_model=IndyCredInfo)
@router.get(
"/{credential_id}",
response_model=IndyCredInfo,
summary="Fetch a credential by ID",
)
async def get_credential_record(
credential_id: str,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> IndyCredInfo:
"""Fetch a specific credential by ID."""
"""
Fetch a specific credential by ID
---
Parameters:
---
credential_id: str
The ID of the credential to fetch.
Returns:
---
IndyCredInfo
The credential record.
"""
bound_logger = logger.bind(credential_id=credential_id)
bound_logger.debug("GET request received: Fetch specific credential by ID")

Expand All @@ -66,12 +108,24 @@ async def get_credential_record(
return result


@router.delete("/{credential_id}", status_code=204)
@router.delete("/{credential_id}", status_code=204, summary="Delete a credential by ID")
async def delete_credential(
credential_id: str,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> None:
"""Remove a specific credential from the wallet by ID."""
"""
Remove a specific credential from the wallet by ID
---
Parameters:
---
credential_id: str
The ID of the credential to delete.
Returns:
---
status_code: 204
"""
bound_logger = logger.bind(credential_id=credential_id)
bound_logger.debug("DELETE request received: Remove specific credential by ID")

Expand All @@ -86,12 +140,29 @@ async def delete_credential(
bound_logger.debug("Successfully deleted credential.")


@router.get("/{credential_id}/mime-types", response_model=AttributeMimeTypesResult)
@router.get(
"/{credential_id}/mime-types",
response_model=AttributeMimeTypesResult,
summary="Retrieve attribute MIME types of a credential",
)
async def get_credential_mime_types(
credential_id: str,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> AttributeMimeTypesResult:
"""Retrieve attribute MIME types of a specific credential by ID."""
"""
Retrieve attribute MIME types of a specific credential by ID
---
Parameters:
---
credential_id: str
The ID of the credential to fetch attribute MIME types for.
Returns:
---
AttributeMimeTypesResult
The attribute MIME types of the credential.
"""
bound_logger = logger.bind(credential_id=credential_id)
bound_logger.debug(
"GET request received: Retrieve attribute MIME types for a specific credential"
Expand All @@ -109,14 +180,39 @@ async def get_credential_mime_types(
return result


@router.get("/{credential_id}/revocation-status", response_model=CredRevokedResult)
@router.get(
"/{credential_id}/revocation-status",
response_model=CredRevokedResult,
summary="Get revocation status of a credential",
)
async def get_credential_revocation_status(
credential_id: str,
from_: Optional[str] = None,
to: Optional[str] = None,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> CredRevokedResult:
"""Query the revocation status of a specific credential by ID."""
"""
Query the revocation status of a specific credential by ID
---
The revocation status of a credential can be queried over a specific time range
by passing unix timestamps to the `from_` and `to` parameters.
Leaving these parameters blank will return the current revocation status.
Parameters:
---
credential_id: str
The ID of the credential to query revocation status for.
from_: Optional[str]
The timestamp to start the query from.
to: Optional[str]
The timestamp to end the query at.
Returns:
---
CredRevokedResult
The revocation status of the credential.
"""
bound_logger = logger.bind(credential_id=credential_id)
bound_logger.debug(
"GET request received: Query revocation status for a specific credential"
Expand All @@ -136,38 +232,80 @@ async def get_credential_revocation_status(
return result


@router.get("/w3c", response_model=VCRecordList)
@router.get(
"/list/w3c",

This comment has been minimized.

Copy link
@ff137

ff137 Dec 2, 2024

Author Collaborator

Ek het hierdie gemis. GET /w3c was ge-rename na GET /list/w3c. Ek dink nie ons moes dit verander nie.

response_model=VCRecordList,
summary="Fetch a list of W3C credentials from the wallet",
)
async def list_w3c_credentials(
count: Optional[str] = None,
start: Optional[str] = None,
wql: Optional[str] = None,
body: Optional[W3CCredentialsListRequest] = None,
schema_ids: Optional[List[str]] = None,
issuer_did: Optional[str] = None,
limit: Optional[int] = None,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> VCRecordList:
"""Fetch a list of W3C credentials from the wallet."""
"""
Fetch a list of W3C credentials from the wallet
---
The W3C credentials can be filtered by the parameters provided.
Optional Parameters:
---
schema_ids: List[str]
Schema identifiers to match
issuer_did: str
Credential issuer did to match
limit: int
Maximum number of results to return
Returns:
---
VCRecordList
A list of W3C credential records.
"""
logger.debug("GET request received: List W3C credentials")

body = W3CCredentialsListRequest(
schema_ids=schema_ids,
issuer_id=issuer_did,
max_results=limit,
)

async with client_from_auth(auth) as aries_controller:
logger.debug("Fetching W3C credentials")
results = await handle_acapy_call(
logger=logger,
acapy_call=aries_controller.credentials.get_w3c_credentials,
count=count,
start=start,
wql=wql,
body=body,
)

logger.debug("Successfully listed W3C credentials.")
return results


@router.get("/w3c/{credential_id}", response_model=VCRecord)
@router.get(
"/w3c/{credential_id}",
response_model=VCRecord,
summary="Fetch a W3C credential by ID",
)
async def get_w3c_credential(
credential_id: str,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> VCRecord:
"""Fetch a specific W3C credential by ID."""
"""
Fetch a specific W3C credential by ID
---
Parameters:
---
credential_id: str
The ID of the W3C credential to fetch.
Returns:
---
VCRecord
The W3C credential.
"""
bound_logger = logger.bind(credential_id=credential_id)
bound_logger.debug("GET request received: Fetch specific W3C credential by ID")

Expand All @@ -183,12 +321,24 @@ async def get_w3c_credential(
return result


@router.delete("/w3c/{credential_id}", status_code=204)
@router.delete("/w3c/{credential_id}", status_code=204, summary="Delete W3C credential")
async def delete_w3c_credential(
credential_id: str,
auth: AcaPyAuth = Depends(acapy_auth_from_header),
) -> None:
"""Remove a specific W3C credential from the wallet by ID."""
"""
Remove a specific W3C credential from the wallet by ID
---
Parameters:
---
credential_id: str
The ID of the W3C credential to delete.
Returns:
---
status_code: 204
"""
bound_logger = logger.bind(credential_id=credential_id)
bound_logger.debug("DELETE request received: Remove specific W3C credential by ID")

Expand Down

0 comments on commit 2bbe280

Please sign in to comment.