Skip to content

Commit

Permalink
feat: add credential endpoint with ability to return only raw data
Browse files Browse the repository at this point in the history
Signed-off-by: Akiff Manji <akiff.manji@quartech.com>
  • Loading branch information
amanji committed Sep 21, 2024
1 parent 49510ea commit 671731c
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 11 deletions.
16 changes: 14 additions & 2 deletions server/vcr-server/api/v4/serializers/rest/credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from api.v2.models.Attribute import Attribute
from api.v2.models.Credential import Credential
from api.v2.models.CredentialType import CredentialType
from api.v2.models.Issuer import Issuer
from api.v2.models.Schema import Schema

from api.v2.serializers.rest import CredentialNameSerializer, IssuerSerializer
Expand All @@ -20,6 +19,8 @@ class Meta:

class CredentialAttributeSerializer(AttributeSerializer):
class Meta(AttributeSerializer.Meta):
ref_name = "V4CredentialAttributeSerializer"

fields = (
"id",
"type",
Expand All @@ -43,9 +44,10 @@ class Meta:
"processor_config",
"highlighted_attributes",
"credential_title",
"issuer"
"issuer",
)


class CredentialTypeExtendedSerializer(ModelSerializer):
issuer = IssuerSerializer()
has_logo = BooleanField(source="get_has_logo", read_only=True)
Expand Down Expand Up @@ -110,3 +112,13 @@ class Meta:

class RestSerializer(CredentialSerializer):
credential_type = CredentialTypeExtendedSerializer()


class RawCredentialSerializer(ModelSerializer):
class Meta:
model = Credential
fields = ("raw_data",)
read_only_fields = fields

def to_representation(self, instance):
return instance.raw_data or {}
56 changes: 56 additions & 0 deletions server/vcr-server/api/v4/tests/test_rest_view_credential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from django.urls import reverse
from rest_framework.test import APITestCase

from api.v2.models import Credential, CredentialType, Issuer, Schema, Topic


class TestRestViewCredential(APITestCase):
def setUp(self) -> None:
"""Add a test credential type and credential to the database."""

self.test_credential_type = CredentialType(
schema=Schema.objects.create(
name="test_schema", version="0.0.1", origin_did="a:did:123"
),
issuer=Issuer.objects.create(
did="a:did:123",
name="Test Issuer 1",
abbreviation="TI-1",
email="",
url="",
),
)
self.test_credential_type.save()

self.test_topic = Topic(source_id="test_source_id", type="test_topic_type")
self.test_topic.save()

self.test_credential = Credential(
credential_id="test_credential",
credential_type=self.test_credential_type,
topic=self.test_topic,
)
self.test_credential.save()

def test_get_credential(self):
"""Test that the API returns the correct credential data."""
response = self.client.get("/api/v4/credential/test_credential")

self.assertEqual(response.status_code, 200)
self.assertEqual(response.data.get("credential_id"), "test_credential")
self.assertEqual(
response.data.get("credential_type"), self.test_credential_type.id
)
self.assertIn("attributes", response.data)
self.assertIn("names", response.data)

def test_get_credential_raw(self):
"""Test that the API returns the correct credential data when raw_data is requested"""
response = self.client.get("/api/v4/credential/test_credential?raw_data=true")

self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, {})
self.assertNotIn("credential_id", response.data)
self.assertNotIn("credential_type", response.data)
self.assertNotIn("attributes", response.data)
self.assertNotIn("names", response.data)
17 changes: 8 additions & 9 deletions server/vcr-server/api/v4/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# DEPRECATED: this should not be used in new code and will be removed imminently
autocomplete as search_autocomplete,
)
from api.v4.views.rest import credential_type, issuer, topic, schema
from api.v4.views.rest import credential, credential_type, issuer, topic, schema
from api.v4.views.misc.contact import send_contact
from api.v4.views.misc.feedback import send_feedback

Expand All @@ -35,18 +35,18 @@

router = SimpleRouter(trailing_slash=False)

router.register(r"credential-type",
credential_type.RestView, "Credential Type")
router.register(r"credential", credential.RestView, "Credential")
router.register(r"credential-type", credential_type.RestView, "Credential Type")
router.register(r"issuer", issuer.RestView, "Issuer")
router.register(r"schema", schema.RestView, "Schema")
router.register(r"topic", topic.RestView, "Topic")
router.register(r"search/credential",
search_credential.SearchView, "Credential Search")
router.register(r"search/credential", search_credential.SearchView, "Credential Search")
router.register(r"search/topic", search_topic.SearchView, "Topic Search")
router.register(r"search/fuzzy", search_fuzzy.SearchView, "Fuzzy Search")
# DEPRECATED: this should not be used in new code and will be removed imminently
router.register(r"search/autocomplete",
search_autocomplete.SearchView, "Aggregate Autocomplete")
router.register(
r"search/autocomplete", search_autocomplete.SearchView, "Aggregate Autocomplete"
)

# Misc endpoints
miscPatterns = [
Expand All @@ -58,5 +58,4 @@
path("", schema_view.with_ui("swagger", cache_timeout=None), name="api-docs")
]

urlpatterns = format_suffix_patterns(
router.urls) + miscPatterns + swaggerPatterns
urlpatterns = format_suffix_patterns(router.urls) + miscPatterns + swaggerPatterns
40 changes: 40 additions & 0 deletions server/vcr-server/api/v4/views/rest/credential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django.http import Http404
from django.shortcuts import get_object_or_404
from rest_framework import mixins
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from api.v2.models.Credential import Credential

from api.v4.serializers.rest.credential import CredentialSerializer, RawCredentialSerializer

class RestView(mixins.RetrieveModelMixin, GenericViewSet):
serializer_class = CredentialSerializer
queryset = Credential.objects.all()
lookup_field = "credential_id"

def get_serializer_class(self):
if self.request.query_params.get("raw_data", None) == "true":
return RawCredentialSerializer
return CredentialSerializer

def get_object(self):
credential_id = self.kwargs.get("credential_id", None)

if not credential_id:
raise Http404()

filter = {"credential_id": credential_id}
# If the input parameter is a pure int, treat as an internal database pk
try:
filter = {"pk": int(credential_id)}
except (ValueError, TypeError):
pass

queryset = self.filter_queryset(self.get_queryset())
obj = get_object_or_404(queryset, **filter)

# May raise a permission denied
self.check_object_permissions(self.request, obj)

return obj

0 comments on commit 671731c

Please sign in to comment.