mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-21 11:35:34 +01:00
stub out angular with webpack
This commit is contained in:
parent
848117ff86
commit
4d56d12ccb
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,5 +10,6 @@ webfonts/
|
||||
*.pem
|
||||
*.zip
|
||||
build/
|
||||
build2/
|
||||
build.safariextension/
|
||||
coverage/
|
||||
|
742
package-lock.json
generated
742
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@ -9,6 +9,8 @@
|
||||
"start:firefox": "web-ext run --source-dir ./dist/",
|
||||
"dev": "gulp build && webpack --config webpack.dev.js",
|
||||
"dev:watch": "gulp build && webpack --config webpack.dev.js --watch",
|
||||
"dev2": "webpack --config webpack2.js",
|
||||
"dev2:watch": "webpack --config webpack2.js --watch",
|
||||
"prod": "gulp build && webpack --config webpack.prod.js",
|
||||
"dist": "npm run prod && gulp dist",
|
||||
"dist:firefox": "npm run prod && gulp dist:firefox",
|
||||
@ -20,7 +22,18 @@
|
||||
"test:watch": "karma start"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ngtools/webpack": "1.10.2",
|
||||
"@types/angular": "^1.6.34",
|
||||
"@types/chrome": "0.0.51",
|
||||
"@types/jasmine": "^2.8.2",
|
||||
"@types/jquery": "^3.2.16",
|
||||
"@types/lunr": "2.1.5",
|
||||
"@types/node-forge": "0.6.10",
|
||||
"@types/papaparse": "4.1.31",
|
||||
"@types/safari-extension": "^0.0.27",
|
||||
"@types/safari-extension-content": "^0.0.14",
|
||||
"@types/tldjs": "1.7.1",
|
||||
"@types/webcrypto": "^0.0.28",
|
||||
"angular": "1.6.9",
|
||||
"angular-animate": "1.6.9",
|
||||
"angular-sweetalert": "1.1.2",
|
||||
@ -59,11 +72,11 @@
|
||||
"karma-typescript": "^3.0.8",
|
||||
"less": "^3.0.0-alpha.3",
|
||||
"less-loader": "^4.0.5",
|
||||
"lunr": "2.1.6",
|
||||
"ng-infinite-scroll": "1.3.0",
|
||||
"ngclipboard": "1.1.1",
|
||||
"node-forge": "0.7.1",
|
||||
"node-sass": "^4.7.2",
|
||||
"papaparse": "4.3.5",
|
||||
"sass-loader": "^6.0.6",
|
||||
"style-loader": "^0.19.0",
|
||||
"sweetalert": "1.1.3",
|
||||
"tldjs": "2.0.0",
|
||||
@ -76,16 +89,23 @@
|
||||
"webpack-merge": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/angular": "^1.6.34",
|
||||
"@types/chrome": "0.0.51",
|
||||
"@types/jquery": "^3.2.16",
|
||||
"@types/lunr": "2.1.5",
|
||||
"@types/node-forge": "0.6.10",
|
||||
"@types/papaparse": "4.1.31",
|
||||
"@types/safari-extension": "^0.0.27",
|
||||
"@types/safari-extension-content": "^0.0.14",
|
||||
"@types/tldjs": "1.7.1",
|
||||
"@types/webcrypto": "^0.0.28",
|
||||
"@uirouter/angularjs": "^1.0.10"
|
||||
"@angular/animations": "5.2.0",
|
||||
"@angular/common": "5.2.0",
|
||||
"@angular/compiler": "5.2.0",
|
||||
"@angular/core": "5.2.0",
|
||||
"@angular/forms": "5.2.0",
|
||||
"@angular/http": "5.2.0",
|
||||
"@angular/platform-browser": "5.2.0",
|
||||
"@angular/platform-browser-dynamic": "5.2.0",
|
||||
"@angular/router": "5.2.0",
|
||||
"@angular/upgrade": "5.2.0",
|
||||
"@uirouter/angularjs": "^1.0.10",
|
||||
"angular2-toaster": "4.0.2",
|
||||
"angulartics2": "5.0.1",
|
||||
"core-js": "2.4.1",
|
||||
"lunr": "2.1.6",
|
||||
"node-forge": "0.7.1",
|
||||
"rxjs": "5.5.6",
|
||||
"zone.js": "0.8.19"
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,7 @@
|
||||
"webRequest",
|
||||
"webRequestBlocking"
|
||||
],
|
||||
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
|
||||
"commands": {
|
||||
"autofill_login": {
|
||||
"suggested_key": {
|
||||
|
3
src/popup2/accounts/login.component.html
Normal file
3
src/popup2/accounts/login.component.html
Normal file
@ -0,0 +1,3 @@
|
||||
<form id="login-page" #form>
|
||||
Login Form
|
||||
</form>
|
44
src/popup2/accounts/login.component.ts
Normal file
44
src/popup2/accounts/login.component.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import * as template from './login.component.html';
|
||||
|
||||
import {
|
||||
Component,
|
||||
ComponentFactoryResolver,
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
import { AuthResult } from 'jslib/models/domain/authResult';
|
||||
|
||||
import { AuthService } from 'jslib/abstractions/auth.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { SyncService } from 'jslib/abstractions/sync.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
template: template,
|
||||
})
|
||||
export class LoginComponent {
|
||||
@ViewChild('environment', { read: ViewContainerRef }) environmentModal: ViewContainerRef;
|
||||
|
||||
email: string = '';
|
||||
masterPassword: string = '';
|
||||
showPassword: boolean = false;
|
||||
formPromise: Promise<AuthResult>;
|
||||
|
||||
constructor(private router: Router, private analytics: Angulartics2,
|
||||
private toasterService: ToasterService) { }
|
||||
|
||||
async submit() {
|
||||
|
||||
}
|
||||
|
||||
togglePassword() {
|
||||
this.analytics.eventTrack.next({ action: 'Toggled Master Password on Login' });
|
||||
this.showPassword = !this.showPassword;
|
||||
document.getElementById('masterPassword').focus();
|
||||
}
|
||||
}
|
21
src/popup2/app-routing.module.ts
Normal file
21
src/popup2/app-routing.module.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import {
|
||||
RouterModule,
|
||||
Routes,
|
||||
} from '@angular/router';
|
||||
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: '/login', pathMatch: 'full' },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, {
|
||||
useHash: true,
|
||||
/*enableTracing: true,*/
|
||||
})],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule { }
|
39
src/popup2/app.component.ts
Normal file
39
src/popup2/app.component.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import {
|
||||
ToasterConfig,
|
||||
ToasterContainerComponent,
|
||||
} from 'angular2-toaster';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
|
||||
import {
|
||||
Component,
|
||||
ComponentFactoryResolver,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Type,
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
styles: [],
|
||||
template: `
|
||||
<toaster-container [toasterconfig]="toasterConfig"></toaster-container>
|
||||
<router-outlet></router-outlet>`,
|
||||
})
|
||||
export class AppComponent {
|
||||
toasterConfig: ToasterConfig = new ToasterConfig({
|
||||
showCloseButton: true,
|
||||
mouseoverTimerStop: true,
|
||||
animation: 'flyRight',
|
||||
limit: 5,
|
||||
});
|
||||
|
||||
constructor(private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics, private analytics: Angulartics2,
|
||||
private toasterService: ToasterService) { }
|
||||
}
|
1
src/popup2/app.d.ts
vendored
Normal file
1
src/popup2/app.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module '*.html';
|
44
src/popup2/app.module.ts
Normal file
44
src/popup2/app.module.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import 'core-js';
|
||||
import 'zone.js/dist/zone';
|
||||
|
||||
import { ToasterModule } from 'angular2-toaster';
|
||||
import { Angulartics2Module } from 'angulartics2';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { ServicesModule } from './services/services.module';
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
AppRoutingModule,
|
||||
ServicesModule,
|
||||
Angulartics2Module.forRoot([Angulartics2GoogleAnalytics], {
|
||||
pageTracking: {
|
||||
clearQueryParams: true,
|
||||
},
|
||||
}),
|
||||
ToasterModule,
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
LoginComponent,
|
||||
],
|
||||
entryComponents: [
|
||||
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
14
src/popup2/index.html
Normal file
14
src/popup2/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Bitwarden</title>
|
||||
<base href="">
|
||||
</head>
|
||||
<body>
|
||||
<app-root>
|
||||
<div id="loading"><i class="fa fa-spinner fa-spin fa-3x"></i></div>
|
||||
</app-root>
|
||||
</body>
|
||||
</html>
|
15
src/popup2/main.ts
Normal file
15
src/popup2/main.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
// tslint:disable-next-line
|
||||
require('../scss/popup.scss');
|
||||
// tslint:disable-next-line
|
||||
require('../scripts/duo.js');
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
//if (!isDev()) {
|
||||
// enableProdMode();
|
||||
//}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
31
src/popup2/services/auth-guard.service.ts
Normal file
31
src/popup2/services/auth-guard.service.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
CanActivate,
|
||||
Router,
|
||||
} from '@angular/router';
|
||||
|
||||
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||
import { UserService } from 'jslib/abstractions/user.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuardService implements CanActivate {
|
||||
constructor(private cryptoService: CryptoService, private userService: UserService, private router: Router,
|
||||
private messagingService: MessagingService) { }
|
||||
|
||||
async canActivate() {
|
||||
const isAuthed = await this.userService.isAuthenticated();
|
||||
if (!isAuthed) {
|
||||
this.messagingService.send('logout');
|
||||
return false;
|
||||
}
|
||||
|
||||
const key = await this.cryptoService.getKey();
|
||||
if (key == null) {
|
||||
this.router.navigate(['lock']);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
33
src/popup2/services/broadcaster.service.ts
Normal file
33
src/popup2/services/broadcaster.service.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class BroadcasterService {
|
||||
subscribers: Map<string, (message: any) => any> = new Map<string, (message: any) => any>();
|
||||
|
||||
send(message: any, id?: string) {
|
||||
if (id != null) {
|
||||
if (this.subscribers.has(id)) {
|
||||
this.subscribers.get(id)(message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.subscribers.forEach((value) => {
|
||||
value(message);
|
||||
});
|
||||
}
|
||||
|
||||
subscribe(id: string, messageCallback: (message: any) => any) {
|
||||
if (this.subscribers.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.subscribers.set(id, messageCallback);
|
||||
}
|
||||
|
||||
unsubscribe(id: string) {
|
||||
if (this.subscribers.has(id)) {
|
||||
this.subscribers.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
35
src/popup2/services/services.module.ts
Normal file
35
src/popup2/services/services.module.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import {
|
||||
APP_INITIALIZER,
|
||||
NgModule,
|
||||
} from '@angular/core';
|
||||
|
||||
import { ToasterModule } from 'angular2-toaster';
|
||||
|
||||
import { AuthGuardService } from './auth-guard.service';
|
||||
import { BroadcasterService } from './broadcaster.service';
|
||||
import { ValidationService } from './validation.service';
|
||||
|
||||
function initFactory(): Function {
|
||||
return async () => {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
ToasterModule,
|
||||
],
|
||||
declarations: [],
|
||||
providers: [
|
||||
ValidationService,
|
||||
AuthGuardService,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initFactory,
|
||||
deps: [],
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class ServicesModule {
|
||||
}
|
37
src/popup2/services/validation.service.ts
Normal file
37
src/popup2/services/validation.service.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
@Injectable()
|
||||
export class ValidationService {
|
||||
constructor(private toasterService: ToasterService, private i18nService: I18nService) { }
|
||||
|
||||
showError(data: any): string[] {
|
||||
const defaultErrorMessage = this.i18nService.t('unexpectedError');
|
||||
const errors: string[] = [];
|
||||
|
||||
if (data == null || typeof data !== 'object') {
|
||||
errors.push(defaultErrorMessage);
|
||||
} else if (data.validationErrors == null) {
|
||||
errors.push(data.message ? data.message : defaultErrorMessage);
|
||||
} else {
|
||||
for (const key in data.validationErrors) {
|
||||
if (!data.validationErrors.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data.validationErrors[key].forEach((item: string) => {
|
||||
errors.push(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), errors[0]);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
3
src/scss/popup.scss
Normal file
3
src/scss/popup.scss
Normal file
@ -0,0 +1,3 @@
|
||||
body {
|
||||
color: black;
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"module": "es6",
|
||||
"target": "ES2016",
|
||||
"allowJs": true,
|
||||
@ -20,6 +22,7 @@
|
||||
"dist",
|
||||
"jslib/dist",
|
||||
"build",
|
||||
"build2",
|
||||
"build.safariextension",
|
||||
"coverage",
|
||||
"store",
|
||||
|
150
webpack2.js
Normal file
150
webpack2.js
Normal file
@ -0,0 +1,150 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
const isVendorModule = (module) => {
|
||||
if (!module.context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nodeModule = module.context.indexOf('node_modules') !== -1;
|
||||
const bitwardenModule = module.context.indexOf('@bitwarden') !== -1;
|
||||
return nodeModule && !bitwardenModule;
|
||||
};
|
||||
|
||||
const extractCss = new ExtractTextPlugin({
|
||||
filename: '[name].css',
|
||||
disable: false,
|
||||
allChunks: true
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
'popup/main': './src/popup2/main.ts',
|
||||
'background': './src/background.ts',
|
||||
'content/autofill': './src/content/autofill.js',
|
||||
'content/autofiller': './src/content/autofiller.js',
|
||||
'content/notificationBar': './src/content/notificationBar.js',
|
||||
'content/shortcuts': './src/content/shortcuts.js',
|
||||
'downloader/downloader': './src/downloader/downloader.ts',
|
||||
'2fa/2fa': './src/2fa/2fa.ts',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
enforce: 'pre',
|
||||
loader: 'tslint-loader'
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules\/(?!(@bitwarden)\/).*/
|
||||
},
|
||||
{
|
||||
test: /\.(html)$/,
|
||||
loader: 'html-loader'
|
||||
},
|
||||
{
|
||||
test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
|
||||
exclude: /loading.svg/,
|
||||
use: [{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'popup/fonts/',
|
||||
publicPath: './fonts/'
|
||||
}
|
||||
}]
|
||||
},
|
||||
{
|
||||
test: /\.(jpe?g|png|gif|svg)$/i,
|
||||
exclude: /.*(fontawesome-webfont|glyphicons-halflings-regular)\.svg/,
|
||||
use: [{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'popup/images/',
|
||||
publicPath: './images/'
|
||||
}
|
||||
}]
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: extractCss.extract({
|
||||
use: [
|
||||
{
|
||||
loader: 'css-loader',
|
||||
},
|
||||
{
|
||||
loader: 'sass-loader',
|
||||
}
|
||||
],
|
||||
publicPath: '../'
|
||||
})
|
||||
},
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new CleanWebpackPlugin([
|
||||
path.resolve(__dirname, 'build2/*')
|
||||
]),
|
||||
// ref: https://github.com/angular/angular/issues/20357
|
||||
new webpack.ContextReplacementPlugin(
|
||||
/\@angular(\\|\/)core(\\|\/)esm5/,
|
||||
path.resolve(__dirname, './src')
|
||||
),
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'popup/vendor',
|
||||
chunks: ['popup/main'],
|
||||
minChunks: isVendorModule
|
||||
}),
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
chunks: ['background'],
|
||||
minChunks: isVendorModule
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/popup2/index.html',
|
||||
filename: 'popup/index.html',
|
||||
chunks: ['popup/vendor', 'popup/main', 'fonts']
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/background.html',
|
||||
filename: 'background.html',
|
||||
chunks: ['vendor', 'background']
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/downloader/index.html',
|
||||
filename: 'downloader/index.html',
|
||||
chunks: ['downloader/downloader']
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/2fa/index.html',
|
||||
filename: '2fa/index.html',
|
||||
chunks: ['2fa/2fa']
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
'./src/manifest.json',
|
||||
{ from: './src/_locales', to: '_locales' },
|
||||
{ from: './src/edge', to: 'edge' },
|
||||
{ from: './src/safari', to: 'safari' },
|
||||
{ from: './src/images', to: 'images' },
|
||||
{ from: './src/content/autofill.css', to: 'content' }
|
||||
]),
|
||||
extractCss
|
||||
],
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
alias: {
|
||||
jslib: path.join(__dirname, 'jslib/src')
|
||||
}
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: path.resolve(__dirname, 'build2')
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user