mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-16 20:21:31 +01:00
notification service implementation
This commit is contained in:
parent
eaf08c45d9
commit
85ca10dbb3
2
jslib
2
jslib
@ -1 +1 @@
|
|||||||
Subproject commit b64757132faf1ebb5438bec00720c58604fd29f6
|
Subproject commit 50666a761dba3d2d7d880f1faf488fd9d719ea50
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -96,6 +96,11 @@
|
|||||||
"tslib": "^1.7.1"
|
"tslib": "^1.7.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@aspnet/signalr": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@aspnet/signalr/-/signalr-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-sXleqUCCbodCOqUA8MjLSvtAgDTvDhEq6j3JyAq/w4RMJhpZ+dXK9+6xEMbzag2hisq5e/8vDC82JYutkcOISQ=="
|
||||||
|
},
|
||||||
"@ngtools/webpack": {
|
"@ngtools/webpack": {
|
||||||
"version": "1.10.2",
|
"version": "1.10.2",
|
||||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.10.2.tgz",
|
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.10.2.tgz",
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
"@angular/platform-browser-dynamic": "5.2.0",
|
"@angular/platform-browser-dynamic": "5.2.0",
|
||||||
"@angular/router": "5.2.0",
|
"@angular/router": "5.2.0",
|
||||||
"@angular/upgrade": "5.2.0",
|
"@angular/upgrade": "5.2.0",
|
||||||
|
"@aspnet/signalr": "1.0.2",
|
||||||
"angular2-toaster": "4.0.2",
|
"angular2-toaster": "4.0.2",
|
||||||
"angulartics2": "5.0.1",
|
"angulartics2": "5.0.1",
|
||||||
"bootstrap": "4.1.1",
|
"bootstrap": "4.1.1",
|
||||||
|
@ -31,6 +31,7 @@ import { CryptoService } from 'jslib/abstractions/crypto.service';
|
|||||||
import { FolderService } from 'jslib/abstractions/folder.service';
|
import { FolderService } from 'jslib/abstractions/folder.service';
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { LockService } from 'jslib/abstractions/lock.service';
|
import { LockService } from 'jslib/abstractions/lock.service';
|
||||||
|
import { NotificationsService } from 'jslib/abstractions/notifications.service';
|
||||||
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
import { SearchService } from 'jslib/abstractions/search.service';
|
import { SearchService } from 'jslib/abstractions/search.service';
|
||||||
@ -71,7 +72,8 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone,
|
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone,
|
||||||
private lockService: LockService, private storageService: StorageService,
|
private lockService: LockService, private storageService: StorageService,
|
||||||
private cryptoService: CryptoService, private collectionService: CollectionService,
|
private cryptoService: CryptoService, private collectionService: CollectionService,
|
||||||
private routerService: RouterService, private searchService: SearchService) { }
|
private routerService: RouterService, private searchService: SearchService,
|
||||||
|
private notificationsService: NotificationsService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.ngZone.runOutsideAngular(() => {
|
this.ngZone.runOutsideAngular(() => {
|
||||||
@ -87,8 +89,10 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
this.ngZone.run(async () => {
|
this.ngZone.run(async () => {
|
||||||
switch (message.command) {
|
switch (message.command) {
|
||||||
case 'loggedIn':
|
case 'loggedIn':
|
||||||
case 'unlocked':
|
|
||||||
case 'loggedOut':
|
case 'loggedOut':
|
||||||
|
this.notificationsService.updateConnection();
|
||||||
|
break;
|
||||||
|
case 'unlocked':
|
||||||
break;
|
break;
|
||||||
case 'logout':
|
case 'logout':
|
||||||
this.logOut(!!message.expired);
|
this.logOut(!!message.expired);
|
||||||
|
@ -209,7 +209,8 @@ export class OrganizationBillingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isExpired() {
|
get isExpired() {
|
||||||
return this.billing != null && this.billing.expiration != null && this.billing.expiration < new Date();
|
return this.billing != null && this.billing.expiration != null &&
|
||||||
|
new Date(this.billing.expiration) < new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
get subscriptionMarkedForCancel() {
|
get subscriptionMarkedForCancel() {
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import {
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
Component,
|
Component,
|
||||||
ComponentFactoryResolver,
|
ComponentFactoryResolver,
|
||||||
|
NgZone,
|
||||||
|
OnDestroy,
|
||||||
OnInit,
|
OnInit,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
@ -16,6 +19,8 @@ import { MessagingService } from 'jslib/abstractions/messaging.service';
|
|||||||
import { SyncService } from 'jslib/abstractions/sync.service';
|
import { SyncService } from 'jslib/abstractions/sync.service';
|
||||||
import { UserService } from 'jslib/abstractions/user.service';
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
|
|
||||||
|
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||||
|
|
||||||
import { Organization } from 'jslib/models/domain/organization';
|
import { Organization } from 'jslib/models/domain/organization';
|
||||||
import { CipherView } from 'jslib/models/view/cipherView';
|
import { CipherView } from 'jslib/models/view/cipherView';
|
||||||
|
|
||||||
@ -30,11 +35,13 @@ import { CiphersComponent } from './ciphers.component';
|
|||||||
import { CollectionsComponent } from './collections.component';
|
import { CollectionsComponent } from './collections.component';
|
||||||
import { GroupingsComponent } from './groupings.component';
|
import { GroupingsComponent } from './groupings.component';
|
||||||
|
|
||||||
|
const BroadcasterSubscriptionId = 'OrgVaultComponent';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-org-vault',
|
selector: 'app-org-vault',
|
||||||
templateUrl: 'vault.component.html',
|
templateUrl: 'vault.component.html',
|
||||||
})
|
})
|
||||||
export class VaultComponent implements OnInit {
|
export class VaultComponent implements OnInit, OnDestroy {
|
||||||
@ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent;
|
@ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent;
|
||||||
@ViewChild(CiphersComponent) ciphersComponent: CiphersComponent;
|
@ViewChild(CiphersComponent) ciphersComponent: CiphersComponent;
|
||||||
@ViewChild('attachments', { read: ViewContainerRef }) attachmentsModalRef: ViewContainerRef;
|
@ViewChild('attachments', { read: ViewContainerRef }) attachmentsModalRef: ViewContainerRef;
|
||||||
@ -52,7 +59,9 @@ export class VaultComponent implements OnInit {
|
|||||||
constructor(private route: ActivatedRoute, private userService: UserService,
|
constructor(private route: ActivatedRoute, private userService: UserService,
|
||||||
private location: Location, private router: Router,
|
private location: Location, private router: Router,
|
||||||
private syncService: SyncService, private i18nService: I18nService,
|
private syncService: SyncService, private i18nService: I18nService,
|
||||||
private componentFactoryResolver: ComponentFactoryResolver, private messagingService: MessagingService) { }
|
private componentFactoryResolver: ComponentFactoryResolver, private messagingService: MessagingService,
|
||||||
|
private broadcasterService: BroadcasterService, private ngZone: NgZone,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.parent.params.subscribe(async (params) => {
|
this.route.parent.params.subscribe(async (params) => {
|
||||||
@ -65,6 +74,21 @@ export class VaultComponent implements OnInit {
|
|||||||
this.ciphersComponent.searchText = this.groupingsComponent.searchText = qParams.search;
|
this.ciphersComponent.searchText = this.groupingsComponent.searchText = qParams.search;
|
||||||
if (!this.organization.isAdmin) {
|
if (!this.organization.isAdmin) {
|
||||||
await this.syncService.fullSync(false);
|
await this.syncService.fullSync(false);
|
||||||
|
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||||
|
this.ngZone.run(async () => {
|
||||||
|
switch (message.command) {
|
||||||
|
case 'syncCompleted':
|
||||||
|
if (message.successfully) {
|
||||||
|
await Promise.all([
|
||||||
|
this.groupingsComponent.load(),
|
||||||
|
this.ciphersComponent.refresh(),
|
||||||
|
]);
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
await this.groupingsComponent.load();
|
await this.groupingsComponent.load();
|
||||||
|
|
||||||
@ -95,6 +119,10 @@ export class VaultComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||||
|
}
|
||||||
|
|
||||||
async clearGroupingFilters() {
|
async clearGroupingFilters() {
|
||||||
this.ciphersComponent.showAddNew = true;
|
this.ciphersComponent.showAddNew = true;
|
||||||
this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchVault');
|
this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchVault');
|
||||||
|
@ -38,6 +38,7 @@ import { ExportService } from 'jslib/services/export.service';
|
|||||||
import { FolderService } from 'jslib/services/folder.service';
|
import { FolderService } from 'jslib/services/folder.service';
|
||||||
import { ImportService } from 'jslib/services/import.service';
|
import { ImportService } from 'jslib/services/import.service';
|
||||||
import { LockService } from 'jslib/services/lock.service';
|
import { LockService } from 'jslib/services/lock.service';
|
||||||
|
import { NotificationsService } from 'jslib/services/notifications.service';
|
||||||
import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service';
|
import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service';
|
||||||
import { SearchService } from 'jslib/services/search.service';
|
import { SearchService } from 'jslib/services/search.service';
|
||||||
import { SettingsService } from 'jslib/services/settings.service';
|
import { SettingsService } from 'jslib/services/settings.service';
|
||||||
@ -64,6 +65,7 @@ import { ImportService as ImportServiceAbstraction } from 'jslib/abstractions/im
|
|||||||
import { LockService as LockServiceAbstraction } from 'jslib/abstractions/lock.service';
|
import { LockService as LockServiceAbstraction } from 'jslib/abstractions/lock.service';
|
||||||
import { LogService as LogServiceAbstraction } from 'jslib/abstractions/log.service';
|
import { LogService as LogServiceAbstraction } from 'jslib/abstractions/log.service';
|
||||||
import { MessagingService as MessagingServiceAbstraction } from 'jslib/abstractions/messaging.service';
|
import { MessagingService as MessagingServiceAbstraction } from 'jslib/abstractions/messaging.service';
|
||||||
|
import { NotificationsService as NotificationsServiceAbstraction } from 'jslib/abstractions/notifications.service';
|
||||||
import {
|
import {
|
||||||
PasswordGenerationService as PasswordGenerationServiceAbstraction,
|
PasswordGenerationService as PasswordGenerationServiceAbstraction,
|
||||||
} from 'jslib/abstractions/passwordGeneration.service';
|
} from 'jslib/abstractions/passwordGeneration.service';
|
||||||
@ -92,7 +94,6 @@ const tokenService = new TokenService(storageService);
|
|||||||
const appIdService = new AppIdService(storageService);
|
const appIdService = new AppIdService(storageService);
|
||||||
const apiService = new ApiService(tokenService, platformUtilsService,
|
const apiService = new ApiService(tokenService, platformUtilsService,
|
||||||
async (expired: boolean) => messagingService.send('logout', { expired: expired }));
|
async (expired: boolean) => messagingService.send('logout', { expired: expired }));
|
||||||
const environmentService = new EnvironmentService(apiService, storageService);
|
|
||||||
const userService = new UserService(tokenService, storageService);
|
const userService = new UserService(tokenService, storageService);
|
||||||
const settingsService = new SettingsService(userService, storageService);
|
const settingsService = new SettingsService(userService, storageService);
|
||||||
export let searchService: SearchService = null;
|
export let searchService: SearchService = null;
|
||||||
@ -114,6 +115,9 @@ const authService = new AuthService(cryptoService, apiService,
|
|||||||
userService, tokenService, appIdService, i18nService, platformUtilsService, messagingService);
|
userService, tokenService, appIdService, i18nService, platformUtilsService, messagingService);
|
||||||
const exportService = new ExportService(folderService, cipherService, apiService);
|
const exportService = new ExportService(folderService, cipherService, apiService);
|
||||||
const importService = new ImportService(cipherService, folderService, apiService, i18nService, collectionService);
|
const importService = new ImportService(cipherService, folderService, apiService, i18nService, collectionService);
|
||||||
|
const notificationsService = new NotificationsService(userService, tokenService, syncService, appIdService,
|
||||||
|
apiService);
|
||||||
|
const environmentService = new EnvironmentService(apiService, storageService, notificationsService);
|
||||||
const auditService = new AuditService(cryptoFunctionService, apiService);
|
const auditService = new AuditService(cryptoFunctionService, apiService);
|
||||||
|
|
||||||
const analytics = new Analytics(window, () => platformUtilsService.isDev() || platformUtilsService.isSelfHost(),
|
const analytics = new Analytics(window, () => platformUtilsService.isDev() || platformUtilsService.isSelfHost(),
|
||||||
@ -127,6 +131,7 @@ export function initFactory(): Function {
|
|||||||
if (!isDev && platformUtilsService.isSelfHost()) {
|
if (!isDev && platformUtilsService.isSelfHost()) {
|
||||||
environmentService.baseUrl = window.location.origin;
|
environmentService.baseUrl = window.location.origin;
|
||||||
}
|
}
|
||||||
|
environmentService.notificationsUrl = isDev ? 'http://localhost:61840' : null;
|
||||||
await apiService.setUrls({
|
await apiService.setUrls({
|
||||||
base: isDev ? null : window.location.origin,
|
base: isDev ? null : window.location.origin,
|
||||||
api: isDev ? 'http://localhost:4000' : null,
|
api: isDev ? 'http://localhost:4000' : null,
|
||||||
@ -139,6 +144,7 @@ export function initFactory(): Function {
|
|||||||
// api: 'https://api.bitwarden.com',
|
// api: 'https://api.bitwarden.com',
|
||||||
// identity: 'https://identity.bitwarden.com',
|
// identity: 'https://identity.bitwarden.com',
|
||||||
});
|
});
|
||||||
|
setTimeout(() => notificationsService.init(environmentService), 3000);
|
||||||
|
|
||||||
lockService.init(true);
|
lockService.init(true);
|
||||||
const locale = await storageService.get<string>(ConstantsService.localeKey);
|
const locale = await storageService.get<string>(ConstantsService.localeKey);
|
||||||
@ -194,6 +200,7 @@ export function initFactory(): Function {
|
|||||||
{ provide: ExportServiceAbstraction, useValue: exportService },
|
{ provide: ExportServiceAbstraction, useValue: exportService },
|
||||||
{ provide: SearchServiceAbstraction, useValue: searchService },
|
{ provide: SearchServiceAbstraction, useValue: searchService },
|
||||||
{ provide: ImportServiceAbstraction, useValue: importService },
|
{ provide: ImportServiceAbstraction, useValue: importService },
|
||||||
|
{ provide: NotificationsServiceAbstraction, useValue: notificationsService },
|
||||||
{ provide: CryptoFunctionServiceAbstraction, useValue: cryptoFunctionService },
|
{ provide: CryptoFunctionServiceAbstraction, useValue: cryptoFunctionService },
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import {
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
Component,
|
Component,
|
||||||
ComponentFactoryResolver,
|
ComponentFactoryResolver,
|
||||||
|
NgZone,
|
||||||
|
OnDestroy,
|
||||||
OnInit,
|
OnInit,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
@ -40,11 +43,15 @@ import { SyncService } from 'jslib/abstractions/sync.service';
|
|||||||
import { TokenService } from 'jslib/abstractions/token.service';
|
import { TokenService } from 'jslib/abstractions/token.service';
|
||||||
import { UserService } from 'jslib/abstractions/user.service';
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
|
|
||||||
|
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||||
|
|
||||||
|
const BroadcasterSubscriptionId = 'VaultComponent';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-vault',
|
selector: 'app-vault',
|
||||||
templateUrl: 'vault.component.html',
|
templateUrl: 'vault.component.html',
|
||||||
})
|
})
|
||||||
export class VaultComponent implements OnInit {
|
export class VaultComponent implements OnInit, OnDestroy {
|
||||||
@ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent;
|
@ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent;
|
||||||
@ViewChild(CiphersComponent) ciphersComponent: CiphersComponent;
|
@ViewChild(CiphersComponent) ciphersComponent: CiphersComponent;
|
||||||
@ViewChild(OrganizationsComponent) organizationsComponent: OrganizationsComponent;
|
@ViewChild(OrganizationsComponent) organizationsComponent: OrganizationsComponent;
|
||||||
@ -74,7 +81,9 @@ export class VaultComponent implements OnInit {
|
|||||||
private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
|
private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
|
||||||
private tokenService: TokenService, private cryptoService: CryptoService,
|
private tokenService: TokenService, private cryptoService: CryptoService,
|
||||||
private messagingService: MessagingService, private userService: UserService,
|
private messagingService: MessagingService, private userService: UserService,
|
||||||
private platformUtilsService: PlatformUtilsService, private toasterService: ToasterService) { }
|
private platformUtilsService: PlatformUtilsService, private toasterService: ToasterService,
|
||||||
|
private broadcasterService: BroadcasterService, private ngZone: NgZone,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef) { }
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.showVerifyEmail = !(await this.tokenService.getEmailVerified());
|
this.showVerifyEmail = !(await this.tokenService.getEmailVerified());
|
||||||
@ -85,6 +94,23 @@ export class VaultComponent implements OnInit {
|
|||||||
|
|
||||||
this.route.queryParams.subscribe(async (params) => {
|
this.route.queryParams.subscribe(async (params) => {
|
||||||
await this.syncService.fullSync(false);
|
await this.syncService.fullSync(false);
|
||||||
|
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||||
|
this.ngZone.run(async () => {
|
||||||
|
switch (message.command) {
|
||||||
|
case 'syncCompleted':
|
||||||
|
if (message.successfully) {
|
||||||
|
await Promise.all([
|
||||||
|
this.groupingsComponent.load(),
|
||||||
|
this.organizationsComponent.load(),
|
||||||
|
this.ciphersComponent.refresh(),
|
||||||
|
]);
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.groupingsComponent.load(),
|
this.groupingsComponent.load(),
|
||||||
this.organizationsComponent.load(),
|
this.organizationsComponent.load(),
|
||||||
@ -120,6 +146,10 @@ export class VaultComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||||
|
}
|
||||||
|
|
||||||
async clearGroupingFilters() {
|
async clearGroupingFilters() {
|
||||||
this.ciphersComponent.showAddNew = true;
|
this.ciphersComponent.showAddNew = true;
|
||||||
this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchVault');
|
this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchVault');
|
||||||
|
Loading…
Reference in New Issue
Block a user