Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: add history entries
Browse files Browse the repository at this point in the history
Signed-off-by: Mirko Mollik <mirko.mollik@fit.fraunhofer.de>
cre8 committed Apr 21, 2024
1 parent c3935f3 commit 88ec75f
Showing 51 changed files with 741 additions and 124 deletions.
14 changes: 13 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
{
"files.eol": "\n",
"cSpell.words": ["keycloak", "sphereon"]
"cSpell.words": ["keycloak", "sphereon"],
"sqltools.connections": [
{
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"database": "nestjs",
"username": "csalkfenvcda",
"password": "hwafkjhea",
"name": "Wallet-DB"
}
]
}
2 changes: 2 additions & 0 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import { CredentialsModule } from './credentials/credentials.module';
import { DB_VALIDATION_SCHEMA, DbModule } from './db/db.module';
import { KeysModule } from './keys/keys.module';
import { Oid4vcModule } from './oid4vc/oid4vc.module';
import { HistoryModule } from './history/history.module';

@Module({
imports: [
@@ -20,6 +21,7 @@ import { Oid4vcModule } from './oid4vc/oid4vc.module';
KeysModule,
CredentialsModule,
Oid4vcModule,
HistoryModule,
],
})
export class AppModule {}
50 changes: 50 additions & 0 deletions apps/backend/src/history/entities/history.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ApiProperty } from '@nestjs/swagger';
import { Column, CreateDateColumn, Entity, PrimaryColumn } from 'typeorm';

type HistoryStatus = 'pending' | 'accepted' | 'declined';

@Entity()
export class History {
/**
* Unique ID of the history entry
*/
@PrimaryColumn({ primary: true })
id: string;

/**
* The user that owns the key
*/
@Column({ primary: true })
user: string;

/**
* Values
*/
@Column()
value: string;

/**
* Relying party
*/
@Column()
relyingParty: string;

/**
*
*/
@Column()
relyingPartyLogo: string;

/**
* Status of the history entry
*/
@ApiProperty({ type: 'string', enum: ['pending', 'accepted', 'declined'] })
@Column()
status: HistoryStatus;

/**
* Date of creation
*/
@CreateDateColumn()
created_at: Date;
}
18 changes: 18 additions & 0 deletions apps/backend/src/history/history.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { HistoryController } from './history.controller';

describe('HistoryController', () => {
let controller: HistoryController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [HistoryController],
}).compile();

