Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check ledger for rev reg delta evidence of cred revocation #735

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions aries_cloudagent/holder/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Tuple, Union

from ..core.error import BaseError
from ..ledger.base import BaseLedger


class HolderError(BaseError):
Expand Down Expand Up @@ -33,6 +34,16 @@ async def get_credential(self, credential_id: str) -> str:

"""

@abstractmethod
async def credential_revoked(self, credential_id: str, ledger: BaseLedger) -> bool:
"""
Check ledger for revocation status of credential by cred id.

Args:
credential_id: Credential id to check

"""

@abstractmethod
async def delete_credential(self, credential_id: str):
"""
Expand Down
22 changes: 21 additions & 1 deletion aries_cloudagent/holder/indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

from ..indy import create_tails_reader
from ..indy.error import IndyErrorHandler
from ..ledger.base import BaseLedger
from ..storage.indy import IndyStorage
from ..storage.error import StorageError, StorageNotFoundError
from ..storage.record import StorageRecord

from ..wallet.error import WalletNotFoundError

from .base import BaseHolder, HolderError
Expand Down Expand Up @@ -288,6 +288,26 @@ async def get_credential(self, credential_id: str) -> str:

return credential_json

async def credential_revoked(self, credential_id: str, ledger: BaseLedger) -> bool:
"""
Check ledger for revocation status of credential by cred id.

Args:
credential_id: Credential id to check
ledger: ledger to open and query

"""
cred = json.loads(await self.get_credential(credential_id))
rev_reg_id = cred["rev_reg_id"]

if rev_reg_id:
cred_rev_id = int(cred["cred_rev_id"])
(rev_reg_delta, _) = await ledger.get_revoc_reg_delta(rev_reg_id)

return cred_rev_id in rev_reg_delta["value"].get("revoked", [])
else:
return False

async def delete_credential(self, credential_id: str):
"""
Remove a credential stored in the wallet.
Expand Down
52 changes: 51 additions & 1 deletion aries_cloudagent/holder/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from aiohttp_apispec import docs, match_info_schema, querystring_schema, response_schema
from marshmallow import fields

from .base import BaseHolder, HolderError
from ..ledger.base import BaseLedger
from ..ledger.error import LedgerError
from ..messaging.models.openapi import OpenAPISchema
from ..messaging.valid import (
INDY_CRED_DEF_ID,
Expand All @@ -19,6 +20,7 @@
UUIDFour,
)
from ..wallet.error import WalletNotFoundError
from .base import BaseHolder, HolderError


class AttributeMimeTypesResultSchema(OpenAPISchema):
Expand Down Expand Up @@ -80,6 +82,12 @@ class CredIdMatchInfoSchema(OpenAPISchema):
)


class CredRevokedResultSchema(OpenAPISchema):
"""Result schema for credential revoked request."""

revoked = fields.Bool(description="Whether credential is revoked on the ledger")


@docs(tags=["credentials"], summary="Fetch a credential from wallet by id")
@match_info_schema(CredIdMatchInfoSchema())
@response_schema(CredBriefSchema(), 200)
Expand Down Expand Up @@ -108,6 +116,43 @@ async def credentials_get(request: web.BaseRequest):
return web.json_response(credential_json)


@docs(tags=["credentials"], summary="Query credential revocation status by id")
@match_info_schema(CredIdMatchInfoSchema())
@response_schema(CredRevokedResultSchema(), 200)
async def credentials_revoked(request: web.BaseRequest):
"""
Request handler for querying revocation status of credential.

Args:
request: aiohttp request object

Returns:
The credential response

"""
context = request.app["request_context"]

credential_id = request.match_info["credential_id"]

ledger: BaseLedger = await context.inject(BaseLedger, required=False)
if not ledger:
reason = "No ledger available"
if not context.settings.get_value("wallet.type"):
reason += ": missing wallet-type?"
raise web.HTTPForbidden(reason=reason)

async with ledger:
try:
holder: BaseHolder = await context.inject(BaseHolder)
revoked = await holder.credential_revoked(credential_id, ledger)
except WalletNotFoundError as err:
raise web.HTTPNotFound(reason=err.roll_up) from err
except LedgerError as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err

return web.json_response({"revoked": revoked})


@docs(tags=["credentials"], summary="Get attribute MIME types from wallet")
@match_info_schema(CredIdMatchInfoSchema())
@response_schema(AttributeMimeTypesResultSchema(), 200)
Expand Down Expand Up @@ -200,6 +245,11 @@ async def register(app: web.Application):
app.add_routes(
[
web.get("/credential/{credential_id}", credentials_get, allow_head=False),
web.get(
"/credential/revoked/{credential_id}",
credentials_revoked,
allow_head=False,
),
web.get(
"/credential/mime-types/{credential_id}",
credentials_attr_mime_types_get,
Expand Down
Loading