Skip to content

Commit

Permalink
chore: add dummy creds
Browse files Browse the repository at this point in the history
  • Loading branch information
coodos committed Nov 4, 2024
1 parent 86552eb commit 7cfe4b4
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 32 deletions.
42 changes: 41 additions & 1 deletion apps/client/src/routes/(private)/credentials/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
let selectedCredential: Record<string, any>;
let showAssignCredModal = false;
let showShareCredModal = false;
let obtainingDummy = false;
let qr: string;
let credentials: Record<string, any>[] = [];
let credentialAssignmentsMap: Record<string, string | null> = {};
Expand Down Expand Up @@ -80,14 +81,53 @@
credentials = data;
}
async function obtainDemoCredentials() {
const {
data: { uri }
} = await apiClient.get('/oid4vc/dummy');
qr = uri;
obtainingDummy = true;
const ws = createWebsocket();
ws.onmessage = async (event) => {
const data = JSON.parse(event.data);
if (data.proceed) {
fetchCredentials();
}
};
}
onMount(() => {
fetchCredentials();
});
</script>

<Modal bind:open={showShareCredModal} title="Add More Credentials">
{#if qr}
<Qr data={qr}></Qr>
{#if obtainingDummy}
<p>
Scan the QR code with an OpenID4VCI Compliant Wallet to Get Demo Credentials to have in your
CV
</p>

<Qr data={qr}></Qr>

<p>Already have credentials to share?</p>
<Button
on:click={() => {
obtainingDummy = false;
handleShareCredentials();
}}>Share Credentials</Button
>
{:else}
<p>
Scan the QR code with an OpenID4VP Compliant Wallet to Share all credentials that you want
to have in your CV
</p>
<Qr data={qr}></Qr>

<p>Don't have any credentials to share?</p>
<Button on:click={obtainDemoCredentials}>Obtain Demo Credentials</Button>
{/if}
{/if}
</Modal>

Expand Down
64 changes: 33 additions & 31 deletions apps/client/src/routes/(public)/verify/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,35 +45,37 @@
});
</script>

