diff --git a/src/abstractions/api.service.ts b/src/abstractions/api.service.ts index 55a636a62..6732b8c04 100644 --- a/src/abstractions/api.service.ts +++ b/src/abstractions/api.service.ts @@ -12,6 +12,7 @@ import { CollectionRequest } from '../models/request/collectionRequest'; import { DeleteRecoverRequest } from '../models/request/deleteRecoverRequest'; import { EmailRequest } from '../models/request/emailRequest'; import { EmailTokenRequest } from '../models/request/emailTokenRequest'; +import { EventRequest } from '../models/request/eventRequest'; import { FolderRequest } from '../models/request/folderRequest'; import { GroupRequest } from '../models/request/groupRequest'; import { ImportCiphersRequest } from '../models/request/importCiphersRequest'; @@ -98,6 +99,7 @@ export abstract class ApiService { urlsSet: boolean; apiBaseUrl: string; identityBaseUrl: string; + eventsBaseUrl: string; setUrls: (urls: EnvironmentUrls) => void; postIdentityToken: (request: TokenRequest) => Promise; @@ -254,6 +256,7 @@ export abstract class ApiService { token: string) => Promise>; getEventsOrganizationUser: (organizationId: string, id: string, start: string, end: string, token: string) => Promise>; + postEventsCollect: (request: EventRequest) => Promise; getUserPublicKey: (id: string) => Promise; diff --git a/src/abstractions/environment.service.ts b/src/abstractions/environment.service.ts index e561341d3..455447bbf 100644 --- a/src/abstractions/environment.service.ts +++ b/src/abstractions/environment.service.ts @@ -5,6 +5,7 @@ export abstract class EnvironmentService { identityUrl: string; iconsUrl: string; notificationsUrl: string; + eventsUrl: string; getWebVaultUrl: () => string; setUrlsFromStorage: () => Promise; diff --git a/src/enums/eventType.ts b/src/enums/eventType.ts index 11b4c26aa..f5b50d8fb 100644 --- a/src/enums/eventType.ts +++ b/src/enums/eventType.ts @@ -6,6 +6,7 @@ export enum EventType { User_Recovered2fa = 1004, User_FailedLogIn = 1005, User_FailedLogIn2fa = 1006, + User_ExportedVault = 1007, Cipher_Created = 1100, Cipher_Updated = 1101, @@ -14,6 +15,12 @@ export enum EventType { Cipher_AttachmentDeleted = 1104, Cipher_Shared = 1105, Cipher_UpdatedCollections = 1106, + Cipher_ClientViewed = 1107, + Cipher_ClientToggledPasswordVisible = 1108, + Cipher_ClientToggledHiddenFieldVisible = 1109, + Cipher_ClientCopiedPassword = 1110, + Cipher_ClientCopedHiddenField = 1111, + Cipher_ClientAutofilled = 1112, Collection_Created = 1300, Collection_Updated = 1301, diff --git a/src/models/domain/environmentUrls.ts b/src/models/domain/environmentUrls.ts index 868cd4321..2241bd0a1 100644 --- a/src/models/domain/environmentUrls.ts +++ b/src/models/domain/environmentUrls.ts @@ -2,4 +2,5 @@ export class EnvironmentUrls { base: string; api: string; identity: string; + events: string; } diff --git a/src/models/request/eventRequest.ts b/src/models/request/eventRequest.ts new file mode 100644 index 000000000..f9f52d910 --- /dev/null +++ b/src/models/request/eventRequest.ts @@ -0,0 +1,6 @@ +import { EventType } from '../../enums/eventType'; + +export class EventRequest { + type: EventType; + cipherId: string; +} diff --git a/src/services/api.service.ts b/src/services/api.service.ts index fcff0bf77..d3db7012e 100644 --- a/src/services/api.service.ts +++ b/src/services/api.service.ts @@ -18,6 +18,7 @@ import { CollectionRequest } from '../models/request/collectionRequest'; import { DeleteRecoverRequest } from '../models/request/deleteRecoverRequest'; import { EmailRequest } from '../models/request/emailRequest'; import { EmailTokenRequest } from '../models/request/emailTokenRequest'; +import { EventRequest } from '../models/request/eventRequest'; import { FolderRequest } from '../models/request/folderRequest'; import { GroupRequest } from '../models/request/groupRequest'; import { ImportCiphersRequest } from '../models/request/importCiphersRequest'; @@ -105,6 +106,7 @@ export class ApiService implements ApiServiceAbstraction { urlsSet: boolean = false; apiBaseUrl: string; identityBaseUrl: string; + eventsBaseUrl: string; private deviceType: string; private isWebClient = false; @@ -130,24 +132,24 @@ export class ApiService implements ApiServiceAbstraction { this.usingBaseUrl = true; this.apiBaseUrl = urls.base + '/api'; this.identityBaseUrl = urls.base + '/identity'; + this.eventsBaseUrl = urls.base + '/events'; return; } - if (urls.api != null && urls.identity != null) { - this.apiBaseUrl = urls.api; - this.identityBaseUrl = urls.identity; - return; - } - - /* tslint:disable */ - // Local Dev - //this.apiBaseUrl = 'http://localhost:4000'; - //this.identityBaseUrl = 'http://localhost:33656'; + this.apiBaseUrl = urls.api; + this.identityBaseUrl = urls.identity; + this.eventsBaseUrl = urls.events; // Production - this.apiBaseUrl = 'https://api.bitwarden.com'; - this.identityBaseUrl = 'https://identity.bitwarden.com'; - /* tslint:enable */ + if (this.apiBaseUrl == null) { + this.apiBaseUrl = 'https://api.bitwarden.com'; + } + if (this.identityBaseUrl == null) { + this.identityBaseUrl = 'https://identity.bitwarden.com'; + } + if (this.eventsBaseUrl == null) { + this.eventsBaseUrl = 'https://events.bitwarden.com'; + } } // Auth APIs @@ -839,6 +841,25 @@ export class ApiService implements ApiServiceAbstraction { return new ListResponse(r, EventResponse); } + async postEventsCollect(request: EventRequest): Promise { + const authHeader = await this.getActiveBearerToken(); + const headers = new Headers({ + 'Device-Type': this.deviceType, + 'Authorization': 'Bearer ' + authHeader, + 'Content-Type': 'application/json; charset=utf-8', + }); + const response = await this.fetch(new Request(this.eventsBaseUrl + '/collect', { + cache: 'no-cache', + credentials: this.getCredentials(), + method: 'POST', + body: JSON.stringify(request), + headers: headers, + })); + if (response.status !== 200) { + return Promise.reject('Event post failed.'); + } + } + // User APIs async getUserPublicKey(id: string): Promise { diff --git a/src/services/environment.service.ts b/src/services/environment.service.ts index 60a2dc8c6..a5bfea267 100644 --- a/src/services/environment.service.ts +++ b/src/services/environment.service.ts @@ -14,6 +14,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { identityUrl: string; iconsUrl: string; notificationsUrl: string; + eventsUrl: string; constructor(private apiService: ApiService, private storageService: StorageService, private notificationsService: NotificationsService) { } @@ -35,6 +36,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { identity: null, icons: null, notifications: null, + events: null, webVault: null, }; @@ -51,6 +53,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { this.identityUrl = envUrls.identity = urls.identity; this.iconsUrl = urls.icons; this.notificationsUrl = urls.notifications; + this.eventsUrl = envUrls.events = urls.events; this.apiService.setUrls(envUrls); } @@ -61,6 +64,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { urls.identity = this.formatUrl(urls.identity); urls.icons = this.formatUrl(urls.icons); urls.notifications = this.formatUrl(urls.notifications); + urls.events = this.formatUrl(urls.events); await this.storageService.save(ConstantsService.environmentUrlsKey, { base: urls.base, @@ -69,6 +73,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { webVault: urls.webVault, icons: urls.icons, notifications: urls.notifications, + events: urls.events, }); this.baseUrl = urls.base; @@ -77,6 +82,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { this.identityUrl = urls.identity; this.iconsUrl = urls.icons; this.notificationsUrl = urls.notifications; + this.eventsUrl = urls.events; const envUrls = new EnvironmentUrls(); if (this.baseUrl) { @@ -84,6 +90,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { } else { envUrls.api = this.apiUrl; envUrls.identity = this.identityUrl; + envUrls.events = this.eventsUrl; } this.apiService.setUrls(envUrls);