mirror of
https://github.com/bitwarden/browser
synced 2026-02-08 04:33:38 +00:00
PM-20532 - WIP on Send Token services.
This commit is contained in:
@@ -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<unknown>;
|
||||
}
|
||||
|
||||
@@ -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<string | null>;
|
||||
abstract setSendAccessToken: (sendId: string, token: string) => Promise<void>;
|
||||
// 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<void>;
|
||||
|
||||
// Private internal logic for getting the access token.
|
||||
// abstract setSendAccessToken: (sendId: string, token: string) => Promise<void>;
|
||||
}
|
||||
|
||||
@@ -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<void> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string, string>(
|
||||
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<void> {
|
||||
// TODO: first
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user