<div class="w-full">
<Label class="text-font-bold text-md mb-1">Upload Document to be signed</Label>
{#if !isPdfUploading}
<Dropzone
on:drop={dropHandle}
on:dragover={(event) => {
event.preventDefault();
}}
on:change={handleChange}
bind:files={pdfFile}
class="bg-gray-200"
accept={'.pdf'}
>
<UploadOutline size="xl"></UploadOutline>
{#if !pdfFile}
<p class="mb-2 text-sm text-gray-500">
<span class="font-semibold">Click to upload</span> or drag and drop
</p>
<p class="text-xs text-gray-500">PDF Format Only (File Size: 30MB)</p>
{:else}
<p>{fileName}</p>
<Button
on:click={() => {
pdfFile = undefined;
}}>Remove</Button
>
{/if}
</Dropzone>
{:else}
<p class="bg-gray-200 p-2 rounded-lg border border-gray-300">Pdf is uploading...</p>
{/if}
<div class="w-full h-screen flex flex-col justify-center items-center">
<div class="w-[800px] ml-50">
<Label class="text-font-bold text-md mb-1">Upload VCV to be verified</Label>
{#if !isPdfUploading}
<Dropzone
on:drop={dropHandle}
on:dragover={(event) => {
event.preventDefault();
}}
on:change={handleChange}
bind:files={pdfFile}
class="bg-gray-200"
accept={'.pdf'}
>
<UploadOutline size="xl"></UploadOutline>
{#if !pdfFile}
<p class="mb-2 text-sm text-gray-500">
<span class="font-semibold">Click to upload</span> or drag and drop
</p>
<p class="text-xs text-gray-500">PDF Format Only (File Size: 30MB)</p>
{:else}
<p>{fileName}</p>
<Button
on:click={() => {
pdfFile = undefined;
}}>Remove</Button
>
{/if}
</Dropzone>
{:else}
<p class="bg-gray-200 p-2 rounded-lg border border-gray-300">Pdf is uploading...</p>
{/if}
</div>
</div>
123 changes: 123 additions & 0 deletions apps/server/src/modules/oid4vc/oid4vc.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { CredentialsService } from '../credential/credential.service';
import { ExperiencesService } from '../cv/experience.service';
import { getResolver, validateJsonWebToken } from 'src/utils';
import { Request } from 'express';
import { v4 as uuid } from 'uuid';

const presentationDefinition = {
id: 'all-credentials-request',
Expand Down Expand Up @@ -137,6 +138,46 @@ export class Oid4vcController {
return response;
}

@Serialize(CredOfferDTO)
@ApiOkResponse({ type: CredOfferDTO })
@ApiNotFoundResponse({ type: NotFoundException })
@IsAuthenticated()
@Get('/dummy')
async createDummyCredentialsOffer(
@UserSession() session: Session,
@CurrentUser() user: User,
) {
const { issuer } = await this.identityService.getAdminDid();

const id = session.id;
const demoCredentials = ['University Degree', 'First Aid Training'];
const offer = await issuer.createCredentialOffer(
{
credentials: demoCredentials,
requestBy: 'reference',
credentialOfferUri: new URL(
`/api/oid4vc/offers/${id}`,
process.env.PUBLIC_BASE_URI,
).toString(),
pinRequired: false,
},
{
state: `${user.id}::${session.id}`,
},
);
const offerExists = await this.credOfferService.findById(id);
if (!offerExists) {
await this.credOfferService
.create({ id, offer: offer.offer })
.catch(() => null);
} else {
await this.credOfferService.findByIdAndUpdate(id, {
offer: offer.offer,
});
}
return offer;
}

@Serialize(CredOfferDTO)
@ApiOkResponse({ type: CredOfferDTO })
@ApiNotFoundResponse({ type: NotFoundException })
Expand Down Expand Up @@ -250,10 +291,92 @@ export class Oid4vcController {
const response = await identity.issuer.createSendCredentialsResponse({
credentials: [verifiableCredential.cred],
});

await this.experienceService.findByIdAndDelete(experience.id);
return response;
}

@Post('/credentials')
async sendBatchCredentials(@Req() req: Request) {
const didJWT = await import('did-jwt');
const token = req.headers.authorization?.split('Bearer ')[1];
const resolver = await getResolver();
if (!token) throw new UnauthorizedException('Bad Token');
const { payload } = await didJWT.verifyJWT(token, {
policies: { aud: false },
resolver,
});
const { state } = payload;
console.log(req.body);

const identity = await this.identityService.getAdminDid();

const did = await identity.issuer.validateCredentialsResponse({
token,
proof: req.body.credential_requests[0].proof.jwt,
});
const id = uuid();

const universityDegree = await identity.account.credentials.create({
recipientDid: did,
body: {
'Issued By': 'Example University',
GPA: 5,
'Student ID': 'S32404333',
Course: 'Masters in Cryptography',
'Course Completed': '12 Sept 2023',
enrichment: {
logo_uri: new URL(
'/images/university.webp',
process.env.PUBLIC_CLIENT_URI,
).toString(),
},
},
id: new URL(`/verify/${id}`, process.env.PUBLIC_CLIENT_URI).toString(),
keyIndex: 0,
type: `University Degree`,
});
const firstAidTraining = await identity.account.credentials.create({
recipientDid: did,
body: {
'Issued By': 'Health and Training Board',
'Training Completion': '02 Sept 2023',
enrichment: {
logo_uri: new URL(
'/images/first-aid.webp',
process.env.PUBLIC_CLIENT_URI,
).toString(),
},
},
id: new URL(
`/verify/${uuid()}`,
process.env.PUBLIC_CLIENT_URI,
).toString(),
keyIndex: 0,
type: `First Aid Training`,
});
const [userId, sessionId] = state.split('::');
const user = await this.usersService.findById(userId);

for (const cred of [firstAidTraining, universityDegree]) {
const decodedVc = await identity.rp.validateJwt(cred.cred);
const credential = await this.credentialsService.create({
name: decodedVc.vc.type[1] ?? decodedVc.vc.type[0],
decoded: decodedVc,
raw: cred.cred,
user: user,
type: 'experience',
});
}

const response = await identity.issuer.createSendCredentialsResponse({
credentials: [universityDegree.cred, firstAidTraining.cred],
});

wsServer.broadcast(sessionId, { proceed: true });
return response;
}

@ApiBody({ type: SiopRequestDTO })
@Post('/auth')
async verifyAuthResponse(@Body() body: Record<string, any>) {
Expand Down
18 changes: 18 additions & 0 deletions apps/server/src/modules/well-known/well-known.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ export class WellKnownController {
},
],
},
{
name: 'University Degree',
type: ['University Degree'],
display: [
{
name: 'University Degree',
},
],
},
{
name: 'First Aid Training',
type: ['First Aid Training'],
display: [
{
name: 'First Aid Training',
},
],
},
];

return issuerDid.issuer.getIssuerMetadata(supportedCreds);
Expand Down

0 comments on commit 7cfe4b4

Please sign in to comment.