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

Commit

Permalink
fix: improve pwa
Browse files Browse the repository at this point in the history
Signed-off-by: Mirko Mollik <[email protected]>
  • Loading branch information
Mirko Mollik committed Apr 27, 2024
1 parent fa8363d commit 2b4fda8
Show file tree
Hide file tree
Showing 22 changed files with 377 additions and 121 deletions.
2 changes: 1 addition & 1 deletion apps/backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Keycloak config
KEYCLOAK_AUTH_URL=https://keycloak.yanacocha.fit.fraunhofer.de
KEYCLOAK_AUTH_URL=http://localhost:8080
KEYCLOAK_REALM=wallet
KEYCLOAK_CLIENT_ID=swagger

Expand Down
6 changes: 5 additions & 1 deletion apps/backend/src/credentials/credentials.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { AuthGuard, AuthenticatedUser } from 'nest-keycloak-connect';
import { KeycloakUser } from 'src/auth/user';
import { CredentialsService } from './credentials.service';
import { CreateCredentialDto } from './dto/create-credential.dto';
import { CredentialResponse } from './dto/credential-response.dto';

@UseGuards(AuthGuard)
@ApiOAuth2([])
Expand Down Expand Up @@ -44,7 +45,10 @@ export class CredentialsController {

@ApiOperation({ summary: 'get a credential' })
@Get(':id')
findOne(@Param('id') id: string, @AuthenticatedUser() user: KeycloakUser) {
findOne(
@Param('id') id: string,
@AuthenticatedUser() user: KeycloakUser
): Promise<CredentialResponse> {
//TODO: return the parsed values so the client does not have to decode it.
return this.credentialsService.findOne(id, user.sub).catch(() => {
throw new ConflictException();
Expand Down
24 changes: 21 additions & 3 deletions apps/backend/src/credentials/credentials.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@ import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateCredentialDto } from './dto/create-credential.dto';
import { Credential } from './entities/credential.entity';
import { SDJwtVcInstance } from '@sd-jwt/sd-jwt-vc';
import { digest } from '@sd-jwt/crypto-nodejs';
import { CredentialResponse } from './dto/credential-response.dto';

@Injectable()
export class CredentialsService {
instance: SDJwtVcInstance;

constructor(
@InjectRepository(Credential)
private credentialRepository: Repository<Credential>
) {}
) {
this.instance = new SDJwtVcInstance({ hasher: digest });
}

async create(createCredentialDto: CreateCredentialDto, user: string) {
const credential = new Credential();
Expand All @@ -28,8 +35,19 @@ export class CredentialsService {
return this.credentialRepository.find({ where: { user } });
}

findOne(id: string, user: string) {
return this.credentialRepository.findOneOrFail({ where: { id, user } });
findOne(id: string, user: string): Promise<CredentialResponse> {
return this.credentialRepository
.findOneOrFail({ where: { id, user } })
.then(async (entry) => {
const sdjwtvc = await this.instance.decode(entry.value);
const claims = await sdjwtvc.getClaims<Record<string, unknown>>(digest);
entry.value = undefined;
entry.user = undefined;
return {
...entry,
credential: claims,
};
});
}

remove(id: string, user: string) {
Expand Down
5 changes: 5 additions & 0 deletions apps/backend/src/credentials/dto/credential-response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Credential } from '../entities/credential.entity';

export class CredentialResponse extends Credential {
credential: Record<string, unknown>;
}
13 changes: 13 additions & 0 deletions apps/backend/src/credentials/entities/credential.entity.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { ApiProperty } from '@nestjs/swagger';
import { CredentialSupported, MetadataDisplay } from '@sphereon/oid4vci-common';
import { Column, Entity, PrimaryColumn } from 'typeorm';

class IssuerMetadataLogo {
url: string;
alt_text: string;
}

class CredentialIssuer {
name: string;
locale: string;
logo?: IssuerMetadataLogo;
}

@Entity()
export class Credential {
/**
Expand Down Expand Up @@ -31,5 +43,6 @@ export class Credential {
* Metadata for the issuer representation
*/
@Column({ nullable: true, type: 'json' })
@ApiProperty({ type: CredentialIssuer })
issuer: MetadataDisplay;
}
4 changes: 0 additions & 4 deletions apps/holder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@
"@angular/platform-browser-dynamic": "^17.3.3",
"@angular/router": "^17.3.3",
"@angular/service-worker": "^17.3.3",
"@sd-jwt/core": "^0.6.1",
"@sd-jwt/crypto-browser": "^0.6.1",
"@sd-jwt/sd-jwt-vc": "^0.6.1",
"@sd-jwt/types": "^0.6.1",
"@sphereon/did-auth-siop": "^0.6.3",
"@sphereon/did-uni-client": "^0.6.2",
"@sphereon/oid4vci-client": "^0.10.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#reader {
width: 100vw !important;
height: 60vh !important;
// height: calc(100vh - 84px) !important;
object-fit: cover;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export class ScannerComponent implements OnInit, OnDestroy {
{
fps: 10,
qrbox: { width: 250, height: 250 },
// aspectRatio: window.innerWidth / window.innerHeight,
aspectRatio: window.innerWidth / window.innerHeight,
},
this.onScanSuccess,
// we do nothing when a scan failed
Expand Down
5 changes: 4 additions & 1 deletion apps/holder/projects/shared/api/kms/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ README.md
api.module.ts
api/api.ts
api/credentials.service.ts
api/default.service.ts
api/history.service.ts
api/keys.service.ts
api/oid4vci.service.ts
Expand All @@ -14,8 +15,10 @@ index.ts
model/createCredentialDto.ts
model/createKey.ts
model/cred.ts
model/credential.ts
model/credentialIssuer.ts
model/credentialResponse.ts
model/history.ts
model/issuerMetadataLogo.ts
model/keyResponse.ts
model/keyType.ts
model/models.ts
Expand Down
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,5 +1,7 @@
export * from './credentials.service';
import { CredentialsApiService } from './credentials.service';
export * from './default.service';
import { DefaultApiService } from './default.service';
export * from './history.service';
import { HistoryApiService } from './history.service';
export * from './keys.service';
Expand All @@ -8,4 +10,4 @@ export * from './oid4vci.service';
import { Oid4vciApiService } from './oid4vci.service';
export * from './oid4vcp.service';
import { Oid4vcpApiService } from './oid4vcp.service';
export const APIS = [CredentialsApiService, HistoryApiService, KeysApiService, Oid4vciApiService, Oid4vcpApiService];
export const APIS = [CredentialsApiService, DefaultApiService, HistoryApiService, KeysApiService, Oid4vciApiService, Oid4vcpApiService];
10 changes: 5 additions & 5 deletions apps/holder/projects/shared/api/kms/api/credentials.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Observable } from 'rxjs';
// @ts-ignore
import { CreateCredentialDto } from '../model/createCredentialDto';
// @ts-ignore
import { Credential } from '../model/credential';
import { CredentialResponse } from '../model/credentialResponse';

// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
Expand Down Expand Up @@ -245,9 +245,9 @@ export class CredentialsApiService {
* @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 credentialsControllerFindOne(id: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<Credential>;
public credentialsControllerFindOne(id: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<Credential>>;
public credentialsControllerFindOne(id: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<Credential>>;
public credentialsControllerFindOne(id: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<CredentialResponse>;
public credentialsControllerFindOne(id: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<CredentialResponse>>;
public credentialsControllerFindOne(id: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<CredentialResponse>>;
public credentialsControllerFindOne(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 credentialsControllerFindOne.');
Expand Down Expand Up @@ -297,7 +297,7 @@ export class CredentialsApiService {
}

let localVarPath = `/credentials/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}`;
return this.httpClient.request<Credential>('get', `${this.configuration.basePath}${localVarPath}`,
return this.httpClient.request<CredentialResponse>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
Expand Down
151 changes: 151 additions & 0 deletions apps/holder/projects/shared/api/kms/api/default.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**
* 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 { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';



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

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;
}

/**
* @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 appControllerHealth(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<string>;
public appControllerHealth(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<string>>;
public appControllerHealth(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<string>>;
public appControllerHealth(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {

let localVarHeaders = this.defaultHeaders;

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 = `/health`;
return this.httpClient.request<string>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

}
20 changes: 20 additions & 0 deletions apps/holder/projects/shared/api/kms/model/credentialIssuer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* 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.
*/
import { IssuerMetadataLogo } from './issuerMetadataLogo';


export interface CredentialIssuer {
name: string;
locale: string;
logo?: IssuerMetadataLogo;
}

Loading

0 comments on commit 2b4fda8

Please sign in to comment.