From d2bf588d69ec287325205463879505c54e7dee78 Mon Sep 17 00:00:00 2001 From: Lars Mitsem Selbekk Date: Wed, 15 May 2024 12:55:30 +0200 Subject: [PATCH] feat: digital signatures (#228) * refactor: move editable-text to proper folder * feat: add digital signatures * v0.19.14 * fix: export SignatureService * v0.19.15 * fix: export SignatureService from public_api * v0.19.16 * feat: add signature helpers * v0.19.17 * feat(signature): take now-timestamp * v0.19.18 * refactor(signature): don't require UserDetailService * v0.19.19 * feat(branch): add upper secondary check method * 0.19.20 * Revert "feat(branch): add upper secondary check method" This reverts commit fbf473f56682697df89ffd0720fbd4c2fa695428. * chore: prettier * build(deps): bump prettier * 0.19.21 --- package.json | 4 +- public_api.ts | 3 +- src/app/bl-connect/bl-config.ts | 1 + src/app/bl-connect/bl-connect.module.ts | 4 +- .../editable-text/editable-text.service.ts | 4 +- .../signature/signature.service.ts | 59 +++++++++++++++++++ .../user-detail/user-detail.service.ts | 16 +++-- yarn.lock | 8 +-- 8 files changed, 84 insertions(+), 15 deletions(-) rename src/app/{ => document-services}/editable-text/editable-text.service.ts (87%) create mode 100644 src/app/document-services/signature/signature.service.ts diff --git a/package.json b/package.json index 73c72f4..5b50f55 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@boklisten/bl-connect", - "version": "0.19.13", + "version": "0.19.21", "license": "MIT", "scripts": { "dev": "yarn serve", @@ -34,7 +34,7 @@ "@angular/platform-browser": "^11.1.2", "@angular/platform-browser-dynamic": "^11.1.2", "@auth0/angular-jwt": "^5.0.2", - "@boklisten/bl-model": "^0.25.30", + "@boklisten/bl-model": "^0.25.37", "@types/jasmine": "~3.6.3", "@types/jasminewd2": "~2.0.8", "@types/node": "^14.14.25", diff --git a/public_api.ts b/public_api.ts index 1403c12..ff3401f 100644 --- a/public_api.ts +++ b/public_api.ts @@ -32,4 +32,5 @@ export * from "./src/app/document-services/match/match.service"; export * from "./src/app/document-services/unique-item/unique-item.service"; -export * from "./src/app/editable-text/editable-text.service"; +export * from "./src/app/document-services/editable-text/editable-text.service"; +export * from "./src/app/document-services/signature/signature.service"; diff --git a/src/app/bl-connect/bl-config.ts b/src/app/bl-connect/bl-config.ts index e157d44..51f6779 100644 --- a/src/app/bl-connect/bl-config.ts +++ b/src/app/bl-connect/bl-config.ts @@ -72,6 +72,7 @@ export const BL_CONFIG = { booking: "bookings", uniqueItem: "uniqueitems", editableTexts: "editabletexts", + signature: "signatures", }, editableTextIds: { newsBanner: "65a7f68e81488330ddcd6fd3", diff --git a/src/app/bl-connect/bl-connect.module.ts b/src/app/bl-connect/bl-connect.module.ts index 1a2f92f..e679bbc 100644 --- a/src/app/bl-connect/bl-connect.module.ts +++ b/src/app/bl-connect/bl-connect.module.ts @@ -6,7 +6,7 @@ import { BranchService } from "../document-services/branch/branch.service"; import { OpeningHourService } from "../document-services/opening-hour/opening-hour.service"; import { ApiErrorService } from "../api-error/api-error.service"; import { UserDetailService } from "../document-services/user-detail/user-detail.service"; -import { EditableTextService } from "../editable-text/editable-text.service"; +import { EditableTextService } from "../document-services/editable-text/editable-text.service"; import { TokenService } from "../token/token.service"; import { StorageService } from "../storage/storage.service"; import { LoginService } from "../login/login.service"; @@ -35,6 +35,7 @@ import { CompanyService } from "../document-services/company/company.service"; import { MatchService } from "../document-services/match/match.service"; import { BookingService } from "../document-services/booking/booking.service"; import { UniqueItemService } from "../document-services/unique-item/unique-item.service"; +import { SignatureService } from "../document-services/signature/signature.service"; export function tokenGetter() { return localStorage.getItem(BL_CONFIG.token.accessToken); @@ -95,6 +96,7 @@ export function tokenGetter() { BookingService, UniqueItemService, EditableTextService, + SignatureService, ], }) export class BlConnectModule {} diff --git a/src/app/editable-text/editable-text.service.ts b/src/app/document-services/editable-text/editable-text.service.ts similarity index 87% rename from src/app/editable-text/editable-text.service.ts rename to src/app/document-services/editable-text/editable-text.service.ts index 8ef368c..bcd0320 100644 --- a/src/app/editable-text/editable-text.service.ts +++ b/src/app/document-services/editable-text/editable-text.service.ts @@ -1,7 +1,7 @@ import { Injectable } from "@angular/core"; import { BlApiError, EditableText } from "@boklisten/bl-model"; -import { ApiService } from "../api/api.service"; -import { BL_CONFIG } from "../bl-connect/bl-config"; +import { ApiService } from "../../api/api.service"; +import { BL_CONFIG } from "../../bl-connect/bl-config"; @Injectable() export class EditableTextService { diff --git a/src/app/document-services/signature/signature.service.ts b/src/app/document-services/signature/signature.service.ts new file mode 100644 index 0000000..1b3b9c9 --- /dev/null +++ b/src/app/document-services/signature/signature.service.ts @@ -0,0 +1,59 @@ +import { Injectable } from "@angular/core"; +import { + SerializedSignature, + SignatureMetadata, + UserDetail, +} from "@boklisten/bl-model"; +import { UserDetailService } from "../../document-services/user-detail/user-detail.service"; +import { BL_CONFIG } from "../../bl-connect/bl-config"; +import { BlDocumentService } from "../../document/bl-document.service"; +import { CachedDocumentService } from "../../document/cached-document.service"; + +@Injectable() +export class SignatureService extends BlDocumentService { + constructor( + private cachedDocumentService: CachedDocumentService, + private _userDetailService: UserDetailService + ) { + super(cachedDocumentService); + this.setCollection(BL_CONFIG.collection.signature); + } + + public base64EncodeImage(signatureImage: Buffer): string { + return signatureImage.toString("base64"); + } + + public async hasValidSignature( + userDetail: UserDetail, + now: Date + ): Promise { + if (userDetail.signatures.length === 0) { + return false; + } + + const latestSignature = await this.getById(userDetail.signatures[0]); + if (this.isSignatureExpired(latestSignature, now)) { + return false; + } + + return ( + this._userDetailService.isUnderage(userDetail, now) === + latestSignature.signedByGuardian + ); + } + + public isSignatureExpired( + signature: SignatureMetadata, + now: Date + ): boolean { + if (!signature.creationTime) { + return true; + } + const oldestAllowedSignatureTime = new Date( + now.getFullYear(), + now.getMonth() - SignatureMetadata.NUM_MONTHS_VALID, + now.getDate() + ); + return signature.creationTime < oldestAllowedSignatureTime; + } +} diff --git a/src/app/document-services/user-detail/user-detail.service.ts b/src/app/document-services/user-detail/user-detail.service.ts index de6d852..1c3d366 100644 --- a/src/app/document-services/user-detail/user-detail.service.ts +++ b/src/app/document-services/user-detail/user-detail.service.ts @@ -1,12 +1,8 @@ import { Injectable } from "@angular/core"; import { BlApiError, UserDetail } from "@boklisten/bl-model"; -import { ApiService } from "../../api/api.service"; import { BL_CONFIG } from "../../bl-connect/bl-config"; -import { - CachedDocumentService, - CachedDocumentServiceOptions, -} from "../../document/cached-document.service"; import { BlDocumentService } from "../../document/bl-document.service"; +import { CachedDocumentService } from "../../document/cached-document.service"; @Injectable() export class UserDetailService extends BlDocumentService { @@ -32,4 +28,14 @@ export class UserDetailService extends BlDocumentService { throw blApiError; }); } + + public isUnderage(userDetail: UserDetail, now: Date): boolean { + const latestAdultBirthDate = new Date( + now.getFullYear() - 18, + now.getMonth(), + now.getDate() + ); + + return userDetail.dob > latestAdultBirthDate; + } } diff --git a/yarn.lock b/yarn.lock index e6a150c..500dbdf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1214,10 +1214,10 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@boklisten/bl-model@^0.25.30": - version "0.25.30" - resolved "https://registry.yarnpkg.com/@boklisten/bl-model/-/bl-model-0.25.30.tgz#8989f5fba19d8aa5486d8488d5be7e12f3778083" - integrity sha512-rh250euu/zLldrFNxB9rfTATQ0e3eS6wAFiMJGQ2AUSJTkOXUe9+ozm1/Ft6xkx7Pn7LWsmnLHzuadHLYA/g0A== +"@boklisten/bl-model@^0.25.37": + version "0.25.37" + resolved "https://registry.yarnpkg.com/@boklisten/bl-model/-/bl-model-0.25.37.tgz#53cf9ea5b38bc953ada24b3d1c353707d83496fc" + integrity sha512-+KgdcMqD390D9HCQ/3x5uRpSJdSdbj1s/1mjEbmo6oy48IDwnS9qJbzUFXZ4V0G+4QmrG+cE6AJ3MCC8UNiiBA== dependencies: typescript "^5.2.2"