From 98e2c07a7a6e99def868c985b96cc2d75b1e85a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garci=CC=81a?= <dani-garcia@users.noreply.github.com> Date: Mon, 4 Dec 2023 20:12:51 +0100 Subject: [PATCH] Improve TS bindings --- .../js_webassembly/bitwarden_client/index.ts | 190 +++++++++++------- .../bitwarden_client/logging_level.ts | 7 - languages/js_webassembly/index.html | 2 +- languages/js_webassembly/index.ts | 35 ++-- 4 files changed, 135 insertions(+), 99 deletions(-) delete mode 100644 languages/js_webassembly/bitwarden_client/logging_level.ts diff --git a/languages/js_webassembly/bitwarden_client/index.ts b/languages/js_webassembly/bitwarden_client/index.ts index 3f858fd390..4a7c732745 100644 --- a/languages/js_webassembly/bitwarden_client/index.ts +++ b/languages/js_webassembly/bitwarden_client/index.ts @@ -1,71 +1,54 @@ import * as rust from "../pkg/bitwarden_wasm"; -import { LoggingLevel } from "./logging_level"; import { + AccessTokenLoginResponse, ClientSettings, Convert, - ResponseForPasswordLoginResponse, - ResponseForSecretIdentifiersResponse, - ResponseForSecretResponse, - ResponseForSecretsDeleteResponse, - ResponseForSyncResponse, - ResponseForUserAPIKeyResponse, + ProjectResponse, + ProjectsDeleteResponse, + ProjectsResponse, + SecretIdentifiersResponse, + SecretResponse, + SecretsDeleteResponse, } from "./schemas"; -export class BitwardenClient { - client: rust.BitwardenClient; +export type LogLevel = rust.LogLevel; +export const LogLevel = rust.LogLevel; - constructor(settings?: ClientSettings, logging_level?: LoggingLevel) { - const settings_json = settings == null ? null : Convert.clientSettingsToJson(settings); - this.client = new rust.BitwardenClient(settings_json, logging_level ?? LoggingLevel.Info); +function handleResponse<T>(response: { success: boolean; errorMessage?: string; data?: T }): T { + if (!response.success) { + throw new Error(response.errorMessage); } - async login(email: string, password: string): Promise<ResponseForPasswordLoginResponse> { - const response = await this.client.run_command( - Convert.commandToJson({ - passwordLogin: { - email: email, - password: password, - }, - }) - ); - - return Convert.toResponseForPasswordLoginResponse(response); - } + return response.data as T; +} - async getUserApiKey( - secret: string, - isOtp: boolean = false - ): Promise<ResponseForUserAPIKeyResponse> { - const response = await this.client.run_command( - Convert.commandToJson({ - getUserApiKey: { - masterPassword: isOtp ? null : secret, - otp: isOtp ? secret : null, - }, - }) - ); +export class BitwardenClient { + client: rust.BitwardenClient; - return Convert.toResponseForUserAPIKeyResponse(response); + constructor(settings?: ClientSettings, log_level?: rust.LogLevel) { + const settings_json = settings == null ? null : Convert.clientSettingsToJson(settings); + this.client = new rust.BitwardenClient(settings_json, log_level ?? rust.LogLevel.Info); } - - async sync( - excludeSubdomains: boolean = false - ): Promise<ResponseForSyncResponse> { + async accessTokenLogin(accessToken: string): Promise<AccessTokenLoginResponse> { const response = await this.client.run_command( Convert.commandToJson({ - sync: { - excludeSubdomains + accessTokenLogin: { + accessToken, }, - }) + }), ); - return Convert.toResponseForSyncResponse(response); + return handleResponse(Convert.toResponseForAccessTokenLoginResponse(response)); } secrets(): SecretsClient { return new SecretsClient(this.client); } + + projects(): ProjectsClient { + return new ProjectsClient(this.client); + } } export class SecretsClient { @@ -75,81 +58,142 @@ export class SecretsClient { this.client = client; } - async get( - id: string - ): Promise<ResponseForSecretResponse> { + async get(id: string): Promise<SecretResponse> { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - get: { id } + get: { id }, }, - }) + }), ); - return Convert.toResponseForSecretResponse(response); + return handleResponse(Convert.toResponseForSecretResponse(response)); } async create( key: string, + value: string, note: string, organizationId: string, - value: string, - ): Promise<ResponseForSecretResponse> { + ): Promise<SecretResponse> { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - create: { key, note, organizationId, value } + create: { key, value, note, organizationId }, }, - }) + }), ); - return Convert.toResponseForSecretResponse(response); + return handleResponse(Convert.toResponseForSecretResponse(response)); } - async list( - organizationId: string - ): Promise<ResponseForSecretIdentifiersResponse> { + async list(organizationId: string): Promise<SecretIdentifiersResponse> { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - list: { organizationId } + list: { organizationId }, }, - }) + }), ); - return Convert.toResponseForSecretIdentifiersResponse(response); + return handleResponse(Convert.toResponseForSecretIdentifiersResponse(response)); } async update( id: string, key: string, + value: string, note: string, organizationId: string, - value: string, - ): Promise<ResponseForSecretResponse> { + ): Promise<SecretResponse> { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - update: { id, key, note, organizationId, value } + update: { id, key, value, note, organizationId }, }, - }) + }), ); - return Convert.toResponseForSecretResponse(response); + return handleResponse(Convert.toResponseForSecretResponse(response)); } - async delete( - ids: string[] - ): Promise<ResponseForSecretsDeleteResponse> { + async delete(ids: string[]): Promise<SecretsDeleteResponse> { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - delete: { ids } + delete: { ids }, }, - }) + }), ); - return Convert.toResponseForSecretsDeleteResponse(response); + return handleResponse(Convert.toResponseForSecretsDeleteResponse(response)); + } +} + +export class ProjectsClient { + client: rust.BitwardenClient; + + constructor(client: rust.BitwardenClient) { + this.client = client; } + async get(id: string): Promise<ProjectResponse> { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + get: { id }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectResponse(response)); + } + + async create(name: string, organizationId: string): Promise<ProjectResponse> { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + create: { name, organizationId }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectResponse(response)); + } + + async list(organizationId: string): Promise<ProjectsResponse> { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + list: { organizationId }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectsResponse(response)); + } + + async update(id: string, name: string, organizationId: string): Promise<ProjectResponse> { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + update: { id, name, organizationId }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectResponse(response)); + } + + async delete(ids: string[]): Promise<ProjectsDeleteResponse> { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + delete: { ids }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectsDeleteResponse(response)); + } } diff --git a/languages/js_webassembly/bitwarden_client/logging_level.ts b/languages/js_webassembly/bitwarden_client/logging_level.ts deleted file mode 100644 index 2453b1eb64..0000000000 --- a/languages/js_webassembly/bitwarden_client/logging_level.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum LoggingLevel { - Trace, - Debug, - Info, - Warn, - Error, -} diff --git a/languages/js_webassembly/index.html b/languages/js_webassembly/index.html index 661517934b..229c69bae5 100644 --- a/languages/js_webassembly/index.html +++ b/languages/js_webassembly/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html> <head> diff --git a/languages/js_webassembly/index.ts b/languages/js_webassembly/index.ts index 047a815bbb..e4802ca5e8 100644 --- a/languages/js_webassembly/index.ts +++ b/languages/js_webassembly/index.ts @@ -1,26 +1,25 @@ -import { LoggingLevel } from "./bitwarden_client/logging_level"; import { DeviceType } from "./bitwarden_client/schemas"; import("./bitwarden_client").then(async (module) => { - const client = new module.BitwardenClient({ - apiUrl: "http://localhost:8081/api", - identityUrl: "http://localhost:8081/identity", - deviceType: DeviceType.SDK, - userAgent: "Bitwarden JS SDK", - }, LoggingLevel.Debug); - const result = await client.login("test@bitwarden.com", "asdfasdf"); - console.log(`auth result success: ${result.success}`); + const client = new module.BitwardenClient( + { + apiUrl: "http://localhost:8081/api", + identityUrl: "http://localhost:8081/identity", + deviceType: DeviceType.SDK, + userAgent: "Bitwarden JS SDK", + }, + module.LogLevel.Debug, + ); - const apikeyResponse = await client.getUserApiKey("asdfasdf"); - console.log(`user API key: ${apikeyResponse.data.apiKey}`); + const accessToken = "insert your access token here"; + const organizationId = "insert your organization id here"; - const sync = await client.sync(); - console.log("Sync result", sync); + await client.accessTokenLogin(accessToken); - const org_id = sync.data.profile.organizations[0].id; + const secret = await client + .secrets() + .create("TEST_KEY", "Secret1234!", "This is a test secret", organizationId); + console.log("New secret: ", secret); - const secret = await client.secrets().create("TEST_KEY", "This is a test secret", org_id, "Secret1234!"); - console.log("New secret: ", secret.data); - - await client.secrets().delete([secret.data.id]); + await client.secrets().delete([secret.id]); });