1
0
mirror of https://github.com/bitwarden/directory-connector synced 2026-02-28 02:03:15 +00:00

Compare commits

..

21 Commits

Author SHA1 Message Date
Brandon
b4f84fa209 clean up 2026-02-26 12:26:24 -05:00
Brandon
651867a2e9 wip fix test workflow 2026-02-26 12:20:59 -05:00
Brandon
2f713578a6 update workflow 2026-02-26 12:08:39 -05:00
Brandon
3af1e31168 restructure repo, update eslint rules 2026-02-26 11:29:30 -05:00
Brandon
a74973ccfa remove unused jslib code 2026-02-25 16:44:38 -05:00
Brandon
4eb74cdeb4 cleanup migration key for account, clean up 2026-02-25 15:41:15 -05:00
Brandon
b1a3859516 remove hard coded state keys, fix env urls, fix account state migration 2026-02-25 10:01:35 -05:00
Brandon
4c7afc0e64 Merge branch 'state-service-rewrite' into dev-clarity-hands-on 2026-02-24 10:04:35 -05:00
Brandon
4b079a3ec9 continue removing jslib code 2026-02-23 15:50:31 -05:00
Brandon
77873c3075 migrate electron, window/tray, and UI state to vNext 2026-02-23 14:07:46 -05:00
Brandon
9997e988e6 update callers to vNext state service 2026-02-23 10:32:05 -05:00
Brandon
abdddacb06 merge state service re-write 2026-02-20 16:20:03 -05:00
Brandon
d5566c56b1 Migrate all remaining cjs files to esm 2026-02-19 17:45:04 -05:00
Brandon
a019555143 migrate configuration files to ESM 2026-02-19 17:01:08 -05:00
Brandon
b3cb369ed8 add skill for migrating CJS to ESM + example 2026-02-17 10:36:24 -05:00
Brandon
06edf4cf91 flatten account structure using claude 2026-02-13 16:34:20 -05:00
Brandon
623382f9e1 add tech debt context for DC Modernization 2026-02-11 11:02:56 -05:00
Brandon
a0e74948bd fix integration test 2026-02-05 12:04:41 -05:00
Brandon
9f8018e8f8 fix type issues 2026-02-05 11:53:24 -05:00
Brandon
0bff38c459 add tests 2026-02-04 16:00:01 -05:00
Brandon
94ff20f69f scaffold new state service, add migration, initial commit 2026-01-29 14:36:38 -05:00
312 changed files with 8402 additions and 20598 deletions

View File

@@ -14,9 +14,9 @@ on:
- "docker-compose.yml" # any change to Docker configuration
- "package.json" # dependencies
- "utils/**" # any change to test fixtures
- "src/services/sync.service.ts" # core sync service used by all directory services
- "src/services/directory-services/ldap-directory.service*" # LDAP directory service
- "src/services/directory-services/gsuite-directory.service*" # Google Workspace directory service
- "libs/services/sync.service.ts" # core sync service used by all directory services
- "libs/services/directory-services/ldap-directory.service*" # LDAP directory service
- "libs/services/directory-services/gsuite-directory.service*" # Google Workspace directory service
# Add directory services here as we add test coverage
pull_request:
paths:
@@ -24,9 +24,9 @@ on:
- "docker-compose.yml" # any change to Docker configuration
- "package.json" # dependencies
- "utils/**" # any change to test fixtures
- "src/services/sync.service.ts" # core sync service used by all directory services
- "src/services/directory-services/ldap-directory.service*" # LDAP directory service
- "src/services/directory-services/gsuite-directory.service*" # Google Workspace directory service
- "libs/services/sync.service.ts" # core sync service used by all directory services
- "libs/services/directory-services/ldap-directory.service*" # LDAP directory service
- "libs/services/directory-services/gsuite-directory.service*" # Google Workspace directory service
# Add directory services here as we add test coverage
permissions:
contents: read
@@ -94,12 +94,12 @@ jobs:
- '.github/workflows/integration-test.yml'
- 'utils/**'
- 'package.json'
- 'src/services/sync.service.ts'
- 'libs/services/sync.service.ts'
ldap:
- 'docker-compose.yml'
- 'src/services/directory-services/ldap-directory.service*'
- 'libs/services/directory-services/ldap-directory.service*'
google:
- 'src/services/directory-services/gsuite-directory.service*'
- 'libs/services/directory-services/gsuite-directory.service*'
# LDAP
- name: Setup LDAP integration tests
@@ -108,6 +108,9 @@ jobs:
sudo apt-get update
sudo apt-get -y install mkcert
npm run test:integration:setup
echo "Waiting for LDAP container to be healthy..."
timeout 60 bash -c 'until docker compose ps | grep open-ldap | grep -q "(healthy)"; do sleep 2; done'
echo "LDAP container is ready!"
- name: Run LDAP integration tests
if: steps.changed-files.outputs.common == 'true' || steps.changed-files.outputs.ldap == 'true'

View File

@@ -1,46 +0,0 @@
name: Lint
on:
workflow_dispatch:
push:
branches:
- "main"
- "rc"
- "hotfix-rc"
pull_request:
permissions:
contents: read
jobs:
lint:
name: Run linter
if: ${{ startsWith(github.head_ref, 'version_bump_') == false }}
runs-on: ubuntu-24.04
steps:
- name: Check out repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Get Node version
id: retrieve-node-version
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> "$GITHUB_OUTPUT"
- name: Set up Node
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
- name: Install Node dependencies
run: npm ci
- name: Run ESLint and Prettier
run: npm run lint

View File

@@ -14,7 +14,7 @@
}
},
"root": ".",
"sourceRoot": "src",
"sourceRoot": "src-gui",
"prefix": "app",
"architect": {
"build": {
@@ -23,12 +23,15 @@
"outputPath": {
"base": "dist"
},
"index": "src/index.html",
"index": "src-gui/index.html",
"tsConfig": "tsconfig.json",
"assets": [],
"styles": [],
"assets": [
{ "glob": "**/*", "input": "src-gui/images", "output": "images" },
{ "glob": "**/*", "input": "src-gui/locales", "output": "locales" }
],
"styles": ["src-gui/scss/styles.scss"],
"scripts": [],
"browser": "src/main.ts"
"browser": "src-gui/app/main.ts"
}
}
}

View File

@@ -16,3 +16,22 @@ services:
ports:
- "1389:1389"
- "1636:1636"
healthcheck:
test:
[
"CMD",
"ldapsearch",
"-x",
"-H",
"ldap://localhost:1389",
"-b",
"dc=bitwarden,dc=com",
"-D",
"cn=admin,dc=bitwarden,dc=com",
"-w",
"admin",
]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s

View File