controller = module.get<HistoryController>(HistoryController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
25 changes: 25 additions & 0 deletions apps/backend/src/history/history.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { ApiOAuth2, ApiOperation, ApiTags } from '@nestjs/swagger';
import { AuthGuard, AuthenticatedUser } from 'nest-keycloak-connect';
import { HistoryService } from './history.service';
import { KeycloakUser } from 'src/auth/user';

@UseGuards(AuthGuard)
@ApiOAuth2([])
@ApiTags('history')
@Controller('history')
export class HistoryController {
constructor(private historyService: HistoryService) {}

@ApiOperation({ summary: 'get all elements' })
@Get()
all(@AuthenticatedUser() user: KeycloakUser) {
return this.historyService.all(user.sub);
}

@ApiOperation({ summary: 'get one element' })
@Get(':id')
getOne(@AuthenticatedUser() user: KeycloakUser, @Param('id') id: string) {
return this.historyService.getOne(id, user.sub);
}
}
13 changes: 13 additions & 0 deletions apps/backend/src/history/history.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { HistoryController } from './history.controller';
import { HistoryService } from './history.service';
import { History } from './entities/history.entity';

@Module({
imports: [TypeOrmModule.forFeature([History])],
controllers: [HistoryController],
providers: [HistoryService],
exports: [HistoryService],
})
export class HistoryModule {}
18 changes: 18 additions & 0 deletions apps/backend/src/history/history.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { HistoryService } from './history.service';

describe('HistoryService', () => {
let service: HistoryService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [HistoryService],
}).compile();

service = module.get<HistoryService>(HistoryService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
41 changes: 41 additions & 0 deletions apps/backend/src/history/history.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Injectable } from '@nestjs/common';
import { History } from './entities/history.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

@Injectable()
export class HistoryService {
constructor(
@InjectRepository(History)
private historyRepository: Repository<History>
) {}

all(user: string) {
return this.historyRepository.find({ where: { user } });
}

getOne(id: string, user: string) {
return this.historyRepository.findOne({ where: { id, user } });
}

add(
session: string,
user: string,
relyingParty: string,
logo: string,
url: string
) {
const history = new History();
history.id = session;
history.user = user;
history.relyingParty = relyingParty;
history.relyingPartyLogo = logo;
history.value = url;
history.status = 'pending';
return this.historyRepository.save(history);
}

setStatus(id: string, status: 'accepted' | 'declined') {
return this.historyRepository.update({ id }, { status });
}
}
3 changes: 2 additions & 1 deletion apps/backend/src/oid4vc/oid4vc.module.ts
Original file line number Diff line number Diff line change
@@ -6,9 +6,10 @@ import { Oid4vciController } from './oid4vci/oid4vci.controller';
import { Oid4vciService } from './oid4vci/oid4vci.service';
import { Oid4vpController } from './oid4vp/oid4vp.controller';
import { Oid4vpService } from './oid4vp/oid4vp.service';
import { HistoryModule } from 'src/history/history.module';

@Module({
imports: [HttpModule, KeysModule, CredentialsModule],
imports: [HttpModule, KeysModule, CredentialsModule, HistoryModule],
controllers: [Oid4vciController, Oid4vpController],
providers: [Oid4vciService, Oid4vpService],
})
28 changes: 17 additions & 11 deletions apps/backend/src/oid4vc/oid4vp/oid4vp.service.ts
Original file line number Diff line number Diff line change
@@ -11,13 +11,15 @@ import {
SupportedVersion,
VPTokenLocation,
type VerifiedAuthorizationRequest,
RPRegistrationMetadataPayload,
} from '@sphereon/did-auth-siop';
import { SdJwtDecodedVerifiableCredentialWithKbJwtInput } from '@sphereon/pex';
import { CredentialsService } from 'src/credentials/credentials.service';
import { KeysService } from 'src/keys/keys.service';
import { v4 as uuid } from 'uuid';
import { Oid4vpParseRepsonse } from './dto/parse-response.dto';
import { SubmissionRequest } from './dto/submission-request.dto';
import { HistoryService } from 'src/history/history.service';

interface Session {
user: string;
@@ -34,15 +36,12 @@ export class Oid4vpService {

constructor(
private credentialsService: CredentialsService,
private keysService: KeysService
private keysService: KeysService,
private historyService: HistoryService
) {
this.sdjwt = new SDJwtVcInstance({ hasher: digest });
}

process(url: string, user: string) {
throw new Error('Method not implemented.');
}

async parse(url: string, user: string): Promise<Oid4vpParseRepsonse> {
const sessionId = uuid();
const op = await this.getOp(user);
@@ -53,6 +52,13 @@ export class Oid4vpService {
await op.verifyAuthorizationRequest(
parsedAuthReqURI.requestObjectJwt as string
);
const issuer =
(
verifiedAuthReqWithJWT.authorizationRequestPayload
.client_metadata as RPRegistrationMetadataPayload
).client_name ?? verifiedAuthReqWithJWT.issuer;
const logo = verifiedAuthReqWithJWT.registrationMetadataPayload.logo_uri;
await this.historyService.add(sessionId, user, issuer, logo, url);

// get all credentials from the client, required for the presentation exchange
const credentials = (await this.credentialsService.findAll(user)).map(
@@ -113,8 +119,7 @@ export class Oid4vpService {
return {
rp: {
name: verifiedAuthReqWithJWT.registrationMetadataPayload.client_name,
logo: verifiedAuthReqWithJWT.registrationMetadataPayload
.client_logo_uri,
logo: verifiedAuthReqWithJWT.registrationMetadataPayload.logo_uri,
},
purpose: pds[0].definition.purpose,
requests,
@@ -144,7 +149,8 @@ export class Oid4vpService {
).kbJwt;
args.selectedCredentials[0];
//TODO: set the correct value for aud
const aud = 'Audience';
const aud =
session.verifiedAuthReqWithJWT.authorizationRequest.payload.client_id;
const cnf = args.presentation.decodedPayload.cnf;
const kid = this.keysService.decodeDidJWK(cnf.kid).kid as string;
const signwedKbJwt = await this.keysService.signkbJwt(
@@ -194,22 +200,22 @@ export class Oid4vpService {
const res = await session.op
.submitAuthorizationResponse(authenticationResponseWithJWT)
.catch(() => '');
console.log(res);
await this.historyService.setStatus(sessionId, 'accepted');
this.sessions.delete(sessionId);
//TODO: save that the user accepted the request and the data was sent successfully
}

/**
* Deletes the session of a user since he declined the request
* @param id
* @param user
*/
decline(id: string, user: string) {
async decline(id: string, user: string) {
//TODO: document that the user declined it
const session = this.sessions.get(id);
if (!session || session.user !== user) {
throw new ConflictException('Session not found');
}
await this.historyService.setStatus(id, 'declined');
this.sessions.delete(id);
}

5 changes: 0 additions & 5 deletions apps/holder/projects/browser-extension/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Routes } from '@angular/router';
import { CredentialsListComponent } from '../../../shared/credentials/credentials-list/credentials-list.component';
import { CredentialsShowComponent } from '../../../shared/credentials/credentials-show/credentials-show.component';
import { KeysListComponent } from '../../../shared/keys-list/keys-list.component';
import { ScannerComponent } from './scanner/scanner.component';
import { SettingsComponent } from '../../../shared/settings/settings.component';
import { authGuard } from './auth/auth.guard';
@@ -20,10 +19,6 @@ export const routes: Routes = [
path: 'scan',
component: ScannerComponent,
},
{
path: 'keys',
component: KeysListComponent,
},
{
path: 'credentials',
component: CredentialsListComponent,
6 changes: 6 additions & 0 deletions apps/holder/projects/pwa/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -14,6 +14,12 @@
>
<span class="info">credentials</span>
</div>
<div fxLayout="column" fxLayoutAlign=" center">
<a mat-icon-button routerLink="/history" routerLinkActive="active-link"
><mat-icon>history</mat-icon></a
>
<span class="info">History</span>
</div>
<div fxLayout="column" fxLayoutAlign=" center">
<a mat-icon-button routerLink="/settings" routerLinkActive="active-link"
><mat-icon>settings</mat-icon></a
15 changes: 10 additions & 5 deletions apps/holder/projects/pwa/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -2,10 +2,11 @@ import { Routes } from '@angular/router';
import { authGuard } from '../../../shared/auth/auth.guard';
import { CredentialsListComponent } from '../../../shared/credentials/credentials-list/credentials-list.component';
import { CredentialsShowComponent } from '../../../shared/credentials/credentials-show/credentials-show.component';
import { KeysListComponent } from '../../../shared/keys-list/keys-list.component';
import { SettingsComponent } from '../../../shared/settings/settings.component';
import { ScannerComponent } from './scanner/scanner.component';
import { LoginComponent } from '../../../shared/login/login.component';
import { HistoryListComponent } from '../../../shared/history/history-list/history-list.component';
import { HistoryShowComponent } from '../../../shared/history/history-show/history-show.component';

export const routes: Routes = [
{
@@ -21,10 +22,6 @@ export const routes: Routes = [
path: 'scan',
component: ScannerComponent,
},
{
path: 'keys',
component: KeysListComponent,
},
{
path: 'credentials',
component: CredentialsListComponent,
@@ -33,6 +30,14 @@ export const routes: Routes = [
path: 'credentials/:id',
component: CredentialsShowComponent,
},
{
path: 'history',
component: HistoryListComponent,
},
{
path: 'history/:id',
component: HistoryShowComponent,
},
{
path: 'settings',
component: SettingsComponent,
Binary file not shown.
Binary file modified apps/holder/projects/pwa/src/assets/icons/icon-128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/holder/projects/pwa/src/assets/icons/icon-144x144.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/holder/projects/pwa/src/assets/icons/icon-152x152.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file modified apps/holder/projects/pwa/src/assets/icons/icon-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/holder/projects/pwa/src/assets/icons/icon-72x72.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/holder/projects/pwa/src/assets/icons/icon-96x96.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 14 additions & 9 deletions apps/holder/projects/pwa/src/index.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta charset="utf-8" />
<title>Wallet</title>
<base href="/"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
<link rel="manifest" href="manifest.webmanifest">
<meta name="theme-color" content="#1976d2">
</head>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
<link rel="manifest" href="manifest.webmanifest" />
<meta name="theme-color" content="#D7E3FF" />
</head>
<body>
<app-root></app-root>
<noscript>Please enable JavaScript to continue using this application.</noscript>
</body>
<noscript
>Please enable JavaScript to continue using this application.</noscript
>
</body>
</html>
62 changes: 43 additions & 19 deletions apps/holder/projects/pwa/src/manifest.webmanifest
Original file line number Diff line number Diff line change
@@ -1,59 +1,83 @@
{
"name": "Wallet",
"short_name": "Wallet",
"theme_color": "#1976d2",
"background_color": "#fafafa",
"theme_color": "#D7E3FF",
"background_color": "#FFFFFF",
"display": "standalone",
"description": "A client to connect to a cloud wallet",
"id": "/",
"scope": "./",
"start_url": "./",
"screenshots": [
{
"src": "assets/screenshot/main.png",
"sizes": "750x1334",
"type": "image/png",
"form_factor": "narrow",
"label": "Home screen of the credentials"
},
{
"src": "assets/screenshot/main-wide.png",
"sizes": "1536x1476",
"type": "image/png",
"form_factor": "wide",
"label": "Home screen of the credentials"
}
],
"icons": [
{
"src": "assets/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable any"
"type": "image/png"
},
{
"src": "assets/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable any"
"type": "image/png"
},
{
"src": "assets/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png",
"purpose": "maskable any"
"type": "image/png"
},
{
"src": "assets/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "maskable any"
"type": "image/png"
},
{
"src": "assets/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "assets/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "assets/icons/maskable_icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable any"
"purpose": "maskable"
},
{
"src": "assets/icons/icon-192x192.png",
"sizes": "192x192",
"src": "assets/icons/maskable_icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable any"
"purpose": "maskable"
},
{
"src": "assets/icons/icon-384x384.png",
"sizes": "384x384",
"src": "assets/icons/maskable_icon-128x128.png",
"sizes": "128x128",
"type": "image/png",
"purpose": "maskable any"
"purpose": "maskable"
},
{
"src": "assets/icons/icon-512x512.png",
"src": "assets/icons/maskable_icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable any"
"purpose": "maskable"
}
]
}
2 changes: 2 additions & 0 deletions apps/holder/projects/shared/api/kms/.openapi-generator/FILES
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ README.md
api.module.ts
api/api.ts
api/credentials.service.ts
api/history.service.ts
api/keys.service.ts
api/oid4vci.service.ts
api/oid4vcp.service.ts
@@ -14,6 +15,7 @@ model/createCredentialDto.ts
model/createKey.ts
model/cred.ts
model/credential.ts
model/history.ts
model/keyResponse.ts
model/keyType.ts
model/models.ts
4 changes: 3 additions & 1 deletion apps/holder/projects/shared/api/kms/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
export * from './credentials.service';
import { CredentialsApiService } from './credentials.service';
export * from './history.service';
import { HistoryApiService } from './history.service';
export * from './keys.service';
import { KeysApiService } from './keys.service';
export * from './oid4vci.service';
import { Oid4vciApiService } from './oid4vci.service';
export * from './oid4vcp.service';
import { Oid4vcpApiService } from './oid4vcp.service';
export const APIS = [CredentialsApiService, KeysApiService, Oid4vciApiService, Oid4vcpApiService];
export const APIS = [CredentialsApiService, HistoryApiService, KeysApiService, Oid4vciApiService, Oid4vcpApiService];
232 changes: 232 additions & 0 deletions apps/holder/projects/shared/api/kms/api/history.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/**
* API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpParameterCodec, HttpContext
} from '@angular/common/http';
import { CustomHttpParameterCodec } from '../encoder';
import { Observable } from 'rxjs';

// @ts-ignore
import { History } from '../model/history';

// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';



@Injectable({
providedIn: 'root'
})
export class HistoryApiService {

protected basePath = 'http://localhost';
public defaultHeaders = new HttpHeaders();
public configuration = new Configuration();
public encoder: HttpParameterCodec;

constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string|string[], @Optional() configuration: Configuration) {
if (configuration) {
this.configuration = configuration;
}
if (typeof this.configuration.basePath !== 'string') {
if (Array.isArray(basePath) && basePath.length > 0) {
basePath = basePath[0];
}

if (typeof basePath !== 'string') {
basePath = this.basePath;
}
this.configuration.basePath = basePath;
}
this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
}


// @ts-ignore
private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
if (typeof value === "object" && value instanceof Date === false) {
httpParams = this.addToHttpParamsRecursive(httpParams, value);
} else {
httpParams = this.addToHttpParamsRecursive(httpParams, value, key);
}
return httpParams;
}

private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams {
if (value == null) {
return httpParams;
}

if (typeof value === "object") {
if (Array.isArray(value)) {
(value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
} else if (value instanceof Date) {
if (key != null) {
httpParams = httpParams.append(key, (value as Date).toISOString().substring(0, 10));
} else {
throw Error("key may not be null if value is Date");
}
} else {
Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive(
httpParams, value[k], key != null ? `${key}.${k}` : k));
}
} else if (key != null) {
httpParams = httpParams.append(key, value);
} else {
throw Error("key may not be null if value is not object or array");
}
return httpParams;
}

/**
* get all elements
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public historyControllerAll(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<Array<History>>;
public historyControllerAll(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<Array<History>>>;
public historyControllerAll(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<Array<History>>>;
public historyControllerAll(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {

let localVarHeaders = this.defaultHeaders;

let localVarCredential: string | undefined;
// authentication (oauth2) required
localVarCredential = this.configuration.lookupCredential('oauth2');
if (localVarCredential) {
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
}

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/history`;
return this.httpClient.request<Array<History>>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

/**
* get one element
* @param id
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public historyControllerGetOne(id: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<History>;
public historyControllerGetOne(id: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<History>>;
public historyControllerGetOne(id: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<History>>;
public historyControllerGetOne(id: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (id === null || id === undefined) {
throw new Error('Required parameter id was null or undefined when calling historyControllerGetOne.');
}

let localVarHeaders = this.defaultHeaders;

let localVarCredential: string | undefined;
// authentication (oauth2) required
localVarCredential = this.configuration.lookupCredential('oauth2');
if (localVarCredential) {
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
}

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/history/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}`;
return this.httpClient.request<History>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

}
50 changes: 50 additions & 0 deletions apps/holder/projects/shared/api/kms/model/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/


export interface History {
/**
* Status of the history entry
*/
status: History.StatusEnum;
/**
* Unique ID of the history entry
*/
id: string;
/**
* The user that owns the key
*/
user: string;
/**
* Values
*/
value: string;
/**
* Relying party
*/
relyingParty: string;
relyingPartyLogo: string;
/**
* Date of creation
*/
created_at: string;
}
export namespace History {
export type StatusEnum = 'pending' | 'accepted' | 'declined';
export const StatusEnum = {
pending: 'pending' as StatusEnum,
accepted: 'accepted' as StatusEnum,
declined: 'declined' as StatusEnum
};
}


1 change: 1 addition & 0 deletions apps/holder/projects/shared/api/kms/model/models.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ export * from './createCredentialDto';
export * from './createKey';
export * from './cred';
export * from './credential';
export * from './history';
export * from './keyResponse';
export * from './keyType';
export * from './oid4vciParseRepsonse';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<h3>My Credentials</h3>
<h3>My Credentials!</h3>
<div fxLayout="column" fxLayoutGap="16px">
@for (credential of credentials; track credential) {
<img
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<h3>History</h3>
<mat-nav-list>
@for (history of values; track history) {
<a mat-list-item [routerLink]="history.id">
<!-- <img matListAvatar [src]="history.relyingPartyLogo" alt="logo" /> -->
<mat-icon
matListItemIcon
[ngClass]="{
success: history.status === 'accepted',
declined: history.status === 'declined'
}"
>call_made</mat-icon
>
<h3 matListItemTitle>{{ history.relyingParty }}</h3>
<p matListItemLine>{{ history.created_at | date: 'medium' }}</p>
</a>
}
</mat-nav-list>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
:host {
padding: 16px;
display: block;
}

.success {
color: #66BB6A !important;
}

.declined {
color: #B71C1C !important;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { HistoryListComponent } from './history-list.component';

describe('HistoryListComponent', () => {
let component: HistoryListComponent;
let fixture: ComponentFixture<HistoryListComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HistoryListComponent]
})
.compileComponents();

fixture = TestBed.createComponent(HistoryListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Component, OnInit } from '@angular/core';
import { History, HistoryApiService } from '../../api/kms';
import { firstValueFrom } from 'rxjs';
import { MatListModule } from '@angular/material/list';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { MatIconModule } from '@angular/material/icon';

@Component({
selector: 'app-history-list',
standalone: true,
imports: [CommonModule, RouterModule, MatListModule, MatIconModule],
templateUrl: './history-list.component.html',
styleUrl: './history-list.component.scss',
})
export class HistoryListComponent implements OnInit {
values: History[] = [];
constructor(private historyApiService: HistoryApiService) {}

async ngOnInit(): Promise<void> {
this.values = await firstValueFrom(
this.historyApiService.historyControllerAll()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayout="row" fxLayoutGap="16px" fxLayoutAlign="start center">
<button mat-icon-button [routerLink]="'../'">
<mat-icon>arrow_back</mat-icon>
</button>
<h3>{{ element.relyingParty }}</h3>
</div>
</div>
<mat-card>
<mat-card-content>
<mat-list>
<mat-list-item>
<div matListItemTitle>Created at</div>
<div matListItemLine>{{ element.created_at | date: 'medium' }}</div>
</mat-list-item>
<mat-list-item>
<div matListItemTitle>Action</div>
<div matListItemLine>{{ element.status }}</div>
</mat-list-item>
</mat-list>
</mat-card-content>
</mat-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:host {
padding: 16px;
display: block;
max-width: 400px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { HistoryShowComponent } from './history-show.component';

describe('HistoryShowComponent', () => {
let component: HistoryShowComponent;
let fixture: ComponentFixture<HistoryShowComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HistoryShowComponent]
})
.compileComponents();

fixture = TestBed.createComponent(HistoryShowComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { History, HistoryApiService } from '../../api/kms';
import { firstValueFrom } from 'rxjs';
import { MatCardModule } from '@angular/material/card';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { FlexLayoutModule } from 'ng-flex-layout';
import { MatButtonModule } from '@angular/material/button';
import { MatListModule } from '@angular/material/list';

@Component({
selector: 'app-history-show',
standalone: true,
imports: [
CommonModule,
RouterModule,
MatIconModule,
MatCardModule,
MatButtonModule,
MatListModule,
FlexLayoutModule,
],
templateUrl: './history-show.component.html',
styleUrl: './history-show.component.scss',
})
export class HistoryShowComponent implements OnInit {
element!: History;

constructor(
private route: ActivatedRoute,
private historyApiService: HistoryApiService,
private router: Router
) {}

async ngOnInit(): Promise<void> {
const id = this.route.snapshot.paramMap.get('id');
if (!id) this.router.navigate(['/']);
this.element = await firstValueFrom(
this.historyApiService.historyControllerGetOne(id as string)
);
}
}

This file was deleted.

Empty file.
22 changes: 0 additions & 22 deletions apps/holder/projects/shared/keys-list/keys-list.component.spec.ts

This file was deleted.

37 changes: 0 additions & 37 deletions apps/holder/projects/shared/keys-list/keys-list.component.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<mat-card *ngIf="response && !auto">
<mat-card *ngIf="response && !auto && status !== 'done'">
<mat-card-header>
<img
mat-card-avatar
Original file line number Diff line number Diff line change
@@ -85,13 +85,15 @@ export class VerifyRequestComponent implements OnInit {
)
).then(() => {
this.status = 'done';
// this.router
// .navigate(['/'])
// .then(() => this.snackBar.open('Submitted', '', { duration: 3000 }))
});
}

cancel() {
async cancel() {
await firstValueFrom(
this.oid4vpApiService.oid4vpControllerDecline(
(this.response as Oid4vpParseRepsonse).sessionId
)
);
this.router.navigate(['/']);
this.snackBar.open('Cancelled', '', { duration: 3000 });
}
3 changes: 2 additions & 1 deletion apps/verifier/src/main.ts
Original file line number Diff line number Diff line change
@@ -36,7 +36,8 @@ const { privateKey, publicKey } = await getKeys();

const clientId = 'client';
const clientName = 'Verifier';
const logo_uri = '';
const logo_uri =
'https://upload.wikimedia.org/wikipedia/de/thumb/e/ee/Fraunhofer-Gesellschaft_2009_logo.svg/2560px-Fraunhofer-Gesellschaft_2009_logo.svg.png';
const did = encodeDidJWK(publicKey as JWK);
const kid = did;

0 comments on commit 88ec75f

Please sign in to comment.