1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-15 07:54:55 +00:00

even more cleanup!

This commit is contained in:
✨ Audrey ✨
2025-03-20 22:35:46 -04:00
parent 786603559a
commit 9f3d80255e
7 changed files with 30 additions and 170 deletions

View File

@@ -248,7 +248,7 @@ import { EventCollectionService } from "@bitwarden/common/services/event/event-c
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
import { SearchService } from "@bitwarden/common/services/search.service";
import { AchievementService } from "@bitwarden/common/tools/achievements/achievement.service.abstraction";
import { DefaultAchievementService } from "@bitwarden/common/tools/achievements/next-achievement.service";
import { DefaultAchievementService } from "@bitwarden/common/tools/achievements/default-achievement.service";
import { DefaultUserEventCollector } from "@bitwarden/common/tools/log/default-user-event-collector";
import { UserEventCollector } from "@bitwarden/common/tools/log/user-event-collector";
import {

View File

@@ -16,8 +16,6 @@ export type ServiceFormat = EcsFormat & {
/** a unique identifier(s) for this client installation */
name: string;
};
/** The environment to which the client was connected */
environment: "production" | "testing" | "development" | "local";
/** the unique identifier(s) for this client installation */
version: string;

View File

@@ -1,21 +0,0 @@
// eslint-disable-next-line -- `StateDefinition` used as a type
import { StateDefinition } from "../../platform/state/state-definition";
import { Classifier } from "../state/classifier";
import { EcsFormat } from "./ecs-format";
export type LogKey<LogFormat extends EcsFormat, N extends number = 100> = {
target: "log";
format: "classified_circular_buffer";
size: N;
key: string;
state: StateDefinition;
cleanupDelayMs?: number;
classifier: Classifier<LogFormat, unknown, unknown>;
/** For encrypted outputs, determines how much padding is applied to
* encoded inputs. When this isn't specified, each frame is 32 bytes
* long.
*/
frame?: number;
};

View File

@@ -1,16 +0,0 @@
import { LogService } from "../../platform/abstractions/log.service";
import { StateProvider } from "../../platform/state";
import { LegacyEncryptorProvider } from "../cryptography/legacy-encryptor-provider";
export abstract class LogSubjectDependencyProvider {
/** Provides objects that encrypt and decrypt user and organization data */
abstract encryptor: LegacyEncryptorProvider;
/** Provides local object persistence */
abstract state: StateProvider;
/** `LogSubject` uses the log service instead of semantic logging
* to avoid creating a loop where it logs its own actions.
*/
abstract log: LogService;
}

View File

@@ -1,4 +1,4 @@
import { BehaviorSubject, SubjectLike, from, map, zip } from "rxjs";
import { BehaviorSubject, SubjectLike, from, map, of, zip } from "rxjs";
import { Primitive } from "type-fest";
import { Account } from "../../auth/abstractions/account.service";
@@ -22,40 +22,41 @@ export class UserEventMonitor {
constructor(
idService: AppIdService,
utilService: PlatformUtilsService,
account: Account,
private account: Account,
private now: () => number,
private events$: SubjectLike<UserActionEvent>,
private log: SemanticLogger = disabledSemanticLoggerProvider({}),
) {
zip(from(idService.getAppId()), from(utilService.getApplicationVersion()))
.pipe(
map(
([appId, version]) =>
({
event: {
kind: "event",
category: "session",
},
service: {
name: utilService.getDeviceString(),
type: "client",
node: {
name: appId,
},
environment: "local",
version,
},
user: {
// `account` verified not-null via `filter`
id: account!.id,
email: (account!.emailVerified && account!.email) || undefined,
},
}) satisfies BaselineType,
),
)
zip(
from(idService.getAppId()),
from(utilService.getApplicationVersion()),
of(utilService.getDeviceString()),
)
.pipe(map(([appId, version, device]) => this.template(appId, device, version)))
.subscribe((next) => this.baseline$.next(next));
}
template(appId: string, device: string, version: string): BaselineType {
return {
event: {
kind: "event",
category: "session",
},
service: {
name: device,
type: "client",
node: {
name: appId,
},
version,
},
user: {
id: this.account.id,
email: (this.account.emailVerified && this.account.email) || undefined,
},
};
}
private readonly baseline$ = new BehaviorSubject<BaselineType | null>(null);
creation(event: EventInfo) {

View File

@@ -1,55 +0,0 @@
/** A simple ring buffer; not in any way threadsafe */
export class RingBuffer<T> {
constructor(private capacity: number) {
this.buffer = new Array(capacity).fill(null);
}
private buffer: Array<T>;
private head: number = 0;
private tail: number = 0;
private _length: number = 0;
/** The number of entries presently stored by the ring buffer */
get length() {
return this._length;
}
/** `true` when the buffer is full. */
get full() {
return this.length === this.capacity;
}
/** `true` when the buffer is empty */
get empty() {
return !this.length;
}
/** Adds an item to the head of the buffer
* @param value the item to add
* @returns `true` if the item was added, otherwise `false`.
*/
enqueue(value: T) {
if (this.full) {
return false;
}
this.buffer[this.head] = value;
this.head = (this.head + 1) % this.capacity;
this._length++;
}
/** Removes the item at the tail of the buffer
* @returns the tail item if the buffer contains any entries,
* otherwise `undefined`.
*/
dequeue(): T | undefined {
if (this.empty) {
return undefined;
}
const value = this.buffer[this.tail];
this.tail = (this.tail + 1) % this.capacity;
this._length--;
return value;
}
}

View File

@@ -1,47 +0,0 @@
import { firstValueFrom } from "rxjs";
import { StateProvider, UserKeyDefinition } from "../../platform/state";
import { UserId } from "../../types/guid";
/** Utility for spooling data to and from append-only storage. */
export class Spooler<T> {
/** Instantiates a spooler
* @param state loads and stores the spool
* @param location where spooled records are stored
* @param userId user performing the spooling
*/
constructor(
private state: StateProvider,
private location: UserKeyDefinition<T[]>,
private userId: UserId,
) {}
private buffer = new Array<T>();
/** Append a value to append-only storage */
async spool(value: T) {
// TODO: encrypt spooled records? Or should that be done by the calling code?
// either way, the value pushed to `this.buffer` should be ready-to-spool.
this.buffer.push(value);
await this.state.setUserState(this.location, this.buffer, this.userId);
}
/** Read all values from append-only storage */
async read(): Promise<T[]> {
// TODO: decrypt spooled records? Or should that be done by the calling code?
return await firstValueFrom(this.state.getUserState$(this.location, this.userId));
}
/** Read all values from append-only storage */
async unspool(): Promise<T[]> {
const results = await this.read();
await this.clear();
return results;
}
/** Erase append-only storage */
async clear() {
await this.state.setUserState(this.location, null, this.userId);
}
}