All files / src/app/api/credentials route.ts

66.66% Statements 6/9
50% Branches 1/2
100% Functions 1/1
75% Lines 6/8

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70        1x                                                         3x 3x   3x 3x                                                   3x            
import { NextResponse } from "next/server";
import { runQuery } from "@/lib/neo4j";
import { requireAuth, isAuthError } from "@/lib/auth-guard";
 
export const dynamic = "force-dynamic";
 
interface Credential {
  credentialId: string;
  credentialType: string;
  subjectDid: string;
  issuerDid: string;
  status: string;
  participantRole: string | null;
  holderName: string | null;
  holderType: string | null;
  issuedAt: string;
  expiresAt: string;
  // Membership fields
  membership: string | null;
  membershipType: string | null;
  // EHDS fields
  jurisdiction: string | null;
  ehdsArticle: string | null;
  // DataProcessingPurpose fields
  purpose: string | null;
  // DataQualityLabel fields
  datasetId: string | null;
  completeness: number | null;
  conformance: number | null;
  timeliness: number | null;
}
 
export async function GET() {
  const auth = await requireAuth();
  Iif (isAuthError(auth)) return auth;
 
  try {
    const credentials = await runQuery<Credential>(
      `MATCH (vc:VerifiableCredential)
     OPTIONAL MATCH (p:Participant)-[:HOLDS_CREDENTIAL]->(vc)
     OPTIONAL MATCH (vc)-[:ATTESTS_QUALITY]->(ds:HealthDataset)
     RETURN vc.credentialId     AS credentialId,
            vc.credentialType   AS credentialType,
            vc.subjectDid       AS subjectDid,
            vc.issuerDid        AS issuerDid,
            vc.status           AS status,
            vc.participantRole  AS participantRole,
            p.name              AS holderName,
            p.participantType   AS holderType,
            toString(vc.issuedAt)  AS issuedAt,
            toString(vc.expiresAt) AS expiresAt,
            vc.membership       AS membership,
            vc.membershipType   AS membershipType,
            vc.jurisdiction     AS jurisdiction,
            vc.ehdsArticle      AS ehdsArticle,
            vc.purpose          AS purpose,
            vc.datasetId        AS datasetId,
            vc.completeness     AS completeness,
            vc.conformance      AS conformance,
            vc.timeliness       AS timeliness
     ORDER BY p.name, vc.credentialType`,
    );
 
    return NextResponse.json({ credentials });
  } catch (err) {
    console.error("GET /api/credentials error:", err);
    return NextResponse.json({ error: "Neo4j unavailable" }, { status: 502 });
  }
}