@@ -87,14 +87,24 @@ export default [
"newlines-between": "always",
pathGroups: [
{
pattern: "@/jslib/**/*",
pattern: "@/libs/**",
group: "external",
position: "after",
},
{
pattern: "@/src/**/*",
group: "parent",
position: "before",
pattern: "@/jslib/**",
group: "external",
position: "after",
},
{
pattern: "@/src-gui/**",
group: "external",
position: "after",
},
{
pattern: "@/src-cli/**",
group: "external",
position: "after",
},
],
pathGroupsExcludedImportTypes: ["builtin"],

View File

745
jslib-removal-plan.md Normal file
View File

@@ -0,0 +1,745 @@
# Plan: Remove StateService and jslib Dependencies
## Context
Directory Connector currently depends on StateService from jslib, which is a massive pre-StateProvider monolith containing 200+ getter/setter methods for all Bitwarden clients. This creates significant maintenance burden and blocks deletion of unused jslib code.
**Current State (Phase 1 Complete):**
- ✅ StateServiceVNext has been implemented with a flat key-value structure
- ✅ Migration service handles transition from old account-based structure to new flat structure
- ⚠️ Both old and new StateService implementations coexist during migration
- ❌ Three jslib services still depend on old StateService: TokenService, CryptoService, EnvironmentService
- ❌ Two Electron components depend on old StateService: WindowMain, TrayMain
**Problem:**
The old StateService cannot be removed until all dependencies are eliminated. Analysis reveals:
- **TokenService**: Used for API authentication (9/32 methods actually used)
- **CryptoService**: Completely unused by DC (0/61 methods used) - carried over from monolith
- **EnvironmentService**: Used for custom server URLs (4/11 methods used)
- **WindowMain/TrayMain**: Used for Electron window/tray state persistence (6 methods total)
**Goal:**
Replace jslib services with simplified DC-specific implementations that use StateServiceVNext, enabling complete removal of old StateService and unlocking Phase 2 (jslib code cleanup).
**User Decisions:**
1. ✅ Create simplified DC-specific versions of Token/Environment services (clean break from jslib)
2. ✅ Keep WindowMain/TrayMain as-is (minimize scope, focus on StateService removal)
3. ✅ Automatic migration on first launch (transparent to users)
## Critical Files
### Files to Create (New Implementations)
- `src/services/token/token.service.ts` - DC-specific token service
- `src/abstractions/token.service.ts` - Token service interface
- `src/services/environment/environment.service.ts` - DC-specific environment service
- `src/abstractions/environment.service.ts` - Environment service interface
- `src/utils/jwt.util.ts` - JWT decoding utility (no dependencies)
### Files to Modify (Update Dependencies)
- `src/services/api.service.ts` - Switch from jslib TokenService to DC TokenService
- `src/services/auth.service.ts` - Update EnvironmentService import
- `src/services/sync.service.ts` - Update EnvironmentService import
- `src/commands/config.command.ts` - Update EnvironmentService import
- `src/bwdc.ts` - Remove old StateService, instantiate new services
- `src/main.ts` - Remove old StateService, instantiate new services
- `src/app/services/services.module.ts` - Remove old StateService, provide new services
- `src/app/app.component.ts` - Update TokenService import
- `jslib/electron/src/window.main.ts` - Adapt to use StateServiceVNext
- `jslib/electron/src/tray.main.ts` - Adapt to use StateServiceVNext
### Files to Delete (After Migration)
- `jslib/common/src/services/token.service.ts` - jslib TokenService
- `jslib/common/src/abstractions/token.service.ts` - jslib TokenService interface
- `jslib/common/src/services/crypto.service.ts` - Unused CryptoService
- `jslib/common/src/abstractions/crypto.service.ts` - Unused CryptoService interface
- `jslib/common/src/services/environment.service.ts` - jslib EnvironmentService
- `jslib/common/src/abstractions/environment.service.ts` - jslib EnvironmentService interface
- `src/services/state-service/state.service.ts` - Old DC StateService
- `src/abstractions/state.service.ts` - Old DC StateService interface
- `jslib/common/src/services/state.service.ts` - Old jslib StateService
- `jslib/common/src/abstractions/state.service.ts` - Old jslib StateService interface
## Implementation Plan
### Step 1: Create JWT Utility (No Dependencies)
Create `src/utils/jwt.util.ts` with standalone JWT decoding function:
```typescript
export interface DecodedToken {
exp: number;
iat: number;
nbf: number;
sub: string; // user ID
client_id?: string;
[key: string]: any;
}
export function decodeJwt(token: string): DecodedToken {
// Validate JWT structure (3 parts: header.payload.signature)
const parts = token.split(".");
if (parts.length !== 3) {
throw new Error("Invalid JWT format");
}
// Decode payload (base64url to JSON)
const payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
return JSON.parse(atob(payload));
}
export function getTokenExpirationDate(token: string): Date | null {
const decoded = decodeJwt(token);
if (!decoded.exp) return null;
return new Date(decoded.exp * 1000);
}
export function tokenSecondsRemaining(token: string, offsetSeconds = 0): number {
const expDate = getTokenExpirationDate(token);
if (!expDate) return 0;
const msRemaining = expDate.getTime() - Date.now() - offsetSeconds * 1000;
return Math.floor(msRemaining / 1000);
}
export function tokenNeedsRefresh(token: string, minutesBeforeExpiration = 5): boolean {
const secondsRemaining = tokenSecondsRemaining(token);
return secondsRemaining < minutesBeforeExpiration * 60;
}
```
**Why:** Standalone utility avoids service dependencies, can be tested independently, reusable.
### Step 2: Create DC TokenService
Create `src/abstractions/token.service.ts`:
```typescript
export interface TokenService {
// Token storage
setTokens(
accessToken: string,
refreshToken: string,
clientIdClientSecret?: [string, string],
): Promise<void>;
getToken(): Promise<string | null>;
getRefreshToken(): Promise<string | null>;
clearToken(): Promise<void>;
// API key authentication
getClientId(): Promise<string | null>;
getClientSecret(): Promise<string | null>;
// Two-factor token (rarely used)
getTwoFactorToken(): Promise<string | null>;
clearTwoFactorToken(): Promise<void>;
// Token validation (delegates to jwt.util)
decodeToken(token?: string): Promise<DecodedToken | null>;
tokenNeedsRefresh(minutesBeforeExpiration?: number): Promise<boolean>;
}
```
Create `src/services/token/token.service.ts`:
```typescript
import { StateServiceVNext } from "@/abstractions/state-vNext.service";
import { SecureStorageService } from "@/jslib/common/src/abstractions/storage.service";
import { TokenService as ITokenService } from "@/abstractions/token.service";
import {
decodeJwt,
tokenNeedsRefresh as checkTokenNeedsRefresh,
DecodedToken,
} from "@/utils/jwt.util";
export class TokenService implements ITokenService {
// Storage keys
private TOKEN_KEY = "accessToken";
private REFRESH_TOKEN_KEY = "refreshToken";
private CLIENT_ID_KEY = "apiKeyClientId";
private CLIENT_SECRET_KEY = "apiKeyClientSecret";
private TWO_FACTOR_TOKEN_KEY = "twoFactorToken";
constructor(
private stateService: StateServiceVNext,
private secureStorageService: SecureStorageService,
) {}
async setTokens(
accessToken: string,
refreshToken: string,
clientIdClientSecret?: [string, string],
): Promise<void> {
await this.secureStorageService.save(this.TOKEN_KEY, accessToken);
await this.secureStorageService.save(this.REFRESH_TOKEN_KEY, refreshToken);
if (clientIdClientSecret) {
await this.secureStorageService.save(this.CLIENT_ID_KEY, clientIdClientSecret[0]);
await this.secureStorageService.save(this.CLIENT_SECRET_KEY, clientIdClientSecret[1]);
}
}
async getToken(): Promise<string | null> {
return await this.secureStorageService.get<string>(this.TOKEN_KEY);
}
async getRefreshToken(): Promise<string | null> {
return await this.secureStorageService.get<string>(this.REFRESH_TOKEN_KEY);
}
async clearToken(): Promise<void> {
await this.secureStorageService.remove(this.TOKEN_KEY);
await this.secureStorageService.remove(this.REFRESH_TOKEN_KEY);
await this.secureStorageService.remove(this.CLIENT_ID_KEY);
await this.secureStorageService.remove(this.CLIENT_SECRET_KEY);
}
async getClientId(): Promise<string | null> {
return await this.secureStorageService.get<string>(this.CLIENT_ID_KEY);
}
async getClientSecret(): Promise<string | null> {
return await this.secureStorageService.get<string>(this.CLIENT_SECRET_KEY);
}
async getTwoFactorToken(): Promise<string | null> {
return await this.secureStorageService.get<string>(this.TWO_FACTOR_TOKEN_KEY);
}
async clearTwoFactorToken(): Promise<void> {
await this.secureStorageService.remove(this.TWO_FACTOR_TOKEN_KEY);
}
async decodeToken(token?: string): Promise<DecodedToken | null> {
const tokenToUse = token ?? (await this.getToken());
if (!tokenToUse) return null;
try {
return decodeJwt(tokenToUse);
} catch {
return null;
}
}
async tokenNeedsRefresh(minutesBeforeExpiration = 5): Promise<boolean> {
const token = await this.getToken();
if (!token) return true;
try {
return checkTokenNeedsRefresh(token, minutesBeforeExpiration);
} catch {
return true;
}
}
}
```
Create `src/services/token/token.service.spec.ts` with comprehensive tests covering:
- Token storage/retrieval
- Token clearing
- JWT decoding
- Token expiration logic
- Error handling for malformed tokens
### Step 3: Create DC EnvironmentService
Create `src/abstractions/environment.service.ts`:
```typescript
export interface EnvironmentUrls {
base?: string;
api?: string;
identity?: string;
webVault?: string;
icons?: string;
notifications?: string;
events?: string;
keyConnector?: string;
}
export interface EnvironmentService {
setUrls(urls: EnvironmentUrls): Promise<void>;
setUrlsFromStorage(): Promise<void>;
hasBaseUrl(): boolean;
getApiUrl(): string;
getIdentityUrl(): string;
getWebVaultUrl(): string;
getIconsUrl(): string;
getNotificationsUrl(): string;
getEventsUrl(): string;
getKeyConnectorUrl(): string;
}
```
Create `src/services/environment/environment.service.ts`:
```typescript
import { StateServiceVNext } from "@/abstractions/state-vNext.service";
import {
EnvironmentService as IEnvironmentService,
EnvironmentUrls,
} from "@/abstractions/environment.service";
export class EnvironmentService implements IEnvironmentService {
private readonly DEFAULT_URLS = {
api: "https://api.bitwarden.com",
identity: "https://identity.bitwarden.com",
webVault: "https://vault.bitwarden.com",
icons: "https://icons.bitwarden.net",
notifications: "https://notifications.bitwarden.com",
events: "https://events.bitwarden.com",
};
private urls: EnvironmentUrls = {};
constructor(private stateService: StateServiceVNext) {}
async setUrls(urls: EnvironmentUrls): Promise<void> {
// Normalize URLs: trim whitespace, remove trailing slashes, add https:// if missing
const normalized: EnvironmentUrls = {};
for (const [key, value] of Object.entries(urls)) {
if (!value) continue;
let url = value.trim();
url = url.replace(/\/+$/, ""); // Remove trailing slashes
if (!/^https?:\/\//i.test(url)) {
url = `https://${url}`;
}
normalized[key] = url;
}
this.urls = normalized;
await this.stateService.setEnvironmentUrls(normalized);
}
async setUrlsFromStorage(): Promise<void> {
const stored = await this.stateService.getEnvironmentUrls();
this.urls = stored ?? {};
}
hasBaseUrl(): boolean {
return !!this.urls.base;
}
getApiUrl(): string {
return this.urls.api ?? this.urls.base + "/api" ?? this.DEFAULT_URLS.api;
}
getIdentityUrl(): string {
return this.urls.identity ?? this.urls.base + "/identity" ?? this.DEFAULT_URLS.identity;
}
getWebVaultUrl(): string {
return this.urls.webVault ?? this.urls.base ?? this.DEFAULT_URLS.webVault;
}
getIconsUrl(): string {
return this.urls.icons ?? this.urls.base + "/icons" ?? this.DEFAULT_URLS.icons;
}
getNotificationsUrl(): string {
return (
this.urls.notifications ??
this.urls.base + "/notifications" ??
this.DEFAULT_URLS.notifications
);
}
getEventsUrl(): string {
return this.urls.events ?? this.urls.base + "/events" ?? this.DEFAULT_URLS.events;
}
getKeyConnectorUrl(): string {
return this.urls.keyConnector ?? "";
}
}
```
Create `src/services/environment/environment.service.spec.ts` with tests covering:
- URL normalization (trailing slashes, https prefix)
- Storage persistence
- Default URL fallbacks
- Custom URL override
- Base URL derivation
### Step 4: Add Environment URL Storage to StateServiceVNext
Update `src/models/state.model.ts` to add environment URL storage key:
```typescript
export const StorageKeysVNext = {
// ... existing keys ...
environmentUrls: "environmentUrls",
};
```
Update `src/abstractions/state-vNext.service.ts` to add methods:
```typescript
export interface StateServiceVNext {
// ... existing methods ...
getEnvironmentUrls(): Promise<EnvironmentUrls | null>;
setEnvironmentUrls(urls: EnvironmentUrls): Promise<void>;
}
```
Update `src/services/state-service/state-vNext.service.ts` implementation to add storage methods.
### Step 5: Update StateMigrationService for Token/Environment Data
Update `src/services/state-service/stateMigration.service.ts` to migrate:
**Token data (from secure storage):**
- `accessToken``accessToken` (same key, no change needed)
- `refreshToken``refreshToken` (same key, no change needed)
- `apiKeyClientId``apiKeyClientId` (same key, no change needed)
- `apiKeyClientSecret``apiKeyClientSecret` (same key, no change needed)
**Environment URLs (from account state):**
- `environmentUrls` from account → `environmentUrls` in flat structure
Add migration test cases to `src/services/state-service/stateMigration.service.spec.ts`.
### Step 6: Remove CryptoService Dependencies
Since CryptoService is completely unused by DC:
1. Search for all imports of `CryptoService` in `src/` code
2. Remove all instantiations and injections
3. Verify no methods are actually called
4. Remove from DI containers (services.module.ts, bwdc.ts, main.ts)
Expected: Zero usage, straightforward removal.
### Step 7: Update WindowMain/TrayMain to Use StateServiceVNext
Update `jslib/electron/src/window.main.ts`:
```typescript
// Change constructor to accept StateServiceVNext instead of StateService
constructor(
private stateService: StateServiceVNext, // Changed from StateService
// ... other params
) {}
// Update method calls to use StateServiceVNext interface
async getWindowSettings(): Promise<any> {
return await this.stateService.getWindowSettings();
}
async setWindowSettings(settings: any): Promise<void> {
await this.stateService.setWindowSettings(settings);
}
```
Update `jslib/electron/src/tray.main.ts` similarly:
```typescript
constructor(
private stateService: StateServiceVNext, // Changed from StateService
// ... other params
) {}
// Update method calls
async getEnableTray(): Promise<boolean> {
return await this.stateService.getEnableTray();
}
// ... etc for other tray settings
```
**Required:** Add window/tray setting storage to StateServiceVNext:
- `getWindowSettings()` / `setWindowSettings()`
- `getEnableTray()` / `getEnableMinimizeToTray()` / `getEnableCloseToTray()` / `getAlwaysShowDock()`
### Step 8: Update Service Registrations
**In `src/app/services/services.module.ts`:**
```typescript
// Remove old services
- import { StateService } from '@/services/state-service/state.service';
- import { TokenService } from '@/jslib/common/src/services/token.service';
- import { CryptoService } from '@/jslib/common/src/services/crypto.service';
- import { EnvironmentService } from '@/jslib/common/src/services/environment.service';
// Add new services
+ import { TokenService } from '@/services/token/token.service';
+ import { EnvironmentService } from '@/services/environment/environment.service';
providers: [
// Remove old StateService provider
- { provide: StateService, useClass: StateService },
// Add new service providers
+ { provide: TokenService, useClass: TokenService },
+ { provide: EnvironmentService, useClass: EnvironmentService },
// Keep StateServiceVNext
{ provide: StateServiceVNext, useClass: StateServiceVNextImplementation },
]
```
**In `src/bwdc.ts` (CLI):**
```typescript
// Remove old service instantiations
- this.stateService = new StateService(/* ... */);
- this.cryptoService = new CryptoService(/* ... */);
- this.tokenService = new TokenService(/* ... */);
- this.environmentService = new EnvironmentService(this.stateService);
// Add new service instantiations
+ this.tokenService = new TokenService(this.stateServiceVNext, secureStorageService);
+ this.environmentService = new EnvironmentService(this.stateServiceVNext);
```
**In `src/main.ts` (Electron):**
```typescript
// Remove old service instantiations
- this.stateService = new StateService(/* ... */);
- this.cryptoService = new CryptoService(/* ... */);
- this.tokenService = new TokenService(/* ... */);
- this.environmentService = new EnvironmentService(this.stateService);
// Add new service instantiations
+ this.tokenService = new TokenService(this.stateServiceVNext, secureStorageService);
+ this.environmentService = new EnvironmentService(this.stateServiceVNext);
// Update WindowMain/TrayMain to use StateServiceVNext
- this.windowMain = new WindowMain(this.stateService, /* ... */);
- this.trayMain = new TrayMain(this.stateService, /* ... */);
+ this.windowMain = new WindowMain(this.stateServiceVNext, /* ... */);
+ this.trayMain = new TrayMain(this.stateServiceVNext, /* ... */);
```
### Step 9: Update Import Statements
Update all files that import Token/Environment services:
**Files to update:**
- `src/services/api.service.ts` - Change TokenService import to DC version
- `src/services/auth.service.ts` - Change EnvironmentService import to DC version
- `src/services/sync.service.ts` - Change EnvironmentService import to DC version
- `src/commands/config.command.ts` - Change EnvironmentService import to DC version
- `src/app/app.component.ts` - Change TokenService import to DC version
**Pattern:**
```typescript
// Before
import { TokenService } from "@/jslib/common/src/services/token.service";
import { EnvironmentService } from "@/jslib/common/src/services/environment.service";
// After
import { TokenService } from "@/abstractions/token.service";
import { EnvironmentService } from "@/abstractions/environment.service";
```
### Step 10: Delete Old StateService and jslib Services
**Delete these files (after all references removed):**
```bash
# Old StateService implementations
src/services/state-service/state.service.ts
src/abstractions/state.service.ts
jslib/common/src/services/state.service.ts
jslib/common/src/abstractions/state.service.ts
# jslib Token/Crypto/Environment services
jslib/common/src/services/token.service.ts
jslib/common/src/abstractions/token.service.ts
jslib/common/src/services/crypto.service.ts
jslib/common/src/abstractions/crypto.service.ts
jslib/common/src/services/environment.service.ts
jslib/common/src/abstractions/environment.service.ts
```
**Rename StateServiceVNext to StateService:**
```bash
# Rename files
mv src/services/state-service/state-vNext.service.ts src/services/state-service/state.service.ts
mv src/services/state-service/state-vNext.service.spec.ts src/services/state-service/state.service.spec.ts
mv src/abstractions/state-vNext.service.ts src/abstractions/state.service.ts
# Update all imports from StateServiceVNext to StateService
# Find and replace: StateServiceVNext → StateService
```
### Step 11: Update Tests
**Update existing tests that mock StateService:**
- Update mocks to use new StateService interface (flat key-value structure)
- Remove mocks for Token/Crypto/Environment services where they inject old versions
- Add mocks for new DC Token/Environment services
**Add new test files:**
- `src/services/token/token.service.spec.ts` (created in Step 2)
- `src/services/environment/environment.service.spec.ts` (created in Step 3)
- `src/utils/jwt.util.spec.ts` (JWT utility tests)
**Update integration tests:**
- Verify token storage/retrieval works correctly
- Verify environment URL configuration persists
- Verify window/tray settings persist in Electron app
## Verification Plan
### Unit Tests
```bash
npm test # Run all unit tests
```
**Expected:**
- All new service tests pass (TokenService, EnvironmentService, JWT util)
- All existing tests pass with updated mocks
- No test failures due to StateService removal
### Integration Tests
```bash
npm run test:integration
```
**Expected:**
- LDAP sync tests pass
- Authentication flow works correctly
- Configuration persistence works
### Manual Testing - CLI
```bash
# Build and run CLI
npm run build:cli:watch
node ./build-cli/bwdc.js --help
# Test authentication
node ./build-cli/bwdc.js config server https://vault.bitwarden.com
node ./build-cli/bwdc.js login --apikey
# Test sync
node ./build-cli/bwdc.js config directory ldap
node ./build-cli/bwdc.js config ldap.hostname ldap.example.com
node ./build-cli/bwdc.js sync
# Test logout
node ./build-cli/bwdc.js logout
```
**Verify:**
- ✅ Server URL configuration persists
- ✅ Login stores tokens correctly
- ✅ Token refresh works automatically
- ✅ Sync completes successfully
- ✅ Logout clears tokens
### Manual Testing - Desktop App
```bash
# Build and run desktop app
npm run electron
```
**Verify:**
- ✅ Window position/size persists across restarts
- ✅ "Always on top" setting persists
- ✅ Tray icon shows/hides based on settings
- ✅ Minimize/close to tray works
- ✅ Login/logout flow works
- ✅ Sync functionality works
- ✅ Custom server URL configuration works
### Migration Testing
**Test migration from existing installation:**
1. Install current production version
2. Configure directory connection and run sync
3. Install new version with StateService removal
4. Launch app - verify automatic migration occurs
5. Verify all settings preserved:
- Directory configuration
- Organization ID
- Server URLs
- Window/tray settings
- Authentication tokens
**Expected:**
- ✅ Migration runs automatically on first launch
- ✅ All user data preserved
- ✅ No user action required
- ✅ App functions identically to before
### Regression Testing
Run through all major workflows:
1. **Configuration**: Set up each directory type (LDAP, Entra, Google, Okta, OneLogin)
2. **Authentication**: Login with API key, verify token refresh
3. **Sync**: Full sync, incremental sync (delta tokens), detect changes via hash
4. **Custom server**: Configure self-hosted Bitwarden server
5. **Electron features**: Window management, tray behavior
**Expected:** No regressions in functionality.
## Rollback Plan
If critical issues discovered post-deployment:
1. **Revert commit** removing StateService
2. **Keep StateServiceVNext in parallel** (already coexisting)
3. **Debug issues** in development
4. **Re-attempt removal** after fixes
**Risk Assessment:** Low - StateServiceVNext has been in production since Phase 1 PR merge, proven stable.
## Success Criteria
- ✅ All old StateService implementations deleted
- ✅ StateServiceVNext renamed to StateService (becomes primary)
- ✅ jslib TokenService, CryptoService, EnvironmentService deleted
- ✅ DC-specific Token/Environment services implemented and tested
- ✅ All unit tests pass
- ✅ All integration tests pass
- ✅ Manual testing shows no regressions
- ✅ Migration from old state structure works automatically
- ✅ WindowMain/TrayMain adapted to new StateService
- ✅ Zero references to old StateService in codebase
## Next Steps (After Completion)
This unblocks **Phase 2: Remove Remaining jslib Code**:
- Delete unused jslib models (AccountData, AccountSettings, etc.)
- Delete unused jslib services that referenced StateService
- Clean up jslib/common folder of unused client code
- Potentially merge remaining jslib code into src/ (flatten structure)
Estimated effort: 2-3 days for experienced developer familiar with codebase.

View File

@@ -1,28 +0,0 @@
import { webcrypto } from "crypto";
import "jest-preset-angular/setup-jest";
Object.defineProperty(window, "CSS", { value: null });
Object.defineProperty(window, "getComputedStyle", {
value: () => {
return {
display: "none",
appearance: ["-webkit-appearance"],
};
},
});
Object.defineProperty(document, "doctype", {
value: "<!DOCTYPE html>",
});
Object.defineProperty(document.body.style, "transform", {
value: () => {
return {
enumerable: true,
configurable: true,
};
},
});
Object.defineProperty(window, "crypto", {
value: webcrypto,
});

View File

@@ -1,63 +0,0 @@
import { Directive, EventEmitter, Output } from "@angular/core";
import { EnvironmentService } from "@/jslib/common/src/abstractions/environment.service";
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
@Directive()
export class EnvironmentComponent {
@Output() onSaved = new EventEmitter();
iconsUrl: string;
identityUrl: string;
apiUrl: string;
webVaultUrl: string;
notificationsUrl: string;
baseUrl: string;
showCustom = false;
constructor(
protected platformUtilsService: PlatformUtilsService,
protected environmentService: EnvironmentService,
protected i18nService: I18nService,
) {
const urls = this.environmentService.getUrls();
this.baseUrl = urls.base || "";
this.webVaultUrl = urls.webVault || "";
this.apiUrl = urls.api || "";
this.identityUrl = urls.identity || "";
this.iconsUrl = urls.icons || "";
this.notificationsUrl = urls.notifications || "";
}
async submit() {
const resUrls = await this.environmentService.setUrls({
base: this.baseUrl,
api: this.apiUrl,
identity: this.identityUrl,
webVault: this.webVaultUrl,
icons: this.iconsUrl,
notifications: this.notificationsUrl,
});
// re-set urls since service can change them, ex: prefixing https://
this.baseUrl = resUrls.base;
this.apiUrl = resUrls.api;
this.identityUrl = resUrls.identity;
this.webVaultUrl = resUrls.webVault;
this.iconsUrl = resUrls.icons;
this.notificationsUrl = resUrls.notifications;
this.platformUtilsService.showToast("success", null, this.i18nService.t("environmentSaved"));
this.saved();
}
toggleCustom() {
this.showCustom = !this.showCustom;
}
protected saved() {
this.onSaved.emit();
}
}

View File

@@ -1,143 +0,0 @@
import { LOCALE_ID, NgModule } from "@angular/core";
import { ApiService as ApiServiceAbstraction } from "@/jslib/common/src/abstractions/api.service";
import { AppIdService as AppIdServiceAbstraction } from "@/jslib/common/src/abstractions/appId.service";
import { BroadcasterService as BroadcasterServiceAbstraction } from "@/jslib/common/src/abstractions/broadcaster.service";
import { CryptoService as CryptoServiceAbstraction } from "@/jslib/common/src/abstractions/crypto.service";
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@/jslib/common/src/abstractions/cryptoFunction.service";
import { EnvironmentService as EnvironmentServiceAbstraction } from "@/jslib/common/src/abstractions/environment.service";
import { I18nService as I18nServiceAbstraction } from "@/jslib/common/src/abstractions/i18n.service";
import { LogService } from "@/jslib/common/src/abstractions/log.service";
import { MessagingService as MessagingServiceAbstraction } from "@/jslib/common/src/abstractions/messaging.service";
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@/jslib/common/src/abstractions/platformUtils.service";
import { StateService as StateServiceAbstraction } from "@/jslib/common/src/abstractions/state.service";
import { StateMigrationService as StateMigrationServiceAbstraction } from "@/jslib/common/src/abstractions/stateMigration.service";
import { StorageService as StorageServiceAbstraction } from "@/jslib/common/src/abstractions/storage.service";
import { TokenService as TokenServiceAbstraction } from "@/jslib/common/src/abstractions/token.service";
import { StateFactory } from "@/jslib/common/src/factories/stateFactory";
import { Account } from "@/jslib/common/src/models/domain/account";
import { GlobalState } from "@/jslib/common/src/models/domain/globalState";
import { ApiService } from "@/jslib/common/src/services/api.service";
import { AppIdService } from "@/jslib/common/src/services/appId.service";
import { ConsoleLogService } from "@/jslib/common/src/services/consoleLog.service";
import { CryptoService } from "@/jslib/common/src/services/crypto.service";
import { EnvironmentService } from "@/jslib/common/src/services/environment.service";
import { StateService } from "@/jslib/common/src/services/state.service";
import { StateMigrationService } from "@/jslib/common/src/services/stateMigration.service";
import { TokenService } from "@/jslib/common/src/services/token.service";
import {
SafeInjectionToken,
SECURE_STORAGE,
WINDOW,
} from "../../../../src/app/services/injection-tokens";
import { SafeProvider, safeProvider } from "../../../../src/app/services/safe-provider";
import { BroadcasterService } from "./broadcaster.service";
import { ModalService } from "./modal.service";
import { ValidationService } from "./validation.service";
@NgModule({
declarations: [],
providers: [
safeProvider({ provide: WINDOW, useValue: window }),
safeProvider({
provide: LOCALE_ID as SafeInjectionToken<string>,
useFactory: (i18nService: I18nServiceAbstraction) => i18nService.translationLocale,
deps: [I18nServiceAbstraction],
}),
safeProvider(ValidationService),
safeProvider(ModalService),
safeProvider({
provide: AppIdServiceAbstraction,
useClass: AppIdService,
deps: [StorageServiceAbstraction],
}),
safeProvider({ provide: LogService, useFactory: () => new ConsoleLogService(false), deps: [] }),
safeProvider({
provide: EnvironmentServiceAbstraction,
useClass: EnvironmentService,
deps: [StateServiceAbstraction],
}),
safeProvider({
provide: TokenServiceAbstraction,
useClass: TokenService,
deps: [StateServiceAbstraction],
}),
safeProvider({
provide: CryptoServiceAbstraction,
useClass: CryptoService,
deps: [
CryptoFunctionServiceAbstraction,
PlatformUtilsServiceAbstraction,
LogService,
StateServiceAbstraction,
],
}),
safeProvider({
provide: ApiServiceAbstraction,
useFactory: (
tokenService: TokenServiceAbstraction,
platformUtilsService: PlatformUtilsServiceAbstraction,
environmentService: EnvironmentServiceAbstraction,
messagingService: MessagingServiceAbstraction,
appIdService: AppIdServiceAbstraction,
) =>
new ApiService(
tokenService,
platformUtilsService,
environmentService,
appIdService,
async (expired: boolean) => messagingService.send("logout", { expired: expired }),
),
deps: [
TokenServiceAbstraction,
PlatformUtilsServiceAbstraction,
EnvironmentServiceAbstraction,
MessagingServiceAbstraction,
AppIdServiceAbstraction,
],
}),
safeProvider({
provide: BroadcasterServiceAbstraction,
useClass: BroadcasterService,
useAngularDecorators: true,
}),
safeProvider({
provide: StateServiceAbstraction,
useFactory: (
storageService: StorageServiceAbstraction,
secureStorageService: StorageServiceAbstraction,
logService: LogService,
stateMigrationService: StateMigrationServiceAbstraction,
) =>
new StateService(
storageService,
secureStorageService,
logService,
stateMigrationService,
new StateFactory(GlobalState, Account),
),
deps: [
StorageServiceAbstraction,
SECURE_STORAGE,
LogService,
StateMigrationServiceAbstraction,
],
}),
safeProvider({
provide: StateMigrationServiceAbstraction,
useFactory: (
storageService: StorageServiceAbstraction,
secureStorageService: StorageServiceAbstraction,
) =>
new StateMigrationService(
storageService,
secureStorageService,
new StateFactory(GlobalState, Account),
),
deps: [StorageServiceAbstraction, SECURE_STORAGE],
}),
] satisfies SafeProvider[],
})
export class JslibServicesModule {}

View File

@@ -1,69 +0,0 @@
import { EncryptionType } from "@/jslib/common/src/enums/encryptionType";
import { SymmetricCryptoKey } from "@/jslib/common/src/models/domain/symmetricCryptoKey";
import { makeStaticByteArray } from "../utils";
describe("SymmetricCryptoKey", () => {
it("errors if no key", () => {
const t = () => {
new SymmetricCryptoKey(null);
};
expect(t).toThrow("Must provide key");
});
describe("guesses encKey from key length", () => {
it("AesCbc256_B64", () => {
const key = makeStaticByteArray(32);
const cryptoKey = new SymmetricCryptoKey(key);
expect(cryptoKey).toEqual({
encKey: key,
encKeyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
encType: 0,
key: key,
keyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
macKey: null,
});
});
it("AesCbc128_HmacSha256_B64", () => {
const key = makeStaticByteArray(32);
const cryptoKey = new SymmetricCryptoKey(key, EncryptionType.AesCbc128_HmacSha256_B64);
expect(cryptoKey).toEqual({
encKey: key.slice(0, 16),
encKeyB64: "AAECAwQFBgcICQoLDA0ODw==",
encType: 1,
key: key,
keyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
macKey: key.slice(16, 32),
macKeyB64: "EBESExQVFhcYGRobHB0eHw==",
});
});
it("AesCbc256_HmacSha256_B64", () => {
const key = makeStaticByteArray(64);
const cryptoKey = new SymmetricCryptoKey(key);
expect(cryptoKey).toEqual({
encKey: key.slice(0, 32),
encKeyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
encType: 2,
key: key,
keyB64:
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==",
macKey: key.slice(32, 64),
macKeyB64: "ICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8=",
});
});
it("unknown length", () => {
const t = () => {
new SymmetricCryptoKey(makeStaticByteArray(30));
};
expect(t).toThrow("Unable to determine encType.");
});
});
});

View File

@@ -1,127 +0,0 @@
import { sequentialize } from "@/jslib/common/src/misc/sequentialize";
describe("sequentialize decorator", () => {
it("should call the function once", async () => {
const foo = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.bar(1));
}
await Promise.all(promises);
expect(foo.calls).toBe(1);
});
it("should call the function once for each instance of the object", async () => {
const foo = new Foo();
const foo2 = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.bar(1));
promises.push(foo2.bar(1));
}
await Promise.all(promises);
expect(foo.calls).toBe(1);
expect(foo2.calls).toBe(1);
});
it("should call the function once with key function", async () => {
const foo = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.baz(1));
}
await Promise.all(promises);
expect(foo.calls).toBe(1);
});
it("should call the function again when already resolved", async () => {
const foo = new Foo();
await foo.bar(1);
expect(foo.calls).toBe(1);
await foo.bar(1);
expect(foo.calls).toBe(2);
});
it("should call the function again when already resolved with a key function", async () => {
const foo = new Foo();
await foo.baz(1);
expect(foo.calls).toBe(1);
await foo.baz(1);
expect(foo.calls).toBe(2);
});
it("should call the function for each argument", async () => {
const foo = new Foo();
await Promise.all([foo.bar(1), foo.bar(1), foo.bar(2), foo.bar(2), foo.bar(3), foo.bar(3)]);
expect(foo.calls).toBe(3);
});
it("should call the function for each argument with key function", async () => {
const foo = new Foo();
await Promise.all([foo.baz(1), foo.baz(1), foo.baz(2), foo.baz(2), foo.baz(3), foo.baz(3)]);
expect(foo.calls).toBe(3);
});
it("should return correct result for each call", async () => {
const foo = new Foo();
const allRes: number[] = [];
await Promise.all([
foo.bar(1).then((res) => allRes.push(res)),
foo.bar(1).then((res) => allRes.push(res)),
foo.bar(2).then((res) => allRes.push(res)),
foo.bar(2).then((res) => allRes.push(res)),
foo.bar(3).then((res) => allRes.push(res)),
foo.bar(3).then((res) => allRes.push(res)),
]);
expect(foo.calls).toBe(3);
expect(allRes.length).toBe(6);
allRes.sort();
expect(allRes).toEqual([2, 2, 4, 4, 6, 6]);
});
it("should return correct result for each call with key function", async () => {
const foo = new Foo();
const allRes: number[] = [];
await Promise.all([
foo.baz(1).then((res) => allRes.push(res)),
foo.baz(1).then((res) => allRes.push(res)),
foo.baz(2).then((res) => allRes.push(res)),
foo.baz(2).then((res) => allRes.push(res)),
foo.baz(3).then((res) => allRes.push(res)),
foo.baz(3).then((res) => allRes.push(res)),
]);
expect(foo.calls).toBe(3);
expect(allRes.length).toBe(6);
allRes.sort();
expect(allRes).toEqual([3, 3, 6, 6, 9, 9]);
});
});
class Foo {
calls = 0;
@sequentialize((args) => "bar" + args[0])
bar(a: number): Promise<number> {
this.calls++;
return new Promise((res) => {
setTimeout(() => {
res(a * 2);
}, Math.random() * 100);
});
}
@sequentialize((args) => "baz" + args[0])
baz(a: number): Promise<number> {
this.calls++;
return new Promise((res) => {
setTimeout(() => {
res(a * 3);
}, Math.random() * 100);
});
}
}

View File

@@ -1,110 +0,0 @@
import { sequentialize } from "@/jslib/common/src/misc/sequentialize";
import { throttle } from "@/jslib/common/src/misc/throttle";
describe("throttle decorator", () => {
it("should call the function once at a time", async () => {
const foo = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.bar(1));
}
await Promise.all(promises);
expect(foo.calls).toBe(10);
});
it("should call the function once at a time for each object", async () => {
const foo = new Foo();
const foo2 = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.bar(1));
promises.push(foo2.bar(1));
}
await Promise.all(promises);
expect(foo.calls).toBe(10);
expect(foo2.calls).toBe(10);
});
it("should call the function limit at a time", async () => {
const foo = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.baz(1));
}
await Promise.all(promises);
expect(foo.calls).toBe(10);
});
it("should call the function limit at a time for each object", async () => {
const foo = new Foo();
const foo2 = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.baz(1));
promises.push(foo2.baz(1));
}
await Promise.all(promises);
expect(foo.calls).toBe(10);
expect(foo2.calls).toBe(10);
});
it("should work together with sequentialize", async () => {
const foo = new Foo();
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(foo.qux(Math.floor(i / 2) * 2));
}
await Promise.all(promises);
expect(foo.calls).toBe(5);
});
});
class Foo {
calls = 0;
inflight = 0;
@throttle(1, () => "bar")
bar(a: number) {
this.calls++;
this.inflight++;
return new Promise((res) => {
setTimeout(() => {
expect(this.inflight).toBe(1);
this.inflight--;
res(a * 2);
}, Math.random() * 10);
});
}
@throttle(5, () => "baz")
baz(a: number) {
this.calls++;
this.inflight++;
return new Promise((res) => {
setTimeout(() => {
expect(this.inflight).toBeLessThanOrEqual(5);
this.inflight--;
res(a * 3);
}, Math.random() * 10);
});
}
@sequentialize((args) => "qux" + args[0])
@throttle(1, () => "qux")
qux(a: number) {
this.calls++;
this.inflight++;
return new Promise((res) => {
setTimeout(() => {
expect(this.inflight).toBe(1);
this.inflight--;
res(a * 3);
}, Math.random() * 10);
});
}
}

View File

@@ -1,99 +0,0 @@
import { ConsoleLogService } from "@/jslib/common/src/services/consoleLog.service";
const originalConsole = console;
let caughtMessage: any;
declare let console: any;
export function interceptConsole(interceptions: any): object {
console = {
log: function () {
interceptions.log = arguments;
},
warn: function () {
interceptions.warn = arguments;
},
error: function () {
interceptions.error = arguments;
},
};
return interceptions;
}
export function restoreConsole() {
console = originalConsole;
}
describe("ConsoleLogService", () => {
let logService: ConsoleLogService;
beforeEach(() => {
caughtMessage = {};
interceptConsole(caughtMessage);
logService = new ConsoleLogService(true);
});
afterAll(() => {
restoreConsole();
});
it("filters messages below the set threshold", () => {
logService = new ConsoleLogService(true, () => true);
logService.debug("debug");
logService.info("info");
logService.warning("warning");
logService.error("error");
expect(caughtMessage).toEqual({});
});
it("only writes debug messages in dev mode", () => {
logService = new ConsoleLogService(false);
logService.debug("debug message");
expect(caughtMessage.log).toBeUndefined();
});
it("writes debug/info messages to console.log", () => {
logService.debug("this is a debug message");
expect(caughtMessage).toMatchObject({
log: { "0": "this is a debug message" },
});
logService.info("this is an info message");
expect(caughtMessage).toMatchObject({
log: { "0": "this is an info message" },
});
});
it("writes warning messages to console.warn", () => {
logService.warning("this is a warning message");
expect(caughtMessage).toMatchObject({
warn: { 0: "this is a warning message" },
});
});
it("writes error messages to console.error", () => {
logService.error("this is an error message");
expect(caughtMessage).toMatchObject({
error: { 0: "this is an error message" },
});
});
it("times with output to info", async () => {
logService.time();
await new Promise((r) => setTimeout(r, 250));
const duration = logService.timeEnd();
expect(duration[0]).toBe(0);
expect(duration[1]).toBeGreaterThan(0);
expect(duration[1]).toBeLessThan(500 * 10e6);
expect(caughtMessage).toEqual(expect.arrayContaining([]));
expect(caughtMessage.log.length).toBe(1);
expect(caughtMessage.log[0]).toEqual(expect.stringMatching(/^default: \d+\.?\d*ms$/));
});
it("filters time output", async () => {
logService = new ConsoleLogService(true, () => true);
logService.time();
logService.timeEnd();
expect(caughtMessage).toEqual({});
});
});

View File

@@ -1,5 +0,0 @@
import { webcrypto } from "crypto";
Object.defineProperty(window, "crypto", {
value: webcrypto,
});

View File

@@ -1,86 +0,0 @@
import { HashPurpose } from "../enums/hashPurpose";
import { KdfType } from "../enums/kdfType";
import { KeySuffixOptions } from "../enums/keySuffixOptions";
import { EncArrayBuffer } from "../models/domain/encArrayBuffer";
import { EncString } from "../models/domain/encString";
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
import { ProfileOrganizationResponse } from "../models/response/profileOrganizationResponse";
import { ProfileProviderOrganizationResponse } from "../models/response/profileProviderOrganizationResponse";
import { ProfileProviderResponse } from "../models/response/profileProviderResponse";
export abstract class CryptoService {
setKey: (key: SymmetricCryptoKey) => Promise<any>;
setKeyHash: (keyHash: string) => Promise<void>;
setEncKey: (encKey: string) => Promise<void>;
setEncPrivateKey: (encPrivateKey: string) => Promise<void>;
setOrgKeys: (
orgs: ProfileOrganizationResponse[],
providerOrgs: ProfileProviderOrganizationResponse[],
) => Promise<void>;
setProviderKeys: (orgs: ProfileProviderResponse[]) => Promise<void>;
getKey: (keySuffix?: KeySuffixOptions, userId?: string) => Promise<SymmetricCryptoKey>;
getKeyFromStorage: (keySuffix: KeySuffixOptions, userId?: string) => Promise<SymmetricCryptoKey>;
getKeyHash: () => Promise<string>;
compareAndUpdateKeyHash: (masterPassword: string, key: SymmetricCryptoKey) => Promise<boolean>;
getEncKey: (key?: SymmetricCryptoKey) => Promise<SymmetricCryptoKey>;
getPublicKey: () => Promise<ArrayBuffer>;
getPrivateKey: () => Promise<ArrayBuffer>;
getFingerprint: (userId: string, publicKey?: ArrayBuffer) => Promise<string[]>;
getOrgKeys: () => Promise<Map<string, SymmetricCryptoKey>>;
getOrgKey: (orgId: string) => Promise<SymmetricCryptoKey>;
getProviderKey: (providerId: string) => Promise<SymmetricCryptoKey>;
hasKey: () => Promise<boolean>;
hasKeyInMemory: (userId?: string) => Promise<boolean>;
hasKeyStored: (keySuffix?: KeySuffixOptions, userId?: string) => Promise<boolean>;
hasEncKey: () => Promise<boolean>;
clearKey: (clearSecretStorage?: boolean, userId?: string) => Promise<any>;
clearKeyHash: () => Promise<any>;
clearEncKey: (memoryOnly?: boolean, userId?: string) => Promise<any>;
clearKeyPair: (memoryOnly?: boolean, userId?: string) => Promise<any>;
clearOrgKeys: (memoryOnly?: boolean, userId?: string) => Promise<any>;
clearProviderKeys: (memoryOnly?: boolean) => Promise<any>;
clearPinProtectedKey: () => Promise<any>;
clearKeys: (userId?: string) => Promise<any>;
toggleKey: () => Promise<any>;
makeKey: (
password: string,
salt: string,
kdf: KdfType,
kdfIterations: number,
) => Promise<SymmetricCryptoKey>;
makeKeyFromPin: (
pin: string,
salt: string,
kdf: KdfType,
kdfIterations: number,
protectedKeyCs?: EncString,
) => Promise<SymmetricCryptoKey>;
makeShareKey: () => Promise<[EncString, SymmetricCryptoKey]>;
makeKeyPair: (key?: SymmetricCryptoKey) => Promise<[string, EncString]>;
makePinKey: (
pin: string,
salt: string,
kdf: KdfType,
kdfIterations: number,
) => Promise<SymmetricCryptoKey>;
makeSendKey: (keyMaterial: ArrayBuffer) => Promise<SymmetricCryptoKey>;
hashPassword: (
password: string,
key: SymmetricCryptoKey,
hashPurpose?: HashPurpose,
) => Promise<string>;
makeEncKey: (key: SymmetricCryptoKey) => Promise<[SymmetricCryptoKey, EncString]>;
remakeEncKey: (
key: SymmetricCryptoKey,
encKey?: SymmetricCryptoKey,
) => Promise<[SymmetricCryptoKey, EncString]>;
encrypt: (plainValue: string | ArrayBuffer, key?: SymmetricCryptoKey) => Promise<EncString>;
encryptToBytes: (plainValue: ArrayBuffer, key?: SymmetricCryptoKey) => Promise<EncArrayBuffer>;
rsaEncrypt: (data: ArrayBuffer, publicKey?: ArrayBuffer) => Promise<EncString>;
rsaDecrypt: (encValue: string, privateKeyValue?: ArrayBuffer) => Promise<ArrayBuffer>;
decryptToBytes: (encString: EncString, key?: SymmetricCryptoKey) => Promise<ArrayBuffer>;
decryptToUtf8: (encString: EncString, key?: SymmetricCryptoKey) => Promise<string>;
decryptFromBytes: (encBuf: ArrayBuffer, key: SymmetricCryptoKey) => Promise<ArrayBuffer>;
randomNumber: (min: number, max: number) => Promise<number>;
validateKey: (key: SymmetricCryptoKey) => Promise<boolean>;
}

View File

@@ -1,34 +1,2 @@
import { Observable } from "rxjs";
export type Urls = {
base?: string;
webVault?: string;
api?: string;
identity?: string;
icons?: string;
notifications?: string;
events?: string;
keyConnector?: string;
};
export type PayPalConfig = {
businessId?: string;
buttonAction?: string;
};
export abstract class EnvironmentService {
urls: Observable<Urls>;
hasBaseUrl: () => boolean;
getNotificationsUrl: () => string;
getWebVaultUrl: () => string;
getSendUrl: () => string;
getIconsUrl: () => string;
getApiUrl: () => string;
getIdentityUrl: () => string;
getEventsUrl: () => string;
getKeyConnectorUrl: () => string;
setUrlsFromStorage: () => Promise<void>;
setUrls: (urls: Urls) => Promise<Urls>;
getUrls: () => Urls;
}
// Stub file - re-exports DC EnvironmentService
export { EnvironmentService, EnvironmentUrls } from "@/libs/abstractions/environment.service";

View File

@@ -1,218 +1,2 @@
import { Observable } from "rxjs";
import { KdfType } from "../enums/kdfType";
import { ThemeType } from "../enums/themeType";
import { UriMatchType } from "../enums/uriMatchType";
import { OrganizationData } from "../models/data/organizationData";
import { ProviderData } from "../models/data/providerData";
import { Account } from "../models/domain/account";
import { EncString } from "../models/domain/encString";
import { EnvironmentUrls } from "../models/domain/environmentUrls";
import { StorageOptions } from "../models/domain/storageOptions";
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
import { WindowState } from "../models/domain/windowState";
export abstract class StateService<T extends Account = Account> {
accounts$: Observable<{ [userId: string]: T }>;
activeAccount$: Observable<string>;
addAccount: (account: T) => Promise<void>;
setActiveUser: (userId: string) => Promise<void>;
clean: (options?: StorageOptions) => Promise<void>;
init: () => Promise<void>;
getAccessToken: (options?: StorageOptions) => Promise<string>;
setAccessToken: (value: string, options?: StorageOptions) => Promise<void>;
getAddEditCipherInfo: (options?: StorageOptions) => Promise<any>;
setAddEditCipherInfo: (value: any, options?: StorageOptions) => Promise<void>;
getAlwaysShowDock: (options?: StorageOptions) => Promise<boolean>;
setAlwaysShowDock: (value: boolean, options?: StorageOptions) => Promise<void>;
getApiKeyClientId: (options?: StorageOptions) => Promise<string>;
setApiKeyClientId: (value: string, options?: StorageOptions) => Promise<void>;
getApiKeyClientSecret: (options?: StorageOptions) => Promise<string>;
setApiKeyClientSecret: (value: string, options?: StorageOptions) => Promise<void>;
getAutoConfirmFingerPrints: (options?: StorageOptions) => Promise<boolean>;
setAutoConfirmFingerprints: (value: boolean, options?: StorageOptions) => Promise<void>;
getBiometricAwaitingAcceptance: (options?: StorageOptions) => Promise<boolean>;
setBiometricAwaitingAcceptance: (value: boolean, options?: StorageOptions) => Promise<void>;
getBiometricFingerprintValidated: (options?: StorageOptions) => Promise<boolean>;
setBiometricFingerprintValidated: (value: boolean, options?: StorageOptions) => Promise<void>;
getBiometricLocked: (options?: StorageOptions) => Promise<boolean>;
setBiometricLocked: (value: boolean, options?: StorageOptions) => Promise<void>;
getBiometricText: (options?: StorageOptions) => Promise<string>;
setBiometricText: (value: string, options?: StorageOptions) => Promise<void>;
getBiometricUnlock: (options?: StorageOptions) => Promise<boolean>;
setBiometricUnlock: (value: boolean, options?: StorageOptions) => Promise<void>;
getCanAccessPremium: (options?: StorageOptions) => Promise<boolean>;
getClearClipboard: (options?: StorageOptions) => Promise<number>;
setClearClipboard: (value: number, options?: StorageOptions) => Promise<void>;
getCollapsedGroupings: (options?: StorageOptions) => Promise<string[]>;
setCollapsedGroupings: (value: string[], options?: StorageOptions) => Promise<void>;
getConvertAccountToKeyConnector: (options?: StorageOptions) => Promise<boolean>;
setConvertAccountToKeyConnector: (value: boolean, options?: StorageOptions) => Promise<void>;
getCryptoMasterKey: (options?: StorageOptions) => Promise<SymmetricCryptoKey>;
setCryptoMasterKey: (value: SymmetricCryptoKey, options?: StorageOptions) => Promise<void>;
getCryptoMasterKeyAuto: (options?: StorageOptions) => Promise<string>;
setCryptoMasterKeyAuto: (value: string, options?: StorageOptions) => Promise<void>;
getCryptoMasterKeyB64: (options?: StorageOptions) => Promise<string>;
setCryptoMasterKeyB64: (value: string, options?: StorageOptions) => Promise<void>;
getCryptoMasterKeyBiometric: (options?: StorageOptions) => Promise<string>;
hasCryptoMasterKeyBiometric: (options?: StorageOptions) => Promise<boolean>;
setCryptoMasterKeyBiometric: (value: string, options?: StorageOptions) => Promise<void>;
getDecodedToken: (options?: StorageOptions) => Promise<any>;
setDecodedToken: (value: any, options?: StorageOptions) => Promise<void>;
getDecryptedCryptoSymmetricKey: (options?: StorageOptions) => Promise<SymmetricCryptoKey>;
setDecryptedCryptoSymmetricKey: (
value: SymmetricCryptoKey,
options?: StorageOptions,
) => Promise<void>;
getDecryptedOrganizationKeys: (
options?: StorageOptions,
) => Promise<Map<string, SymmetricCryptoKey>>;
setDecryptedOrganizationKeys: (
value: Map<string, SymmetricCryptoKey>,
options?: StorageOptions,
) => Promise<void>;
getDecryptedPinProtected: (options?: StorageOptions) => Promise<EncString>;
setDecryptedPinProtected: (value: EncString, options?: StorageOptions) => Promise<void>;
getDecryptedPrivateKey: (options?: StorageOptions) => Promise<ArrayBuffer>;
setDecryptedPrivateKey: (value: ArrayBuffer, options?: StorageOptions) => Promise<void>;
getDecryptedProviderKeys: (options?: StorageOptions) => Promise<Map<string, SymmetricCryptoKey>>;
setDecryptedProviderKeys: (
value: Map<string, SymmetricCryptoKey>,
options?: StorageOptions,
) => Promise<void>;
getDefaultUriMatch: (options?: StorageOptions) => Promise<UriMatchType>;
setDefaultUriMatch: (value: UriMatchType, options?: StorageOptions) => Promise<void>;
getDisableAutoBiometricsPrompt: (options?: StorageOptions) => Promise<boolean>;
setDisableAutoBiometricsPrompt: (value: boolean, options?: StorageOptions) => Promise<void>;
getDisableAutoTotpCopy: (options?: StorageOptions) => Promise<boolean>;
setDisableAutoTotpCopy: (value: boolean, options?: StorageOptions) => Promise<void>;
getDisableBadgeCounter: (options?: StorageOptions) => Promise<boolean>;
setDisableBadgeCounter: (value: boolean, options?: StorageOptions) => Promise<void>;
getDisableContextMenuItem: (options?: StorageOptions) => Promise<boolean>;
setDisableContextMenuItem: (value: boolean, options?: StorageOptions) => Promise<void>;
getDisableGa: (options?: StorageOptions) => Promise<boolean>;
setDisableGa: (value: boolean, options?: StorageOptions) => Promise<void>;
getEmail: (options?: StorageOptions) => Promise<string>;
setEmail: (value: string, options?: StorageOptions) => Promise<void>;
getEmailVerified: (options?: StorageOptions) => Promise<boolean>;
setEmailVerified: (value: boolean, options?: StorageOptions) => Promise<void>;
getEnableAlwaysOnTop: (options?: StorageOptions) => Promise<boolean>;
setEnableAlwaysOnTop: (value: boolean, options?: StorageOptions) => Promise<void>;
getEnableBiometric: (options?: StorageOptions) => Promise<boolean>;
setEnableBiometric: (value: boolean, options?: StorageOptions) => Promise<void>;
getEnableCloseToTray: (options?: StorageOptions) => Promise<boolean>;
setEnableCloseToTray: (value: boolean, options?: StorageOptions) => Promise<void>;
getEnableFullWidth: (options?: StorageOptions) => Promise<boolean>;
setEnableFullWidth: (value: boolean, options?: StorageOptions) => Promise<void>;
getEnableMinimizeToTray: (options?: StorageOptions) => Promise<boolean>;
setEnableMinimizeToTray: (value: boolean, options?: StorageOptions) => Promise<void>;
getEnableStartToTray: (options?: StorageOptions) => Promise<boolean>;
setEnableStartToTray: (value: boolean, options?: StorageOptions) => Promise<void>;
getEnableTray: (options?: StorageOptions) => Promise<boolean>;
setEnableTray: (value: boolean, options?: StorageOptions) => Promise<void>;
getEncryptedCryptoSymmetricKey: (options?: StorageOptions) => Promise<string>;
setEncryptedCryptoSymmetricKey: (value: string, options?: StorageOptions) => Promise<void>;
getEncryptedOrganizationKeys: (options?: StorageOptions) => Promise<any>;
setEncryptedOrganizationKeys: (
value: Map<string, SymmetricCryptoKey>,
options?: StorageOptions,
) => Promise<void>;
getEncryptedPinProtected: (options?: StorageOptions) => Promise<string>;
setEncryptedPinProtected: (value: string, options?: StorageOptions) => Promise<void>;
getEncryptedPrivateKey: (options?: StorageOptions) => Promise<string>;
setEncryptedPrivateKey: (value: string, options?: StorageOptions) => Promise<void>;
getEncryptedProviderKeys: (options?: StorageOptions) => Promise<any>;
setEncryptedProviderKeys: (value: any, options?: StorageOptions) => Promise<void>;
getEntityId: (options?: StorageOptions) => Promise<string>;
getEnvironmentUrls: (options?: StorageOptions) => Promise<EnvironmentUrls>;
setEnvironmentUrls: (value: EnvironmentUrls, options?: StorageOptions) => Promise<void>;
getEquivalentDomains: (options?: StorageOptions) => Promise<any>;
setEquivalentDomains: (value: string, options?: StorageOptions) => Promise<void>;
getEverBeenUnlocked: (options?: StorageOptions) => Promise<boolean>;
setEverBeenUnlocked: (value: boolean, options?: StorageOptions) => Promise<void>;
getForcePasswordReset: (options?: StorageOptions) => Promise<boolean>;
setForcePasswordReset: (value: boolean, options?: StorageOptions) => Promise<void>;
getInstalledVersion: (options?: StorageOptions) => Promise<string>;
setInstalledVersion: (value: string, options?: StorageOptions) => Promise<void>;
getIsAuthenticated: (options?: StorageOptions) => Promise<boolean>;
getKdfIterations: (options?: StorageOptions) => Promise<number>;
setKdfIterations: (value: number, options?: StorageOptions) => Promise<void>;
getKdfType: (options?: StorageOptions) => Promise<KdfType>;
setKdfType: (value: KdfType, options?: StorageOptions) => Promise<void>;
getKeyHash: (options?: StorageOptions) => Promise<string>;
setKeyHash: (value: string, options?: StorageOptions) => Promise<void>;
getLastActive: (options?: StorageOptions) => Promise<number>;
setLastActive: (value: number, options?: StorageOptions) => Promise<void>;
getLastSync: (options?: StorageOptions) => Promise<string>;
setLastSync: (value: string, options?: StorageOptions) => Promise<void>;
getLegacyEtmKey: (options?: StorageOptions) => Promise<SymmetricCryptoKey>;
setLegacyEtmKey: (value: SymmetricCryptoKey, options?: StorageOptions) => Promise<void>;
getLocalData: (options?: StorageOptions) => Promise<any>;
setLocalData: (value: string, options?: StorageOptions) => Promise<void>;
getLocale: (options?: StorageOptions) => Promise<string>;
setLocale: (value: string, options?: StorageOptions) => Promise<void>;
getLoginRedirect: (options?: StorageOptions) => Promise<any>;
setLoginRedirect: (value: any, options?: StorageOptions) => Promise<void>;
getMainWindowSize: (options?: StorageOptions) => Promise<number>;
setMainWindowSize: (value: number, options?: StorageOptions) => Promise<void>;
getMinimizeOnCopyToClipboard: (options?: StorageOptions) => Promise<boolean>;
setMinimizeOnCopyToClipboard: (value: boolean, options?: StorageOptions) => Promise<void>;
getNeverDomains: (options?: StorageOptions) => Promise<{ [id: string]: any }>;
setNeverDomains: (value: { [id: string]: any }, options?: StorageOptions) => Promise<void>;
getNoAutoPromptBiometrics: (options?: StorageOptions) => Promise<boolean>;
setNoAutoPromptBiometrics: (value: boolean, options?: StorageOptions) => Promise<void>;
getNoAutoPromptBiometricsText: (options?: StorageOptions) => Promise<string>;
setNoAutoPromptBiometricsText: (value: string, options?: StorageOptions) => Promise<void>;
getOpenAtLogin: (options?: StorageOptions) => Promise<boolean>;
setOpenAtLogin: (value: boolean, options?: StorageOptions) => Promise<void>;
getOrganizationInvitation: (options?: StorageOptions) => Promise<any>;
setOrganizationInvitation: (value: any, options?: StorageOptions) => Promise<void>;
getOrganizations: (options?: StorageOptions) => Promise<{ [id: string]: OrganizationData }>;
setOrganizations: (
value: { [id: string]: OrganizationData },
options?: StorageOptions,
) => Promise<void>;
getPasswordGenerationOptions: (options?: StorageOptions) => Promise<any>;
setPasswordGenerationOptions: (value: any, options?: StorageOptions) => Promise<void>;
getUsernameGenerationOptions: (options?: StorageOptions) => Promise<any>;
setUsernameGenerationOptions: (value: any, options?: StorageOptions) => Promise<void>;
getGeneratorOptions: (options?: StorageOptions) => Promise<any>;
setGeneratorOptions: (value: any, options?: StorageOptions) => Promise<void>;
getProtectedPin: (options?: StorageOptions) => Promise<string>;
setProtectedPin: (value: string, options?: StorageOptions) => Promise<void>;
getProviders: (options?: StorageOptions) => Promise<{ [id: string]: ProviderData }>;
setProviders: (value: { [id: string]: ProviderData }, options?: StorageOptions) => Promise<void>;
getPublicKey: (options?: StorageOptions) => Promise<ArrayBuffer>;
setPublicKey: (value: ArrayBuffer, options?: StorageOptions) => Promise<void>;
getRefreshToken: (options?: StorageOptions) => Promise<string>;
setRefreshToken: (value: string, options?: StorageOptions) => Promise<void>;
getRememberedEmail: (options?: StorageOptions) => Promise<string>;
setRememberedEmail: (value: string, options?: StorageOptions) => Promise<void>;
getSecurityStamp: (options?: StorageOptions) => Promise<string>;
setSecurityStamp: (value: string, options?: StorageOptions) => Promise<void>;
getSettings: (options?: StorageOptions) => Promise<any>;
setSettings: (value: string, options?: StorageOptions) => Promise<void>;
getSsoCodeVerifier: (options?: StorageOptions) => Promise<string>;
setSsoCodeVerifier: (value: string, options?: StorageOptions) => Promise<void>;
getSsoOrgIdentifier: (options?: StorageOptions) => Promise<string>;
setSsoOrganizationIdentifier: (value: string, options?: StorageOptions) => Promise<void>;
getSsoState: (options?: StorageOptions) => Promise<string>;
setSsoState: (value: string, options?: StorageOptions) => Promise<void>;
getTheme: (options?: StorageOptions) => Promise<ThemeType>;
setTheme: (value: ThemeType, options?: StorageOptions) => Promise<void>;
getTwoFactorToken: (options?: StorageOptions) => Promise<string>;
setTwoFactorToken: (value: string, options?: StorageOptions) => Promise<void>;
getUserId: (options?: StorageOptions) => Promise<string>;
getUsesKeyConnector: (options?: StorageOptions) => Promise<boolean>;
setUsesKeyConnector: (vaule: boolean, options?: StorageOptions) => Promise<void>;
getVaultTimeout: (options?: StorageOptions) => Promise<number>;
setVaultTimeout: (value: number, options?: StorageOptions) => Promise<void>;
getVaultTimeoutAction: (options?: StorageOptions) => Promise<string>;
setVaultTimeoutAction: (value: string, options?: StorageOptions) => Promise<void>;
getStateVersion: () => Promise<number>;
setStateVersion: (value: number) => Promise<void>;
getWindow: () => Promise<WindowState>;
setWindow: (value: WindowState) => Promise<void>;
}
// Stub file - re-exports DC StateService
export { StateService } from "@/libs/abstractions/state.service";

View File

@@ -1,4 +0,0 @@
export abstract class StateMigrationService {
needsMigration: () => Promise<boolean>;
migrate: () => Promise<void>;
}

View File

@@ -1,32 +1,2 @@
import { IdentityTokenResponse } from "../models/response/identityTokenResponse";
export abstract class TokenService {
setTokens: (
accessToken: string,
refreshToken: string,
clientIdClientSecret: [string, string],
) => Promise<any>;
setToken: (token: string) => Promise<any>;
getToken: () => Promise<string>;
setRefreshToken: (refreshToken: string) => Promise<any>;
getRefreshToken: () => Promise<string>;
setClientId: (clientId: string) => Promise<any>;
getClientId: () => Promise<string>;
setClientSecret: (clientSecret: string) => Promise<any>;
getClientSecret: () => Promise<string>;
setTwoFactorToken: (tokenResponse: IdentityTokenResponse) => Promise<any>;
getTwoFactorToken: () => Promise<string>;
clearTwoFactorToken: () => Promise<any>;
clearToken: (userId?: string) => Promise<any>;
decodeToken: (token?: string) => any;
getTokenExpirationDate: () => Promise<Date>;
tokenSecondsRemaining: (offsetSeconds?: number) => Promise<number>;
tokenNeedsRefresh: (minutes?: number) => Promise<boolean>;
getUserId: () => Promise<string>;
getEmail: () => Promise<string>;
getEmailVerified: () => Promise<boolean>;
getName: () => Promise<string>;
getPremium: () => Promise<boolean>;
getIssuer: () => Promise<string>;
getIsExternal: () => Promise<boolean>;
}
// Stub file - re-exports DC TokenService
export { TokenService } from "@/libs/abstractions/token.service";

View File

@@ -1,6 +0,0 @@
export enum AuthenticationStatus {
Locked = "locked",
Unlocked = "unlocked",
LoggedOut = "loggedOut",
Active = "active",
}

View File

@@ -1,4 +0,0 @@
export enum CipherRepromptType {
None = 0,
Password = 1,
}

View File

@@ -1,6 +0,0 @@
export enum CipherType {
Login = 1,
SecureNote = 2,
Card = 3,
Identity = 4,
}

View File

@@ -1,7 +0,0 @@
export enum EmergencyAccessStatusType {
Invited = 0,
Accepted = 1,
Confirmed = 2,
RecoveryInitiated = 3,
RecoveryApproved = 4,
}

View File

@@ -1,4 +0,0 @@
export enum EmergencyAccessType {
View = 0,
Takeover = 1,
}

View File

@@ -1,6 +0,0 @@
export enum FieldType {
Text = 0,
Hidden = 1,
Boolean = 2,
Linked = 3,
}

View File

@@ -1,4 +0,0 @@
export enum FileUploadType {
Direct = 0,
Azure = 1,
}

View File

@@ -1,4 +0,0 @@
export enum HashPurpose {
ServerAuthorization = 1,
LocalAuthorization = 2,
}

View File

@@ -1,4 +0,0 @@
export enum KeySuffixOptions {
Auto = "auto",
Biometric = "biometric",
}

View File

@@ -1,20 +0,0 @@
export enum NotificationType {
SyncCipherUpdate = 0,
SyncCipherCreate = 1,
SyncLoginDelete = 2,
SyncFolderDelete = 3,
SyncCiphers = 4,
SyncVault = 5,
SyncOrgKeys = 6,
SyncFolderCreate = 7,
SyncFolderUpdate = 8,
SyncCipherDelete = 9,
SyncSettings = 10,
LogOut = 11,
SyncSendCreate = 12,
SyncSendUpdate = 13,
SyncSendDelete = 14,
}

View File

@@ -1,5 +0,0 @@
export enum OrganizationUserStatusType {
Invited = 0,
Accepted = 1,
Confirmed = 2,
}

View File

@@ -1,7 +0,0 @@
export enum OrganizationUserType {
Owner = 0,
Admin = 1,
User = 2,
Manager = 3,
Custom = 4,
}

View File

@@ -1,11 +0,0 @@
export enum PaymentMethodType {
Card = 0,
BankAccount = 1,
PayPal = 2,
BitPay = 3,
Credit = 4,
WireTransfer = 5,
AppleInApp = 6,
GoogleInApp = 7,
Check = 8,
}

View File

@@ -1,27 +0,0 @@
export enum Permissions {
AccessEventLogs,
AccessImportExport,
AccessReports,
/**
* @deprecated Sep 29 2021: This permission has been split out to `createNewCollections`, `editAnyCollection`, and
* `deleteAnyCollection`. It exists here for backwards compatibility with Server versions <= 1.43.0
*/
ManageAllCollections,
/**
* @deprecated Sep 29 2021: This permission has been split out to `editAssignedCollections` and
* `deleteAssignedCollections`. It exists here for backwards compatibility with Server versions <= 1.43.0
*/
ManageAssignedCollections,
ManageGroups,
ManageOrganization,
ManagePolicies,
ManageProvider,
ManageUsers,
ManageUsersPassword,
CreateNewCollections,
EditAnyCollection,
DeleteAnyCollection,
EditAssignedCollections,
DeleteAssignedCollections,
ManageSso,
}

View File

@@ -1,3 +0,0 @@
export enum PlanSponsorshipType {
FamiliesForEnterprise = 0,
}

View File

@@ -1,14 +0,0 @@
export enum PlanType {
Free = 0,
FamiliesAnnually2019 = 1,
TeamsMonthly2019 = 2,
TeamsAnnually2019 = 3,
EnterpriseMonthly2019 = 4,
EnterpriseAnnually2019 = 5,
Custom = 6,
FamiliesAnnually = 7,
TeamsMonthly = 8,
TeamsAnnually = 9,
EnterpriseMonthly = 10,
EnterpriseAnnually = 11,
}

View File

@@ -1,6 +0,0 @@
export enum ProductType {
Free = 0,
Families = 1,
Teams = 2,
Enterprise = 3,
}

View File

@@ -1,5 +0,0 @@
export enum ProviderUserStatusType {
Invited = 0,
Accepted = 1,
Confirmed = 2,
}

View File

@@ -1,4 +0,0 @@
export enum ProviderUserType {
ProviderAdmin = 0,
ServiceUser = 1,
}

View File

@@ -1,33 +0,0 @@
export enum SsoType {
None = 0,
OpenIdConnect = 1,
Saml2 = 2,
}
export enum OpenIdConnectRedirectBehavior {
RedirectGet = 0,
FormPost = 1,
}
export enum Saml2BindingType {
HttpRedirect = 1,
HttpPost = 2,
}
export enum Saml2NameIdFormat {
NotConfigured = 0,
Unspecified = 1,
EmailAddress = 2,
X509SubjectName = 3,
WindowsDomainQualifiedName = 4,
KerberosPrincipalName = 5,
EntityIdentifier = 6,
Persistent = 7,
Transient = 8,
}
export enum Saml2SigningBehavior {
IfIdpWantAuthnRequestsSigned = 0,
Always = 1,
Never = 3,
}

View File

@@ -1,7 +0,0 @@
export enum TransactionType {
Charge = 0,
Credit = 1,
PromotionalCredit = 2,
ReferralCredit = 3,
Refund = 4,
}

View File

@@ -1,8 +0,0 @@
export enum UriMatchType {
Domain = 0,
Host = 1,
StartsWith = 2,
Exact = 3,
RegularExpression = 4,
Never = 5,
}

View File

@@ -1,13 +0,0 @@
import { Account } from "../models/domain/account";
export class AccountFactory<T extends Account = Account> {
private accountConstructor: new (init: Partial<T>) => T;
constructor(accountConstructor: new (init: Partial<T>) => T) {
this.accountConstructor = accountConstructor;
}
create(args: Partial<T>) {
return new this.accountConstructor(args);
}
}

View File

@@ -1,13 +0,0 @@
import { GlobalState } from "../models/domain/globalState";
export class GlobalStateFactory<T extends GlobalState = GlobalState> {
private globalStateConstructor: new (init: Partial<T>) => T;
constructor(globalStateConstructor: new (init: Partial<T>) => T) {
this.globalStateConstructor = globalStateConstructor;
}
create(args?: Partial<T>) {
return new this.globalStateConstructor(args);
}
}

View File

@@ -1,29 +0,0 @@
import { Account } from "../models/domain/account";
import { GlobalState } from "../models/domain/globalState";
import { AccountFactory } from "./accountFactory";
import { GlobalStateFactory } from "./globalStateFactory";
export class StateFactory<
TGlobal extends GlobalState = GlobalState,
TAccount extends Account = Account,
> {
private globalStateFactory: GlobalStateFactory<TGlobal>;
private accountFactory: AccountFactory<TAccount>;
constructor(
globalStateConstructor: new (init: Partial<TGlobal>) => TGlobal,
accountConstructor: new (init: Partial<TAccount>) => TAccount,
) {
this.globalStateFactory = new GlobalStateFactory(globalStateConstructor);
this.accountFactory = new AccountFactory(accountConstructor);
}
createGlobal(args: Partial<TGlobal>): TGlobal {
return this.globalStateFactory.create(args);
}
createAccount(args: Partial<TAccount>): TAccount {
return this.accountFactory.create(args);
}
}

View File

@@ -1,72 +0,0 @@
import { ITreeNodeObject, TreeNode } from "../models/domain/treeNode";
export class ServiceUtils {
static nestedTraverse(
nodeTree: TreeNode<ITreeNodeObject>[],
partIndex: number,
parts: string[],
obj: ITreeNodeObject,
parent: ITreeNodeObject,
delimiter: string,
) {
if (parts.length <= partIndex) {
return;
}
const end = partIndex === parts.length - 1;
const partName = parts[partIndex];
for (let i = 0; i < nodeTree.length; i++) {
if (nodeTree[i].node.name !== parts[partIndex]) {
continue;
}
if (end && nodeTree[i].node.id !== obj.id) {
// Another node with the same name.
nodeTree.push(new TreeNode(obj, partName, parent));
return;
}
ServiceUtils.nestedTraverse(
nodeTree[i].children,
partIndex + 1,
parts,
obj,
nodeTree[i].node,
delimiter,
);
return;
}
if (nodeTree.filter((n) => n.node.name === partName).length === 0) {
if (end) {
nodeTree.push(new TreeNode(obj, partName, parent));
return;
}
const newPartName = parts[partIndex] + delimiter + parts[partIndex + 1];
ServiceUtils.nestedTraverse(
nodeTree,
0,
[newPartName, ...parts.slice(partIndex + 2)],
obj,
parent,
delimiter,
);
}
}
static getTreeNodeObject(
nodeTree: TreeNode<ITreeNodeObject>[],
id: string,
): TreeNode<ITreeNodeObject> {
for (let i = 0; i < nodeTree.length; i++) {
if (nodeTree[i].node.id === id) {
return nodeTree[i];
} else if (nodeTree[i].children != null) {
const node = ServiceUtils.getTreeNodeObject(nodeTree[i].children, id);
if (node !== null) {
return node;
}
}
}
return null;
}
}

View File

@@ -1,69 +0,0 @@
/**
* Use as a Decorator on async functions, it will limit how many times the function can be
* in-flight at a time.
*
* Calls beyond the limit will be queued, and run when one of the active calls finishes
*/
export function throttle(limit: number, throttleKey: (args: any[]) => string) {
return <T>(
target: any,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<T>>,
) => {
const originalMethod: () => Promise<T> = descriptor.value;
const allThrottles = new Map<any, Map<string, (() => void)[]>>();
const getThrottles = (obj: any) => {
let throttles = allThrottles.get(obj);
if (throttles != null) {
return throttles;
}
throttles = new Map<string, (() => void)[]>();
allThrottles.set(obj, throttles);
return throttles;
};
return {
value: function (...args: any[]) {
const throttles = getThrottles(this);
const argsThrottleKey = throttleKey(args);
let queue = throttles.get(argsThrottleKey);
if (queue == null) {
queue = [];
throttles.set(argsThrottleKey, queue);
}
return new Promise<T>((resolve, reject) => {
const exec = () => {
const onFinally = () => {
queue.splice(queue.indexOf(exec), 1);
if (queue.length >= limit) {
queue[limit - 1]();
} else if (queue.length === 0) {
throttles.delete(argsThrottleKey);
if (throttles.size === 0) {
allThrottles.delete(this);
}
}
};
originalMethod
.apply(this, args)
.then((val: any) => {
onFinally();
return val;
})
.catch((err: any) => {
onFinally();
throw err;
})
.then(resolve, reject);
};
queue.push(exec);
if (queue.length <= limit) {
exec();
}
});
},
};
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +0,0 @@
import { BaseResponse } from "../response/baseResponse";
export class PermissionsApi extends BaseResponse {
accessEventLogs: boolean;
accessImportExport: boolean;
accessReports: boolean;
/**
* @deprecated Sep 29 2021: This permission has been split out to `createNewCollections`, `editAnyCollection`, and
* `deleteAnyCollection`. It exists here for backwards compatibility with Server versions <= 1.43.0
*/
manageAllCollections: boolean;
createNewCollections: boolean;
editAnyCollection: boolean;
deleteAnyCollection: boolean;
/**
* @deprecated Sep 29 2021: This permission has been split out to `editAssignedCollections` and
* `deleteAssignedCollections`. It exists here for backwards compatibility with Server versions <= 1.43.0
*/
manageAssignedCollections: boolean;
editAssignedCollections: boolean;
deleteAssignedCollections: boolean;
manageCiphers: boolean;
manageGroups: boolean;
manageSso: boolean;
managePolicies: boolean;
manageUsers: boolean;
manageResetPassword: boolean;
constructor(data: any = null) {
super(data);
if (data == null) {
return this;
}
this.accessEventLogs = this.getResponseProperty("AccessEventLogs");
this.accessImportExport = this.getResponseProperty("AccessImportExport");
this.accessReports = this.getResponseProperty("AccessReports");
// For backwards compatibility with Server <= 1.43.0
this.manageAllCollections = this.getResponseProperty("ManageAllCollections");
this.manageAssignedCollections = this.getResponseProperty("ManageAssignedCollections");
this.createNewCollections = this.getResponseProperty("CreateNewCollections");
this.editAnyCollection = this.getResponseProperty("EditAnyCollection");
this.deleteAnyCollection = this.getResponseProperty("DeleteAnyCollection");
this.editAssignedCollections = this.getResponseProperty("EditAssignedCollections");
this.deleteAssignedCollections = this.getResponseProperty("DeleteAssignedCollections");
this.manageCiphers = this.getResponseProperty("ManageCiphers");
this.manageGroups = this.getResponseProperty("ManageGroups");
this.manageSso = this.getResponseProperty("ManageSso");
this.managePolicies = this.getResponseProperty("ManagePolicies");
this.manageUsers = this.getResponseProperty("ManageUsers");
this.manageResetPassword = this.getResponseProperty("ManageResetPassword");
}
}

View File

@@ -1,136 +0,0 @@
import {
OpenIdConnectRedirectBehavior,
Saml2BindingType,
Saml2NameIdFormat,
Saml2SigningBehavior,
SsoType,
} from "../../enums/ssoEnums";
import { BaseResponse } from "../response/baseResponse";
import { SsoConfigView } from "../view/ssoConfigView";
export class SsoConfigApi extends BaseResponse {
static fromView(view: SsoConfigView, api = new SsoConfigApi()) {
api.configType = view.configType;
api.keyConnectorEnabled = view.keyConnectorEnabled;
api.keyConnectorUrl = view.keyConnectorUrl;
if (api.configType === SsoType.OpenIdConnect) {
api.authority = view.openId.authority;
api.clientId = view.openId.clientId;
api.clientSecret = view.openId.clientSecret;
api.metadataAddress = view.openId.metadataAddress;
api.redirectBehavior = view.openId.redirectBehavior;
api.getClaimsFromUserInfoEndpoint = view.openId.getClaimsFromUserInfoEndpoint;
api.additionalScopes = view.openId.additionalScopes;
api.additionalUserIdClaimTypes = view.openId.additionalUserIdClaimTypes;
api.additionalEmailClaimTypes = view.openId.additionalEmailClaimTypes;
api.additionalNameClaimTypes = view.openId.additionalNameClaimTypes;
api.acrValues = view.openId.acrValues;
api.expectedReturnAcrValue = view.openId.expectedReturnAcrValue;
} else if (api.configType === SsoType.Saml2) {
api.spNameIdFormat = view.saml.spNameIdFormat;
api.spOutboundSigningAlgorithm = view.saml.spOutboundSigningAlgorithm;
api.spSigningBehavior = view.saml.spSigningBehavior;
api.spMinIncomingSigningAlgorithm = view.saml.spMinIncomingSigningAlgorithm;
api.spWantAssertionsSigned = view.saml.spWantAssertionsSigned;
api.spValidateCertificates = view.saml.spValidateCertificates;
api.idpEntityId = view.saml.idpEntityId;
api.idpBindingType = view.saml.idpBindingType;
api.idpSingleSignOnServiceUrl = view.saml.idpSingleSignOnServiceUrl;
api.idpSingleLogoutServiceUrl = view.saml.idpSingleLogoutServiceUrl;
api.idpX509PublicCert = view.saml.idpX509PublicCert;
api.idpOutboundSigningAlgorithm = view.saml.idpOutboundSigningAlgorithm;
api.idpAllowUnsolicitedAuthnResponse = view.saml.idpAllowUnsolicitedAuthnResponse;
api.idpWantAuthnRequestsSigned = view.saml.idpWantAuthnRequestsSigned;
// Value is inverted in the api model (disable instead of allow)
api.idpDisableOutboundLogoutRequests = !view.saml.idpAllowOutboundLogoutRequests;
}
return api;
}
configType: SsoType;
keyConnectorEnabled: boolean;
keyConnectorUrl: string;
// OpenId
authority: string;
clientId: string;
clientSecret: string;
metadataAddress: string;
redirectBehavior: OpenIdConnectRedirectBehavior;
getClaimsFromUserInfoEndpoint: boolean;
additionalScopes: string;
additionalUserIdClaimTypes: string;
additionalEmailClaimTypes: string;
additionalNameClaimTypes: string;
acrValues: string;
expectedReturnAcrValue: string;
// SAML
spNameIdFormat: Saml2NameIdFormat;
spOutboundSigningAlgorithm: string;
spSigningBehavior: Saml2SigningBehavior;
spMinIncomingSigningAlgorithm: boolean;
spWantAssertionsSigned: boolean;
spValidateCertificates: boolean;
idpEntityId: string;
idpBindingType: Saml2BindingType;
idpSingleSignOnServiceUrl: string;
idpSingleLogoutServiceUrl: string;
idpX509PublicCert: string;
idpOutboundSigningAlgorithm: string;
idpAllowUnsolicitedAuthnResponse: boolean;
idpDisableOutboundLogoutRequests: boolean;
idpWantAuthnRequestsSigned: boolean;
constructor(data: any = null) {
super(data);
if (data == null) {
return;
}
this.configType = this.getResponseProperty("ConfigType");
this.keyConnectorEnabled = this.getResponseProperty("KeyConnectorEnabled");
this.keyConnectorUrl = this.getResponseProperty("KeyConnectorUrl");
this.authority = this.getResponseProperty("Authority");
this.clientId = this.getResponseProperty("ClientId");
this.clientSecret = this.getResponseProperty("ClientSecret");
this.metadataAddress = this.getResponseProperty("MetadataAddress");
this.redirectBehavior = this.getResponseProperty("RedirectBehavior");
this.getClaimsFromUserInfoEndpoint = this.getResponseProperty("GetClaimsFromUserInfoEndpoint");
this.additionalScopes = this.getResponseProperty("AdditionalScopes");
this.additionalUserIdClaimTypes = this.getResponseProperty("AdditionalUserIdClaimTypes");
this.additionalEmailClaimTypes = this.getResponseProperty("AdditionalEmailClaimTypes");
this.additionalNameClaimTypes = this.getResponseProperty("AdditionalNameClaimTypes");
this.acrValues = this.getResponseProperty("AcrValues");
this.expectedReturnAcrValue = this.getResponseProperty("ExpectedReturnAcrValue");
this.spNameIdFormat = this.getResponseProperty("SpNameIdFormat");
this.spOutboundSigningAlgorithm = this.getResponseProperty("SpOutboundSigningAlgorithm");
this.spSigningBehavior = this.getResponseProperty("SpSigningBehavior");
this.spMinIncomingSigningAlgorithm = this.getResponseProperty("SpMinIncomingSigningAlgorithm");
this.spWantAssertionsSigned = this.getResponseProperty("SpWantAssertionsSigned");
this.spValidateCertificates = this.getResponseProperty("SpValidateCertificates");
this.idpEntityId = this.getResponseProperty("IdpEntityId");
this.idpBindingType = this.getResponseProperty("IdpBindingType");
this.idpSingleSignOnServiceUrl = this.getResponseProperty("IdpSingleSignOnServiceUrl");
this.idpSingleLogoutServiceUrl = this.getResponseProperty("IdpSingleLogoutServiceUrl");
this.idpX509PublicCert = this.getResponseProperty("IdpX509PublicCert");
this.idpOutboundSigningAlgorithm = this.getResponseProperty("IdpOutboundSigningAlgorithm");
this.idpAllowUnsolicitedAuthnResponse = this.getResponseProperty(
"IdpAllowUnsolicitedAuthnResponse",
);
this.idpDisableOutboundLogoutRequests = this.getResponseProperty(
"IdpDisableOutboundLogoutRequests",
);
this.idpWantAuthnRequestsSigned = this.getResponseProperty("IdpWantAuthnRequestsSigned");
}
}

View File

@@ -1,78 +0,0 @@
import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType";
import { OrganizationUserType } from "../../enums/organizationUserType";
import { ProductType } from "../../enums/productType";
import { PermissionsApi } from "../api/permissionsApi";
import { ProfileOrganizationResponse } from "../response/profileOrganizationResponse";
export class OrganizationData {
id: string;
name: string;
status: OrganizationUserStatusType;
type: OrganizationUserType;
enabled: boolean;
usePolicies: boolean;
useGroups: boolean;
useDirectory: boolean;
useEvents: boolean;
useTotp: boolean;
use2fa: boolean;
useApi: boolean;
useSso: boolean;
useKeyConnector: boolean;
useResetPassword: boolean;
selfHost: boolean;
usersGetPremium: boolean;
seats: number;
maxCollections: number;
maxStorageGb?: number;
ssoBound: boolean;
identifier: string;
permissions: PermissionsApi;
resetPasswordEnrolled: boolean;
userId: string;
hasPublicAndPrivateKeys: boolean;
providerId: string;
providerName: string;
isProviderUser: boolean;
familySponsorshipFriendlyName: string;
familySponsorshipAvailable: boolean;
planProductType: ProductType;
keyConnectorEnabled: boolean;
keyConnectorUrl: string;
constructor(response: ProfileOrganizationResponse) {
this.id = response.id;
this.name = response.name;
this.status = response.status;
this.type = response.type;
this.enabled = response.enabled;
this.usePolicies = response.usePolicies;
this.useGroups = response.useGroups;
this.useDirectory = response.useDirectory;
this.useEvents = response.useEvents;
this.useTotp = response.useTotp;
this.use2fa = response.use2fa;
this.useApi = response.useApi;
this.useSso = response.useSso;
this.useKeyConnector = response.useKeyConnector;
this.useResetPassword = response.useResetPassword;
this.selfHost = response.selfHost;
this.usersGetPremium = response.usersGetPremium;
this.seats = response.seats;
this.maxCollections = response.maxCollections;
this.maxStorageGb = response.maxStorageGb;
this.ssoBound = response.ssoBound;
this.identifier = response.identifier;
this.permissions = response.permissions;
this.resetPasswordEnrolled = response.resetPasswordEnrolled;
this.userId = response.userId;
this.hasPublicAndPrivateKeys = response.hasPublicAndPrivateKeys;
this.providerId = response.providerId;
this.providerName = response.providerName;
this.familySponsorshipFriendlyName = response.familySponsorshipFriendlyName;
this.familySponsorshipAvailable = response.familySponsorshipAvailable;
this.planProductType = response.planProductType;
this.keyConnectorEnabled = response.keyConnectorEnabled;
this.keyConnectorUrl = response.keyConnectorUrl;
}
}

View File

@@ -1,23 +0,0 @@
import { ProviderUserStatusType } from "../../enums/providerUserStatusType";
import { ProviderUserType } from "../../enums/providerUserType";
import { ProfileProviderResponse } from "../response/profileProviderResponse";
export class ProviderData {
id: string;
name: string;
status: ProviderUserStatusType;
type: ProviderUserType;
enabled: boolean;
userId: string;
useEvents: boolean;
constructor(response: ProfileProviderResponse) {
this.id = response.id;
this.name = response.name;
this.status = response.status;
this.type = response.type;
this.enabled = response.enabled;
this.userId = response.userId;
this.useEvents = response.useEvents;
}
}

View File

@@ -1,151 +0,0 @@
import { AuthenticationStatus } from "../../enums/authenticationStatus";
import { KdfType } from "../../enums/kdfType";
import { UriMatchType } from "../../enums/uriMatchType";
import { OrganizationData } from "../data/organizationData";
import { ProviderData } from "../data/providerData";
import { EncString } from "./encString";
import { EnvironmentUrls } from "./environmentUrls";
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
export class EncryptionPair<TEncrypted, TDecrypted> {
encrypted?: TEncrypted;
decrypted?: TDecrypted;
}
export class DataEncryptionPair<TEncrypted, TDecrypted> {
encrypted?: { [id: string]: TEncrypted };
decrypted?: TDecrypted[];
}
export class AccountData {
ciphers?: any = new DataEncryptionPair<any, any>();
folders?: DataEncryptionPair<any, any> = new DataEncryptionPair<any, any>();
localData?: any;
sends?: any = new DataEncryptionPair<any, any>();
collections?: DataEncryptionPair<any, any> = new DataEncryptionPair<any, any>();
policies?: DataEncryptionPair<any, any> = new DataEncryptionPair<any, any>();
passwordGenerationHistory?: EncryptionPair<any[], any[]> = new EncryptionPair<any[], any[]>();
addEditCipherInfo?: any;
eventCollection?: any[];
organizations?: { [id: string]: OrganizationData };
providers?: { [id: string]: ProviderData };
}
export class AccountKeys {
cryptoMasterKey?: SymmetricCryptoKey;
cryptoMasterKeyAuto?: string;
cryptoMasterKeyB64?: string;
cryptoMasterKeyBiometric?: string;
cryptoSymmetricKey?: EncryptionPair<string, SymmetricCryptoKey> = new EncryptionPair<
string,
SymmetricCryptoKey
>();
organizationKeys?: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair<
any,
Map<string, SymmetricCryptoKey>
>();
providerKeys?: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair<
any,
Map<string, SymmetricCryptoKey>
>();
privateKey?: EncryptionPair<string, ArrayBuffer> = new EncryptionPair<string, ArrayBuffer>();
legacyEtmKey?: SymmetricCryptoKey;
publicKey?: ArrayBuffer;
apiKeyClientSecret?: string;
}
export class AccountProfile {
apiKeyClientId?: string;
authenticationStatus?: AuthenticationStatus;
convertAccountToKeyConnector?: boolean;
email?: string;
emailVerified?: boolean;
entityId?: string;
entityType?: string;
everBeenUnlocked?: boolean;
forcePasswordReset?: boolean;
hasPremiumPersonally?: boolean;
lastSync?: string;
userId?: string;
usesKeyConnector?: boolean;
keyHash?: string;
kdfIterations?: number;
kdfType?: KdfType;
}
export class AccountSettings {
autoConfirmFingerPrints?: boolean;
autoFillOnPageLoadDefault?: boolean;
biometricLocked?: boolean;
biometricUnlock?: boolean;
clearClipboard?: number;
collapsedGroupings?: string[];
defaultUriMatch?: UriMatchType;
disableAddLoginNotification?: boolean;
disableAutoBiometricsPrompt?: boolean;
disableAutoTotpCopy?: boolean;
disableBadgeCounter?: boolean;
disableChangedPasswordNotification?: boolean;
disableContextMenuItem?: boolean;
disableGa?: boolean;
dontShowCardsCurrentTab?: boolean;
dontShowIdentitiesCurrentTab?: boolean;
enableAlwaysOnTop?: boolean;
enableAutoFillOnPageLoad?: boolean;
enableBiometric?: boolean;
enableFullWidth?: boolean;
enableGravitars?: boolean;
environmentUrls: EnvironmentUrls = new EnvironmentUrls();
equivalentDomains?: any;
minimizeOnCopyToClipboard?: boolean;
neverDomains?: { [id: string]: any };
passwordGenerationOptions?: any;
usernameGenerationOptions?: any;
generatorOptions?: any;
pinProtected?: EncryptionPair<string, EncString> = new EncryptionPair<string, EncString>();
protectedPin?: string;
settings?: any; // TODO: Merge whatever is going on here into the AccountSettings model properly
vaultTimeout?: number;
vaultTimeoutAction?: string = "lock";
}
export class AccountTokens {
accessToken?: string;
decodedToken?: any;
refreshToken?: string;
securityStamp?: string;
}
export class Account {
data?: AccountData = new AccountData();
keys?: AccountKeys = new AccountKeys();
profile?: AccountProfile = new AccountProfile();
settings?: AccountSettings = new AccountSettings();
tokens?: AccountTokens = new AccountTokens();
constructor(init: Partial<Account>) {
Object.assign(this, {
data: {
...new AccountData(),
...init?.data,
},
keys: {
...new AccountKeys(),
...init?.keys,
},
profile: {
...new AccountProfile(),
...init?.profile,
},
settings: {
...new AccountSettings(),
...init?.settings,
},
tokens: {
...new AccountTokens(),
...init?.tokens,
},
});
}
}

View File

@@ -1,82 +0,0 @@
import { View } from "../view/view";
import { EncString } from "./encString";
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
export default class Domain {
protected buildDomainModel<D extends Domain>(
domain: D,
dataObj: any,
map: any,
notEncList: any[] = [],
) {
for (const prop in map) {
// eslint-disable-next-line
if (!map.hasOwnProperty(prop)) {
continue;
}
const objProp = dataObj[map[prop] || prop];
if (notEncList.indexOf(prop) > -1) {
(domain as any)[prop] = objProp ? objProp : null;
} else {
(domain as any)[prop] = objProp ? new EncString(objProp) : null;
}
}
}
protected buildDataModel<D extends Domain>(
domain: D,
dataObj: any,
map: any,
notEncStringList: any[] = [],
) {
for (const prop in map) {
// eslint-disable-next-line
if (!map.hasOwnProperty(prop)) {
continue;
}
const objProp = (domain as any)[map[prop] || prop];
if (notEncStringList.indexOf(prop) > -1) {
(dataObj as any)[prop] = objProp != null ? objProp : null;
} else {
(dataObj as any)[prop] = objProp != null ? (objProp as EncString).encryptedString : null;
}
}
}
protected async decryptObj<T extends View>(
viewModel: T,
map: any,
orgId: string,
key: SymmetricCryptoKey = null,
): Promise<T> {
const promises = [];
const self: any = this;
for (const prop in map) {
// eslint-disable-next-line
if (!map.hasOwnProperty(prop)) {
continue;
}
(function (theProp) {
const p = Promise.resolve()
.then(() => {
const mapProp = map[theProp] || theProp;
if (self[mapProp]) {
return self[mapProp].decrypt(orgId, key);
}
return null;
})
.then((val: any) => {
(viewModel as any)[theProp] = val;
});
promises.push(p);
})(prop);
}
await Promise.all(promises);
return viewModel;
}
}

View File

@@ -1,3 +0,0 @@
export class EncArrayBuffer {
constructor(public buffer: ArrayBuffer) {}
}

View File

@@ -1,122 +0,0 @@
import { CryptoService } from "../../abstractions/crypto.service";
import { EncryptionType } from "../../enums/encryptionType";
import { Utils } from "../../misc/utils";
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
export class EncString {
encryptedString?: string;
encryptionType?: EncryptionType;
decryptedValue?: string;
data?: string;
iv?: string;
mac?: string;
constructor(
encryptedStringOrType: string | EncryptionType,
data?: string,
iv?: string,
mac?: string,
) {
if (data != null) {
// data and header
const encType = encryptedStringOrType as EncryptionType;
if (iv != null) {
this.encryptedString = encType + "." + iv + "|" + data;
} else {
this.encryptedString = encType + "." + data;
}
// mac
if (mac != null) {
this.encryptedString += "|" + mac;
}
this.encryptionType = encType;
this.data = data;
this.iv = iv;
this.mac = mac;
return;
}
this.encryptedString = encryptedStringOrType as string;
if (!this.encryptedString) {
return;
}
const headerPieces = this.encryptedString.split(".");
let encPieces: string[] = null;
if (headerPieces.length === 2) {
try {
this.encryptionType = parseInt(headerPieces[0], null);
encPieces = headerPieces[1].split("|");
} catch {
return;
}
} else {
encPieces = this.encryptedString.split("|");
this.encryptionType =
encPieces.length === 3
? EncryptionType.AesCbc128_HmacSha256_B64
: EncryptionType.AesCbc256_B64;
}
switch (this.encryptionType) {
case EncryptionType.AesCbc128_HmacSha256_B64:
case EncryptionType.AesCbc256_HmacSha256_B64:
if (encPieces.length !== 3) {
return;
}
this.iv = encPieces[0];
this.data = encPieces[1];
this.mac = encPieces[2];
break;
case EncryptionType.AesCbc256_B64:
if (encPieces.length !== 2) {
return;
}
this.iv = encPieces[0];
this.data = encPieces[1];
break;
case EncryptionType.Rsa2048_OaepSha256_B64:
case EncryptionType.Rsa2048_OaepSha1_B64:
if (encPieces.length !== 1) {
return;
}
this.data = encPieces[0];
break;
default:
return;
}
}
async decrypt(orgId: string, key: SymmetricCryptoKey = null): Promise<string> {
if (this.decryptedValue != null) {
return this.decryptedValue;
}
let cryptoService: CryptoService;
const containerService = (Utils.global as any).bitwardenContainerService;
if (containerService) {
cryptoService = containerService.getCryptoService();
} else {
throw new Error("global bitwardenContainerService not initialized.");
}
try {
if (key == null) {
key = await cryptoService.getOrgKey(orgId);
}
this.decryptedValue = await cryptoService.decryptToUtf8(this, key);
} catch {
this.decryptedValue = "[error: cannot decrypt]";
}
return this.decryptedValue;
}
}

View File

@@ -1,8 +0,0 @@
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
export class EncryptedObject {
iv: ArrayBuffer;
data: ArrayBuffer;
mac: ArrayBuffer;
key: SymmetricCryptoKey;
}

View File

@@ -2,9 +2,5 @@ export class EnvironmentUrls {
base: string = null;
api: string = null;
identity: string = null;
icons: string = null;
notifications: string = null;
events: string = null;
webVault: string = null;
keyConnector: string = null;
}

View File

@@ -1,40 +0,0 @@
import { StateVersion } from "../../enums/stateVersion";
import { ThemeType } from "../../enums/themeType";
import { EnvironmentUrls } from "./environmentUrls";
import { WindowState } from "./windowState";
export class GlobalState {
enableAlwaysOnTop?: boolean;
installedVersion?: string;
locale?: string = "en";
organizationInvitation?: any;
ssoCodeVerifier?: string;
ssoOrganizationIdentifier?: string;
ssoState?: string;
rememberedEmail?: string;
theme?: ThemeType = ThemeType.System;
window?: WindowState = new WindowState();
twoFactorToken?: string;
disableFavicon?: boolean;
biometricAwaitingAcceptance?: boolean;
biometricFingerprintValidated?: boolean;
vaultTimeout?: number;
vaultTimeoutAction?: string;
loginRedirect?: any;
mainWindowSize?: number;
enableBiometrics?: boolean;
biometricText?: string;
noAutoPromptBiometrics?: boolean;
noAutoPromptBiometricsText?: string;
stateVersion: StateVersion = StateVersion.One;
environmentUrls: EnvironmentUrls = new EnvironmentUrls();
enableTray?: boolean;
enableMinimizeToTray?: boolean;
enableCloseToTray?: boolean;
enableStartToTray?: boolean;
openAtLogin?: boolean;
alwaysShowDock?: boolean;
enableBrowserIntegration?: boolean;
enableBrowserIntegrationFingerprint?: boolean;
}

View File

@@ -1,184 +0,0 @@
import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType";
import { OrganizationUserType } from "../../enums/organizationUserType";
import { ProductType } from "../../enums/productType";
import { PermissionsApi } from "../api/permissionsApi";
import { OrganizationData } from "../data/organizationData";
export class Organization {
id: string;
name: string;
status: OrganizationUserStatusType;
type: OrganizationUserType;
enabled: boolean;
usePolicies: boolean;
useGroups: boolean;
useDirectory: boolean;
useEvents: boolean;
useTotp: boolean;
use2fa: boolean;
useApi: boolean;
useSso: boolean;
useKeyConnector: boolean;
useResetPassword: boolean;
selfHost: boolean;
usersGetPremium: boolean;
seats: number;
maxCollections: number;
maxStorageGb?: number;
ssoBound: boolean;
identifier: string;
permissions: PermissionsApi;
resetPasswordEnrolled: boolean;
userId: string;
hasPublicAndPrivateKeys: boolean;
providerId: string;
providerName: string;
isProviderUser: boolean;
familySponsorshipFriendlyName: string;
familySponsorshipAvailable: boolean;
planProductType: ProductType;
keyConnectorEnabled: boolean;
keyConnectorUrl: string;
constructor(obj?: OrganizationData) {
if (obj == null) {
return;
}
this.id = obj.id;
this.name = obj.name;
this.status = obj.status;
this.type = obj.type;
this.enabled = obj.enabled;
this.usePolicies = obj.usePolicies;
this.useGroups = obj.useGroups;
this.useDirectory = obj.useDirectory;
this.useEvents = obj.useEvents;
this.useTotp = obj.useTotp;
this.use2fa = obj.use2fa;
this.useApi = obj.useApi;
this.useSso = obj.useSso;
this.useKeyConnector = obj.useKeyConnector;
this.useResetPassword = obj.useResetPassword;
this.selfHost = obj.selfHost;
this.usersGetPremium = obj.usersGetPremium;
this.seats = obj.seats;
this.maxCollections = obj.maxCollections;
this.maxStorageGb = obj.maxStorageGb;
this.ssoBound = obj.ssoBound;
this.identifier = obj.identifier;
this.permissions = obj.permissions;
this.resetPasswordEnrolled = obj.resetPasswordEnrolled;
this.userId = obj.userId;
this.hasPublicAndPrivateKeys = obj.hasPublicAndPrivateKeys;
this.providerId = obj.providerId;
this.providerName = obj.providerName;
this.isProviderUser = obj.isProviderUser;
this.familySponsorshipFriendlyName = obj.familySponsorshipFriendlyName;
this.familySponsorshipAvailable = obj.familySponsorshipAvailable;
this.planProductType = obj.planProductType;
this.keyConnectorEnabled = obj.keyConnectorEnabled;
this.keyConnectorUrl = obj.keyConnectorUrl;
}
get canAccess() {
if (this.type === OrganizationUserType.Owner) {
return true;
}
return this.enabled && this.status === OrganizationUserStatusType.Confirmed;
}
get isManager() {
return (
this.type === OrganizationUserType.Manager ||
this.type === OrganizationUserType.Owner ||
this.type === OrganizationUserType.Admin
);
}
get isAdmin() {
return this.type === OrganizationUserType.Owner || this.type === OrganizationUserType.Admin;
}
get isOwner() {
return this.type === OrganizationUserType.Owner || this.isProviderUser;
}
get canAccessEventLogs() {
return this.isAdmin || this.permissions.accessEventLogs;
}
get canAccessImportExport() {
return this.isAdmin || this.permissions.accessImportExport;
}
get canAccessReports() {
return this.isAdmin || this.permissions.accessReports;
}
get canCreateNewCollections() {
return (
this.isManager ||
(this.permissions.createNewCollections ?? this.permissions.manageAllCollections)
);
}
get canEditAnyCollection() {
return (
this.isAdmin || (this.permissions.editAnyCollection ?? this.permissions.manageAllCollections)
);
}
get canDeleteAnyCollection() {
return (
this.isAdmin ||
(this.permissions.deleteAnyCollection ?? this.permissions.manageAllCollections)
);
}
get canViewAllCollections() {
return this.canCreateNewCollections || this.canEditAnyCollection || this.canDeleteAnyCollection;
}
get canEditAssignedCollections() {
return (
this.isManager ||
(this.permissions.editAssignedCollections ?? this.permissions.manageAssignedCollections)
);
}
get canDeleteAssignedCollections() {
return (
this.isManager ||
(this.permissions.deleteAssignedCollections ?? this.permissions.manageAssignedCollections)
);
}
get canViewAssignedCollections() {
return this.canDeleteAssignedCollections || this.canEditAssignedCollections;
}
get canManageGroups() {
return this.isAdmin || this.permissions.manageGroups;
}
get canManageSso() {
return this.isAdmin || this.permissions.manageSso;
}
get canManagePolicies() {
return this.isAdmin || this.permissions.managePolicies;
}
get canManageUsers() {
return this.isAdmin || this.permissions.manageUsers;
}
get canManageUsersPassword() {
return this.isAdmin || this.permissions.manageResetPassword;
}
get isExemptFromPolicies() {
return this.canManagePolicies;
}
}

View File

@@ -1,50 +0,0 @@
import { ProviderUserStatusType } from "../../enums/providerUserStatusType";
import { ProviderUserType } from "../../enums/providerUserType";
import { ProviderData } from "../data/providerData";
export class Provider {
id: string;
name: string;
status: ProviderUserStatusType;
type: ProviderUserType;
enabled: boolean;
userId: string;
useEvents: boolean;
constructor(obj?: ProviderData) {
if (obj == null) {
return;
}
this.id = obj.id;
this.name = obj.name;
this.status = obj.status;
this.type = obj.type;
this.enabled = obj.enabled;
this.userId = obj.userId;
this.useEvents = obj.useEvents;
}
get canAccess() {
if (this.isProviderAdmin) {
return true;
}
return this.enabled && this.status === ProviderUserStatusType.Confirmed;
}
get canCreateOrganizations() {
return this.enabled && this.isProviderAdmin;
}
get canManageUsers() {
return this.isProviderAdmin;
}
get canAccessEventLogs() {
return this.isProviderAdmin;
}
get isProviderAdmin() {
return this.type === ProviderUserType.ProviderAdmin;
}
}

View File

@@ -1,17 +0,0 @@
import { Account } from "./account";
import { GlobalState } from "./globalState";
export class State<
TGlobalState extends GlobalState = GlobalState,
TAccount extends Account = Account,
> {
accounts: { [userId: string]: TAccount } = {};
globals: TGlobalState;
activeUserId: string;
authenticatedAccounts: string[] = [];
accountActivity: { [userId: string]: number } = {};
constructor(globals: TGlobalState) {
this.globals = globals;
}
}

View File

@@ -1,16 +0,0 @@
export class TreeNode<T extends ITreeNodeObject> {
parent: T;
node: T;
children: TreeNode<T>[] = [];
constructor(node: T, name: string, parent: T) {
this.parent = parent;
this.node = node;
this.node.name = name;
}
}
export interface ITreeNodeObject {
id: string;
name: string;
}

View File

@@ -1,10 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class ApiKeyResponse extends BaseResponse {
apiKey: string;
constructor(response: any) {
super(response);
this.apiKey = this.getResponseProperty("ApiKey");
}
}

View File

@@ -1,83 +0,0 @@
import { PaymentMethodType } from "../../enums/paymentMethodType";
import { TransactionType } from "../../enums/transactionType";
import { BaseResponse } from "./baseResponse";
export class BillingResponse extends BaseResponse {
balance: number;
paymentSource: BillingSourceResponse;
invoices: BillingInvoiceResponse[] = [];
transactions: BillingTransactionResponse[] = [];
constructor(response: any) {
super(response);
this.balance = this.getResponseProperty("Balance");
const paymentSource = this.getResponseProperty("PaymentSource");
const transactions = this.getResponseProperty("Transactions");
const invoices = this.getResponseProperty("Invoices");
this.paymentSource = paymentSource == null ? null : new BillingSourceResponse(paymentSource);
if (transactions != null) {
this.transactions = transactions.map((t: any) => new BillingTransactionResponse(t));
}
if (invoices != null) {
this.invoices = invoices.map((i: any) => new BillingInvoiceResponse(i));
}
}
}
export class BillingSourceResponse extends BaseResponse {
type: PaymentMethodType;
cardBrand: string;
description: string;
needsVerification: boolean;
constructor(response: any) {
super(response);
this.type = this.getResponseProperty("Type");
this.cardBrand = this.getResponseProperty("CardBrand");
this.description = this.getResponseProperty("Description");
this.needsVerification = this.getResponseProperty("NeedsVerification");
}
}
export class BillingInvoiceResponse extends BaseResponse {
url: string;
pdfUrl: string;
number: string;
paid: boolean;
date: string;
amount: number;
constructor(response: any) {
super(response);
this.url = this.getResponseProperty("Url");
this.pdfUrl = this.getResponseProperty("PdfUrl");
this.number = this.getResponseProperty("Number");
this.paid = this.getResponseProperty("Paid");
this.date = this.getResponseProperty("Date");
this.amount = this.getResponseProperty("Amount");
}
}
export class BillingTransactionResponse extends BaseResponse {
createdDate: string;
amount: number;
refunded: boolean;
partiallyRefunded: boolean;
refundedAmount: number;
type: TransactionType;
paymentMethodType: PaymentMethodType;
details: string;
constructor(response: any) {
super(response);
this.createdDate = this.getResponseProperty("CreatedDate");
this.amount = this.getResponseProperty("Amount");
this.refunded = this.getResponseProperty("Refunded");
this.partiallyRefunded = this.getResponseProperty("PartiallyRefunded");
this.refundedAmount = this.getResponseProperty("RefundedAmount");
this.type = this.getResponseProperty("Type");
this.paymentMethodType = this.getResponseProperty("PaymentMethodType");
this.details = this.getResponseProperty("Details");
}
}

View File

@@ -1,32 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class BreachAccountResponse extends BaseResponse {
addedDate: string;
breachDate: string;
dataClasses: string[];
description: string;
domain: string;
isActive: boolean;
isVerified: boolean;
logoPath: string;
modifiedDate: string;
name: string;
pwnCount: number;
title: string;
constructor(response: any) {
super(response);
this.addedDate = this.getResponseProperty("AddedDate");
this.breachDate = this.getResponseProperty("BreachDate");
this.dataClasses = this.getResponseProperty("DataClasses");
this.description = this.getResponseProperty("Description");
this.domain = this.getResponseProperty("Domain");
this.isActive = this.getResponseProperty("IsActive");
this.isVerified = this.getResponseProperty("IsVerified");
this.logoPath = this.getResponseProperty("LogoPath");
this.modifiedDate = this.getResponseProperty("ModifiedDate");
this.name = this.getResponseProperty("Name");
this.pwnCount = this.getResponseProperty("PwnCount");
this.title = this.getResponseProperty("Title");
}
}

View File

@@ -1,20 +0,0 @@
import { DeviceType } from "../../enums/deviceType";
import { BaseResponse } from "./baseResponse";
export class DeviceResponse extends BaseResponse {
id: string;
name: number;
identifier: string;
type: DeviceType;
creationDate: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.name = this.getResponseProperty("Name");
this.identifier = this.getResponseProperty("Identifier");
this.type = this.getResponseProperty("Type");
this.creationDate = this.getResponseProperty("CreationDate");
}
}

View File

@@ -1,20 +0,0 @@
import { BaseResponse } from "./baseResponse";
import { GlobalDomainResponse } from "./globalDomainResponse";
export class DomainsResponse extends BaseResponse {
equivalentDomains: string[][];
globalEquivalentDomains: GlobalDomainResponse[] = [];
constructor(response: any) {
super(response);
this.equivalentDomains = this.getResponseProperty("EquivalentDomains");
const globalEquivalentDomains = this.getResponseProperty("GlobalEquivalentDomains");
if (globalEquivalentDomains != null) {
this.globalEquivalentDomains = globalEquivalentDomains.map(
(d: any) => new GlobalDomainResponse(d),
);
} else {
this.globalEquivalentDomains = [];
}
}
}

View File

@@ -1,14 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class GlobalDomainResponse extends BaseResponse {
type: number;
domains: string[];
excluded: boolean;
constructor(response: any) {
super(response);
this.type = this.getResponseProperty("Type");
this.domains = this.getResponseProperty("Domains");
this.excluded = this.getResponseProperty("Excluded");
}
}

View File

@@ -1,31 +0,0 @@
import { BaseResponse } from "./baseResponse";
import { SelectionReadOnlyResponse } from "./selectionReadOnlyResponse";
export class GroupResponse extends BaseResponse {
id: string;
organizationId: string;
name: string;
accessAll: boolean;
externalId: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.organizationId = this.getResponseProperty("OrganizationId");
this.name = this.getResponseProperty("Name");
this.accessAll = this.getResponseProperty("AccessAll");
this.externalId = this.getResponseProperty("ExternalId");
}
}
export class GroupDetailsResponse extends GroupResponse {
collections: SelectionReadOnlyResponse[] = [];
constructor(response: any) {
super(response);
const collections = this.getResponseProperty("Collections");
if (collections != null) {
this.collections = collections.map((c: any) => new SelectionReadOnlyResponse(c));
}
}
}

View File

@@ -1,10 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class KeyConnectorUserKeyResponse extends BaseResponse {
key: string;
constructor(response: any) {
super(response);
this.key = this.getResponseProperty("Key");
}
}

View File

@@ -1,12 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class KeysResponse extends BaseResponse {
privateKey: string;
publicKey: string;
constructor(response: any) {
super(response);
this.privateKey = this.getResponseProperty("PrivateKey");
this.publicKey = this.getResponseProperty("PublicKey");
}
}

View File

@@ -1,13 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class ListResponse<T> extends BaseResponse {
data: T[];
continuationToken: string;
constructor(response: any, t: new (dataResponse: any) => T) {
super(response);
const data = this.getResponseProperty("Data");
this.data = data == null ? [] : data.map((dr: any) => new t(dr));
this.continuationToken = this.getResponseProperty("ContinuationToken");
}
}

View File

@@ -1,98 +0,0 @@
import { NotificationType } from "../../enums/notificationType";
import { BaseResponse } from "./baseResponse";
export class NotificationResponse extends BaseResponse {
contextId: string;
type: NotificationType;
payload: any;
constructor(response: any) {
super(response);
this.contextId = this.getResponseProperty("ContextId");
this.type = this.getResponseProperty("Type");
const payload = this.getResponseProperty("Payload");
switch (this.type) {
case NotificationType.SyncCipherCreate:
case NotificationType.SyncCipherDelete:
case NotificationType.SyncCipherUpdate:
case NotificationType.SyncLoginDelete:
this.payload = new SyncCipherNotification(payload);
break;
case NotificationType.SyncFolderCreate:
case NotificationType.SyncFolderDelete:
case NotificationType.SyncFolderUpdate:
this.payload = new SyncFolderNotification(payload);
break;
case NotificationType.SyncVault:
case NotificationType.SyncCiphers:
case NotificationType.SyncOrgKeys:
case NotificationType.SyncSettings:
case NotificationType.LogOut:
this.payload = new UserNotification(payload);
break;
case NotificationType.SyncSendCreate:
case NotificationType.SyncSendUpdate:
case NotificationType.SyncSendDelete:
this.payload = new SyncSendNotification(payload);
break;
default:
break;
}
}
}
export class SyncCipherNotification extends BaseResponse {
id: string;
userId: string;
organizationId: string;
collectionIds: string[];
revisionDate: Date;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.userId = this.getResponseProperty("UserId");
this.organizationId = this.getResponseProperty("OrganizationId");
this.collectionIds = this.getResponseProperty("CollectionIds");
this.revisionDate = new Date(this.getResponseProperty("RevisionDate"));
}
}
export class SyncFolderNotification extends BaseResponse {
id: string;
userId: string;
revisionDate: Date;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.userId = this.getResponseProperty("UserId");
this.revisionDate = new Date(this.getResponseProperty("RevisionDate"));
}
}
export class UserNotification extends BaseResponse {
userId: string;
date: Date;
constructor(response: any) {
super(response);
this.userId = this.getResponseProperty("UserId");
this.date = new Date(this.getResponseProperty("Date"));
}
}
export class SyncSendNotification extends BaseResponse {
id: string;
userId: string;
revisionDate: Date;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.userId = this.getResponseProperty("UserId");
this.revisionDate = new Date(this.getResponseProperty("RevisionDate"));
}
}

View File

@@ -1,35 +0,0 @@
import { SsoConfigApi } from "../../api/ssoConfigApi";
import { BaseResponse } from "../baseResponse";
export class OrganizationSsoResponse extends BaseResponse {
enabled: boolean;
data: SsoConfigApi;
urls: SsoUrls;
constructor(response: any) {
super(response);
this.enabled = this.getResponseProperty("Enabled");
this.data =
this.getResponseProperty("Data") != null
? new SsoConfigApi(this.getResponseProperty("Data"))
: null;
this.urls = new SsoUrls(this.getResponseProperty("Urls"));
}
}
class SsoUrls extends BaseResponse {
callbackPath: string;
signedOutCallbackPath: string;
spEntityId: string;
spMetadataUrl: string;
spAcsUrl: string;
constructor(response: any) {
super(response);
this.callbackPath = this.getResponseProperty("CallbackPath");
this.signedOutCallbackPath = this.getResponseProperty("SignedOutCallbackPath");
this.spEntityId = this.getResponseProperty("SpEntityId");
this.spMetadataUrl = this.getResponseProperty("SpMetadataUrl");
this.spAcsUrl = this.getResponseProperty("SpAcsUrl");
}
}

View File

@@ -1,12 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class OrganizationAutoEnrollStatusResponse extends BaseResponse {
id: string;
resetPasswordEnabled: boolean;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.resetPasswordEnabled = this.getResponseProperty("ResetPasswordEnabled");
}
}

View File

@@ -1,7 +0,0 @@
import { KeysResponse } from "./keysResponse";
export class OrganizationKeysResponse extends KeysResponse {
constructor(response: any) {
super(response);
}
}

View File

@@ -1,60 +0,0 @@
import { PlanType } from "../../enums/planType";
import { BaseResponse } from "./baseResponse";
import { PlanResponse } from "./planResponse";
export class OrganizationResponse extends BaseResponse {
id: string;
identifier: string;
name: string;
businessName: string;
businessAddress1: string;
businessAddress2: string;
businessAddress3: string;
businessCountry: string;
businessTaxNumber: string;
billingEmail: string;
plan: PlanResponse;
planType: PlanType;
seats: number;
maxAutoscaleSeats: number;
maxCollections: number;
maxStorageGb: number;
useGroups: boolean;
useDirectory: boolean;
useEvents: boolean;
useTotp: boolean;
use2fa: boolean;
useApi: boolean;
useResetPassword: boolean;
hasPublicAndPrivateKeys: boolean;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.identifier = this.getResponseProperty("Identifier");
this.name = this.getResponseProperty("Name");
this.businessName = this.getResponseProperty("BusinessName");
this.businessAddress1 = this.getResponseProperty("BusinessAddress1");
this.businessAddress2 = this.getResponseProperty("BusinessAddress2");
this.businessAddress3 = this.getResponseProperty("BusinessAddress3");
this.businessCountry = this.getResponseProperty("BusinessCountry");
this.businessTaxNumber = this.getResponseProperty("BusinessTaxNumber");
this.billingEmail = this.getResponseProperty("BillingEmail");
const plan = this.getResponseProperty("Plan");
this.plan = plan == null ? null : new PlanResponse(plan);
this.planType = this.getResponseProperty("PlanType");
this.seats = this.getResponseProperty("Seats");
this.maxAutoscaleSeats = this.getResponseProperty("MaxAutoscaleSeats");
this.maxCollections = this.getResponseProperty("MaxCollections");
this.maxStorageGb = this.getResponseProperty("MaxStorageGb");
this.useGroups = this.getResponseProperty("UseGroups");
this.useDirectory = this.getResponseProperty("UseDirectory");
this.useEvents = this.getResponseProperty("UseEvents");
this.useTotp = this.getResponseProperty("UseTotp");
this.use2fa = this.getResponseProperty("Use2fa");
this.useApi = this.getResponseProperty("UseApi");
this.useResetPassword = this.getResponseProperty("UseResetPassword");
this.hasPublicAndPrivateKeys = this.getResponseProperty("HasPublicAndPrivateKeys");
}
}

View File

@@ -1,27 +0,0 @@
import { OrganizationResponse } from "./organizationResponse";
import {
BillingSubscriptionResponse,
BillingSubscriptionUpcomingInvoiceResponse,
} from "./subscriptionResponse";
export class OrganizationSubscriptionResponse extends OrganizationResponse {
storageName: string;
storageGb: number;
subscription: BillingSubscriptionResponse;
upcomingInvoice: BillingSubscriptionUpcomingInvoiceResponse;
expiration: string;
constructor(response: any) {
super(response);
this.storageName = this.getResponseProperty("StorageName");
this.storageGb = this.getResponseProperty("StorageGb");
const subscription = this.getResponseProperty("Subscription");
this.subscription = subscription == null ? null : new BillingSubscriptionResponse(subscription);
const upcomingInvoice = this.getResponseProperty("UpcomingInvoice");
this.upcomingInvoice =
upcomingInvoice == null
? null
: new BillingSubscriptionUpcomingInvoiceResponse(upcomingInvoice);
this.expiration = this.getResponseProperty("Expiration");
}
}

View File

@@ -1,14 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class OrganizationUserBulkPublicKeyResponse extends BaseResponse {
id: string;
userId: string;
key: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.userId = this.getResponseProperty("UserId");
this.key = this.getResponseProperty("Key");
}
}

View File

@@ -1,12 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class OrganizationUserBulkResponse extends BaseResponse {
id: string;
error: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.error = this.getResponseProperty("Error");
}
}

View File

@@ -1,70 +0,0 @@
import { KdfType } from "../../enums/kdfType";
import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType";
import { OrganizationUserType } from "../../enums/organizationUserType";
import { PermissionsApi } from "../api/permissionsApi";
import { BaseResponse } from "./baseResponse";
import { SelectionReadOnlyResponse } from "./selectionReadOnlyResponse";
export class OrganizationUserResponse extends BaseResponse {
id: string;
userId: string;
type: OrganizationUserType;
status: OrganizationUserStatusType;
accessAll: boolean;
permissions: PermissionsApi;
resetPasswordEnrolled: boolean;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.userId = this.getResponseProperty("UserId");
this.type = this.getResponseProperty("Type");
this.status = this.getResponseProperty("Status");
this.permissions = new PermissionsApi(this.getResponseProperty("Permissions"));
this.accessAll = this.getResponseProperty("AccessAll");
this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled");
}
}
export class OrganizationUserUserDetailsResponse extends OrganizationUserResponse {
name: string;
email: string;
twoFactorEnabled: boolean;
usesKeyConnector: boolean;
constructor(response: any) {
super(response);
this.name = this.getResponseProperty("Name");
this.email = this.getResponseProperty("Email");
this.twoFactorEnabled = this.getResponseProperty("TwoFactorEnabled");
this.usesKeyConnector = this.getResponseProperty("UsesKeyConnector") ?? false;
}
}
export class OrganizationUserDetailsResponse extends OrganizationUserResponse {
collections: SelectionReadOnlyResponse[] = [];
constructor(response: any) {
super(response);
const collections = this.getResponseProperty("Collections");
if (collections != null) {
this.collections = collections.map((c: any) => new SelectionReadOnlyResponse(c));
}
}
}
export class OrganizationUserResetPasswordDetailsReponse extends BaseResponse {
kdf: KdfType;
kdfIterations: number;
resetPasswordKey: string;
encryptedPrivateKey: string;
constructor(response: any) {
super(response);
this.kdf = this.getResponseProperty("Kdf");
this.kdfIterations = this.getResponseProperty("KdfIterations");
this.resetPasswordKey = this.getResponseProperty("ResetPasswordKey");
this.encryptedPrivateKey = this.getResponseProperty("EncryptedPrivateKey");
}
}

View File

@@ -1,18 +0,0 @@
import { BaseResponse } from "./baseResponse";
import { ProfileResponse } from "./profileResponse";
export class PaymentResponse extends BaseResponse {
userProfile: ProfileResponse;
paymentIntentClientSecret: string;
success: boolean;
constructor(response: any) {
super(response);
const userProfile = this.getResponseProperty("UserProfile");
if (userProfile != null) {
this.userProfile = new ProfileResponse(userProfile);
}
this.paymentIntentClientSecret = this.getResponseProperty("PaymentIntentClientSecret");
this.success = this.getResponseProperty("Success");
}
}

View File

@@ -1,95 +0,0 @@
import { PlanType } from "../../enums/planType";
import { ProductType } from "../../enums/productType";
import { BaseResponse } from "./baseResponse";
export class PlanResponse extends BaseResponse {
type: PlanType;
product: ProductType;
name: string;
isAnnual: boolean;
nameLocalizationKey: string;
descriptionLocalizationKey: string;
canBeUsedByBusiness: boolean;
baseSeats: number;
baseStorageGb: number;
maxCollections: number;
maxUsers: number;
hasAdditionalSeatsOption: boolean;
maxAdditionalSeats: number;
hasAdditionalStorageOption: boolean;
maxAdditionalStorage: number;
hasPremiumAccessOption: boolean;
trialPeriodDays: number;
hasSelfHost: boolean;
hasPolicies: boolean;
hasGroups: boolean;
hasDirectory: boolean;
hasEvents: boolean;
hasTotp: boolean;
has2fa: boolean;
hasApi: boolean;
hasSso: boolean;
hasResetPassword: boolean;
usersGetPremium: boolean;
upgradeSortOrder: number;
displaySortOrder: number;
legacyYear: number;
disabled: boolean;
stripePlanId: string;
stripeSeatPlanId: string;
stripeStoragePlanId: string;
stripePremiumAccessPlanId: string;
basePrice: number;
seatPrice: number;
additionalStoragePricePerGb: number;
premiumAccessOptionPrice: number;
constructor(response: any) {
super(response);
this.type = this.getResponseProperty("Type");
this.product = this.getResponseProperty("Product");
this.name = this.getResponseProperty("Name");
this.isAnnual = this.getResponseProperty("IsAnnual");
this.nameLocalizationKey = this.getResponseProperty("NameLocalizationKey");
this.descriptionLocalizationKey = this.getResponseProperty("DescriptionLocalizationKey");
this.canBeUsedByBusiness = this.getResponseProperty("CanBeUsedByBusiness");
this.baseSeats = this.getResponseProperty("BaseSeats");
this.baseStorageGb = this.getResponseProperty("BaseStorageGb");
this.maxCollections = this.getResponseProperty("MaxCollections");
this.maxUsers = this.getResponseProperty("MaxUsers");
this.hasAdditionalSeatsOption = this.getResponseProperty("HasAdditionalSeatsOption");
this.maxAdditionalSeats = this.getResponseProperty("MaxAdditionalSeats");
this.hasAdditionalStorageOption = this.getResponseProperty("HasAdditionalStorageOption");
this.maxAdditionalStorage = this.getResponseProperty("MaxAdditionalStorage");
this.hasPremiumAccessOption = this.getResponseProperty("HasPremiumAccessOption");
this.trialPeriodDays = this.getResponseProperty("TrialPeriodDays");
this.hasSelfHost = this.getResponseProperty("HasSelfHost");
this.hasPolicies = this.getResponseProperty("HasPolicies");
this.hasGroups = this.getResponseProperty("HasGroups");
this.hasDirectory = this.getResponseProperty("HasDirectory");
this.hasEvents = this.getResponseProperty("HasEvents");
this.hasTotp = this.getResponseProperty("HasTotp");
this.has2fa = this.getResponseProperty("Has2fa");
this.hasApi = this.getResponseProperty("HasApi");
this.hasSso = this.getResponseProperty("HasSso");
this.hasResetPassword = this.getResponseProperty("HasResetPassword");
this.usersGetPremium = this.getResponseProperty("UsersGetPremium");
this.upgradeSortOrder = this.getResponseProperty("UpgradeSortOrder");
this.displaySortOrder = this.getResponseProperty("SortOrder");
this.legacyYear = this.getResponseProperty("LegacyYear");
this.disabled = this.getResponseProperty("Disabled");
this.stripePlanId = this.getResponseProperty("StripePlanId");
this.stripeSeatPlanId = this.getResponseProperty("StripeSeatPlanId");
this.stripeStoragePlanId = this.getResponseProperty("StripeStoragePlanId");
this.stripePremiumAccessPlanId = this.getResponseProperty("StripePremiumAccessPlanId");
this.basePrice = this.getResponseProperty("BasePrice");
this.seatPrice = this.getResponseProperty("SeatPrice");
this.additionalStoragePricePerGb = this.getResponseProperty("AdditionalStoragePricePerGb");
this.premiumAccessOptionPrice = this.getResponseProperty("PremiumAccessOptionPrice");
}
}

View File

@@ -1,14 +0,0 @@
import { KdfType } from "../../enums/kdfType";
import { BaseResponse } from "./baseResponse";
export class PreloginResponse extends BaseResponse {
kdf: KdfType;
kdfIterations: number;
constructor(response: any) {
super(response);
this.kdf = this.getResponseProperty("Kdf");
this.kdfIterations = this.getResponseProperty("KdfIterations");
}
}

View File

@@ -1,81 +0,0 @@
import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType";
import { OrganizationUserType } from "../../enums/organizationUserType";
import { ProductType } from "../../enums/productType";
import { PermissionsApi } from "../api/permissionsApi";
import { BaseResponse } from "./baseResponse";
export class ProfileOrganizationResponse extends BaseResponse {
id: string;
name: string;
usePolicies: boolean;
useGroups: boolean;
useDirectory: boolean;
useEvents: boolean;
useTotp: boolean;
use2fa: boolean;
useApi: boolean;
useSso: boolean;
useKeyConnector: boolean;
useResetPassword: boolean;
selfHost: boolean;
usersGetPremium: boolean;
seats: number;
maxCollections: number;
maxStorageGb?: number;
key: string;
hasPublicAndPrivateKeys: boolean;
status: OrganizationUserStatusType;
type: OrganizationUserType;
enabled: boolean;
ssoBound: boolean;
identifier: string;
permissions: PermissionsApi;
resetPasswordEnrolled: boolean;
userId: string;
providerId: string;
providerName: string;
familySponsorshipFriendlyName: string;
familySponsorshipAvailable: boolean;
planProductType: ProductType;
keyConnectorEnabled: boolean;
keyConnectorUrl: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.name = this.getResponseProperty("Name");
this.usePolicies = this.getResponseProperty("UsePolicies");
this.useGroups = this.getResponseProperty("UseGroups");
this.useDirectory = this.getResponseProperty("UseDirectory");
this.useEvents = this.getResponseProperty("UseEvents");
this.useTotp = this.getResponseProperty("UseTotp");
this.use2fa = this.getResponseProperty("Use2fa");
this.useApi = this.getResponseProperty("UseApi");
this.useSso = this.getResponseProperty("UseSso");
this.useKeyConnector = this.getResponseProperty("UseKeyConnector") ?? false;
this.useResetPassword = this.getResponseProperty("UseResetPassword");
this.selfHost = this.getResponseProperty("SelfHost");
this.usersGetPremium = this.getResponseProperty("UsersGetPremium");
this.seats = this.getResponseProperty("Seats");
this.maxCollections = this.getResponseProperty("MaxCollections");
this.maxStorageGb = this.getResponseProperty("MaxStorageGb");
this.key = this.getResponseProperty("Key");
this.hasPublicAndPrivateKeys = this.getResponseProperty("HasPublicAndPrivateKeys");
this.status = this.getResponseProperty("Status");
this.type = this.getResponseProperty("Type");
this.enabled = this.getResponseProperty("Enabled");
this.ssoBound = this.getResponseProperty("SsoBound");
this.identifier = this.getResponseProperty("Identifier");
this.permissions = new PermissionsApi(this.getResponseProperty("permissions"));
this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled");
this.userId = this.getResponseProperty("UserId");
this.providerId = this.getResponseProperty("ProviderId");
this.providerName = this.getResponseProperty("ProviderName");
this.familySponsorshipFriendlyName = this.getResponseProperty("FamilySponsorshipFriendlyName");
this.familySponsorshipAvailable = this.getResponseProperty("FamilySponsorshipAvailable");
this.planProductType = this.getResponseProperty("PlanProductType");
this.keyConnectorEnabled = this.getResponseProperty("KeyConnectorEnabled") ?? false;
this.keyConnectorUrl = this.getResponseProperty("KeyConnectorUrl");
}
}

View File

@@ -1,8 +0,0 @@
import { ProfileOrganizationResponse } from "./profileOrganizationResponse";
export class ProfileProviderOrganizationResponse extends ProfileOrganizationResponse {
constructor(response: any) {
super(response);
this.keyConnectorEnabled = false;
}
}

View File

@@ -1,30 +0,0 @@
import { ProviderUserStatusType } from "../../enums/providerUserStatusType";
import { ProviderUserType } from "../../enums/providerUserType";
import { PermissionsApi } from "../api/permissionsApi";
import { BaseResponse } from "./baseResponse";
export class ProfileProviderResponse extends BaseResponse {
id: string;
name: string;
key: string;
status: ProviderUserStatusType;
type: ProviderUserType;
enabled: boolean;
permissions: PermissionsApi;
userId: string;
useEvents: boolean;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.name = this.getResponseProperty("Name");
this.key = this.getResponseProperty("Key");
this.status = this.getResponseProperty("Status");
this.type = this.getResponseProperty("Type");
this.enabled = this.getResponseProperty("Enabled");
this.permissions = new PermissionsApi(this.getResponseProperty("permissions"));
this.userId = this.getResponseProperty("UserId");
this.useEvents = this.getResponseProperty("UseEvents");
}
}

View File

@@ -1,55 +0,0 @@
import { BaseResponse } from "./baseResponse";
import { ProfileOrganizationResponse } from "./profileOrganizationResponse";
import { ProfileProviderOrganizationResponse } from "./profileProviderOrganizationResponse";
import { ProfileProviderResponse } from "./profileProviderResponse";
export class ProfileResponse extends BaseResponse {
id: string;
name: string;
email: string;
emailVerified: boolean;
masterPasswordHint: string;
premium: boolean;
culture: string;
twoFactorEnabled: boolean;
key: string;
privateKey: string;
securityStamp: string;
forcePasswordReset: boolean;
usesKeyConnector: boolean;
organizations: ProfileOrganizationResponse[] = [];
providers: ProfileProviderResponse[] = [];
providerOrganizations: ProfileProviderOrganizationResponse[] = [];
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.name = this.getResponseProperty("Name");
this.email = this.getResponseProperty("Email");
this.emailVerified = this.getResponseProperty("EmailVerified");
this.masterPasswordHint = this.getResponseProperty("MasterPasswordHint");
this.premium = this.getResponseProperty("Premium");
this.culture = this.getResponseProperty("Culture");
this.twoFactorEnabled = this.getResponseProperty("TwoFactorEnabled");
this.key = this.getResponseProperty("Key");
this.privateKey = this.getResponseProperty("PrivateKey");
this.securityStamp = this.getResponseProperty("SecurityStamp");
this.forcePasswordReset = this.getResponseProperty("ForcePasswordReset") ?? false;
this.usesKeyConnector = this.getResponseProperty("UsesKeyConnector") ?? false;
const organizations = this.getResponseProperty("Organizations");
if (organizations != null) {
this.organizations = organizations.map((o: any) => new ProfileOrganizationResponse(o));
}
const providers = this.getResponseProperty("Providers");
if (providers != null) {
this.providers = providers.map((o: any) => new ProfileProviderResponse(o));
}
const providerOrganizations = this.getResponseProperty("ProviderOrganizations");
if (providerOrganizations != null) {
this.providerOrganizations = providerOrganizations.map(
(o: any) => new ProfileProviderOrganizationResponse(o),
);
}
}
}

View File

@@ -1,31 +0,0 @@
import { BaseResponse } from "../baseResponse";
export class ProviderOrganizationResponse extends BaseResponse {
id: string;
providerId: string;
organizationId: string;
key: string;
settings: string;
creationDate: string;
revisionDate: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.providerId = this.getResponseProperty("ProviderId");
this.organizationId = this.getResponseProperty("OrganizationId");
this.key = this.getResponseProperty("Key");
this.settings = this.getResponseProperty("Settings");
this.creationDate = this.getResponseProperty("CreationDate");
this.revisionDate = this.getResponseProperty("RevisionDate");
}
}
export class ProviderOrganizationOrganizationDetailsResponse extends ProviderOrganizationResponse {
organizationName: string;
constructor(response: any) {
super(response);
this.organizationName = this.getResponseProperty("OrganizationName");
}
}

View File

@@ -1,16 +0,0 @@
import { BaseResponse } from "../baseResponse";
export class ProviderResponse extends BaseResponse {
id: string;
name: string;
businessName: string;
billingEmail: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.name = this.getResponseProperty("Name");
this.businessName = this.getResponseProperty("BusinessName");
this.billingEmail = this.getResponseProperty("BillingEmail");
}
}

View File

@@ -1,3 +0,0 @@
import { OrganizationUserBulkPublicKeyResponse } from "../organizationUserBulkPublicKeyResponse";
export class ProviderUserBulkPublicKeyResponse extends OrganizationUserBulkPublicKeyResponse {}

View File

@@ -1,12 +0,0 @@
import { BaseResponse } from "../baseResponse";
export class ProviderUserBulkResponse extends BaseResponse {
id: string;
error: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.error = this.getResponseProperty("Error");
}
}

View File

@@ -1,32 +0,0 @@
import { ProviderUserStatusType } from "../../../enums/providerUserStatusType";
import { ProviderUserType } from "../../../enums/providerUserType";
import { PermissionsApi } from "../../api/permissionsApi";
import { BaseResponse } from "../baseResponse";
export class ProviderUserResponse extends BaseResponse {
id: string;
userId: string;
type: ProviderUserType;
status: ProviderUserStatusType;
permissions: PermissionsApi;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.userId = this.getResponseProperty("UserId");
this.type = this.getResponseProperty("Type");
this.status = this.getResponseProperty("Status");
this.permissions = new PermissionsApi(this.getResponseProperty("Permissions"));
}
}
export class ProviderUserUserDetailsResponse extends ProviderUserResponse {
name: string;
email: string;
constructor(response: any) {
super(response);
this.name = this.getResponseProperty("Name");
this.email = this.getResponseProperty("Email");
}
}

View File

@@ -1,14 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class SelectionReadOnlyResponse extends BaseResponse {
id: string;
readOnly: boolean;
hidePasswords: boolean;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.readOnly = this.getResponseProperty("ReadOnly");
this.hidePasswords = this.getResponseProperty("HidePasswords");
}
}

View File

@@ -1,85 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class SubscriptionResponse extends BaseResponse {
storageName: string;
storageGb: number;
maxStorageGb: number;
subscription: BillingSubscriptionResponse;
upcomingInvoice: BillingSubscriptionUpcomingInvoiceResponse;
license: any;
expiration: string;
usingInAppPurchase: boolean;
constructor(response: any) {
super(response);
this.storageName = this.getResponseProperty("StorageName");
this.storageGb = this.getResponseProperty("StorageGb");
this.maxStorageGb = this.getResponseProperty("MaxStorageGb");
this.license = this.getResponseProperty("License");
this.expiration = this.getResponseProperty("Expiration");
this.usingInAppPurchase = this.getResponseProperty("UsingInAppPurchase");
const subscription = this.getResponseProperty("Subscription");
const upcomingInvoice = this.getResponseProperty("UpcomingInvoice");
this.subscription = subscription == null ? null : new BillingSubscriptionResponse(subscription);
this.upcomingInvoice =
upcomingInvoice == null
? null
: new BillingSubscriptionUpcomingInvoiceResponse(upcomingInvoice);
}
}
export class BillingSubscriptionResponse extends BaseResponse {
trialStartDate: string;
trialEndDate: string;
periodStartDate: string;
periodEndDate: string;
cancelledDate: string;
cancelAtEndDate: boolean;
status: string;
cancelled: boolean;
items: BillingSubscriptionItemResponse[] = [];
constructor(response: any) {
super(response);
this.trialEndDate = this.getResponseProperty("TrialStartDate");
this.trialEndDate = this.getResponseProperty("TrialEndDate");
this.periodStartDate = this.getResponseProperty("PeriodStartDate");
this.periodEndDate = this.getResponseProperty("PeriodEndDate");
this.cancelledDate = this.getResponseProperty("CancelledDate");
this.cancelAtEndDate = this.getResponseProperty("CancelAtEndDate");
this.status = this.getResponseProperty("Status");
this.cancelled = this.getResponseProperty("Cancelled");
const items = this.getResponseProperty("Items");
if (items != null) {
this.items = items.map((i: any) => new BillingSubscriptionItemResponse(i));
}
}
}
export class BillingSubscriptionItemResponse extends BaseResponse {
name: string;
amount: number;
quantity: number;
interval: string;
sponsoredSubscriptionItem: boolean;
constructor(response: any) {
super(response);
this.name = this.getResponseProperty("Name");
this.amount = this.getResponseProperty("Amount");
this.quantity = this.getResponseProperty("Quantity");
this.interval = this.getResponseProperty("Interval");
this.sponsoredSubscriptionItem = this.getResponseProperty("SponsoredSubscriptionItem");
}
}
export class BillingSubscriptionUpcomingInvoiceResponse extends BaseResponse {
date: string;
amount: number;
constructor(response: any) {
super(response);
this.date = this.getResponseProperty("Date");
this.amount = this.getResponseProperty("Amount");
}
}

View File

@@ -1,24 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class TaxInfoResponse extends BaseResponse {
taxId: string;
taxIdType: string;
line1: string;
line2: string;
city: string;
state: string;
country: string;
postalCode: string;
constructor(response: any) {
super(response);
this.taxId = this.getResponseProperty("TaxIdNumber");
this.taxIdType = this.getResponseProperty("TaxIdType");
this.line1 = this.getResponseProperty("Line1");
this.line2 = this.getResponseProperty("Line2");
this.city = this.getResponseProperty("City");
this.state = this.getResponseProperty("State");
this.postalCode = this.getResponseProperty("PostalCode");
this.country = this.getResponseProperty("Country");
}
}

View File

@@ -1,18 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class TaxRateResponse extends BaseResponse {
id: string;
country: string;
state: string;
postalCode: string;
rate: number;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.country = this.getResponseProperty("Country");
this.state = this.getResponseProperty("State");
this.postalCode = this.getResponseProperty("PostalCode");
this.rate = this.getResponseProperty("Rate");
}
}

View File

@@ -1,12 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class TwoFactorAuthenticatorResponse extends BaseResponse {
enabled: boolean;
key: string;
constructor(response: any) {
super(response);
this.enabled = this.getResponseProperty("Enabled");
this.key = this.getResponseProperty("Key");
}
}

View File

@@ -1,16 +0,0 @@
import { BaseResponse } from "./baseResponse";
export class TwoFactorDuoResponse extends BaseResponse {
enabled: boolean;
host: string;
secretKey: string;
integrationKey: string;
constructor(response: any) {
super(response);
this.enabled = this.getResponseProperty("Enabled");
this.host = this.getResponseProperty("Host");
this.secretKey = this.getResponseProperty("SecretKey");
this.integrationKey = this.getResponseProperty("IntegrationKey");
}
}

Some files were not shown because too many files have changed in this diff Show More