From 0a803958e91c7f1b493ff113d516fc1a7dec8c8d Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 22 Jan 2018 23:37:36 -0500 Subject: [PATCH] service implementations --- package.json | 4 + src/app/accounts/login.component.ts | 8 +- src/app/app-routing.module.ts | 2 +- src/app/app.d.ts | 1 - src/app/app.module.ts | 3 + src/app/services/desktopMessaging.service.ts | 14 +++ .../services/desktopPlatformUtils.service.ts | 84 +++++++++++++++++ .../services/desktopSecureStorage.service.ts | 20 ++++ src/app/services/desktopStorage.service.ts | 24 +++++ src/app/services/services.module.ts | 91 +++++++++++++++++++ src/global.d.ts | 3 + tsconfig.json | 1 + webpack.common.js | 5 + 13 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 src/app/services/desktopMessaging.service.ts create mode 100644 src/app/services/desktopPlatformUtils.service.ts create mode 100644 src/app/services/desktopSecureStorage.service.ts create mode 100644 src/app/services/desktopStorage.service.ts create mode 100644 src/app/services/services.module.ts create mode 100644 src/global.d.ts diff --git a/package.json b/package.json index 4445d346..944307b5 100644 --- a/package.json +++ b/package.json @@ -12,18 +12,22 @@ }, "devDependencies": { "@bitwarden/jslib": "git+https://github.com/bitwarden/jslib.git", + "@types/keytar": "^4.0.1", "clean-webpack-plugin": "^0.1.17", "copy-webpack-plugin": "^4.2.0", "css-loader": "^0.28.7", "electron": "1.7.10", "electron-builder": "19.53.7", "electron-reload": "1.2.2", + "electron-store": "^1.3.0", "extract-text-webpack-plugin": "^3.0.1", "file-loader": "^1.1.5", "font-awesome": "4.7.0", "google-fonts-webpack-plugin": "^0.4.4", "html-loader": "^0.5.1", "html-webpack-plugin": "^2.30.1", + "keytar": "^4.1.0", + "node-loader": "^0.6.0", "node-sass": "^4.7.2", "sass-loader": "^6.0.6", "style-loader": "^0.19.0", diff --git a/src/app/accounts/login.component.ts b/src/app/accounts/login.component.ts index 88335241..55523cbf 100644 --- a/src/app/accounts/login.component.ts +++ b/src/app/accounts/login.component.ts @@ -5,11 +5,17 @@ import { OnInit, } from '@angular/core'; +import { AuthService } from 'jslib/abstractions/auth.service'; + @Component({ selector: 'app-login', - template: template, + template: template }) export class LoginComponent implements OnInit { + constructor(authService: AuthService) { + console.log(authService); + } + ngOnInit() { // TODO? } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 278a80f8..fc858be0 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -8,7 +8,7 @@ import { LoginComponent } from './accounts/login.component'; import { VaultComponent } from './vault/vault.component'; const routes: Routes = [ - { path: '', redirectTo: '/vault', pathMatch: 'full' }, + { path: '', redirectTo: '/login', pathMatch: 'full' }, { path: 'login', component: LoginComponent }, { path: 'vault', component: VaultComponent }, ]; diff --git a/src/app/app.d.ts b/src/app/app.d.ts index 23de474b..7bf7506f 100644 --- a/src/app/app.d.ts +++ b/src/app/app.d.ts @@ -1,2 +1 @@ declare module '*.html'; -declare function require(s: string): any; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 814ed6eb..88a38235 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,8 +1,10 @@ +import 'core-js'; import 'zone.js/dist/zone'; import { AppRoutingModule } from './app-routing.module'; import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; +import { ServicesModule } from './services/services.module'; import { AppComponent } from './app.component'; import { LoginComponent } from './accounts/login.component'; @@ -12,6 +14,7 @@ import { VaultComponent } from './vault/vault.component'; imports: [ BrowserModule, AppRoutingModule, + ServicesModule, ], declarations: [ AppComponent, diff --git a/src/app/services/desktopMessaging.service.ts b/src/app/services/desktopMessaging.service.ts new file mode 100644 index 00000000..5f32c71d --- /dev/null +++ b/src/app/services/desktopMessaging.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; + +import { + MessagingService, + PlatformUtilsService, +} from 'jslib/abstractions'; + +@Injectable() +export class DesktopMessagingService implements MessagingService { + send(subscriber: string, arg: any = {}) { + const message = Object.assign({}, { command: subscriber }, arg); + // TODO + } +} diff --git a/src/app/services/desktopPlatformUtils.service.ts b/src/app/services/desktopPlatformUtils.service.ts new file mode 100644 index 00000000..f6578a7b --- /dev/null +++ b/src/app/services/desktopPlatformUtils.service.ts @@ -0,0 +1,84 @@ +import { Injectable } from '@angular/core'; + +import { DeviceType } from 'jslib/enums'; + +import { PlatformUtilsService } from 'jslib/abstractions'; + +const AnalyticsIds = { + [DeviceType.Windows]: 'UA-81915606-17', + [DeviceType.Linux]: 'UA-81915606-19', + [DeviceType.MacOs]: 'UA-81915606-18', +}; + +@Injectable() +export class DesktopPlatformUtilsService implements PlatformUtilsService { + private deviceCache: DeviceType = null; + private analyticsIdCache: string = null; + + getDevice(): DeviceType { + if (!this.deviceCache) { + switch (process.platform) { + case 'win32': + this.deviceCache = DeviceType.Windows; + break; + case 'darwin': + this.deviceCache = DeviceType.MacOs; + break; + case 'linux': + this.deviceCache = DeviceType.Linux; + break; + default: + this.deviceCache = DeviceType.Linux; + break; + } + } + + return this.deviceCache; + } + + getDeviceString(): string { + return DeviceType[this.getDevice()].toLowerCase(); + } + + isFirefox(): boolean { + return false; + } + + isChrome(): boolean { + return true; + } + + isEdge(): boolean { + return false; + } + + isOpera(): boolean { + return false; + } + + isVivaldi(): boolean { + return false; + } + + isSafari(): boolean { + return false; + } + + analyticsId(): string { + if (this.analyticsIdCache) { + return this.analyticsIdCache; + } + + // FIX? + // this.analyticsIdCache = AnalyticsIds[this.getDevice() as DeviceType]; + return this.analyticsIdCache; + } + + getDomain(uriString: string): string { + return uriString; + } + + isViewOpen(): boolean { + return true; + } +} diff --git a/src/app/services/desktopSecureStorage.service.ts b/src/app/services/desktopSecureStorage.service.ts new file mode 100644 index 00000000..4ffff727 --- /dev/null +++ b/src/app/services/desktopSecureStorage.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { getPassword, setPassword, deletePassword } from 'keytar'; + +import { StorageService } from 'jslib/abstractions'; + +@Injectable() +export class DesktopSecureStorageService implements StorageService { + async get(key: string): Promise { + const val: string = await getPassword('bitwarden', key); + return val ? JSON.parse(val) as T : null + } + + async save(key: string, obj: any): Promise { + await setPassword('bitwarden', key, JSON.stringify(obj)); + } + + async remove(key: string): Promise { + await deletePassword('bitwarden', key); + } +} diff --git a/src/app/services/desktopStorage.service.ts b/src/app/services/desktopStorage.service.ts new file mode 100644 index 00000000..e6e6b0c9 --- /dev/null +++ b/src/app/services/desktopStorage.service.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; + +import { StorageService } from 'jslib/abstractions'; + +const Store = require('electron-store'); +const store = new Store(); + +@Injectable() +export class DesktopStorageService implements StorageService { + get(key: string): Promise { + const val = store.get(key) as T; + return Promise.resolve(val ? val : null); + } + + save(key: string, obj: any): Promise { + store.set(key, obj); + return Promise.resolve(); + } + + remove(key: string): Promise { + store.delete(key); + return Promise.resolve(); + } +} diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts new file mode 100644 index 00000000..bc74d241 --- /dev/null +++ b/src/app/services/services.module.ts @@ -0,0 +1,91 @@ +import { NgModule } from '@angular/core'; + +import { DesktopMessagingService } from './desktopMessaging.service'; +import { DesktopPlatformUtilsService } from './desktopPlatformUtils.service'; +import { DesktopStorageService } from './desktopStorage.service'; +import { DesktopSecureStorageService } from './desktopSecureStorage.service'; + +import { + ApiService, + AppIdService, + AuthService, + CipherService, + CollectionService, + ConstantsService, + ContainerService, + CryptoService, + EnvironmentService, + FolderService, + LockService, + PasswordGenerationService, + SettingsService, + SyncService, + TokenService, + TotpService, + UserService, + UtilsService, +} from 'jslib/services'; + +import { + ApiService as ApiServiceAbstraction, + AppIdService as AppIdServiceAbstraction, + AuthService as AuthServiceAbstraction, + CipherService as CipherServiceAbstraction, + CollectionService as CollectionServiceAbstraction, + CryptoService as CryptoServiceAbstraction, + EnvironmentService as EnvironmentServiceAbstraction, + FolderService as FolderServiceAbstraction, + LockService as LockServiceAbstraction, + MessagingService as MessagingServiceAbstraction, + PasswordGenerationService as PasswordGenerationServiceAbstraction, + PlatformUtilsService as PlatformUtilsServiceAbstraction, + SettingsService as SettingsServiceAbstraction, + StorageService as StorageServiceAbstraction, + SyncService as SyncServiceAbstraction, + TokenService as TokenServiceAbstraction, + TotpService as TotpServiceAbstraction, + UserService as UserServiceAbstraction, + UtilsService as UtilsServiceAbstraction, +} from 'jslib/abstractions'; + +const utilsService = new UtilsService(); +const platformUtilsService = new DesktopPlatformUtilsService(); +const messagingService = new DesktopMessagingService(); +const storageService: StorageServiceAbstraction = new DesktopStorageService(); +//const secureStorageService: StorageServiceAbstraction = new DesktopSecureStorageService(); +const constantsService = new ConstantsService({}, 0); +const cryptoService = new CryptoService(storageService, storageService); +const tokenService = new TokenService(storageService); +const appIdService = new AppIdService(storageService); +const apiService = new ApiService(tokenService, platformUtilsService, + (expired: boolean) => { /* log out */ }); +const environmentService = new EnvironmentService(apiService, storageService); +const userService = new UserService(tokenService, storageService); +const settingsService = new SettingsService(userService, storageService); +const cipherService = new CipherService(cryptoService, userService, settingsService, + apiService, storageService); +const folderService = new FolderService(cryptoService, userService, + () => 'No Folder', apiService, storageService); +const collectionService = new CollectionService(cryptoService, userService, storageService); +const lockService = new LockService(cipherService, folderService, collectionService, + cryptoService, platformUtilsService, storageService, + () => { /* set icon */ }, () => { /* refresh badge and menu */ }); +const syncService = new SyncService(userService, apiService, settingsService, + folderService, cipherService, cryptoService, collectionService, + storageService, messagingService, (expired: boolean) => { /* log out */ }); +const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService); +const totpService = new TotpService(storageService); +const containerService = new ContainerService(cryptoService, platformUtilsService); +const authService: AuthServiceAbstraction = new AuthService(cryptoService, apiService, + userService, tokenService, appIdService, platformUtilsService, constantsService, + messagingService); + +@NgModule({ + imports: [], + declarations: [], + providers: [ + { provide: AuthServiceAbstraction, useValue: authService }, + ], +}) +export class ServicesModule { +} diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 00000000..4c0acc64 --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,3 @@ +declare function require(s: string): any; +declare function escape(s: string): string; +declare function unescape(s: string): string; diff --git a/tsconfig.json b/tsconfig.json index 331f7ac8..90eaf865 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "moduleResolution": "node", "noImplicitAny": true, + "emitDecoratorMetadata": true, "experimentalDecorators": true, "module": "es6", "target": "ES2016", diff --git a/webpack.common.js b/webpack.common.js index e695747e..d00e2e45 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -16,6 +16,7 @@ const isVendorModule = (module) => { }; module.exports = { + target: 'electron-renderer', devServer: { contentBase: './src', historyApiFallback: true, @@ -37,6 +38,10 @@ module.exports = { use: 'ts-loader', exclude: /node_modules\/(?!(@bitwarden)\/).*/ }, + { + test: /\.node$/, + loader: 'node-loader' + }, { test: /\.(html)$/, loader: 'html-loader'