From e4299dac262c907dd07491a01580c7bf24ea1c07 Mon Sep 17 00:00:00 2001 From: Jared Snider Date: Tue, 20 May 2025 17:11:00 -0400 Subject: [PATCH] PM-20532 - WIP on Send Token services. --- .../abstractions/send-token-api.service.ts | 7 +++++ .../abstractions/send-token.service.ts | 30 ++++++++++++++++--- .../services/send-token-api.service.ts | 3 +- .../services/send-token.service.ts | 29 ++++++++++++++++++ .../src/platform/state/state-definitions.ts | 2 ++ 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/libs/common/src/auth/send-access/abstractions/send-token-api.service.ts b/libs/common/src/auth/send-access/abstractions/send-token-api.service.ts index 4adbb3500b3..77cfdc5e167 100644 --- a/libs/common/src/auth/send-access/abstractions/send-token-api.service.ts +++ b/libs/common/src/auth/send-access/abstractions/send-token-api.service.ts @@ -6,5 +6,12 @@ import { SendAccessTokenRequest } from "../../models/request/identity-token/send */ export abstract class SendTokenApiService { // TODO: add return type for requestSendAccessToken and error scenarios + // Returns a valid send access token or several error types (use discriminated union): + // RequiresPassword + // RequiresEmailOtp + // InvalidCredentials + // ExpiredRequiredPassword // these will live at higher level in SendTokenService + // ExpiredRequiredEmailOtp + abstract requestSendAccessToken: (request: SendAccessTokenRequest) => Promise; } diff --git a/libs/common/src/auth/send-access/abstractions/send-token.service.ts b/libs/common/src/auth/send-access/abstractions/send-token.service.ts index 1e1b74c8bef..83b7f04d432 100644 --- a/libs/common/src/auth/send-access/abstractions/send-token.service.ts +++ b/libs/common/src/auth/send-access/abstractions/send-token.service.ts @@ -1,3 +1,12 @@ +export interface SendPasswordCredentials { + password: string; +} +export interface SendEmailOtpCredentials { + email: string; + otp: string; +} +export type SendAccessCredentials = SendPasswordCredentials | SendEmailOtpCredentials; + export abstract class SendTokenService { // TODO: talk with Tools about what expected behavior is for expired access tokens. // Do we implement any local TTL or do we just rely on the server to return a 401 and then we handle that in the api service? @@ -6,9 +15,22 @@ export abstract class SendTokenService { // All SendAccessTokens are scoped to a specific send id so all getting and setting should accept a send id. // TODO: should this abstraction have separate methods for requesting an access token from the server - // and for getting the access token from storage? Or should it just be one method that does both? + // and for getting the access token from storage? + // One method that does both is ideal. + // We will need to extend inputs to include the send id and the credentials. + // We will also need to store the send access token with it's expires_in value so we know if it's expired + // so that we don't hand out an expired token to make a request. - // Get the access token for a specific send id. - abstract getSendAccessToken: (sendId: string) => Promise; - abstract setSendAccessToken: (sendId: string, token: string) => Promise; + // Returned error types should be discriminated union with a type that can be conditioned off for logic. + + // Attempts to get a send access token for a specific send id. + // If the token is not found or is expired, it will request a new token from the server. + // As send access tokens can be protected by different credentials, the credentials must be passed in for those sends. + abstract getSendAccessToken: ( + sendId: string, + sendCredentials?: SendAccessCredentials, + ) => Promise; + + // Private internal logic for getting the access token. + // abstract setSendAccessToken: (sendId: string, token: string) => Promise; } diff --git a/libs/common/src/auth/send-access/services/send-token-api.service.ts b/libs/common/src/auth/send-access/services/send-token-api.service.ts index a8db308b6c2..63dbf9aba41 100644 --- a/libs/common/src/auth/send-access/services/send-token-api.service.ts +++ b/libs/common/src/auth/send-access/services/send-token-api.service.ts @@ -11,7 +11,6 @@ export class SendTokenApiService implements SendTokenApiServiceAbstraction { private apiService: ApiService, ) {} - // TODO: talk with Justin about needing to use httpOperations or not. async requestSendAccessToken(request: SendAccessTokenRequest): Promise { const payload = request.toIdentityTokenPayload(); @@ -34,6 +33,6 @@ export class SendTokenApiService implements SendTokenApiServiceAbstraction { await this.apiService.fetch(req); - // TODO: add processing. + // TODO: add result processing } } diff --git a/libs/common/src/auth/send-access/services/send-token.service.ts b/libs/common/src/auth/send-access/services/send-token.service.ts index e69de29bb2d..0d2e94f9801 100644 --- a/libs/common/src/auth/send-access/services/send-token.service.ts +++ b/libs/common/src/auth/send-access/services/send-token.service.ts @@ -0,0 +1,29 @@ +import { GlobalStateProvider, KeyDefinition, SEND_AUTH_DISK } from "../../../platform/state"; +import { + SendAccessCredentials, + SendTokenService as SendTokenServiceAbstraction, +} from "../abstractions/send-token.service"; + +import { SendTokenApiService } from "./send-token-api.service"; + +// Will need to map sendId to access token +// TODO: will need to build a better type for access token where it contains +// the expires in and the token itself. +export const SEND_ACCESS_TOKEN_DICT = KeyDefinition.record( + SEND_AUTH_DISK, + "accessTokenDict", + { + deserializer: (accessTokenDict) => accessTokenDict, + }, +); + +export class SendTokenService implements SendTokenServiceAbstraction { + constructor( + private globalStateProvider: GlobalStateProvider, + private sendTokenApiService: SendTokenApiService, + ) {} + + async getSendAccessToken(sendId: string, sendCredentials?: SendAccessCredentials): Promise { + // TODO: first + } +} diff --git a/libs/common/src/platform/state/state-definitions.ts b/libs/common/src/platform/state/state-definitions.ts index d7a5b4795e5..fdfd429284c 100644 --- a/libs/common/src/platform/state/state-definitions.ts +++ b/libs/common/src/platform/state/state-definitions.ts @@ -76,6 +76,8 @@ export const TOKEN_DISK = new StateDefinition("token", "disk"); export const TOKEN_DISK_LOCAL = new StateDefinition("tokenDiskLocal", "disk", { web: "disk-local", }); +export const SEND_AUTH_DISK = new StateDefinition("sendAuth", "disk"); + export const TOKEN_MEMORY = new StateDefinition("token", "memory"); export const TWO_FACTOR_MEMORY = new StateDefinition("twoFactor", "memory"); export const USER_DECRYPTION_OPTIONS_DISK = new StateDefinition("userDecryptionOptions", "disk");