mirror of
https://github.com/bitwarden/browser
synced 2025-12-21 02:33:46 +00:00
notification service
This commit is contained in:
@@ -4,6 +4,7 @@ export abstract class EnvironmentService {
|
||||
apiUrl: string;
|
||||
identityUrl: string;
|
||||
iconsUrl: string;
|
||||
notificationsUrl: string;
|
||||
|
||||
getWebVaultUrl: () => string;
|
||||
setUrlsFromStorage: () => Promise<void>;
|
||||
|
||||
6
src/abstractions/notifications.service.ts
Normal file
6
src/abstractions/notifications.service.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { EnvironmentService } from './environment.service';
|
||||
|
||||
export abstract class NotificationsService {
|
||||
init: (environmentService: EnvironmentService) => Promise<void>;
|
||||
updateConnection: () => Promise<void>;
|
||||
}
|
||||
@@ -16,6 +16,7 @@ export class EnvironmentComponent {
|
||||
identityUrl: string;
|
||||
apiUrl: string;
|
||||
webVaultUrl: string;
|
||||
notificationsUrl: string;
|
||||
baseUrl: string;
|
||||
showCustom = false;
|
||||
|
||||
@@ -26,6 +27,7 @@ export class EnvironmentComponent {
|
||||
this.apiUrl = environmentService.apiUrl || '';
|
||||
this.identityUrl = environmentService.identityUrl || '';
|
||||
this.iconsUrl = environmentService.iconsUrl || '';
|
||||
this.notificationsUrl = environmentService.notificationsUrl || '';
|
||||
}
|
||||
|
||||
async submit() {
|
||||
@@ -35,6 +37,7 @@ export class EnvironmentComponent {
|
||||
identity: this.identityUrl,
|
||||
webVault: this.webVaultUrl,
|
||||
icons: this.iconsUrl,
|
||||
notifications: this.notificationsUrl,
|
||||
});
|
||||
|
||||
// re-set urls since service can change them, ex: prefixing https://
|
||||
@@ -43,6 +46,7 @@ export class EnvironmentComponent {
|
||||
this.identityUrl = resUrls.identity;
|
||||
this.webVaultUrl = resUrls.webVault;
|
||||
this.iconsUrl = resUrls.icons;
|
||||
this.notificationsUrl = resUrls.notifications;
|
||||
|
||||
this.analytics.eventTrack.next({ action: 'Set Environment URLs' });
|
||||
this.toasterService.popAsync('success', null, this.i18nService.t('environmentSaved'));
|
||||
|
||||
14
src/enums/notificationType.ts
Normal file
14
src/enums/notificationType.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
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,
|
||||
}
|
||||
71
src/models/response/notificationResponse.ts
Normal file
71
src/models/response/notificationResponse.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { NotificationType } from '../../enums/notificationType';
|
||||
|
||||
export class NotificationResponse {
|
||||
contextId: string;
|
||||
type: NotificationType;
|
||||
payload: any;
|
||||
|
||||
constructor(response: any) {
|
||||
this.contextId = response.contextId || response.ContextId;
|
||||
this.type = response.type != null ? response.type : response.Type;
|
||||
|
||||
const payload = response.payload || response.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:
|
||||
this.payload = new SyncUserNotification(payload);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SyncCipherNotification {
|
||||
id: string;
|
||||
userId: string;
|
||||
organizationId: string;
|
||||
revisionDate: Date;
|
||||
|
||||
constructor(response: any) {
|
||||
this.id = response.Id;
|
||||
this.userId = response.UserId;
|
||||
this.organizationId = response.OrganizationId;
|
||||
this.revisionDate = new Date(response.RevisionDate);
|
||||
}
|
||||
}
|
||||
|
||||
export class SyncFolderNotification {
|
||||
id: string;
|
||||
userId: string;
|
||||
revisionDate: Date;
|
||||
|
||||
constructor(response: any) {
|
||||
this.id = response.Id;
|
||||
this.userId = response.UserId;
|
||||
this.revisionDate = new Date(response.RevisionDate);
|
||||
}
|
||||
}
|
||||
|
||||
export class SyncUserNotification {
|
||||
userId: string;
|
||||
date: Date;
|
||||
|
||||
constructor(response: any) {
|
||||
this.userId = response.UserId;
|
||||
this.date = new Date(response.Date);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
apiUrl: string;
|
||||
identityUrl: string;
|
||||
iconsUrl: string;
|
||||
notificationsUrl: string;
|
||||
|
||||
constructor(private apiService: ApiService, private storageService: StorageService) {}
|
||||
|
||||
@@ -31,6 +32,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
api: null,
|
||||
identity: null,
|
||||
icons: null,
|
||||
notifications: null,
|
||||
webVault: null,
|
||||
};
|
||||
|
||||
@@ -46,6 +48,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
this.apiUrl = envUrls.api = urls.api;
|
||||
this.identityUrl = envUrls.identity = urls.identity;
|
||||
this.iconsUrl = urls.icons;
|
||||
this.notificationsUrl = urls.notifications;
|
||||
await this.apiService.setUrls(envUrls);
|
||||
}
|
||||
|
||||
@@ -55,6 +58,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
urls.api = this.formatUrl(urls.api);
|
||||
urls.identity = this.formatUrl(urls.identity);
|
||||
urls.icons = this.formatUrl(urls.icons);
|
||||
urls.notifications = this.formatUrl(urls.notifications);
|
||||
|
||||
await this.storageService.save(ConstantsService.environmentUrlsKey, {
|
||||
base: urls.base,
|
||||
@@ -62,6 +66,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
identity: urls.identity,
|
||||
webVault: urls.webVault,
|
||||
icons: urls.icons,
|
||||
notifications: urls.notifications,
|
||||
});
|
||||
|
||||
this.baseUrl = urls.base;
|
||||
@@ -69,6 +74,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
this.apiUrl = urls.api;
|
||||
this.identityUrl = urls.identity;
|
||||
this.iconsUrl = urls.icons;
|
||||
this.notificationsUrl = urls.notifications;
|
||||
|
||||
const envUrls = new EnvironmentUrls();
|
||||
if (this.baseUrl) {
|
||||
|
||||
90
src/services/notifications.service.ts
Normal file
90
src/services/notifications.service.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import * as signalR from '@aspnet/signalr';
|
||||
|
||||
import { NotificationType } from '../enums/notificationType';
|
||||
|
||||
import { CipherService } from '../abstractions/cipher.service';
|
||||
import { CollectionService } from '../abstractions/collection.service';
|
||||
import { EnvironmentService } from '../abstractions/environment.service';
|
||||
import { FolderService } from '../abstractions/folder.service';
|
||||
import { NotificationsService as NotificationsServiceAbstraction } from '../abstractions/notifications.service';
|
||||
import { SettingsService } from '../abstractions/settings.service';
|
||||
import { SyncService } from '../abstractions/sync.service';
|
||||
import { TokenService } from '../abstractions/token.service';
|
||||
import { UserService } from '../abstractions/user.service';
|
||||
|
||||
import { NotificationResponse } from '../models/response/notificationResponse';
|
||||
|
||||
export class NotificationsService implements NotificationsServiceAbstraction {
|
||||
private signalrConnection: signalR.HubConnection;
|
||||
|
||||
constructor(private userService: UserService, private tokenService: TokenService,
|
||||
private syncService: SyncService) { }
|
||||
|
||||
async init(environmentService: EnvironmentService): Promise<void> {
|
||||
let url = 'https://notifications.bitwarden.com';
|
||||
if (environmentService.notificationsUrl != null) {
|
||||
url = environmentService.notificationsUrl;
|
||||
} else if (environmentService.baseUrl != null) {
|
||||
url = environmentService.baseUrl + '/notifications';
|
||||
}
|
||||
|
||||
if (this.signalrConnection != null) {
|
||||
await this.signalrConnection.stop();
|
||||
this.signalrConnection = null;
|
||||
}
|
||||
|
||||
this.signalrConnection = new signalR.HubConnectionBuilder()
|
||||
.withUrl(url + '/hub', {
|
||||
accessTokenFactory: () => this.tokenService.getToken(),
|
||||
})
|
||||
.configureLogging(signalR.LogLevel.Information)
|
||||
.build();
|
||||
|
||||
this.signalrConnection.on('ReceiveMessage', async (data: any) => {
|
||||
await this.processNotification(new NotificationResponse(data));
|
||||
});
|
||||
|
||||
this.updateConnection();
|
||||
}
|
||||
|
||||
async updateConnection(): Promise<void> {
|
||||
try {
|
||||
if (await this.userService.isAuthenticated()) {
|
||||
await this.signalrConnection.start();
|
||||
} else {
|
||||
await this.signalrConnection.stop();
|
||||
}
|
||||
} catch (e) {
|
||||
// tslint:disable-next-line
|
||||
console.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private async processNotification(notification: NotificationResponse) {
|
||||
if (notification == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (notification.type) {
|
||||
case NotificationType.SyncCipherCreate:
|
||||
case NotificationType.SyncCipherDelete:
|
||||
case NotificationType.SyncCipherUpdate:
|
||||
case NotificationType.SyncLoginDelete:
|
||||
this.syncService.fullSync(false);
|
||||
break;
|
||||
case NotificationType.SyncFolderCreate:
|
||||
case NotificationType.SyncFolderDelete:
|
||||
case NotificationType.SyncFolderUpdate:
|
||||
this.syncService.fullSync(false);
|
||||
break;
|
||||
case NotificationType.SyncVault:
|
||||
case NotificationType.SyncCiphers:
|
||||
case NotificationType.SyncOrgKeys:
|
||||
case NotificationType.SyncSettings:
|
||||
this.syncService.fullSync(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user